<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【深度學習】深度學習刷SOTA的一堆trick

          共 9145字,需瀏覽 19分鐘

           ·

          2022-07-31 15:36

          一般通用的trick都被寫進論文和代碼庫里了,

          像優(yōu)秀的優(yōu)化器,學習率調(diào)度方法,數(shù)據(jù)增強,dropout,初始化,BN,LN,確實是調(diào)參大師的寶貴經(jīng)驗,大家平常用的也很多。

          這里主要有幾個,我們分成三部分,穩(wěn)定有用型trick,場景受限型trick,性能加速型trick。

          穩(wěn)定有用型trick

          0.模型融合

          懂得都懂,打比賽必備,做文章沒卵用的人人皆知trick,早年模型小的時候還用stacking,直接概率融合效果也不錯。

          1. 對抗訓練


          對抗訓練就是在輸入的層次增加擾動,根據(jù)擾動產(chǎn)生的樣本,來做一次反向傳播。以FGM為例,在NLP上,擾動作用于embedding層。給個即插即用代碼片段吧,引用了知乎id:Nicolas的代碼,寫的不錯,帶著看原理很容易就明白了。

          # 初始化
          fgm = FGM(model)
          for batch_input, batch_label in data:
              # 正常訓練
              loss = model(batch_input, batch_label)
              loss.backward() # 反向傳播,得到正常的grad
              # 對抗訓練
              fgm.attack() # 在embedding上添加對抗擾動
              loss_adv = model(batch_input, batch_label)
              loss_adv.backward() # 反向傳播,并在正常的grad基礎(chǔ)上,累加對抗訓練的梯度
              fgm.restore() # 恢復embedding參數(shù)
              # 梯度下降,更新參數(shù)
              optimizer.step()
              model.zero_grad()


          具體FGM的實現(xiàn)


          import torch
          class FGM():
              def __init__(self, model):
                  self.model = model
                  self.backup = {}

              def attack(self, epsilon=1., emb_name='emb.'):
                  # emb_name這個參數(shù)要換成你模型中embedding的參數(shù)名
                  for name, param in self.model.named_parameters():
                      if param.requires_grad and emb_name in name:
                          self.backup[name] = param.data.clone()
                          norm = torch.norm(param.grad)
                          if norm != 0 and not torch.isnan(norm):
                              r_at = epsilon * param.grad / norm
                              param.data.add_(r_at)

              def restore(self, emb_name='emb.'):
                  # emb_name這個參數(shù)要換成你模型中embedding的參數(shù)名
                  for name, param in self.model.named_parameters():
                      if param.requires_grad and emb_name in name: 
                          assert name in self.backup
                          param.data = self.backup[name]
                  self.backup = {}


          2.EMA/SWA

          移動平均,保存歷史的一份參數(shù),在一定訓練階段后,拿歷史的參數(shù)給目前學習的參數(shù)做一次平滑。這個東西,我之前在earhian的祖?zhèn)鞔a里看到的。他喜歡這東西+衰減學習率。確實每次都有用。

          # 初始化
          ema = EMA(model, 0.999)
          ema.register()

          # 訓練過程中,更新完參數(shù)后,同步update shadow weights
          def train():
              optimizer.step()
              ema.update()

          # eval前,apply shadow weights;eval之后,恢復原來模型的參數(shù)
          def evaluate():
              ema.apply_shadow()
              # evaluate
              ema.restore()

          具體EMA實現(xiàn),即插即用:

          class EMA():
              def __init__(self, model, decay):
                  self.model = model
                  self.decay = decay
                  self.shadow = {}
                  self.backup = {}

              def register(self):
                  for name, param in self.model.named_parameters():
                      if param.requires_grad:
                          self.shadow[name] = param.data.clone()

              def update(self):
                  for name, param in self.model.named_parameters():
                      if param.requires_grad:
                          assert name in self.shadow
                          new_average = (1.0 - self.decay) * param.data + self.decay * self.shadow[name]
                          self.shadow[name] = new_average.clone()

              def apply_shadow(self):
                  for name, param in self.model.named_parameters():
                      if param.requires_grad:
                          assert name in self.shadow
                          self.backup[name] = param.data
                          param.data = self.shadow[name]

              def restore(self):
                  for name, param in self.model.named_parameters():
                      if param.requires_grad:
                          assert name in self.backup
                          param.data = self.backup[name]
                  self.backup = {}

           這兩個方法的問題就是跑起來會變慢,并且提分點都在前分位,不過可以是即插即用類型

          3.Rdrop等對比學習方法

          有點用,不會變差,實現(xiàn)起來也很簡單

          #訓練過程上下文
          ce = CrossEntropyLoss(reduction='none')
          kld = nn.KLDivLoss(reduction='none')
          logits1 = model(input)
          logits2 = model(input)
          #下面是訓練過程中對比學習的核心實現(xiàn)!!!!
          kl_weight = 0.5 #對比loss權(quán)重
          ce_loss = (ce(logits1, target) + ce(logits2, target)) / 2
          kl_1 = kld(F.log_softmax(logits1, dim=-1), F.softmax(logits2, dim=-1)).sum(-1)
          kl_2 = kld(F.log_softmax(logits2, dim=-1), F.softmax(logits1, dim=-1)).sum(-1)
          loss = ce_loss + kl_weight * (kl_1 + kl_2) / 2

          大家都知道,在訓練階段。dropout是開啟的,你多次推斷dropout是有隨機性的。

          模型如果魯棒的話,你同一個樣本,即使推斷時候,開著dropout,結(jié)果也應該差不多。好了,那么它的原理也呼之欲出了。用一張圖來形容就是:



          隨便你怎么踹(dropout),本AI穩(wěn)如老狗。


          KLD loss是衡量兩個分布的距離的,所以說他就是在原始的loss上,加了一個loss,這個loss刻畫了模型經(jīng)過兩次推斷,抵抗因dropout造成擾動的能力。



          4.TTA

          這個一句話說明白,測試時候構(gòu)造靠譜的數(shù)據(jù)增強,簡單一點的數(shù)據(jù)增強方式比較好,然后把預測結(jié)果加起來算個平均。


          5.偽標簽

          代碼和原理實現(xiàn)也不難,代價也是訓練變慢,畢竟多了一些數(shù)據(jù)一句話說明白,就是用訓練的模型,把測試數(shù)據(jù),或者沒有標簽的數(shù)據(jù),推斷一遍。構(gòu)成偽標簽,然后拿回去訓練。注意不要leak。

          聽起來挺離譜的,我們把步驟用偽代碼實現(xiàn)一下。


          model1.fit(train_set,label,  val=validation_set) #step1
          pseudo_label=model.pridict(test_set)  #step2
          new_label = concat(pseudo_label, label) #step3
          new_train_set =  concat(test_set, train_set)  #step3
          model2.fit(new_train_set, new_label,   val=validation_set) #step4
          final_predict = model2.predict(test_set) #step5


          用網(wǎng)上一個經(jīng)典的圖來說就是。



          6.神經(jīng)網(wǎng)絡自動填空值

          表數(shù)據(jù)在NN上的trick,快被tabnet 集大成了,這個方法是把缺失值的位置之外的地方mask,本身當成1這樣可以學習出一個參數(shù),再加回這個feature的輸入上。可以看看他文章的實現(xiàn)。

          場景受限型trick

          有用但場景受限或者不穩(wěn)定

          1.PET或者其他prompt的方案

          在一些特定場景上有用,比如zeroshot,或者小樣本的監(jiān)督訓練,在數(shù)據(jù)量充足情況下拿來做模型融合有點用,單模型不一定干的過硬懟。

          2.Focalloss

           偶爾有用,大部分時候用處不大,看指標,在一些對長尾,和稀有類別特別關(guān)注的任務和指標上有所作為。

          3.mixup/cutmix等數(shù)據(jù)增強

          挑數(shù)據(jù),大部分數(shù)據(jù)和任務用處不大,局部特征比較敏感的任務有用,比如音頻分類等

          4人臉等一些改動softmax的方式

          在數(shù)據(jù)量偏少的時候有用,在工業(yè)界數(shù)據(jù)量巨大的情況下用處不大

          5.領(lǐng)域后預訓練

          把自己的數(shù)據(jù)集,在Bert base上用MLM任務再過一遍,代價也是變慢,得益于huggingface可用性極高的代碼,實現(xiàn)起來也非常簡單,適用于和預訓練預料差別比較大的一些場景,比如中藥,ai4code等,在一些普通的新聞文本分類數(shù)據(jù)集上用處不大。

          6.分類變檢索

          這算是小樣本分類問題的標準解法了,類似于人臉領(lǐng)域的baseline,在這上面有很多圍繞類間可分,類內(nèi)聚集的loss改進,像aa-softmax,arcface,am-softmax等

          在文本分類,圖像分類上效果都不錯。


          突破性能型trick

          1.混合精度訓練

          AMP即插即用,立竿見影。

          2.梯度累積

          在優(yōu)化器更新參數(shù)之前,用相同的模型參數(shù)進行幾次前后向傳播。在每次反向傳播時計算的梯度被累積(加總)。不過這種方法會影響B(tài)N的計算,可以用來突破batchsize上限。

          3.Queue或者memery  bank

          可以讓batchsize突破天際,可以參考MoCo用來做對比學習的那個實現(xiàn)方式

          4.非必要不同步

          多卡ddp訓練的時候,用到梯度累積時,可以使用no_sync減少不必要的梯度同步,加快速度

          往期精彩回顧




          瀏覽 106
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.蜜桃 | 大鸡吧视频免费在线看 | 狅操美女嫩穴传媒 | 久热精品在线视频 | 国产黄色中文字幕 |