1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        PyTorch重大更新:將支持自動(dòng)混合精度訓(xùn)練!

        共 3720字,需瀏覽 8分鐘

         ·

        2020-07-30 00:16

        AI編輯:我是小將

        混合精度訓(xùn)練mixed precision training)可以讓模型訓(xùn)練在盡量不降低性能的情形下提升訓(xùn)練速度,而且也可以降低顯卡使用內(nèi)存。目前主流的深度學(xué)習(xí)框架都開始支持混合精度訓(xùn)練。對于PyTorch,混合精度訓(xùn)練還主要是采用NVIDIA開源的apex庫。但是,PyTorch將迎來重大更新,那就是提供內(nèi)部支持的混合精度訓(xùn)練,而且是自動(dòng)混合精度訓(xùn)練:

        • torch.cuda.amp.autocast?:自動(dòng)為GPU op選擇精度來提升訓(xùn)練性能而不降低模型準(zhǔn)確度。

        • torch.cuda.amp.GradScaler?:?對梯度進(jìn)行scale來加快模型收斂,因?yàn)閒loat16梯度容易出現(xiàn)underflow(梯度過?。?/span>

        兩者結(jié)合在一起,可以實(shí)現(xiàn)自動(dòng)混合精度訓(xùn)練:

        #?Creates?model?and?optimizer?in?default?precision
        model?=?Net().cuda()
        optimizer?=?optim.SGD(model.parameters(),?...)

        #?Creates?a?GradScaler?once?at?the?beginning?of?training.
        scaler?=?GradScaler()

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

        ????????#?Runs?the?forward?pass?with?autocasting.
        ????????with?autocast():
        ????????????output?=?model(input)
        ????????????loss?=?loss_fn(output,?target)

        ????????#?Scales?loss.??Calls?backward()?on?scaled?loss?to?create?scaled?gradients.
        ????????#?Backward?passes?under?autocast?are?not?recommended.
        ????????#?Backward?ops?run?in?the?same?precision?that?autocast?used?for?corresponding?forward?ops.
        ????????scaler.scale(loss).backward()

        ????????#?scaler.step()?first?unscales?the?gradients?of?the?optimizer's?assigned?params.
        ????????#?If?these?gradients?do?not?contain?infs?or?NaNs,?optimizer.step()?is?then?called,
        ????????#?otherwise,?optimizer.step()?is?skipped.
        ????????scaler.step(optimizer)

        ????????#?Updates?the?scale?for?next?iteration.
        ????????scaler.update()

        可以看到,為了防止梯度的underflow,首先scaler.scale(loss).backward()會(huì)對loss乘以一個(gè)scale因子,然后backward時(shí)所有梯度都會(huì)乘以相同的scale因子,這樣保證梯度有較大的magnitude而不會(huì)出現(xiàn)為0。我們不希望這個(gè)scale因子對學(xué)習(xí)速率產(chǎn)生影響,那么scaler.step(optimizer)會(huì)先unscale要更新的梯度然后再更新,如果梯度出現(xiàn)infs或者NaNs,optimizer將忽略這次迭代訓(xùn)練。

        如果你想在梯度更新前對梯度進(jìn)行clip,也是可以的:

        scaler?=?GradScaler()

        for?epoch?in?epochs:
        ????for?input,?target?in?data:
        ????????optimizer.zero_grad()
        ????????with?autocast():
        ????????????output?=?model(input)
        ????????????loss?=?loss_fn(output,?target)
        ????????scaler.scale(loss).backward()

        ????????#?Unscales?the?gradients?of?optimizer's?assigned?params?in-place
        ????????scaler.unscale_(optimizer)

        ????????#?Since?the?gradients?of?optimizer's?assigned?params?are?unscaled,?clips?as?usual:
        ????????torch.nn.utils.clip_grad_norm_(model.parameters(),?max_norm)

        ????????#?optimizer's?gradients?are?already?unscaled,?so?scaler.step?does?not?unscale?them,
        ????????#?although?it?still?skips?optimizer.step()?if?the?gradients?contain?infs?or?NaNs.
        ????????scaler.step(optimizer)

        ????????#?Updates?the?scale?for?next?iteration.
        ????????scaler.update()

        當(dāng)然,混合精度訓(xùn)練肯定要支持分布式訓(xùn)練,由于autocastthread local的,所以要注意以下不同的情形:

        如果使用torch.nn.DataParallel

        此時(shí)只有一個(gè)進(jìn)程,而不同GPU上是各自的線程跑forward過程的,所以下面操作時(shí)無效的:

        model?=?MyModel()
        dp_model?=?nn.DataParallel(model)

        #?Sets?autocast?in?the?main?thread
        with?autocast():
        ????#?dp_model's?internal?threads?won't?autocast.??The?main?thread's?autocast?state?has?no?effect.
        ????output?=?dp_model(input)
        ????#?loss_fn?still?autocasts,?but?it's?too?late...
        ????loss?=?loss_fn(output)

        此時(shí)你需要對model的forward方法用autocast裝飾:

        MyModel(nn.Module):
        ????...
        ????@autocast()
        ????def?forward(self,?input):
        ???????...

        #?Alternatively
        MyModel(nn.Module):
        ????...
        ????def?forward(self,?input):
        ????????with?autocast():
        ????????????...
        model?=?MyModel()
        dp_model?=?nn.DataParallel(model)

        with?autocast():
        ????output?=?dp_model(input)
        ????loss?=?loss_fn(output)

        如果使用torch.nn.parallel.DistributedDataParallel

        一般情形下是單GPU進(jìn)程的,此時(shí)原來的用來就沒有問題,但是如果是多GPU一個(gè)進(jìn)程那么就和上述問題一樣,需要用autocast裝飾model的forward。



        更多內(nèi)容見:?https://pytorch.org/docs/master/notes/amp_examples.html#amp-examples


        推薦閱讀

        堪比Focal Loss!解決目標(biāo)檢測中樣本不平衡的無采樣方法

        超越BN和GN!谷歌提出新的歸一化層:FRN

        CVPR2020 論文系列一:VSGNet

        PyTorch分布式訓(xùn)練簡明教程

        圖神經(jīng)網(wǎng)絡(luò)入門

        另辟蹊徑!斯坦福大學(xué)提出邊界框回歸任務(wù)新Loss:GIoU

        人人必須要知道的語義分割模型:DeepLabv3+



        機(jī)器學(xué)習(xí)算法工程師


        ? ??? ? ? ? ? ? ? ? ? ? ? ??????????????????一個(gè)用心的公眾號(hào)


        ?

        瀏覽 31
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            女士内裤开裆无遮掩动漫 | 国产精品久久久久永久免费 | 国产精品肏屄视频 | 国产片婬乱18一级毛片小说 | 国产69精品久久久久毛片 | 51久久成人国产精品麻豆 | 美女操逼网站视频 | 国产伦一区二区三区四区 | 中文熟妇在线视频HD | 刘亦菲的全身裸体无遮挡 |