【深度学习】pytorch——Autograd

news2024/11/25 22:36:33

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~

深度学习专栏链接:
http://t.csdnimg.cn/dscW7

pytorch——Autograd

  • Autograd简介
  • requires_grad
  • 计算图
    • 没有梯度追踪的张量ensor.data 、tensor.detach()
    • 非叶子节点的梯度
    • 计算图特点总结
  • 利用Autograd实现线性回归

Autograd简介

autograd是PyTorch中的自动微分引擎,它是PyTorch的核心组件之一。autograd提供了一种用于计算梯度的机制,使得神经网络的训练变得更加简洁和高效。

在深度学习中,梯度是优化算法(如反向传播)的关键部分。通过计算输入变量相对于输出变量的梯度,可以确定如何更新模型的参数以最小化损失函数。

autograd的工作原理是跟踪在张量上进行的所有操作,并构建一个有向无环图(DAG),称为计算图。这个计算图记录了张量之间的依赖关系,以及每个操作的梯度函数。当向前传播时,autograd会自动执行所需的计算并保存中间结果。当调用.backward()函数时,autograd会根据计算图自动计算梯度,并将梯度存储在每个张量的.grad属性中。

使用autograd非常简单。只需将需要进行梯度计算的张量设置为requires_grad=True,然后执行前向传播和反向传播操作即可。例如:

import torch as t

x = t.tensor([2.0], requires_grad=True)
y = x**2 + 3*x + 1

y.backward()

print(x.grad)  # 输出:tensor([7.])

在上述代码中,首先创建了一个张量 x,并设置了 requires_grad=True,表示想要计算关于 x 的梯度。然后,定义了一个计算图 y,通过对 x 进行一系列操作得到结果 y。最后,调用 .backward() 函数执行反向传播,并通过 x.grad 获取计算得到的梯度。

autograd的存在使得训练神经网络变得更加方便,无需手动计算和更新梯度。同时,它也为实现更复杂的计算图和自定义的梯度函数提供了灵活性和扩展性。

requires_grad

requires_grad是PyTorch中张量的一个属性,用于指定是否需要计算该张量的梯度。如果需要计算梯度,则需将其设置为True,否则设置为False。默认情况下,该属性值为False

在深度学习中,通常需要对模型的参数进行优化,因此需要计算这些参数的梯度。通过将参数张量的requires_grad属性设置为True,可以告诉PyTorch跟踪其计算并计算梯度。除了参数张量之外,还可以将其他需要计算梯度的张量设置为requires_grad=True,以便计算它们的梯度。

需要注意的是,如果张量的requires_grad属性为True,则计算成本会略微增加,因为PyTorch需要跟踪该张量的计算并计算其梯度。因此,对于不需要计算梯度的张量,最好将其requires_grad属性设置为False,以减少计算成本。

计算图

在这里插入图片描述
PyTorch中autograd的底层采用了计算图,计算图是一种特殊的有向无环图(DAG),用于记录算子与变量之间的关系。一般用矩形表示算子,椭圆形表示变量。其计算图如图所示,图中MULADD都是算子, a \textbf{a} a b \textbf{b} b c \textbf{c} c即变量。
在这里插入图片描述

没有梯度追踪的张量ensor.data 、tensor.detach()

tensor.datatensor.detach()都可以用于获取一个没有梯度追踪的张量副本,但它们之间有一些细微的区别。

tensor.data是一个属性,用于返回一个与原始张量共享数据存储的新张量,但不会共享梯度信息。这意味着对返回的张量进行操作不会影响到原始张量的梯度。然而,如果在计算图中使用了这个新的张量,梯度仍会通过原始张量进行传播。

以下是一个示例说明:

import torch

x = torch.tensor([2.0], requires_grad=True)
y = x**2 + 3*x + 1

z = y.data
z *= 2  # 操作z不会影响到y的梯度

y.backward()

print(x.grad)  # 输出:tensor([7.])

在上述代码中,我们首先创建了一个张量x,并设置了requires_grad=True,表示我们希望计算关于x的梯度。然后,我们定义了一个计算图y,并将其赋值给z,通过操作z不会影响到y的梯度。最后,我们调用.backward()方法计算相对于x的梯度,并将梯度存储在x.grad属性中。

tensor.detach()是一个函数,用于返回一个新的张量,与原始张量具有相同的数据内容,但不会共享梯度信息。与tensor.data不同的是,tensor.detach()可以应用于任何张量,而不仅限于具有requires_grad=True的张量。

以下是使用tensor.detach()的示例:

import torch

