PyTorch深度学习教程:神经网络训练原理与实践
神经网络训练基础概念
神经网络本质上是一种通用的函数逼近器。当我们构建一个神经网络时,它最初对输入数据(如手写数字图像)与输出结果(如类别概率)之间的映射关系一无所知。通过训练过程,我们可以调整网络参数,使其逐渐逼近这种映射关系。
损失函数:衡量预测误差
训练神经网络的核心在于定义一个损失函数(也称为代价函数),用于量化预测值与真实值之间的差异。对于分类问题,常用的损失函数包括:
-
均方误差损失(MSE):适用于回归和二分类问题 $$\large \ell = \frac{1}{2n}\sum_i^n{\left(y_i - \hat{y}_i\right)^2}$$
-
交叉熵损失:适用于多分类问题
其中n是训练样本数量,$y_i$是真实标签,$\hat{y}_i$是预测标签。
梯度下降:寻找最优参数
通过最小化损失函数,我们可以找到使网络预测准确率最高的参数配置。梯度下降是实现这一目标的关键算法:
- 梯度表示损失函数的斜率,指向变化最快的方向
- 沿着梯度反方向(下降方向)调整参数,可以最快到达最小值
- 类似于沿着山坡最陡峭的路径下山
反向传播:多层网络训练的关键
对于单层网络,梯度下降实现简单。但对于深度神经网络,需要使用反向传播算法,这实际上是微积分中链式法则的应用。
反向传播工作原理
- 前向传播:数据从输入层流向输出层,计算预测值和损失
- 反向传播:将损失梯度从输出层传回输入层,逐层计算各参数的梯度
- 参数更新:使用梯度下降法更新权重和偏置
数学表达式示例: $$\large \frac{\partial \ell}{\partial W_1} = \frac{\partial L_1}{\partial W_1} \frac{\partial S}{\partial L_1} \frac{\partial L_2}{\partial S} \frac{\partial \ell}{\partial L_2}$$
参数更新公式: $$\large W^\prime_1 = W_1 - \alpha \frac{\partial \ell}{\partial W_1}$$
其中$\alpha$是学习率,控制参数更新的步长。
PyTorch中的损失函数实现
PyTorch通过nn
模块提供了多种损失函数。对于MNIST这样的分类问题:
- 使用
nn.CrossEntropyLoss
(结合了nn.LogSoftmax
和nn.NLLLoss
) - 需要直接传入网络的原始输出(logits),而非softmax后的概率
- 这是因为浮点数对接近0或1的概率值表示不精确
# 构建网络
model = nn.Sequential(
nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10)
)
# 定义损失函数
criterion = nn.CrossEntropyLoss()
# 计算损失
logits = model(images)
loss = criterion(logits, labels)
另一种常见做法是使用log-softmax输出配合负对数似然损失:
model = nn.Sequential(
nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.LogSoftmax(dim=1)
)
criterion = nn.NLLLoss()
logps = model(images)
loss = criterion(logps, labels)
自动微分(Autograd)
PyTorch的autograd
模块自动计算张量的梯度,实现反向传播:
- 通过设置
requires_grad=True
跟踪张量操作 - 使用
backward()
方法计算梯度 - 可以通过
torch.no_grad()
临时禁用梯度计算
x = torch.randn(2,2, requires_grad=True)
y = x**2
z = y.mean()
z.backward() # 计算梯度
print(x.grad) # 查看x的梯度
完整训练流程
结合损失函数和优化器实现完整训练:
- 定义网络结构和优化器
- 前向传播计算损失
- 反向传播计算梯度
- 使用优化器更新参数
from torch import optim
# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 训练步骤
for epoch in range(epochs):
running_loss = 0
for images, labels in trainloader:
# 清空梯度
optimizer.zero_grad()
# 前向传播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
# 参数更新
optimizer.step()
running_loss += loss.item()
通过这种系统的训练方法,神经网络可以逐步学习从输入到输出的有效映射,实现准确的预测功能。理解这些基本原理对于深度学习实践至关重要。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考