Pytorch学习笔记

jonathan
2024-05-24 / 0 评论

训练模型数据集划分

数据集通常会被划分为训练集(Training Set)、验证集(Validation Set)和测试集(Test Set),这样可以有效地训练、优化和评估模型的性能。


1. 训练集(Training Set)

  • 作用:用于模型的学习,即让模型调整参数(权重和偏置)。
  • 占比:一般占 60%-80% 的总数据。
  • 细节:模型在这个数据集上不断计算损失 → 反向传播 → 更新参数,以最小化误差。

2. 验证集(Validation Set)

  • 作用:在训练过程中监测模型的表现,用于调整超参数(如学习率、层数、神经元数量等),防止过拟合。
  • 占比:一般占 10%-20% 的总数据。
  • 细节
    • 训练过程中不会对验证集进行梯度更新,仅用于计算指标(如准确率、损失)。
    • 用于超参数调优,选择最优模型配置。

3. 测试集(Test Set)

  • 作用:在模型完全训练好后,用于最终评估模型的泛化能力。
  • 占比:一般占 10%-20% 的总数据。
  • 细节
    • 不能用于训练,也不能用于超参数调优,完全独立。
    • 反映模型对未见过的数据的表现,确保模型不会仅仅记住训练数据(过拟合)。

为什么要区分验证集和测试集?

很多人会问:“为什么不直接用测试集来调优超参数?”
原因

  • 如果我们用测试集来调整超参数,模型就会对测试集产生信息泄露,测试集就不再是真正的未知数据,评估结果会有偏差
  • 验证集的作用是提供反馈,而测试集的作用是提供最终评分

数据集划分方法

1. 直接划分

from sklearn.model_selection import train_test_split

# 生成示例数据
X = [[i] for i in range(1000)]  # 1000 个样本
y = [i % 2 for i in range(1000)]  # 二分类标签

# 先划分为训练集 + 剩余集(80% 训练,20% 剩余)
X_train, X_rem, y_train, y_rem = train_test_split(X, y, test_size=0.2, random_state=42)

# 再划分验证集和测试集(各 10%)
X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, test_size=0.5, random_state=42)

print(f"训练集大小: {len(X_train)}, 验证集大小: {len(X_val)}, 测试集大小: {len(X_test)}")

输出:

训练集大小: 800, 验证集大小: 100, 测试集大小: 100

2. K 折交叉验证(适用于小数据集)

如果数据集较小,可以使用 K 折交叉验证(K-Fold Cross Validation)

from sklearn.model_selection import KFold
import numpy as np

X = np.array(range(100))
kf = KFold(n_splits=5, shuffle=True, random_state=42)  # 5 折交叉验证

for train_index, val_index in kf.split(X):
    print(f"训练集: {train_index}, 验证集: {val_index}")

总结

数据集 作用 是否参与训练 用于超参数调优 何时使用
训练集 训练模型 训练时
验证集 调整超参数,监测过拟合 训练过程中
测试集 评估最终性能 训练结束后

🚀 最佳实践
80%-10%-10% 划分(训练-验证-测试)
K 折交叉验证(当数据较少时)

神经网络模型训练的原理

神经网络模型训练的本质是一个 优化过程,核心目标是 最小化损失函数(Loss Function),使得模型对训练数据的预测尽可能准确。训练过程主要包括 前向传播(Forward Propagation)、损失计算(Loss Calculation)、反向传播(Backward Propagation)、参数更新(Parameter Update) 四个关键步骤。


1. 前向传播(Forward Propagation)

计算从输入到输出的结果

  • 输入数据 ( X ) 经过 加权求和激活函数 处理,得到 预测值 ( Y_{\text{pred}} )
  • 数学公式: [ Z = W \cdot X + b ] [ Y_{\text{pred}} = \sigma(Z) ] 其中:
    • ( W ) 是 权重(Weights)
    • ( b ) 是 偏置(Bias)
    • ( \sigma(Z) ) 是 激活函数(如 ReLU、Sigmoid)

2. 计算损失函数(Loss Calculation)

衡量模型的预测值与真实值之间的差距

  • 损失函数(Loss Function) 用来量化误差,常见损失函数:
    • 回归任务(预测连续值):使用 均方误差(MSE) [ L = \frac{1}{N} \sum (Y_{\text{true}} - Y_{\text{pred}})^2 ]
    • 分类任务(预测类别):使用 交叉熵损失(CrossEntropy) [ L = -\sum Y_{\text{true}} \log(Y_{\text{pred}}) ]

3. 反向传播(Backward Propagation)

计算梯度,调整参数

  • 通过 链式求导法则(Chain Rule) 计算每个参数对损失函数的贡献: [ \frac{\partial L}{\partial W} ]
  • 反向传播的本质是 梯度下降(Gradient Descent): [ W = W - \alpha \cdot \frac{\partial L}{\partial W} ] 其中:
    • ( \alpha ) 是 学习率(Learning Rate)
    • ( \frac{\partial L}{\partial W} ) 是 梯度(Gradient)

4. 参数更新(Parameter Update)