x = torch.tensor([2.0], requires_grad=True)
y = x**2 + 3*x + 1

z = y.detach()
z *= 2  # 操作z不会影响到y的梯度

y.backward()

print(x.grad)  # 输出:tensor([7.])

在上述代码中,我们执行了与前面示例相同的操作,将y赋值给z,并通过操作z不会影响到y的梯度。最后,我们调用.backward()方法计算相对于x的梯度,并将梯度存储在x.grad属性中。

总结来说,tensor.datatensor.detach()都可以用于获取一个没有梯度追踪的张量副本,但tensor.detach()更加通用,可应用于任何张量。

非叶子节点的梯度

在反向传播过程中,非叶子节点的梯度默认情况下是被清空的。

1.使用.retain_grad()方法:在创建张量时,可以使用.retain_grad()方法显式指定要保留梯度信息。然后,在反向传播后,可以访问这些非叶子节点的梯度。

import torch

x = torch.tensor([2.0], requires_grad=True)
y = x**2 + 3*x + 1

y.retain_grad()

z = y.mean()

z.backward()

grad_y = y.grad

print(grad_y)  # 输出:tensor([1.])

2.第二种方法:使用hook。hook是一个函数,输入是梯度,不应该有返回值

import torch

def variable_hook(grad):
    print('y的梯度:',grad)

x = torch.ones(3, requires_grad=True)
w = torch.rand(3, requires_grad=True)
y = x * w
# 注册hook
hook_handle = y.register_hook(variable_hook)
z = y.sum()
z.backward()

# 除非你每次都要用hook,否则用完之后记得移除hook
hook_handle.remove()

计算图特点总结

在PyTorch中,计算图是一种用于表示计算过程的数据结构。

动态计算图:PyTorch使用动态计算图,这意味着计算图是根据实际执行流程动态构建的。这使得在每次前向传播过程中可以根据输入数据的不同而灵活地构建计算图。

自动微分:PyTorch的计算图不仅用于表示计算过程,还支持自动微分。通过计算图,PyTorch可以自动计算梯度,无需手动编写反向传播算法。这大大简化了深度学习模型的训练过程。

基于节点的表示:计算图由一系列节点(Node)和边(Edge)组成,其中节点表示操作(如张量运算)或变量(如权重),边表示数据的流动。每个节点都包含了前向计算和反向传播所需的信息。

叶子节点和非叶子节点:在计算图中,叶子节点是没有输入边的节点,通常表示输入数据或需要求梯度的变量。非叶子节点是具有输入边的节点,表示计算操作。在反向传播过程中,默认情况下,只有叶子节点的梯度会被计算和保留,非叶子节点的梯度会被清空。

延迟执行:PyTorch中的计算图是按需执行的。也就是说,在前向传播过程中,只有实际需要计算的节点才会被执行,不需要计算的节点会被跳过。这种延迟执行的方式提高了效率,尤其对于大型模型和复杂计算图来说。

计算图优化:PyTorch内部使用了一些优化技术来提高计算图的效率。例如,通过共享内存缓存中间结果,避免重复计算;通过融合多个操作为一个操作,减少计算和内存开销等。这些优化技术可以提高计算速度,并减少内存占用。

利用Autograd实现线性回归

【深度学习】pytorch——线性回归:http://t.csdnimg.cn/7KsP3

上一篇文章为手动计算梯度,这里来利用Autograd实现自动计算梯度

import torch as t
%matplotlib inline
from matplotlib import pyplot as plt
from IPython import display
import numpy as np

# 设置随机数种子,保证在不同电脑上运行时下面的输出一致
t.manual_seed(1000) 

def get_fake_data(batch_size=8):
    ''' 产生随机数据:y=x*2+3,加上了一些噪声'''
    x = t.rand(batch_size, 1, device=device) * 5
    y = x * 2 + 3 +  t.randn(batch_size, 1, device=device)
    return x, y

# 随机初始化参数
w = t.rand(1,1, requires_grad=True)
b = t.zeros(1,1, requires_grad=True)
losses = np.zeros(500)

lr =0.02 # 学习率

