Training(模型训练)本质是AI世界的‘科学烹饪实验’——以数据为食材原料,用超参数作配方比例,借验证集做品控质检,将‘玄学炼丹’的试错过程,淬炼成‘可复现的精密工程’。今天用最通俗的话,带你拆解模型训练(Training)全过程。
一、概念解读
二、技术实现
PyTorch如何实现Training(模型训练)?PyTorch通过定义模型结构(继承nn.Module并实现前向传播),配置损失函数(如MSELoss)与优化器(如Adam),在训练循环中反向传播更新参数(通过loss.backward()和optimizer.step()),同时利用DataLoader实现数据批量加载与预处理,最终通过迭代优化使模型拟合数据。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import math
# 参数配置
input_dim = 10 # 输入特征维度
output_dim = 1 # 输出维度(回归任务)
seq_length = 5 # 序列长度
batch_size = 32
num_epochs = 50 # 增加训练轮次
learning_rate = 0.001
d_model = 64 # 模型维度
nhead = 4 # 注意力头数
dim_feedforward = 256 # 前馈网络维度
# 生成虚拟数据(带时序特征)
X = torch.randn(1000, seq_length, input_dim) * torch.arange(1, seq_length+1).view(1, -1, 1)
y = X.mean(dim=(1,2)).unsqueeze(-1) # 目标:带时序权重的均值回归
# 数据标准化
X = (X - X.mean()) / X.std()
y = (y - y.mean()) / y.std()
# 封装为DataLoader
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, num_workers=2)
class TransformerEncoderRegressor(nn.Module):
def __init__(self):
super().__init__()
self.input_proj = nn.Linear(input_dim, d_model)
# Transformer编码器(参考网页7架构)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=dim_feedforward,
batch_first=True # PyTorch 1.9+特性
)
self.encoder = nn.TransformerEncoder(encoder_layer, num_layers=3)
# 输出层(带特征聚合)
self.output_layer = nn.Sequential(
nn.Linear(d_model * seq_length, 128),
nn.ReLU(),
nn.Dropout(0.1),
nn.Linear(128, output_dim)
)
# 位置编码(参考网页4实现)
self.pos_encoder = PositionalEncoding(d_model, dropout=0.1)
def forward(self, src):
# 输入投影 [batch, seq, d_model]
src = self.input_proj(src) * math.sqrt(d_model)
# 添加位置编码
src = self.pos_encoder(src)
# 编码处理 [batch, seq, d_model]
memory = self.encoder(src)
# 特征聚合 [batch, seq*d_model]
flattened = memory.view(memory.size(0), -1)
return self.output_layer(flattened)
class PositionalEncoding(nn.Module):
"""网页4位置编码实现(适配batch_first格式)"""
def __init__(self, d_model: int, dropout: float = 0.1, max_len: int = 5000):
super().__init__()
self.dropout = nn.Dropout(p=dropout)
position = torch.arange(max_len).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))
pe = torch.zeros(max_len, d_model)
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.register_buffer('pe', pe.unsqueeze(0)) # [1, max_len, d_model]
def forward(self, x):
x = x + self.pe[:, :x.size(1), :]
return self.dropout(x)
# 初始化模型
model = TransformerEncoderRegressor()
criterion = nn.MSELoss()
optimizer = optim.AdamW(model.parameters(), lr=learning_rate, weight_decay=1e-4)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5)
# 训练循环(带验证)
for epoch in range(num_epochs):
model.train()
total_loss = 0
for batch_X, batch_y in dataloader:
optimizer.zero_grad()
outputs = model(batch_X)
loss = criterion(outputs, batch_y)
loss.backward()
# 梯度裁剪(网页7实践)
nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
total_loss += loss.item()
avg_loss = total_loss / len(dataloader)
scheduler.step(avg_loss)
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}, LR: {optimizer.param_groups[0]["lr"]:.2e}')
# 测试推理
test_input = torch.randn(3, seq_length, input_dim) # 批量推理测试
model.eval()
with torch.no_grad():
prediction = model(test_input)
print('Test predictions:', prediction.squeeze().tolist())