PyTorch自动微分知识点讲解
PyTorch自动微分知识点讲解
知识导图
PyTorch自动微分
├── 基础认知
│ ├── 自动微分的核心概念
│ └── autograd模块的作用
├── 梯度计算
│ ├── 梯度计算的规则
│ └── backward与grad的使用
└── 实战案例
├── 单参数的更新
└── 多参数的更新
核心名词解释
-
自动微分 (AD):PyTorch 的核心功能,用来自动计算函数的梯度,不需要手动求导,简化了神经网络的训练。
-
autograd:PyTorch 的自动微分模块,实现了自动梯度计算,支持反向传播。
-
反向传播:神经网络的训练算法,通过损失函数的梯度来更新模型的参数,autograd 模块实现了这个过程的自动化。
-
requires_grad:张量的属性,用来标记是否需要对这个张量计算梯度,开启自动微分。
-
backward():反向传播的方法,用来自动计算梯度,调用后会自动计算所有需要梯度的张量的梯度。
-
grad:张量的属性,用来存储计算得到的梯度值,每次调用 backward 后会累加。
-
梯度清零:因为 grad 会累加,所以每次训练前需要把梯度清零,避免上一次的梯度影响本次的计算。
一、自动微分基础认知
本章节学习目标:
- 掌握自动微分模块的使用
1.1 什么是自动微分
自动微分(Automatic Differentiation, AD) 是 PyTorch 的核心功能之一,它通过 autograd 模块实现,无需手动计算梯度,极大简化了神经网络训练等依赖梯度优化的任务。

1.2 autograd 模块的作用
训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应参数的梯度进行调整。
PyTorch 内置的名为 torch\.autograd 的微分模块,它支持自动梯度计算,我们可以通过 backward 方法、grad 属性来实现梯度的计算和访问。

