笔记:神经网络中的“训练”+PyTorch构建简单的二分类模型

一、训练(Training)

流程概览:数据准备 → 前向传播 → 损失计算 → 反向传播 → 优化器更新参数 → 下一批次数据 → 循环多次直到模型收敛或达到最大 Epoch

1. 定义

训练是通过数据不断调整模型参数,使模型能够更准确地完成任务(分类、回归等)。

2. 核心流程

  1. 数据准备

    • 数据划分:训练集(Train)、验证集(Validation)、测试集(Test) 课本-作业-考试
    • 数据处理:归一化、标准化、数据增强
  2. 前向传播(Forward Propagation)

    • 输入数据经过网络层计算,得到模型预测值 \hat{y} 做练习题先写答案
    • 激活函数提供非线性能力
  3. 计算损失(Loss Calculation)

    • 使用损失函数衡量模型预测值 \hat{y} 与真实标签 y 之间的误差 查看标准答案,看看错多少
  4. 反向传播(Backpropagation)

    • 模型根据损失调整内部参数。反思
  5. 优化器更新参数(Optimizer Update)

    • 使用优化器调整权重,使损失 L(\hat{y}, y) 最小化 优化器是“学习方法”,解析里的思路
  6. 迭代训练 (Iteration)

数据分批(batch)处理,每批数据重复上面过程。每批数据做一次前向传播 → 计算损失 → 反向传播 → 参数更新(Iteration
Batch → 数据块
Iteration → 每块数据训练一次、更新一次参数
Epoch → 完整训练整个数据集一次

  • Epoch :训练的次数。所有批次(完整数据集)都训练完一次 = 1 Epoch
  • 多次 Epoch 直到损失收敛或达到预设条件
  • 批次太大或太小都会影响学习效果。

二、损失函数(Loss Function)

1. 定义

损失函数衡量模型预测值 \hat{y} 与真实标签 y 之间的误差,训练目标是最小化损失。

2. 作用

  • 指导模型学习方向 : 告诉模型哪部分预测错误,应该如何调整参数
  • 衡量模型性能 :损失越小,模型预测越准确
  • 定义优化目标 :训练过程中不断最小化损失

3. 常见类型

(1)回归任务

损失函数 公式 特点 通俗理解
均方误差(MSE) L(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^{n} (\hat{y}_i - y_i)^2 对异常值敏感 把每个预测误差平方,惩罚大的错误更多
平均绝对误差(MAE) L(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^{n} \lvert \hat{y}_i - y_i \rvert 稳健,不受异常值影响 计算每个预测误差的绝对值,忽略方向
Huber Loss L_\delta(\hat{y}, y) = \begin{cases} \frac{1}{2} (\hat{y}-y)^2, & \lvert \hat{y}-y \rvert \le \delta \\ \delta \lvert \hat{y}-y \rvert - \frac{1}{2} \delta^2, & \lvert \hat{y}-y \rvert > \delta \end{cases} 综合 MSE 和 MAE 优点 对小错误敏感,对大错误不过分惩罚

(2)分类任务

损失函数 公式 特点 通俗理解
交叉熵(Cross Entropy) L(\hat{y}, y) = -\sum_{i} y_i \log(\hat{y}_i) 最常用分类损失 判断预测概率与真实类别差异,概率越接近真实值损失越小
KL散度(KL Divergence) D_{KL}(P|Q) = \sum_i P(i) \log \frac{P(i)}{Q(i)} 测概率分布差异 衡量两个概率分布的差异
Focal Loss 对难分类样本加权 适合类别不平衡 对模型容易错的样本给更高权重,让模型重点学习难点

(3)特殊应用

场景 常用损失函数 通俗理解
序列生成 交叉熵、CTC Loss 处理时间序列或文本预测任务
图像生成(GAN) 对抗损失(Adversarial Loss) 模型学会生成逼真的图像
自编码器 重构误差(Reconstruction Loss) 模型学习如何压缩和还原数据
表征学习 对比损失(Contrastive Loss)、Triplet Loss 学习数据的向量表示,让相似样本更接近

4. 梯度(Gradient)

  • 梯度是损失函数对模型参数的导数,表示参数改变时损失函数变化的方向和大小。

4.1 通俗理解

梯度就像地图上的坡度,告诉你“往哪儿走能下坡最快”,梯度指向下坡最快的方向 ,也就是让损失函数变小的方向。梯度为 0 → 到达山谷底(最优点)

  • 指导优化器更新参数 :梯度大 → 更新步伐大 ; 梯度小 → 更新步伐小

4.2 公式

假设损失函数为 L(W),参数为 W,梯度为:
\nabla_W L(W) = \frac{\partial L(W)}{\partial W}


5. 使用小技巧

  • 任务匹配:回归用 MSE/MAE,分类用交叉熵
  • 类别不平衡:用加权交叉熵或 Focal Loss
  • 多任务学习:组合多种损失函数,并调节权重
  • 梯度稳定:避免梯度过大或过小,可用 Log 变换、梯度裁剪或平滑处理

三、优化器(Optimizer)

1. 定义

优化器控制模型参数的更新方式,通过梯度下降最小化损失函数 L(\hat{y}, y)


2. 常用优化器

优化器 更新公式(简化) 特点
SGD(随机梯度下降) W \gets W - \eta \frac{\partial L(\hat{y}, y)}{\partial W} 简单,收敛慢,易陷入局部最优
Momentum(动量法) v = \beta v + \eta \frac{\partial L}{\partial W}, \quad W \gets W - v 利用惯性加速收敛,减少震荡
AdaGrad W \gets W - \frac{\eta}{\sqrt{G+\epsilon}} \frac{\partial L}{\partial W} 自适应学习率,频繁更新参数较小,适合稀疏数据
RMSProp E[g^2]_t = \rho E[g^2]_{t-1} + (1-\rho) g_t^2, \quad W \gets W - \frac{\eta}{\sqrt{E[g^2]_t+\epsilon}} g_t 解决 AdaGrad 学习率下降过快问题,深度学习常用
Adam 结合 Momentum 和 RMSProp 高效,适合大多数场景,默认选择

3. 超参数关键点

  • 学习率(Learning Rate, \eta

    • 控制参数每次更新的步长
    • 太大 → 参数跳过最优点,训练可能震荡或发散
    • 太小 → 收敛慢,训练时间长
  • 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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 8,587评论 0 5
  • 为了让我有一个更快速、更精彩、更辉煌的成长,我将开始这段刻骨铭心的自我蜕变之旅!从今天开始,我将每天坚持阅...
    李薇帆阅读 6,036评论 0 3
  • 似乎最近一直都在路上,每次出来走的时候感受都会很不一样。 1、感恩一直遇到好心人,很幸运。在路上总是...
    时间里的花Lily阅读 5,257评论 0 2
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 3,616评论 0 1
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 3,579评论 0 0