PyTorch的自动混合精度amp

 参考自

PyTorch 源码解读之 torch.cuda.amp: 自动混合精度详解 - 知乎

 加入了我自己的一点理解,供自己复习时观看

自动混合精度原理

Tensor的dtype类型会自动变化,也就是框架按需自动调整cuda tensor的dtype

自动混合精度作用

低精度优势在于存储小、计算也会变快。

torch.cuda.amp

开启自动混合精度

torch.cuda.amp.GradScaler

通过放大loss的值来防止梯度的underflow下溢出(这只是BP的时候传递梯度信息使用,真正更新权重的时候还是要把放大的梯度再unscale回去);

使用方法

from torch.cuda.amp import autocast as autocast

# 创建model,默认是torch.FloatTensor
model = Net().cuda()
optimizer = optim.SGD(model.parameters(), ...)

# 在训练最开始之前实例化一个GradScaler对象
scaler = GradScaler()

for epoch in epochs:
    for input, target in data:
        optimizer.zero_grad()

        # 前向过程(model + loss)开启 autocast
        with autocast():
            output = model(input)
            loss = loss_fn(output, target)

        # Scales loss. 为了梯度放大,扩大后得到的loss再执行反向传播
        scaler.scale(loss).backward()

        # scaler.step() 1。首先把梯度的值unscale回来.
        # 2.如果梯度的值不是 infs 或者 NaNs, 那么调用optimizer.step()来更新权重,
        # 否则,忽略step调用,从而保证权重不更新(不被破坏),代替optimizer.step
        scaler.step(optimizer)

        # 准备着,看是否要增大scaler
        scaler.update()

scaler的大小在每次迭代中动态的估计,为了尽可能的减少梯度underflow,scaler应该更大但是如果太大的话,半精度浮点型的tensor又容易overflow(变成inf或者NaN)。所以动态估计的原理就是在不出现inf或者NaN梯度值的情况下尽可能的增大scaler的值——在每次scaler.step(optimizer)中,都会检查是否又inf或NaN的梯度出现: 

1,如果出现了inf或者NaN,scaler.step(optimizer)会忽略此次的权重更新(optimizer.step() ),并且将scaler的大小缩小(乘上backoff_factor);

2,如果没有出现inf或者NaN,那么权重正常更新,并且当连续多次(growth_interval指定)没有出现inf或者NaN,则scaler.update()会将scaler的大小增加(乘上growth_factor)。

也就是1.正向传播要开启混合精度,2.计算loss时要先放缩loss, 3.使用scaler.step(optimizer)代替optimizer.step进行权重更新  4.根据3的结果看看scaler是否要更新,更新scaler

为什么autocast中只有向前传播?

autocast上下文应该只包含网络的前向过程(包括loss的计算),而不要包含反向传播,因为BP的op会使用和前向op相同的类型。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch AMP(Automatic Mixed Precision)是一种用于深度学习模型训练的加速技术,它可以将低精度的计算操作与高精度的计算操作混合使用,从而在保持模型精度的同时提高训练速度和减少显存占用。具体来说,PyTorch AMP 使用了 NVIDIA Apex 库中的混合精度训练技术,将一些计算操作转换为 FP16(半精度浮点数)格式,从而减少计算和存储的需求。 实现 PyTorch AMP 混合精度训练的步骤如下: 1. 引入必要的库和模块: ```python import torch from torch.cuda.amp import autocast, GradScaler ``` 2. 定义模型和优化器: ```python model = MyModel() optimizer = torch.optim.SGD(model.parameters(), lr=1e-3) ``` 3. 定义混合精度训练相关的参数: ```python scaler = GradScaler() ``` 4. 在训练过程中使用 autocast 和 GradScaler 完成混合精度训练: ```python for data, target in train_loader: # 将数据和目标值转换为合适的类型 data, target = data.to(device), target.to(device) # 使用 autocast 进行前向计算和反向传播 with autocast(): output = model(data) loss = loss_function(output, target) # 使用 GradScaler 进行梯度缩放和反向传播 scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() # 清空梯度 optimizer.zero_grad() ``` 在上面的代码中,autocast 用于自动将一些计算操作转换为 FP16 格式,从而提高训练速度;GradScaler 用于梯度缩放和反向传播,确保在低精度的计算下仍能保持模型精度。 需要注意的是,不是所有的计算操作都能够使用 FP16 格式,一些数值较大的计算操作可能会出现溢出等问题。因此,在使用 PyTorch AMP 进行混合精度训练时,需要仔细选择转换的计算操作,并且进行必要的检查和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值