梯度计算
- 深度学习
- 1天前
- 10热度
- 0评论
什么是梯度
梯度(Gradient)是用于描述多元函数在某一点的变化率最大的方向及其大小。在深度学习中,梯度被广泛用于优化模型参数(如神经网络的权重和偏置),通过梯度下降等算法最小化损失函数。
对于多元函数 f(x_1, x_2, \dots, x_n),其梯度是一个向量,由函数对每个变量的偏导数组成,记作:
\nabla f = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \dots, \frac{\partial f}{\partial x_n} \right)
其中:
- $\nabla f$ 是梯度符号(读作“nabla f”)。
- $\frac{\partial f}{\partial x_i}$ 是函数 $f$ 对变量 $x_i$ 的偏导数。
直观理解梯度
假设有一个二元函数 f(x, y) = x^2 + y^2,其梯度为:
\nabla f = \left( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right) = (2x, 2y)
在点 (1, 1) 处,梯度为 (2, 2),表示函数在该点沿方向 (2, 2) 增长最快。
若想最小化 f(x, y),应沿着负梯度方向 -(2, 2) 移动,即更新参数:
x \leftarrow x - \alpha \cdot 2x
y \leftarrow y - \alpha \cdot 2y
其中 \alpha 是学习率。
梯度在机器学习中的作用
在机器学习中,梯度表示损失函数(Loss Function)对模型参数的敏感度。例如,对于模型参数 W(权重)和 b(偏置),梯度 \nabla L 包含两个分量:
\nabla L = \left( \frac{\partial L}{\partial W}, \frac{\partial L}{\partial b} \right)
通过沿着负梯度方向更新参数(即梯度下降),可以逐步降低损失函数的值。
梯度下降的示例
目标:最小化函数 (线性回归的损失函数)。
L(W, b) = (W \cdot x + b - y_{\text{true}})^2
假设
x = 2, \quad y_{\text{true}} = 4, \quad W = 1, \quad b = 0.5
计算预测值:
y_{\text{pred}} = W \cdot x + b = 1 \cdot 2 + 0.5 = 2.5
计算损失:
L = (y_{\text{pred}} - y_{\text{true}})^2 = (2.5 - 4)^2 = 2.25
计算梯度:
\frac{\partial L}{\partial W} = 2 (y_{\text{pred}} - y_{\text{true}}) \cdot x = 2 (2.5 - 4) \cdot 2 = -6.0
\frac{\partial L}{\partial b} = 2 (y_{\text{pred}} - y_{\text{true}}) = 2 (2.5 - 4) = -3.0
梯度为
\nabla L = (-6.0, -3.0)
参数更新(学习率 (\alpha = 0.1)):
W_{\text{new}} = W - \alpha \cdot \frac{\partial L}{\partial W} = 1 - 0.1 \cdot (-6.0) = 1.6
b_{\text{new}} = b - \alpha \cdot \frac{\partial L}{\partial b} = 0.5 - 0.1 \cdot (-3.0) = 0.8
梯度计算推导
这个公式是梯度计算中的一部分,计算的是损失函数 (L) 对参数 (W) 的偏导数。我们来一步步推导这个公式。
假设损失函数为:
L(W, b) = (W \cdot x + b - y_{\text{true}})^2
其中W是权重,b是偏置,x是输入,y_{\text{true}}是真实的标签。我们要计算的是损失函数 L 对权重 W的偏导数\frac{\partial L}{\partial W}。
步骤 1: 定义损失函数
损失函数是预测值和真实值之间的误差的平方,定义为:
L(W, b) = (y_{\text{pred}} - y_{\text{true}})^2
其中,y_{\text{pred}} = W \cdot x + b是模型的预测值。这个损失函数是一个二次函数,目标是最小化它。
步骤 2: 使用链式法则求梯度
我们需要对损失函数 (L) 关于 (W) 求偏导数。首先可以应用链式法则:
\frac{\partial L}{\partial W} = \frac{\partial L}{\partial y_{\text{pred}}} \cdot \frac{\partial y_{\text{pred}}}{\partial W}
步骤 3: 计算每一部分的偏导数
- 第一部分: 计算 \frac{\partial L}{\partial y_{\text{pred}}}。
由于损失函数是平方误差形式:
L = (y_{\text{pred}} - y_{\text{true}})^2
对y_{\text{pred}}求导,得到:
\frac{\partial L}{\partial y_{\text{pred}}} = 2(y_{\text{pred}} - y_{\text{true}})
- 第二部分: 计算 \frac{\partial y_{\text{pred}}}{\partial W}。
由于 y_{\text{pred}}= W \cdot x + b,对W求导,得到:
\frac{\partial y_{\text{pred}}}{\partial W} = x
步骤 4: 合并结果
现在将两部分结果结合起来:
\frac{\partial L}{\partial W} = 2(y_{\text{pred}} - y_{\text{true}}) \cdot x
步骤 5: 将具体数值代入
根据给定的数值 x = 2,y_{\text{true}} = 4, W = 1, 和 b = 0.5,我们首先计算预测值y_{\text{pred}}:
y_{\text{pred}} = W \cdot x + b = 1 \cdot 2 + 0.5 = 2.5
然后代入到梯度公式中:
\frac{\partial L}{\partial W} = 2(2.5 - 4) \cdot 2 = 2(-1.5) \cdot 2 = -6.0
所以,损失函数L 对 W的偏导数是 -6.0。
总结:对于复杂的梯度计算可以利用链式法则。在该示例中,先令 y_{\text{pred}}= W \cdot x + b。对W求偏导,就可以转化为,\frac{\partial L}{\partial W} = \frac{\partial L}{\partial y_{\text{pred}}} \cdot \frac{\partial y_{\text{pred}}}{\partial W},然后可以先求\frac{\partial L}{\partial y_{\text{pred}}},再求\frac{\partial y_{\text{pred}}}{\partial W},这样计算就没有这么复杂了。根据公式\frac{\partial L}{\partial y_{\text{pred}}} = 2(y_{\text{pred}} - y_{\text{true}}),而\frac{\partial y_{\text{pred}}}{\partial W} = x,所以\frac{\partial L}{\partial W} = 2(y_{\text{pred}} - y_{\text{true}}) \cdot x,因此知道预测值、真实值、输入值、当前的权重和偏置即可算出偏导。同理b也可以用类似方法,继而算出损失函数的梯度\nabla L = \left( \frac{\partial L}{\partial W}, \frac{\partial L}{\partial b} \right)
pytorch示例
在pytorch中通过自动微分Autograd自动计算梯度,示例如下:
import torch
# 定义参数(启用梯度追踪)
W = torch.tensor(1.0, requires_grad=True)
b = torch.tensor(0.5, requires_grad=True)
# 输入数据
x = torch.tensor(2.0)
y_true = torch.tensor(4.0)
# 前向传播
y_pred = W * x + b
loss = (y_pred - y_true) ** 2
# 反向传播计算梯度
loss.backward()
# 输出梯度
print(f"dL/dW: {W.grad}") # 输出 tensor(-6.0)
print(f"dL/db: {b.grad}") # 输出 tensor(-3.0)
概念 | 数学表达 | 意义 |
---|---|---|
梯度定义 | ∇f = (∂f/∂x₁, …) | 多元函数变化最快的方向及其速率 |
梯度下降 | W ← W − α ⋅ ∂L/∂W | 沿负梯度方向更新参数以最小化损失函数 |
PyTorch自动微分 | loss.backward() | 通过反向传播自动计算所有参数的梯度并存储在 .grad 中 |