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>

        【深度學(xué)習(xí)】深度學(xué)習(xí)刷SOTA的一堆trick

        共 9145字,需瀏覽 19分鐘

         ·

        2022-07-31 15:36

        一般通用的trick都被寫進(jìn)論文和代碼庫里了,

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

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

        穩(wěn)定有用型trick

        0.模型融合

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

        1. 對(duì)抗訓(xùn)練


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

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


        具體FGM的實(shí)現(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這個(gè)參數(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這個(gè)參數(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

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

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

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

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

        具體EMA實(shí)現(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 = {}

         這兩個(gè)方法的問題就是跑起來會(huì)變慢,并且提分點(diǎn)都在前分位,不過可以是即插即用類型

        3.Rdrop等對(duì)比學(xué)習(xí)方法

        有點(diǎn)用,不會(huì)變差,實(shí)現(xiàn)起來也很簡(jiǎn)單

        #訓(xùn)練過程上下文
        ce = CrossEntropyLoss(reduction='none')
        kld = nn.KLDivLoss(reduction='none')
        logits1 = model(input)
        logits2 = model(input)
        #下面是訓(xùn)練過程中對(duì)比學(xué)習(xí)的核心實(shí)現(xiàn)?。。?!
        kl_weight = 0.5 #對(duì)比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

        大家都知道,在訓(xùn)練階段。dropout是開啟的,你多次推斷dropout是有隨機(jī)性的。

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



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


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



        4.TTA

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


        5.偽標(biāo)簽

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

        聽起來挺離譜的,我們把步驟用偽代碼實(shí)現(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)上一個(gè)經(jīng)典的圖來說就是。



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

        表數(shù)據(jù)在NN上的trick,快被tabnet 集大成了,這個(gè)方法是把缺失值的位置之外的地方mask,本身當(dāng)成1這樣可以學(xué)習(xí)出一個(gè)參數(shù),再加回這個(gè)feature的輸入上??梢钥纯此恼碌膶?shí)現(xiàn)。

        場(chǎng)景受限型trick

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

        1.PET或者其他prompt的方案

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

        2.Focalloss

         偶爾有用,大部分時(shí)候用處不大,看指標(biāo),在一些對(duì)長(zhǎng)尾,和稀有類別特別關(guān)注的任務(wù)和指標(biāo)上有所作為。

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

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

        4人臉等一些改動(dòng)softmax的方式

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

        5.領(lǐng)域后預(yù)訓(xùn)練

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

        6.分類變檢索

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

        在文本分類,圖像分類上效果都不錯(cuò)。


        突破性能型trick

        1.混合精度訓(xùn)練

        AMP即插即用,立竿見影。

        2.梯度累積

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

        3.Queue或者memery  bank

        可以讓batchsize突破天際,可以參考MoCo用來做對(duì)比學(xué)習(xí)的那個(gè)實(shí)現(xiàn)方式

        4.非必要不同步

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

        往期精彩回顧




        瀏覽 106
        點(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>
            91大尺度视频 | 操美女骚逼视频 | 三级片视频播放 | 色婷婷6月亚洲色婷婷 | 一级成人亚欧精品 | 91久久在线观看 | 香蕉大伊人 | 欧美午夜精品福利 | 亚洲天堂乱伦 | 香蕉福利网 |