使用优化算法(如 SGD、Adam)调整权重,使损失减少:

  • 随机梯度下降(SGD): [ W = W - \alpha \cdot \frac{\partial L}{\partial W} ]
  • Adam(自适应学习率优化)
    • 计算梯度的指数加权平均
    • 适用于 非平稳数据和稀疏梯度

完整示例:用 PyTorch 训练神经网络

import torch
import torch.nn as nn
import torch.optim as optim

# 1. 准备数据
X = torch.tensor([[1.0], [2.0], [3.0], [4.0]])  # 输入
Y = torch.tensor([[2.0], [4.0], [6.0], [8.0]])  # 真实值

# 2. 构建模型
class LinearRegressionModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)  # 一层线性回归模型(y = Wx + b)

    def forward(self, x):
        return self.linear(x)

model = LinearRegressionModel()

# 3. 选择损失函数和优化器
loss_fn = nn.MSELoss()  # 均方误差
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 4. 训练模型
for epoch in range(100):
    Y_pred = model(X)  # 前向传播
    loss = loss_fn(Y_pred, Y)  # 计算损失

    optimizer.zero_grad()  # 清除梯度
    loss.backward()  # 反向传播
    optimizer.step()  # 参数更新

    if (epoch + 1) % 10 == 0:
        print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

# 5. 预测新数据
new_X = torch.tensor([[5.0]])
predicted_Y = model(new_X).item()
print(f"预测 5 对应的值: {predicted_Y:.2f}")

总结

步骤 说明
前向传播 计算从输入到输出的预测值
计算损失 计算预测值与真实值的误差
反向传播 计算梯度,优化参数
参数更新 使用梯度下降调整权重
在 PyTorch 中,梯度下降(Gradient Descent)是优化模型参数的核心方法之一。PyTorch 提供了 torch.optim 模块,其中包含了多种优化算法,包括最基本的 随机梯度下降(SGD),以及更高级的优化算法(如 Adam、RMSprop 等)。

1. PyTorch 梯度下降的基本流程

梯度下降的核心步骤如下:

  1. 前向传播(Forward Propagation) 计算损失函数(Loss)。
  2. 反向传播(Backward Propagation) 计算梯度,即对参数求导。
  3. 更新参数(Parameter Update) 使用优化器(如 SGD)更新模型参数。

2. PyTorch 实现梯度下降

(1) 使用 torch.optim.SGD

import torch

# 创建模型参数(需要计算梯度)
w = torch.tensor(2.0, requires_grad=True)

# 定义损失函数 L = (w-3)²
def loss_fn(w):
    return (w - 3) ** 2

# 定义优化器(学习率 lr=0.1)
optimizer = torch.optim.SGD([w], lr=0.1)

# 梯度下降迭代
for i in range(10):
    loss = loss_fn(w)  # 计算损失
    optimizer.zero_grad()  # 清空梯度
    loss.backward()  # 计算梯度
    optimizer.step()  # 更新参数
    
    print(f"Step {i+1}: w = {w.item()}, Loss = {loss.item()}")

流程解析

  • optimizer.zero_grad(): 清空梯度,避免梯度累积。
  • loss.backward(): 计算损失对 w 的梯度 ∂L/∂w
  • optimizer.step(): 使用 SGD 更新参数:
    [ w = w - \text{lr} \times \frac{\partial L}{\partial w} ]

(2) 手动实现梯度下降

如果不使用 torch.optim,可以手动更新参数:

w = torch.tensor(2.0, requires_grad=True)
lr = 0.1  # 学习率

for i in range(10):
    loss = loss_fn(w)  # 计算损失
    loss.backward()  # 计算梯度
    with torch.no_grad():  # 关闭梯度计算,防止 PyTorch 记录计算图
        w -= lr * w.grad  # 参数更新
        w.grad.zero_()  # 清空梯度
        
    print(f"Step {i+1}: w = {w.item()}, Loss = {loss.item()}")

这里手动计算 w -= lr * w.grad,效果等同于 optimizer.step()


3. PyTorch 支持的优化算法

除了 SGD,PyTorch 还提供了更高级的优化器:

  • Adam (torch.optim.Adam):适用于大多数任务,收敛快。
  • RMSprop (torch.optim.RMSprop):适用于非平稳目标函数(如强化学习)。
  • Adagrad (torch.optim.Adagrad):适用于稀疏数据。

示例(使用 Adam):

optimizer = torch.optim.Adam([w], lr=0.1)

4. 选择合适的梯度下降算法

优化器 适用场景 主要特点
SGD 经典梯度下降 适用于凸优化,学习率难以调整
SGD + Momentum 加速收敛 可减少振荡,适用于深度网络
Adam 通用 结合了 RMSprop 和 Momentum,适用性强
RMSprop 适用于非平稳目标 适用于强化学习和递归神经网络
Adagrad 适用于稀疏数据 适合 NLP 任务,梯度会逐渐减小

在深度学习任务中,Adam 是默认的首选优化器。


5. 结论

  • 梯度下降是优化模型的核心方法,PyTorch 提供了自动求导和优化器。
  • 使用 torch.optim 可以方便地管理优化算法,如 SGDAdam
  • 对于深度学习任务,Adam 通常是更好的选择。

评论

博主关闭了当前页面的评论