base model第七彈:pytorch使用warm up、consine learning rate、label smooth、apex混合精度訓練

下列代碼均在pytorch1.4版本中測試過,確認正確無誤。

warm up與consine learning rate

warm up最早來自於這篇文章:https://arxiv.org/pdf/1706.02677.pdf 。根據這篇文章,我們一般只在前5個epoch使用warm up。consine learning rate來自於這篇文章:https://arxiv.org/pdf/1812.01187.pdf 。通常情況下,把warm up和consine learning rate一起使用會達到更好的效果。
代碼實現:

    # MultiStepLR without warm up
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=args.milestones, gamma=0.1)

    # warm_up_with_multistep_lr
    warm_up_with_multistep_lr = lambda epoch: epoch / args.warm_up_epochs if epoch <= args.warm_up_epochs else 0.1**len([m for m in args.milestones if m <= epoch])
    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=warm_up_with_multistep_lr)

    # warm_up_with_cosine_lr
    warm_up_with_cosine_lr = lambda epoch: epoch / args.warm_up_epochs if epoch <= args.warm_up_epochs else 0.5 * ( math.cos((epoch - args.warm_up_epochs) /(args.epochs - args.warm_up_epochs) * math.pi) + 1)
    scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer, lr_lambda=warm_up_with_cosine_lr)

上面的三段代碼分別是不使用warm up+multistep learning rate 衰減、使用warm up+multistep learning rate 衰減、使用warm up+consine learning rate衰減。代碼均使用pytorch中的lr_scheduler。LambdaLR自定義學習率衰減器。

label smooth

對於分類任務,通常我們使用cross entropy損失函數進行訓練,即:

criterion = nn.CrossEntropyLoss().cuda()

在這篇文章:https://arxiv.org/pdf/1812.01187.pdf 中給出了帶label smooth的cross entropy函數計算公式。我們在pytorch中實現了它,代碼如下:

class LabelSmoothCELoss(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, pred, label, smoothing=0.1):
        pred = F.softmax(pred, dim=1)
        one_hot_label = F.one_hot(label, pred.size(1)).float()
        smoothed_one_hot_label = (
            1.0 - smoothing) * one_hot_label + smoothing / pred.size(1)
        loss = (-torch.log(pred)) * smoothed_one_hot_label
        loss = loss.sum(axis=1, keepdim=False)
        loss = loss.mean()

        return loss

使用時,只需要:

criterion = LabelSmoothCELoss().cuda()

替換掉原來的cross entropy損失函數即可。

apex混合精度訓練

apex是NVIDIA發佈的開源混合精度訓練工具庫。該工具庫提供了AMP(自動混合精度)和FP16_Optimizer兩種不同的庫。AMP提供自動混合精度訓練支持,該庫會自動檢查執行的操作,對於FP16安全的操作在訓練中Cast到FP16精度,反之則選擇FP32精度。FP16_Optimizer提供的是高階版混合精度訓練,其提供了更多詳細的實現細節,對於整個網絡完全採用FP16精度訓練。
這裏只介紹如何用apex實現最簡單的自動混合精度訓練支持。
首先安裝apex工具庫。如果你是Python3.7環境,使用下列命令安裝:

git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./

如果你是Python3.6環境,則使用下列命令安裝:

git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir ./

安裝完成後,在train.py中進行下列修改:

from apex import amp
......
......
# 定義好Model和optimizer後,增加下面這行代碼:
model, optimizer = amp.initialize(model, optimizer, opt_level='O1')
# 反傳梯度原本的代碼是loss.backward(),改爲下面兩行代碼:
with amp.scale_loss(loss, optimizer) as scaled_loss:
    scaled_loss.backward()

這樣在訓練時就會使用apex自動混合精度訓練了。使用apex後,對於同一個訓練任務,可有效降低顯存佔用25-30%,但訓練速度會稍稍變慢。最後訓練出的模型性能和未使用apex時基本一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章