for ii in range(500):
    x, y = get_fake_data(batch_size=4)
    
    # forward:计算loss
    y_pred = x.mm(w) + b.expand_as(y) 
    loss = 0.5 * (y_pred - y) ** 2 # 均方误差
    loss = loss.sum()
    losses[ii] = loss.item()
    
    # backward:自动计算梯度
    loss.backward()
    
    # 更新参数
    w.data.sub_(lr * w.grad.data)
    b.data.sub_(lr * b.grad.data)
    
    # 梯度清零
    w.grad.data.zero_()
    b.grad.data.zero_()
    
    if ii%50 ==0:
        # 画图
        display.clear_output(wait=True)
        x = t.arange(0, 6).view(-1, 1).float()
        y = x.mm(w.data) + b.data.expand_as(x)
        plt.plot(x.numpy(), y.numpy(),color='b') # predicted
        
        x2, y2 = get_fake_data(batch_size=100) 
        plt.scatter(x2.numpy(), y2.numpy(),color='r') # true data
        
        plt.xlim(0,5)
        plt.ylim(0,15)   
        plt.show()
        plt.pause(0.5)
        
print('w: ', w.item(), 'b: ', b.item())

在这里插入图片描述
w: 2.036161422729492 b: 3.095750331878662

以下是代码的主要步骤:

  1. 定义了一个get_fake_data函数,用于生成带有噪声的随机数据,数据的真实关系为 y = x ∗ 2 + 3 y=x*2+3 y=x2+3

  2. 初始化参数wb,并设置requires_grad=True以便自动计算梯度。

  3. 进行500轮训练,每轮训练包括以下步骤:

    • get_fake_data函数中获取一个小批量的训练数据。
    • 前向传播:计算模型的预测值y_pred,即 x x x与参数wb的线性组合。
    • 计算均方误差损失函数。
    • 反向传播:自动计算参数wb的梯度。
    • 更新参数:通过梯度下降法更新参数wb
    • 清零梯度:将参数的梯度置零,以便下一轮计算梯度。
    • 每50轮训练,可视化当前模型的预测结果和真实数据的散点图。
  4. 训练结束后,打印出最终学得的参数wb

plt.plot(losses)
plt.ylim(0,50)

实现了对损失函数随训练轮数变化的可视化。losses是一个长度为500的数组,记录了每一轮训练后的损失函数值。plt.plot(losses)会将这些损失函数值随轮数的变化连成一条曲线,可以直观地看到模型在训练过程中损失函数的下降趋势。

plt.ylim(0,50)用于设置y轴的范围,保证曲线能够完整显示在图像中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全网最详细的【shell脚本的入门】

🏅我是默,一个在CSDN分享笔记的博主。📚📚 ​ 🌟在这里,我要推荐给大家我的专栏《Linux》。🎯🎯 🚀无论你是编程小白,还是有一定基础的程序员,这…

【LearnOpenGL基础入门——2】搭建第一个OpenGL窗口

目录 一.配置GLFW 二.配置GLAD 三.第一个OpenGL窗口 3.1 GLFW设置 3.2 GLAD设置 3.3 视口 3.4 输入 3.5渲染 在我们画出出色的效果之前,首先要做的就是创建一个OpenGL上下文(Context)和一个用于显示的窗口。然而,这些操作在每个系统上都是不一样…

Swift 和 Python 两种语言中带关联信息错误(异常)类型的比较

0. 概览 如果我们分别在平静如水、和谐感人的 Swift 和 Python 社区抛出诸如“Python 是天下最好的语言…” 和 “Swift 是宇宙第一语言…”之类的言论会有怎样的“下场”? 我们并不想对可能发生的“炸裂”景象做出什么预测,也无意比较 Swift 与 Pytho…

[pytorch]手动构建一个神经网络并且训练

0.写在前面 上一篇博客全都是说明类型的,实际代码能不能跑起来两说,谨慎观看.本文中直接使用fashions数据实现softmax的简单训练并且完成结果输出.实现一个预测并且观测到输出结果. 并且更重要的是,在这里对一些训练的过程,数据的形式,以及我们在softmax中主要做什么以及怎么…

14.1 Linux 并发与竞争

一、并发与竞争 并发:多个执行单元同时、并行执行。 竞争:并发的执行单元同时访问共享资源(硬件资源和软件上的全局变量等)易导致竞态。 二、原子操作 1. 原子操作简介 原子操作:不能再进一步分割的操作,一般用于变量或位操作。 …

关于iOS:如何使用SwiftUI调整图片大小?

How to resize Image with SwiftUI? 我在Assets.xcassets中拥有很大的形象。 如何使用SwiftUI调整图像大小以缩小图像? 我试图设置框架,但不起作用: 1 2 Image(room.thumbnailImage) .frame(width: 32.0, height: 32.0) 在Image上应用…

数二真题强化

高等数学 定积分 变上限积分求导 被积函数不能含有x,用换元法 线性代数

20.7 OpenSSL 套接字SSL加密传输

