一、训练(Training)
流程概览:数据准备 → 前向传播 → 损失计算 → 反向传播 → 优化器更新参数 → 下一批次数据 → 循环多次直到模型收敛或达到最大 Epoch
1. 定义
训练是通过数据不断调整模型参数,使模型能够更准确地完成任务(分类、回归等)。
2. 核心流程
-
数据准备
- 数据划分:训练集(Train)、验证集(Validation)、测试集(Test)
课本-作业-考试 - 数据处理:归一化、标准化、数据增强
- 数据划分:训练集(Train)、验证集(Validation)、测试集(Test)
-
前向传播(Forward Propagation)
- 输入数据经过网络层计算,得到模型预测值
做练习题先写答案 - 激活函数提供非线性能力
- 输入数据经过网络层计算,得到模型预测值
-
计算损失(Loss Calculation)
- 使用损失函数衡量模型预测值
与真实标签
之间的误差
查看标准答案,看看错多少
- 使用损失函数衡量模型预测值
-
反向传播(Backpropagation)
- 模型根据损失调整内部参数。
反思
- 模型根据损失调整内部参数。
-
优化器更新参数(Optimizer Update)
- 使用优化器调整权重,使损失
最小化
优化器是“学习方法”,解析里的思路
- 使用优化器调整权重,使损失
迭代训练 (Iteration)
数据分批(
batch)处理,每批数据重复上面过程。每批数据做一次前向传播 → 计算损失 → 反向传播 → 参数更新(Iteration)
Batch → 数据块
Iteration → 每块数据训练一次、更新一次参数
Epoch → 完整训练整个数据集一次
-
Epoch:训练的次数。所有批次(完整数据集)都训练完一次 = 1 Epoch - 多次 Epoch 直到损失收敛或达到预设条件
- 批次太大或太小都会影响学习效果。
二、损失函数(Loss Function)
1. 定义
损失函数衡量模型预测值 与真实标签
之间的误差,训练目标是最小化损失。
2. 作用
- 指导模型学习方向 : 告诉模型哪部分预测错误,应该如何调整参数
- 衡量模型性能 :损失越小,模型预测越准确
- 定义优化目标 :训练过程中不断最小化损失
3. 常见类型
(1)回归任务
| 损失函数 | 公式 | 特点 | 通俗理解 |
|---|---|---|---|
| 均方误差(MSE) | 对异常值敏感 | 把每个预测误差平方,惩罚大的错误更多 | |
| 平均绝对误差(MAE) | 稳健,不受异常值影响 | 计算每个预测误差的绝对值,忽略方向 | |
| Huber Loss | 综合 MSE 和 MAE 优点 | 对小错误敏感,对大错误不过分惩罚 |
(2)分类任务
| 损失函数 | 公式 | 特点 | 通俗理解 |
|---|---|---|---|
| 交叉熵(Cross Entropy) | 最常用分类损失 | 判断预测概率与真实类别差异,概率越接近真实值损失越小 | |
| KL散度(KL Divergence) | 测概率分布差异 | 衡量两个概率分布的差异 | |
| Focal Loss | 对难分类样本加权 | 适合类别不平衡 | 对模型容易错的样本给更高权重,让模型重点学习难点 |
(3)特殊应用
| 场景 | 常用损失函数 | 通俗理解 |
|---|---|---|
| 序列生成 | 交叉熵、CTC Loss | 处理时间序列或文本预测任务 |
| 图像生成(GAN) | 对抗损失(Adversarial Loss) | 模型学会生成逼真的图像 |
| 自编码器 | 重构误差(Reconstruction Loss) | 模型学习如何压缩和还原数据 |
| 表征学习 | 对比损失(Contrastive Loss)、Triplet Loss | 学习数据的向量表示,让相似样本更接近 |
4. 梯度(Gradient)
- 梯度是损失函数对模型参数的导数,表示参数改变时损失函数变化的方向和大小。
4.1 通俗理解
梯度就像地图上的坡度,告诉你“往哪儿走能下坡最快”,梯度指向下坡最快的方向 ,也就是让损失函数变小的方向。梯度为 0 → 到达山谷底(最优点)
- 指导优化器更新参数 :梯度大 → 更新步伐大 ; 梯度小 → 更新步伐小
4.2 公式
假设损失函数为 ,参数为
,梯度为:
5. 使用小技巧
- 任务匹配:回归用 MSE/MAE,分类用交叉熵
- 类别不平衡:用加权交叉熵或 Focal Loss
- 多任务学习:组合多种损失函数,并调节权重
- 梯度稳定:避免梯度过大或过小,可用 Log 变换、梯度裁剪或平滑处理
三、优化器(Optimizer)
1. 定义
优化器控制模型参数的更新方式,通过梯度下降最小化损失函数 。
2. 常用优化器
| 优化器 | 更新公式(简化) | 特点 |
|---|---|---|
| SGD(随机梯度下降) | 简单,收敛慢,易陷入局部最优 | |
| Momentum(动量法) | 利用惯性加速收敛,减少震荡 | |
| AdaGrad | 自适应学习率,频繁更新参数较小,适合稀疏数据 | |
| RMSProp | 解决 AdaGrad 学习率下降过快问题,深度学习常用 | |
| Adam | 结合 Momentum 和 RMSProp | 高效,适合大多数场景,默认选择 |
3. 超参数关键点
-
学习率(Learning Rate,
)
- 控制参数每次更新的步长
- 太大 → 参数跳过最优点,训练可能震荡或发散
- 太小 → 收敛慢,训练时间长
-
Batch Size(批大小)
- 每次训练使用的样本数量
- 小 batch → 梯度噪声大,更新不稳定,但可节省显存
- 大 batch → 梯度稳定,训练更平滑,但显存占用高
-
Epoch(训练轮数)
- 模型完整看一遍训练集的次数
- Too few → 欠拟合,模型没学够
- Too many → 过拟合,模型记住训练集过多细节,泛化能力差
超参数是训练性能的关键调节器。通常结合 验证集损失曲线 和 早停法(Early Stopping) 来选择合适的学习率、Batch Size 和 Epoch。
四、训练中的常见问题
| 问题 | 原因 | 表现 | 解决方法 |
|---|---|---|---|
| 过拟合 | 模型容量过大、训练数据不足 | 训练集损失低,验证集损失高 | 数据增强、正则化、Dropout |
| 欠拟合 | 模型容量不足、训练不够或特征不够 | 训练集和验证集损失都高 | 增加模型容量、更多数据、训练更久 |
| 梯度消失 | 网络太深、激活函数饱和、权重初始化不合理 | 参数几乎不更新,训练停滞 | ReLU 激活、残差连接、BatchNorm、梯度裁剪、权重初始化 |
| 梯度爆炸 | 网络太深、权重过大 | 参数更新过大,训练发散 | 梯度裁剪、权重初始化、调整网络结构 |
| 学习率不合适 | 学习率设置太大或太小 | 收敛慢或训练发散 | 调整学习率,使用学习率调度器(Scheduler) |
五、训练策略与技巧-简介
1. 学习率调度(Learning Rate Scheduling)
控制训练过程中参数更新步长的变化:
- 固定学习率:保持不变,简单但可能收敛慢
- 指数衰减(Exponential Decay):学习率随训练轮数逐步减小
- 余弦退火(Cosine Annealing):学习率按余弦曲线下降,提高训练稳定性
- 自适应学习率:如 Adam、AdaGrad 等自动调整每个参数的步长
2. 正则化(Regularization)
防止模型过拟合,提高泛化能力:
- L1/L2 正则化:对参数加约束,防止过大
- Dropout:随机屏蔽一部分神经元,增强模型鲁棒性
- 数据增强(Data Augmentation):扩充训练数据,增加样本多样性
3. 梯度问题处理(Gradient Issues)
- 梯度消失:使用 ReLU 激活、残差网络(ResNet)、BatchNorm
- 梯度爆炸:使用梯度裁剪(Gradient Clipping)
4. 早停法(Early Stopping)
- 当验证集损失连续若干轮不下降时,停止训练
- 避免过拟合,节省训练时间
六、训练监控与评估
- 损失曲线:训练损失和验证损失变化,判断过拟合或欠拟合
- 指标监控:分类(Accuracy、F1、AUC)、回归(MSE、MAE、R²)
- 模型保存与加载:Checkpoints,便于断点训练或推理使用
"""
使用 PyTorch 构建并训练一个简单的二分类神经网络
- 网络结构包括输入层、隐藏层和输出层,使用了 ReLU 激活函数和 Sigmoid 激活函数。
- 采用了均方误差损失函数和随机梯度下降优化器。
- 训练过程是通过前向传播、计算损失、反向传播和参数更新来逐步调整模型参数。
代码逻辑:
1. 定义超参数:
- n_in: 输入特征维度 = 10
- n_h: 隐藏层神经元数 = 5
- n_out: 输出层大小 = 1(二分类结果)
- batch_size: 每批数据样本数 = 10
2. 构造数据:
- 输入 x: 随机生成 (10,10) 张量,表示 10 个样本,每个样本有 10 个特征
- 标签 y: (10,1) 张量,取值为 0 或 1
3. 定义模型:
- 结构:Linear(10→5) → ReLU → Linear(5→1) → Sigmoid
- Sigmoid 将输出压缩到 (0,1),适合二分类
4. 定义损失函数与优化器:
- 损失函数:MSELoss(均方误差,预测值与真实值的平方误差平均)
- 优化器:SGD,学习率 0.01
5. 训练过程:
- 循环 50 个 epoch
- 前向传播:计算预测值 y_pred
- 计算损失:loss = MSE(y_pred, y)
- 反向传播:loss.backward()
- 参数更新:optimizer.step()
- 打印每个 epoch 的损失值
"""
# 导入 PyTorch 库
import torch
import torch.nn as nn
import matplotlib.pyplot as plt # 可视化损失曲线
# ==========================
# 1. 定义超参数
# ==========================
n_in, n_h, n_out, batch_size = 10, 5, 1, 10
learning_rate = 0.01
num_epochs = 50
# ==========================
# 2. 构造输入数据和目标数据
# ==========================
x = torch.randn(batch_size, n_in) # 随机生成输入数据
y = torch.tensor([
[1.0], [0.0], [0.0],
[1.0], [1.0], [1.0],
[0.0], [0.0], [1.0], [1.0]
]) # 构造标签数据
# ==========================
# 3. 定义模型结构
# ==========================
model = nn.Sequential(
nn.Linear(n_in, n_h), # 输入层 → 隐藏层
nn.ReLU(), # 激活函数
nn.Linear(n_h, n_out), # 隐藏层 → 输出层
nn.Sigmoid() # 输出压缩到 (0,1),适合二分类
)
# ==========================
# 4. 定义损失函数和优化器
# ==========================
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# ==========================
# 5. 模型训练循环
# ==========================
losses = [] # 保存每轮 loss
for epoch in range(num_epochs):
y_pred = model(x) # 前向传播
loss = criterion(y_pred, y) # 计算损失
losses.append(loss.item()) # 保存损失
optimizer.zero_grad() # 清零梯度
loss.backward() # 反向传播
optimizer.step() # 参数更新
print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item():.4f}')
# --------------------------
# 可视化训练损失曲线
# --------------------------
plt.figure(figsize=(8, 5))
plt.plot(range(1, num_epochs+1), losses, marker='o', label='Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss Curve')
plt.grid(True)
plt.legend()
plt.show()
# --------------------------
# 可视化预测结果与实际目标值对比
# --------------------------
y_pred_final = model(x).detach().numpy() # 将模型最终预测值从 tensor 转为 numpy 数组
y_actual = y.numpy() # 将真实标签 tensor 转为 numpy 数组
plt.figure(figsize=(8, 5))
# 绘制实际值
plt.plot(range(1, batch_size + 1), y_actual, 'o-', label='Actual', color='blue')
# 绘制预测值
plt.plot(range(1, batch_size + 1), y_pred_final, 'x--', label='Predicted', color='red')
plt.xlabel('Sample Index') # 横轴:样本编号
plt.ylabel('Value') # 纵轴:值(0~1)
plt.title('Actual vs Predicted Values') # 图标题
plt.legend() # 显示图例
plt.grid() # 添加网格线
plt.show()

1

2