日期: 2025-11-23 类型: 性能优化 影响范围: 配置管理、训练器
实现了AMP(Automatic Mixed Precision)混合精度训练支持,允许模型使用FP16精度进行训练以提升速度并减少显存占用。PyTorch的AMP自动管理精度转换和梯度缩放,在保证训练稳定性的同时获得性能提升。
原有训练使用FP32精度,在计算密集的卷积操作中存在性能瓶颈。特别是mini模型(500K参数)的训练速度受限于GPU计算能力。现代GPU(如RTX 20系列及以上)配备Tensor Core,对FP16运算有硬件加速支持,使用混合精度训练可以显著提升训练速度。
同时,项目的输入是图像数据,从0-255归一化到0-1的过程已经损失精度,使用FP16不会对模型性能产生明显影响。DQN配合Target Network、BatchNorm和保守学习率,在FP16下能保持良好的数值稳定性。
使用PyTorch的torch.cuda.amp模块实现自动混合精度训练:
根据model_mode自动决定是否启用AMP:
AMP最终启用需要满足三个条件的与运算:
use_amp=truetorch.cuda.is_available()返回True(有GPU)任一条件不满足,自动fallback到FP32训练。
字段定义(第58-59行):
# Mixed Precision Training
use_amp: bool = None # 是否使用AMP混合精度训练,None表示根据model_mode自动决定
from_yaml加载(第76-84行):
# Read model_mode first
model_mode = data.get('model', {}).get('mode', 'full')
# Read use_amp config, if None, decide based on model_mode
use_amp_config = data.get('training', {}).get('use_amp', None)
if use_amp_config is None:
use_amp = (model_mode == 'mini')
else:
use_amp = use_amp_config
save_yaml保存(第138行):
'use_amp': self.use_amp
关键设计点:
添加配置项(第25行):
use_amp: null # 混合精度训练(FP16),null表示mini模式自动开启,full/high模式自动关闭
AMP初始化(第94-101行):
# AMP (Automatic Mixed Precision)
self.use_amp = config.use_amp and torch.cuda.is_available()
if self.use_amp:
self.scaler = torch.cuda.amp.GradScaler()
print(f" Using AMP: True (FP16 mixed precision)")
else:
self.scaler = None
print(f" Using AMP: False")
训练循环修改(第175-190行):
for batch in dataloader:
self.optimizer.zero_grad()
if self.use_amp:
with torch.cuda.amp.autocast():
loss = self._compute_loss(batch)
self.scaler.scale(loss).backward()
self.scaler.step(self.optimizer)
self.scaler.update()
else:
loss = self._compute_loss(batch)
loss.backward()
self.optimizer.step()
# Record batch loss
epoch_losses.append(loss.item())
进度输出增强(第202-206行):
# Update target network periodically
if self.config.use_target_network and (epoch + 1) % self.config.target_update_epochs == 0:
self.target_model.load_state_dict(self.model.state_dict())
scale_info = f", Scale: {self.scaler.get_scale():.0f}" if self.use_amp else ""
print(f" Epoch {epoch+1}/{self.config.num_epochs}, Avg Loss: {avg_loss:.4f}{scale_info} [Target Network Updated]")
elif (epoch + 1) % 10 == 0 or epoch == 0:
scale_info = f", Scale: {self.scaler.get_scale():.0f}" if self.use_amp else ""
print(f" Epoch {epoch+1}/{self.config.num_epochs}, Avg Loss: {avg_loss:.4f}{scale_info}")
关键设计点:
以下文件自动适配,无需修改:
FP16的数值范围比FP32小,最小正数约6e-8。深度学习中的梯度常常小于这个值,导致underflow(变成0)。
GradScaler通过以下步骤防止underflow:
GradScaler(
init_scale=65536.0, # 初始缩放因子(2^16)
growth_factor=2.0, # 增长倍数
backoff_factor=0.5, # 衰减倍数
growth_interval=2000, # 增长检查间隔
)
这些默认参数对大多数情况都适用,本项目直接使用。
在支持Tensor Core的GPU上:
[Trainer] Init
Device: cuda
Using Target Network: True
Using AMP: True (FP16 mixed precision)
[Train] Starting training...
Epoch 1/320, Avg Loss: 0.1234, Scale: 65536
Epoch 10/320, Avg Loss: 0.0567, Scale: 65536
Epoch 50/320, Avg Loss: 0.0234, Scale: 131072 [Target Network Updated]
loss为nan:
训练很慢:
__getitem__中已将数据移到device手动FP16:
model.half()
data = data.half()
# 需要手动处理loss scaling、数值稳定性等
AMP:
with torch.cuda.amp.autocast():
loss = model(data)
scaler.scale(loss).backward()
选择AMP的原因:
计算逻辑:
决策:
use_amp: true已更新以下文档:
本次开发成功实现了AMP混合精度训练支持,通过最小化的代码改动(仅3个文件,约20行代码)获得了显著的性能提升潜力。设计简洁、易于维护,配置驱动的启用策略兼顾了易用性和灵活性。
AMP的引入为项目带来了:
这一优化将大幅提升autowzry-agent项目的训练效率,特别是在mini模式下进行快速原型验证时。