深度学习02-pytorch-08-自动微分模块
其实自动微分模块,就是求相当于机器学习中的线性回归损失函数的导数。就是求梯度。
反向传播的目的: 更新参数, 所以会使用到自动微分模块。
神经网络传输的数据都是 float32 类型。
案例1:
代码功能概述:
该代码展示了如何在 PyTorch 中使用 自动微分(Autograd) 计算损失函数相对于权重 w 和偏置 b 的梯度。这是机器学习模型训练中非常重要的步骤,因为这些梯度将用于更新模型的参数,从而最小化损失函数
import torch
# 1. 当x为标量时,梯度的计算
def test01():
x = torch.tensor(5) # 输入变量x为标量5
# 目标值
y = torch.tensor(0.) # 目标输出y设置为0
# 设置要更新的权重 和 偏置的初始值
w = torch.tensor(1., requires_grad=True, dtype=torch.float32) # 权重w初始化为1,并启用梯度计算
b = torch.tensor(3., requires_grad=True, dtype=torch.float32) # 偏置b初始化为3,并启用梯度计算
# 设置网络的输出值
z = x * w + b # 计算线性模型的输出 z = x*w + b (等同于线性回归的公式)
# 设置损失函数,并进行损失的计算
loss = torch.nn.MSELoss() # 使用均方误差(MSE)作为损失函数
loss1 = loss(z, y) # 计算损失,z 是模型的预测值,y 是目标值
# 自动微分,计算损失函数相对于w和b的梯度
loss1.backward() # 反向传播计算梯度
# backward 函数计算的梯度值会存储在张量的grad 变量中
print("w的梯度", w.grad) # 打印出损失函数对 w 的梯度
print("b的梯度", b.grad) # 打印出损失函数对 b 的梯度
test01()
w的梯度 tensor(80.)
b的梯度 tensor(16.)
代码讲解:
1. 输入与目标值:
• x = torch.tensor(5):输入为 x = 5,表示输入的特征值。
• y = torch.tensor(0.):目标输出 y 设置为 0,这是我们希望模型最终预测得到的值。
2. 参数的初始化:
• w = torch.tensor(1., requires_grad=True):初始化权重 w 为 1,requires_grad=True 启用对 w 的梯度计算。
• b = torch.tensor(3., requires_grad=True):初始化偏置 b 为 3,同样启用对 b 的梯度计算。
requires_grad=True 的作用是让 PyTorch 知道我们想对这些参数进行梯度计算。
3. 模型计算:
• z = x * w + b:计算模型的输出,类似于线性回归的公式。z 是模型的预测输出。
4. 损失函数:
• loss = torch.nn.MSELoss():选择均方误差(MSE)作为损失函数,用于衡量预测值 z 与目标值 y 之间的误差。
• loss1 = loss(z, y):计算损失值,z 是模型预测输出,y 是目标值。
MSE 的公式为:
在这个例子中,由于我们只使用了一个数据点,损失计算为:
5. 反向传播:
• loss1.backward():通过调用 backward(),PyTorch 会自动计算损失函数对 w 和 b 的梯度。这个过程称为反向传播(Backpropagation)。梯度的计算基于链式法则,PyTorch 会自动追踪所有的计算操作,计算各个参数对损失的导数。
6. 梯度输出:
• w.grad:存储了损失函数对 w 的梯度。
• b.grad:存储了损失函数对 b 的梯度。
案例2:
import torch
def test02():
# 输入张量 2x5,表示 2 个样本,每个样本有 5 个特征
x = torch.ones(2, 5) # 输入数据,全部初始化为 1
# 目标输出张量 2x3,表示我们希望模型预测的输出有 3 个类别
y = torch.zeros(2, 3) # 目标输出,初始化为 0
# 设置可更新的权重和偏置的初始值
# 权重 w 的形状是 5x3,表示输入特征为 5,输出类别为 3
w = torch.randn(5, 3, requires_grad=True) # 随机初始化权重,启用梯度计算
# 偏置 b 的形状是 3,表示每个输出类别有一个偏置
b = torch.randn(3, requires_grad=True) # 随机初始化偏置,启用梯度计算
# 计算网络的输出,z = x * w + b
# x 的形状是 2x5,w 的形状是 5x3,矩阵乘法后的结果 z 的形状是 2x3
z = torch.matmul(x, w) + b # 矩阵乘法和偏置加法
# 设置损失函数,并计算损失
# 这里使用均方误差(MSE),z 是预测值,y 是目标值
loss_fn = torch.nn.MSELoss() # 损失函数为均方误差
loss = loss_fn(z, y) # 计算损失,输出一个标量值
# 自动微分,计算损失函数相对于 w 和 b 的梯度
loss.backward() # 反向传播,计算梯度
# 打印权重和偏置的梯度,梯度值存储在 grad 属性中
print("w 的梯度:\n", w.grad) # 打印权重 w 的梯度
print("b 的梯度:\n", b.grad) # 打印偏置 b 的梯度
# 调用函数进行计算
test02()
自动微分 (Autograd) 的工作原理:
• PyTorch 中的 Autograd 是自动微分引擎,它会记录所有张量的计算历史,并根据这些计算图自动执行反向传播,计算参数的梯度。
• 在向前计算过程中,PyTorch 构建了一个动态计算图(计算图是有向无环图 DAG)。当你调用 .backward(),计算图会根据链式法则从损失开始计算每个变量的梯度。
• 计算的梯度会存储在对应张量的 .grad 属性中,然后可以使用这些梯度来更新模型的参数。
总结:
• w.grad 和 b.grad 的值告诉我们,若我们改变 w 或 b,损失函数会如何变化。
• 梯度的计算对于优化模型非常重要,因为我们会使用这些梯度来更新权重和偏置,使得损失函数最小化。
PyTorch 中的 自动微分模块 是通过 autograd
实现的,这是 PyTorch 中的核心功能之一,它可以帮助用户在神经网络的训练过程中自动计算梯度。autograd
模块使得实现反向传播和梯度计算变得非常简单和高效。
核心概念
-
Tensor: PyTorch 的张量 (
Tensor
) 是自动微分系统的基本单位。如果将Tensor
的requires_grad
属性设置为True
,则 PyTorch 会开始跟踪所有与该张量相关的操作,并在反向传播时自动计算该张量的梯度。 -
Computational Graph (计算图): PyTorch 会构建一个动态图,记录张量的所有操作。这个图是有向无环图(DAG),图中的每个节点代表一个变量,边代表该变量上发生的操作。当你调用
.backward()
时,PyTorch 会根据计算图自动计算每个张量的梯度。 -
梯度 (Gradient): 如果一个张量参与了计算并且
requires_grad=True
,在反向传播时可以通过.grad
属性获取其梯度值。 -
反向传播: 通过
tensor.backward()
来执行反向传播计算张量的梯度,默认情况下会对标量进行求导。
使用案例
-
创建一个张量并启用梯度跟踪:
import torch # 创建一个张量,并启用梯度跟踪 x = torch.tensor([[2.0, 3.0]], requires_grad=True)
-
执行一些操作:
y = x * 3 z = y.sum() print(z)
-
反向传播:
z.backward() # 对 z 求导 print(x.grad) # 查看 x 的梯度
输出:
tensor([[3., 3.]])
在这个例子中,
z = x * 3
,z.backward()
计算了z
对x
的梯度,结果为3
。
PyTorch 自动微分的几个重要点:
-
requires_grad=True: 如果需要对某个张量求导,必须将其
requires_grad
属性设置为True
,否则在反向传播时 PyTorch 不会计算该张量的梯度。 -
grad_fn: 每个跟踪计算的张量都有一个
grad_fn
属性,代表该张量的创建方式和跟踪的操作。例如,如果你对一个张量做了加法操作,它的grad_fn
就会显示AddBackward0
。print(y.grad_fn) # <MulBackward0 object at 0x...>
-
.backward():
backward()
方法会根据计算图反向传播,自动计算梯度。 -
梯度累加: 每次调用
backward()
时,梯度会被累加到.grad
中,因此在多次反向传播之前,最好手动将.grad
清零,使用x.grad.zero_()
。
autograd
的典型使用场景
-
神经网络训练:通过
autograd
,我们可以在每次迭代时计算损失函数的梯度,然后使用这些梯度更新网络的参数。 -
自定义梯度计算:可以通过创建复杂的操作来自动推导梯度。
Example: 简单的线性回归
import torch
# 生成数据
x = torch.randn(10, 1, requires_grad=True)
y = 3 * x + 2
# 定义损失函数
loss = (x - y).pow(2).mean()
# 反向传播
loss.backward()
# 查看 x 的梯度
print(x.grad)
在这个例子中,loss.backward()
会自动计算 x
对 loss
的梯度。
总结
-
PyTorch 的自动微分机制通过
autograd
实现,用户只需要将张量的requires_grad
设置为True
,在执行反向传播时,PyTorch 会自动计算张量的梯度。 -
通过自动构建计算图,
autograd
能够跟踪张量上的所有操作,动态计算梯度,极大地方便了深度学习模型的训练。