二、梯度的基本计算
梯度计算的规则
PyTorch 的梯度计算有以下规则:
-
PyTorch 不支持向量张量对向量张量的求导,只支持标量张量对向量张量的求导
-
如果 x 是张量,那么 loss 必须是标量(一个值)才可以进行求导
-
计算梯度:调用
loss\.backward\(\),其中 loss 是一个标量张量 -
获取 x 点的梯度值:
x\.grad,注意它会累加上一次的梯度值,所以经常要提前梯度清零
三、自动微分实战案例
3.1 单参数的更新
我们先来看单参数的自动微分更新,只更新权重 w:
*""""""*
"""
一次神经网络训练的全流程:初始化参数→前向算损失→反向算梯度→梯度下降更新参数。
"""
*# 导包*
import torch
*# todo 1 模拟初始化权重参数*
w = torch.tensor(data=2.0, requires_grad=True)
*# 只有浮点型的张量才能跟踪梯度,这也是为什么我们用2.0而不是2*
*# todo 2 模拟损失函数,计算损失*
loss = 2*w**2
print("损失值:", loss)
*# 输出: tensor(8., grad_fn=<MulBackward0>)*
*# 这里的`grad_fn=<MulBackward0>`就是autograd的跟踪标记:*
*# 它记录了这个loss是怎么算出来的,反向传播的时候就靠这个算梯度*
*# todo 3 反向传播:自动计算梯度*
loss.backward()
*# 这一步就是我们之前聊的自动微分+反向传播,算完的梯度会自动存到w.grad里*
print("w的梯度:", w.grad)
*# 输出: tensor(8.)*
*# 手动验证一下:损失函数是 loss=2w²,它的导数是 dloss/dw = 4w*
*# w初始是2,所以导数就是 4*2=8,和autograd自动算的完全一致!*
*# --------------------------*
*# todo 4 参数更新:梯度下降*
*# --------------------------*
lr = 0.01 *# 学习率*
print(f'更新前的w: {w.data}') *# 输出: 更新前的w: 2.0*
*# 正确的更新公式:w = w - 学习率 * 梯度*
w.data = w.data - lr * w.grad
print(f'更新后的w: {w.data}') *# 输出: 更新后的w: 1.92*
"""
补充两个实际开发的注意点
为什么更新参数要用w.data?
因为如果直接写w = w - lr * w.grad,会新建一个普通的张量,把原来带requires_grad的参数张量覆盖掉,之后就没法跟踪梯度了。用.data可以直接修改张量的数值,同时保留它的梯度跟踪属性。
梯度要清零!
如果你要跑第二次训练,一定要把上一次的梯度清零,不然梯度会累加:比如你再跑一次loss.backward(),w.grad 会变成 16,而不是重新计算。
实际开发中,优化器会自动帮你做optimizer.zero_grad(),不用你手动清。
"""
*""""""*
"""
一次神经网络训练的全流程:初始化参数→前向算损失→反向算梯度→梯度下降更新参数。
"""
*# 导包*
import torch
*# todo 1 模拟初始化权重参数*
w = torch.tensor(data=[2.0,4.0], requires_grad=True)
*# 只有浮点型的张量才能跟踪梯度,这也是为什么我们用2.0而不是2*
*# todo 2 模拟损失函数,计算损失*
loss = 2*w**2
print("损失值:", loss)
*# 输出: tensor([ 8., 32.], grad_fn=<MulBackward0>)*
*# 这里的`grad_fn=<MulBackward0>`就是autograd的跟踪标记:*
*# 它记录了这个loss是怎么算出来的,反向传播的时候就靠这个算梯度*
*# todo loss 必须是标量张量,否则用它的均值*
*# todo 3 反向传播:自动计算梯度*
loss.mean().backward() *# sum、mean*
*# 这一步就是我们之前聊的自动微分+反向传播,算完的梯度会自动存到w.grad里*
print("w的梯度:", w.grad)
*# 输出:w的梯度: tensor([4., 8.])*
*# 手动验证一下:损失函数是 loss=2w²,它的导数是 dloss/dw = 4w*
*# w初始是2,所以导数就是 4*2=8,和autograd自动算的完全一致!*
*# --------------------------*
*# todo 4 参数更新:梯度下降*
*# --------------------------*
lr = 0.01 *# 学习率*
print(f'更新前的w: {w.data}') *# 输出: 更新前的w: 2.0*
*# 正确的更新公式:w = w - 学习率 * 梯度*
w.data = w.data - lr * w.grad
*# =2-0.01*4*
*# =4-0.01*8*
print(f'更新后的w: {w.data}') *# 输出: 更新后的w: 1.92*
* # 更新后的w: tensor([1.9600, 3.9200])*
"""
补充两个实际开发的注意点
为什么更新参数要用w.data?
因为如果直接写w = w - lr * w.grad,会新建一个普通的张量,把原来带requires_grad的参数张量覆盖掉,之后就没法跟踪梯度了。用.data可以直接修改张量的数值,同时保留它的梯度跟踪属性。
梯度要清零!
如果你要跑第二次训练,一定要把上一次的梯度清零,不然梯度会累加:比如你再跑一次loss.backward(),w.grad 会变成 16,而不是重新计算。
实际开发中,优化器会自动帮你做optimizer.zero_grad(),不用你手动清。
"""
3.2 多参数的更新
接下来我们看同时更新权重 w 和偏置 b 的案例:
import torch
torch.manual_seed(6)
*# todo 1 初始化参数*
*# 1)模拟x数据 --真实特征*
x = torch.ones(size = (5,3))
*# 2)模拟y 数据*
y = torch.zeros(size=(2,3))
*# 3)模拟初始化w数据*
w = torch.randn(size=(2,5),requires_grad=True)
*# 4)模拟初始化b数据*
b = torch.randn(3,requires_grad=True)
*# 5)计算z标签*
z = w@x + b
print(z.shape) *# torch.Size([2, 3]) ->y*
*# 6)损失函数*
loss_fn = torch.nn.MSELoss()
*# 7) 学习率*
lr = 0.01
*# todo 2 前向算损失*
loss = loss_fn(z,y)
print(f'损失值:{loss}') *# loss= 13.9481782913208*
*# todo 3 反向算梯度*
loss.backward() *# ->w.grad*
print(f'w的梯度:{w.grad}')
print(f'b的梯度:{b.grad}')
*# todo 4 梯度下降更新参数 新 = 旧 - 学习率*梯度*
print(f'更新前的w:{w}')
w = w - 0.01*w.grad
print(f'更新后前的w:{w}')
print('-------------------------')
print(f'更新前的b:{b}')
b = b - 0.01*b.grad
print(f'更新后前的b:{b}')
四、知识点小结
本小节主要讲解了 PyTorch 中非常重要的自动微分模块的使用和理解。
我们对需要计算梯度的张量需要设置 requires\_grad=True 属性,这样 autograd 模块就会自动跟踪这个张量的运算,在反向传播的时候自动计算梯度。

更多推荐


所有评论(0)