PyTorch深度学习教程:梯度下降与反向传播算法详解
引言
在深度学习领域,梯度下降和反向传播算法是训练神经网络的两大基石。本文将深入探讨这两个核心概念,并展示如何在PyTorch框架中实现它们。
参数化模型基础
参数化模型是深度学习的核心组件,其数学表达式为:
$$ \bar{y} = G(x,w) $$
其中:
- $x$ 是输入数据
- $w$ 是可训练参数
- $\bar{y}$ 是模型输出
参数化模型的关键特点是参数在不同样本间共享,而输入则随样本变化。这种共享机制使得模型能够从数据中学习通用特征。
常见参数化模型示例
-
线性模型:
- 输出是输入的加权和
- 常用平方差作为损失函数 $$ \bar{y} = \sum_i w_i x_i, \quad C(y,\bar{y}) = \Vert y - \bar{y}\Vert^2 $$
-
最近邻模型:
- 输出是与输入最接近的权重行索引 $$ \bar{y} = \underset{k}{\arg\min} \Vert x - w_{k,.} \Vert^2 $$
计算图表示法
理解计算图对掌握反向传播至关重要。计算图中的基本元素包括:
-
变量节点:
- 表示张量、标量等数据
- 分为观测输入和计算输出
-
确定性函数节点:
- 接收多个输入,产生多个输出
- 包含隐式参数变量
- 圆边表示计算方向
-
标量值函数节点:
- 用于表示损失函数
- 输出单个标量值
损失函数类型
在训练过程中,我们最小化两种损失:
-
单样本损失: $$ L(x,y,w) = C(y, G(x,w)) $$
-
平均损失(更常用): $$ L(S,w) = \frac{1}{P} \sum_{(x,y)} L(x,y,w) $$
平均损失的计算图展示了如何从单样本损失扩展到整个数据集。
梯度下降算法详解
基本概念
梯度下降是一种通过迭代寻找函数最小值的优化方法,核心思想是沿着函数梯度的反方向更新参数。
直观理解:想象在浓雾笼罩的山中寻找下山路径。虽然视野有限,但通过观察周围最陡峭的下坡方向,逐步向山下移动。
梯度下降变体
-
批量梯度下降:
- 使用整个数据集计算梯度
- 更新规则: $$ w \leftarrow w - \eta \frac{\partial L(S,w)}{\partial w} $$
-
随机梯度下降(SGD):
- 每次随机选择一个样本计算梯度
- 更新规则: $$ w \leftarrow w - \eta \frac{\partial L(x[p], y[p],w)}{\partial w} $$
虽然SGD的路径看起来"噪声"更多,但在实际应用中:
- 计算效率更高
- 能更好地避免局部极小值
- 适合大规模数据集
实际应用中的批处理
实践中通常使用小批量(mini-batch)梯度下降:
- 平衡了计算效率与稳定性
- 便于利用GPU并行计算
- 是SGD与批量梯度下降的折中方案
传统神经网络结构
传统神经网络由交替的线性层和非线性层组成:
-
线性操作:
- 实质是矩阵向量乘法
- 形式:$s = Wz$
-
非线性操作:
- 对线性输出逐元素应用激活函数
- 如ReLU、tanh等
- 形式:$z = f(s)$
这种交替结构使得神经网络能够学习复杂的非线性关系。需要注意的是,没有非线性激活的深层网络等价于单层线性网络。
反向传播算法原理
反向传播是高效计算梯度的算法,核心是链式法则的应用。
通过非线性函数的反向传播
对于非线性函数$z = h(s)$,梯度计算为: $$ \frac{\mathrm{d}C}{\mathrm{d}s} = \frac{\mathrm{d}C}{\mathrm{d}z}\cdot h'(s) $$
直观理解:扰动输入$s$会引起输出$z$的变化,进而影响最终损失$C$。
通过加权和的反向传播
当多个变量影响同一节点时,梯度是各路径梯度的加权和: $$ \frac{\mathrm{d}C}{\mathrm{d}z} = \sum_i \frac{\mathrm{d}C}{\mathrm{d}s[i]}\cdot w[i] $$
PyTorch实现示例
以下是一个简单的3层神经网络PyTorch实现:
import torch
from torch import nn
class MyNet(nn.Module):
def __init__(self, d0, d1, d2, d3):
super().__init__()
self.m0 = nn.Linear(d0, d1) # 第一线性层
self.m1 = nn.Linear(d1, d2) # 第二线性层
self.m2 = nn.Linear(d2, d3) # 第三线性层
def forward(self, x):
z0 = x.view(-1) # 展平输入
s1 = self.m0(z0)
z1 = torch.relu(s1) # 第一非线性层
s2 = self.m1(z1)
z2 = torch.relu(s2) # 第二非线性层
s3 = self.m2(z2)
return s3
关键点:
- 使用
nn.Linear
定义线性层,自动包含偏置项 - 激活函数直接使用
torch.relu
等函数 - 无需手动实现反向传播,PyTorch自动计算梯度
广义反向传播理论
对于更复杂的网络结构,可以使用雅可比矩阵进行广义反向传播。
向量函数的链式法则
对于向量函数$z_g = f(z_f)$,梯度计算为: $$ \frac{\partial c}{\partial{z_f}} = \frac{\partial c}{\partial{z_g}} \frac{\partial {z_g}}{\partial{z_f}} $$
其中$\frac{\partial {z_g}}{\partial {z_f}}$是雅可比矩阵,其元素为: $$ \left(\frac{\partial{z_g}}{\partial {z_f}}\right)_{ij} = \frac{(\partial {z_g})_i}{(\partial {z_f})_j} $$
多阶段计算图的反向传播
在多层网络中,每个模块需要计算两个雅可比矩阵:
- 关于输入的雅可比矩阵$\frac{\partial f_k}{\partial z_k}$
- 关于参数的雅可比矩阵$\frac{\partial f_k}{\partial w_k}$
通过连续相乘这些雅可比矩阵,可以将梯度从输出传播到网络的所有部分。
总结
本文详细介绍了梯度下降和反向传播算法的原理及实现,包括:
- 参数化模型的基本概念
- 各种梯度下降变体的特点
- 传统神经网络的结构
- 反向传播的数学原理
- PyTorch中的具体实现
理解这些基础概念对于掌握深度学习至关重要,它们是构建更复杂模型的基础。在实际应用中,现代深度学习框架如PyTorch已经为我们封装了这些复杂计算,但理解底层原理有助于更好地调试和优化模型。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考