OpenSSL 中的 SSL 加密是通过 SSL/TLS 协议来实现的。SSL/TLS 是一种安全通信协议,可以保障通信双方之间的通信安全性和数据完整性。在 SSL/TLS 协议中,加密算法是其中最核心的组成部分之一,SSL可以使用各类加密算法进行密钥协商,…

leetcode-887-鸡蛋掉落(包含最大值最小化,最小值最大化的二分优化+滚动数组的原理)

这里写目录标题 题意解题KNN复杂度DP解法思想(超时)上述方法的优化 (最大值最小化二分优化)完整代码 逆向思维的DP代码空间优化(滚动数组)代码 题意 链接:leetcode-887-鸡蛋掉落 给你 k 枚相同…

AD CS证书攻击与防御:ESC1

简介 2021年的BlackHat大会上,Will Schroeder和Lee Christensen发布了关于Active Directory Certificate Services 利用白皮书《Certified Pre-Owned - Abusing Active Directory Certificate Services》。 攻击对象为AD CS,攻击手法主要是利用证书模版…

【算法专题】双指针—和为s的两个数

一、题目解析 只需在这个数组中找出两个数相加等于target即可 二、算法原理 1、暴力解法&#xff08;时间复杂度&#xff1a;O(n^2)&#xff09; 两个for循环嵌套遍历这个数组即可&#xff0c;不过会超时 class Solution { public:vector<int> twoSum(vector<int&…

开启AWS的ubuntu服务器的root用户登录权限

设置root用户密码 输入以下命令修改root用户密码 sudo passwd root输入以下命令切换到root用户 su root仅允许root用户用密码登录 输入以下命令编辑ssh配置文件 vi /etc/ssh/sshd_config新增以下配置允许root用户登录 PermitRootLogin yes把PasswordAuthentication修改为…

latex设置图片的位置

Latex提供了一些命令来控制图片的位置。我们可以通过使用\begin{figure}[位置选项]来控制图片的位置。位置选项可以有h、t、b、p、!这五个&#xff0c;分别表示以下含义&#xff1a; h:表示放在当前位置&#xff0c;不过有时由于论文的格式限制&#xff0c;可能放不下。 t:表示…

详解IPD需求分析工具$APPEALS

够让企业生存下去的是客户&#xff0c;所以&#xff0c;众多企业提出要“以客户为中心”&#xff0c;那如何做到以客户为中心&#xff1f;IPD中给出的答案是需求管理。 需求管理流程&#xff0c;是IPD&#xff08;集成管理开发&#xff09;体系中的四大支撑流程之一&#xff0…

Transformer的最简洁pytorch实现

目录 前言 1. 数据预处理 2. 模型参数 3. Positional Encoding 4. Pad Mask 5. Subsequence Mask 6. ScaledDotProductAttention 7. MultiHeadAttention 8. FeedForward Networks 9. Encoder Layer 10. Encoder 11. Decoder Layer 12. Decoder 13. Transformer 1…

看!MySQL 8.2 数据库支持读写分离啦!

更多文章&#xff0c;欢迎关注作者公众号&#xff0c;欢迎一起交流。 MySQL 8.2.0创新版本已于2023-10-17发布&#xff0c;MySQL Router 8.2 支持数据库的读/写分离&#xff0c;这里将在InnoDB Cluster集群中演示数如何进行读写分离&#xff0c;本篇内容包括&#xff1a;MySQL …

【数字三角形】

题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径&#xff0c;把路径上面的数加起来可以得到一个和&#xff0c;你的任务就是找到最大的和。 路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外…

逆向学习记录(1)windows系统基本配置

我的环境&#xff1a;win10系统64位。 可以在虚拟机上操作。改天记录一下如何安装虚拟机及里面的系统。 1、查看windows版本情况 按下winr&#xff0c;输入winver&#xff0c;即可。 2、新装的windows系统&#xff0c;桌面上没有我的电脑图标&#xff1f; 在桌面上右键&…

创建基于多任务的并发服务器

有几个请求服务的客户端&#xff0c;我们就创建几个子进程。 这个过程有以下三个阶段&#xff1a; 这里父进程传递的套接字文件描述符&#xff0c;实际上不需要传递&#xff0c;因为子进程会复制父进程拥有的所有资源。 #include <stdio.h> #include <stdlib.h>…

1822_使用python内置的库进行日期序列的生成

使用python的内置的库进行日期序列的生成 用到的库介绍 datetime 实现这样的功能其实只需要这一个库就够了&#xff0c;但是网络上找到的例程很多都额外增加了对time库的引用。只能说&#xff0c;这样不会出现错误&#xff0c;但是这样肯定会有一些计算资源上的消耗。 #!/u…