英译法案例 - 模型训练总结
1 课程概览
本课总结模型训练过程。训练 5 轮,每轮约 1 分钟(GPU),每 1000 条数据约 20 秒。保存了 5 个编码器和 5 个解码器模型。损失曲线持续下降说明模型在收敛。训练策略:单批次训练和多轮多批次训练分成两个函数,提高代码可读性。
2 核心概念与定义
- 单批次训练(train_iterate):一个句子的训练过程。
- 多轮多批次训练:模型训练的骨架和流程。
- Teacher Forcing 概率:0.5,不要太大。
- 三剑客:梯度清零、反向传播、梯度更新。
3 模型与算法详解
训练时长
| 项目 | 时长 |
|---|---|
| 总轮数 | 5 轮 |
| 每轮时长 | 约 1 分钟(GPU) |
| 每 1000 条 | 约 20 秒 |
模型保存
一共保存了 10 个模型:5 个编码器 + 5 个解码器。
损失曲线
- 损失持续下降,说明模型在收敛
- 可调整打印密度(每 10 次或每 100 次打印)
训练流程总结
单批次训练(train_iterate)
- 编码:将英语句子编码为隐藏状态
- 解码:结合 Teacher Forcing 生成法语
- 训练策略:是否使用 Teacher Forcing
- 用:拿上一步真实值作为下一步输入
- 不用:拿本次预测值作为下一次输入
- 三剑客:梯度清零、反向传播、梯度更新
多轮多批次训练
- 定义优化器
- 定义损失函数
- 调用单批次训练函数
代码结构
单批次训练和多轮多批次训练分成两个函数,提高可读性。
def train_iterate():
"""单批次训练"""
# 编码
# 解码(Teacher Forcing)
# 三剑客:梯度清零、反向传播、梯度更新
def train():
"""多轮多批次训练"""
# 定义优化器
# 定义损失函数
# 调用 train_iterate
Teacher Forcing 概率
概率设为 0.5,不要太大。
- 太大:每次都用真实值,效果不好
- 0.5:一半用真实值,一半用预测值
4 数学原理与推导
梯度更新
$$W = W - \alpha \cdot \nabla W$$
其中 $\alpha$ 是学习率,$\nabla W$ 是梯度。
Teacher Forcing
$$\hat{y}t = f(y{t-1}, h_{t-1})$$
以概率 0.5 使用真实值 $y_{t-1}$,否则使用预测值 $\hat{y}_{t-1}$。
5 代码示例
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
def train_iterate(input_tensor, target_tensor, encoder, decoder,
encoder_optimizer, decoder_optimizer, criterion,
teacher_forcing_ratio=0.5, max_length=10):
"""单批次训练函数"""
encoder_optimizer.zero_grad()
decoder_optimizer.zero_grad()
input_length = input_tensor.size(0)
target_length = target_tensor.size(0)
loss = 0
# 编码
encoder_hidden = encoder.initHidden()
for ei in range(input_length):
encoder_output, encoder_hidden = encoder(input_tensor[ei], encoder_hidden)
# 解码
decoder_input = torch.tensor([[SOS]], device=device)
decoder_hidden = encoder_hidden
use_teacher_forcing = torch.rand(1).item() < teacher_forcing_ratio
for di in range(target_length):
decoder_output, decoder_hidden, _ = decoder(
decoder_input, decoder_hidden, encoder_outputs
)
loss += criterion(decoder_output, target_tensor[di])
if use_teacher_forcing:
# Teacher Forcing:用真实值
decoder_input = target_tensor[di]
else:
# 不用 Teacher Forcing:用预测值
topv, topi = decoder_output.topk(1)
decoder_input = topi.squeeze().detach()
# 三剑客:梯度清零、反向传播、梯度更新
loss.backward()
encoder_optimizer.step()
decoder_optimizer.step()
return loss.item() / target_length
def train(encoder, decoder, n_iters, learning_rate=0.001):
"""多轮多批次训练函数"""
# 定义优化器
encoder_optimizer = torch.optim.Adam(encoder.parameters(), lr=learning_rate)
decoder_optimizer = torch.optim.Adam(decoder.parameters(), lr=learning_rate)
# 定义损失函数
criterion = nn.NLLLoss()
# 记录损失
plot_losses = []
for iter in range(1, n_iters + 1):
# 获取数据
for x, y in my_dataloader:
# 调用单批次训练
loss = train_iterate(x, y, encoder, decoder,
encoder_optimizer, decoder_optimizer, criterion)
plot_losses.append(loss)
# 绘制损失曲线
plt.plot(plot_losses)
plt.title('Training Loss')
plt.show()
6 重难点与易错提醒
- ❗重点:单批次训练和多轮多批次训练分成两个函数。
- ❗重点:Teacher Forcing 概率设为 0.5,不要太大。
- ⚠️易错:Teacher Forcing 在推理阶段不能用(没有真实值)。
- ⚠️易错:Teacher Forcing 概率太大会导致推理不稳定。
- 💡深入理解:三剑客——梯度清零、反向传播、梯度更新。
7 课堂问答精选
Q1:Teacher Forcing 在 NLP 中的作用是什么?
A:是一种生成模型的训练技巧,每个时间步接收真实序列作为输入,而不是预测结果。作用是防止"一步错,步步错"。
Q2:使用 Teacher Forcing 哪个描述是正确的?
A:可能导致模型在推理阶段出现不稳定的情况。因为训练时用真实值,推理时没有真实值,可能导致不稳定。所以概率不要设太大(0.5 即可)。
Q3:为什么要将单批次训练和多轮多批次训练分成两个函数?
A:如果写在一个函数中,代码会非常臃肿,可读性差。分开写更清晰,单批次训练是具体训练过程,多轮多批次训练是骨架和流程。
Q4:Teacher Forcing 概率应该设为多少?
A:0.5。不要太大,太大会导致每次都用真实值,推理阶段不稳定。
8 本课小结
- 训练 5 轮,每轮约 1 分钟(GPU)。
- 保存 10 个模型:5 个编码器 + 5 个解码器。
- 损失持续下降,模型在收敛。
- 单批次训练和多轮多批次训练分开写。
- Teacher Forcing 概率 0.5,不要太大。
9 延伸思考
- 如何评估模型效果?
- 如何进行模型预测?