<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>

          讓你的模型acc更上一層樓:模型trick和數(shù)據(jù)方法總結(jié)

          共 12420字,需瀏覽 25分鐘

           ·

          2021-10-02 12:57

          ↑ 點擊藍字 關(guān)注極市平臺

          作者丨FlyEgle
          來源丨GiantPandaCV
          編輯丨極市平臺

          極市導(dǎo)讀

           

          本系列主要探究哪些模型trick和數(shù)據(jù)的方法可以大幅度讓你的分類性能更上一層樓,本篇主要講解了對于大的BatchSize下訓(xùn)練分類模型以及張航的Bag of Tricks for Image Classification with Convolutional Neural Networks中的一些方法以及自己實際使用的一些trick。 >>加入極市CV技術(shù)交流群,走在計算機視覺的最前沿

          一、前言

          如何提升業(yè)務(wù)分類模型的性能,一直是個難題,畢竟沒有99.999%的性能都會帶來一定程度的風(fēng)險,所以很多時候我們只能通過控制閾值來調(diào)整準(zhǔn)召以達到想要的效果。本系列主要探究哪些模型trick和數(shù)據(jù)的方法可以大幅度讓你的分類性能更上一層樓,不過要注意一點的是,tirck不一定是適用于不同的數(shù)據(jù)場景的,但是數(shù)據(jù)處理方法是普適的。

          BatchSize&LARS

          本篇文章主要是對于大的bs下訓(xùn)練分類模型的情況,如果bs比較小的可以忽略,直接看最后的結(jié)論就好了(這個系列以后的文章講述的方法是通用的,無論bs大小都可以用)。

          實驗配置

          • 模型:ResNet50
          • 數(shù)據(jù):ImageNet1k
          • 環(huán)境:8xV100

          BatchSize對精度的影響

          所有的實驗的超參都是統(tǒng)一的,warmup 5個epoch,訓(xùn)練90個epoch,StepLR進行衰減,學(xué)習(xí)率的設(shè)置和bs線性相關(guān),公式為,優(yōu)化器使用帶有0.9的動量的SGD,baselr為0.1(如果采用Adam或者AdamW優(yōu)化器的話,公式需要調(diào)整為),訓(xùn)練的數(shù)據(jù)增強只有RandomCropResize,RandomFlip,驗證的數(shù)據(jù)增強為ResizeCenterCrop。

          訓(xùn)練情況如下:

          • lr調(diào)整曲線如下:

          • 訓(xùn)練曲線如下:

          • 驗證曲線如下:

          我這里設(shè)計了4組對照實驗,256, 1024, 2048和4096的batchsize,開了FP16也只能跑到了4096了。采用的是分布式訓(xùn)練,所以單張卡的bs就是bs = total_bs / ngpus_per_node。這里我沒有使用跨卡bn,對于bs 64單卡來說理論上已經(jīng)很大了,bn的作用是約束數(shù)據(jù)分布,64的bs已經(jīng)可以表達一個分布的subset了,再大的bs還是同分布的,意義不大,跨卡bn的速度也更慢,所以大的bs基本可以忽略這個問題。但是對于檢測的任務(wù),跨卡bn還是有價值的,畢竟輸入的分辨率大,單卡的bs比較小,一般4,8,16,這時候統(tǒng)計更大的bn會對模型收斂更好。

          實驗結(jié)果如下:

          很明顯可以看出來,當(dāng)bs增加到4k的時候,acc下降了將近0.8%個點,1k的時候,下降了0.2%個點,所以,通常我們用大的bs訓(xùn)練的時候,是沒辦法達到最優(yōu)的精度的。個人建議,使用1k的bs和0.4的學(xué)習(xí)率最優(yōu)。

          LARS(Layer-wise Adaptive Rate Scaling)

          1. 理論分析

          由于bs的增加,在同樣的epoch的情況下,會使網(wǎng)絡(luò)的weights更新迭代的次數(shù)變少,所以需要對LR隨著bs的增加而線性增加,但是這樣會導(dǎo)致上面我們看到的問題,過大的lr會導(dǎo)致最終的收斂不穩(wěn)定,精度有所下降。

          LARS的出發(fā)點則是各個層的更新參數(shù)使用的學(xué)習(xí)率應(yīng)該根據(jù)自己的情況有所調(diào)整,而不是所有層使用相同的學(xué)習(xí)率,也就是每層有自己的local lr,所以有:

          這里,表示的是第幾層,表示的是超參數(shù),這個超參數(shù)遠小于1,表示每層會改變參數(shù)的confidence,局部學(xué)習(xí)率可以很方便的替換每層的全局學(xué)習(xí)率,參數(shù)的更新大小為:

          與SGD聯(lián)合使用的算法如下:

          LARS代碼如下:

          class LARC(object):
              def __init__(self, optimizer, trust_coefficient=0.02, clip=True, eps=1e-8):
                  self.optim = optimizer
                  self.trust_coefficient = trust_coefficient
                  self.eps = eps
                  self.clip = clip

              def step(self):
                  with torch.no_grad():
                      weight_decays = []
                      for group in self.optim.param_groups:
                          # absorb weight decay control from optimizer
                          weight_decay = group['weight_decay'if 'weight_decay' in group else 0
                          weight_decays.append(weight_decay)
                          group['weight_decay'] = 0
                          for p in group['params']:
                              if p.grad is None:
                                  continue
                              param_norm = torch.norm(p.data)
                              grad_norm = torch.norm(p.grad.data)

                              if param_norm != 0 and grad_norm != 0:
                                  # calculate adaptive lr + weight decay
                                  adaptive_lr = self.trust_coefficient * (param_norm) / (
                                              grad_norm + param_norm * weight_decay + self.eps)

                                  # clip learning rate for LARC
                                  if self.clip:
                                      # calculation of adaptive_lr so that when multiplied by lr it equals `min(adaptive_lr, lr)`
                                      adaptive_lr = min(adaptive_lr / group['lr'], 1)

                                  p.grad.data += weight_decay * p.data
                                  p.grad.data *= adaptive_lr

                  self.optim.step()
                  # return weight decay control to optimizer
                  for i, group in enumerate(self.optim.param_groups):
                      group['weight_decay'] = weight_decays[i]

          這里有一個超參數(shù),trust_coefficient,也就是公式里面所提到的, 這個參數(shù)對精度的影響比較大,實驗部分我們會給出結(jié)論。

          2. 實驗結(jié)論

          可以很明顯發(fā)現(xiàn),使用了LARS,設(shè)置turst_confidence為1e-3的情況下,有著明顯的掉點,設(shè)置為2e-2的時候,在1k和4k的情況下,有著明顯的提升,但是2k的情況下有所下降。

          LARS一定程度上可以提升精度,但是強依賴超參,還是需要細致的調(diào)參訓(xùn)練。

          結(jié)論

          • 8卡進行分布式訓(xùn)練,使用1k的bs可以很好的平衡acc&speed。
          • LARS一定程度上可以提升精度,但是需要調(diào)參,做業(yè)務(wù)可以不用考慮,刷點的話要好好訓(xùn)練。

          Bag of Tricks

          主要是介紹張航的Bag of Tricks for Image Classification with Convolutional Neural Networks中的一些方法以及自己實際使用的一些trick。

          ps: 文章比較長,不喜歡長文可以直接跳到結(jié)尾看結(jié)論。

          • 使用大的batchsize訓(xùn)練會略微降低acc,可以使用lars進行一定程度的提升,但是需要進行適當(dāng)?shù)奈⒄{(diào),對于業(yè)務(wù)來說,使用1k的batchsize比較合適。

          實驗配置

          • 模型: ResNet50/ResNet50vd, CMT-tiny
          • 數(shù)據(jù): ImageNet1k & 業(yè)務(wù)數(shù)據(jù)
          • 環(huán)境: 8xV100

          CMT-tiny代碼和文章看這里

          ps: 簡單的說明一下,由于部分實驗是從實際的業(yè)務(wù)數(shù)據(jù)得到的結(jié)論,所以可能并不是完全適用于別的數(shù)據(jù)集,domain不同對應(yīng)的方法也不盡相同。本文只是建議和參考,不能盲目的跟從。imagenet數(shù)據(jù)集的場景大部分是每個圖片里面都會包含一個物體,也就是有主體存在的,我這邊的業(yè)務(wù)數(shù)據(jù)的場景很多是理解性的,更加抽象,也更難。

          Bag of Tricks

          數(shù)據(jù)增強
          1. 樸素數(shù)據(jù)增強 通用且常用的數(shù)據(jù)增強有random flip, colorjitter, random crop,基本上可以適用于任意的數(shù)據(jù)集,colorjitter注意一點是一般我們不給hue賦值。
          2. RandAug AutoAug系列之RandAug,相比autoaug的是和否的搜索策略,randaug通過概率的方法來進行搜索,對于大數(shù)據(jù)集的增益更強,遷移能力更好。實際使用的時候,直接用搜索好的imagnet的策略即可。
          3. mixup & cutmix mixup和cutmix均在imagenet上有這不錯的提升,實際使用發(fā)現(xiàn),cutmix相比mixup的通用性更強,業(yè)務(wù)數(shù)據(jù)上mixup幾乎沒有任何的提升,cutmix會提高一點點。不過兩者都會帶來訓(xùn)練時間的開銷, 因為都會導(dǎo)致簡單的樣本變難,需要更多的iter次數(shù)來update,除非0.1%的提升都很重要,不然個人覺得收益不高。在物體識別上,兩者可以一起使用。公式如下:

          \4. gaussianblur和gray這些方法,除非是數(shù)據(jù)集有這樣的數(shù)據(jù),不然實際意義不大,用不用都沒啥影響。

          實驗結(jié)論:

          • 20% imagenet數(shù)據(jù)集 & CMT-tiny

          • 業(yè)務(wù)數(shù)據(jù)上(ResNet50) autoaug&randaug沒有任何的提升(主要問題還是domain不同,搜出來的不適用),cutmix提升很小(適用于物體識別而不是內(nèi)容理解)。
          學(xué)習(xí)率衰減
          1. warmup: 深度學(xué)習(xí)更新權(quán)重的計算公式為,如果bs過大,lr保持不變,會導(dǎo)致Weights更新的次數(shù)相對變少,最終的精度不高。所以要調(diào)整lr隨著bs線性增加而增加,但是lr變大,會導(dǎo)致W更新過快,最終都接近于0,出現(xiàn)nan。所以需要進行warmup,在訓(xùn)練前幾個epoch,按很小的LR(1e-6)線性增長為初始的LR后再進行decay。
          2. LRdecay: 我們常用的LR decay方法一般是Step Decay,按照epoch或者iter的范圍來進行線性衰減,對于SGD等優(yōu)化器來說,效果穩(wěn)定,精度高。進一步提升精度,可以使用CosineDecay,但是需要更長的訓(xùn)練周期。

          CosineDecay公式如下:

          如果不計較訓(xùn)練時間,可以使用更暴力的方法,余弦退火算法(Cosine Annealing Decay), 公式如下:

          這里的表示的是重啟的序號,表示學(xué)習(xí)率,表示當(dāng)前的epoch。


          退火方法常用于圖像復(fù)原等用于L1損失的算法,有著不錯的性能表現(xiàn)。

          個人常用的方法就是cosinedecay,比較喜歡最后的acc曲線像一條"穿天猴", 不過要相對多訓(xùn)練幾k個iter,cosinedecay在最后的acc上升的比較快,前期的會比較緩慢。


          跨卡同步bn&梯度累加

          這兩個方法均是針對卡的顯存比較小,batchsize小(batchszie總數(shù)小于32)的情況。

          1. SyncBN 雖然我們在訓(xùn)練的時候采用的是ddp,實際上就是數(shù)據(jù)并行訓(xùn)練,每個卡的batchnorm只會更新自己的數(shù)據(jù),那么我們實際上得到的running_mean和running_std只是局部的而不是全局的,如果bs比較大,那么可以認(rèn)為局部和全局的是同分布的,如果bs比較小,那么會存在偏差。所以需要SyncBN幫我們同步一下mean和std以及后向的更新。
          2. GradAccumulate 梯度累加和同步BN機制并不相同,也并不沖突,同步BN可以用于任意的bs情況,只是大的bs下沒必要用??缈╞n則是為了解決小bs的問題所帶來的性能問題,通過loss.backward的累加梯度來達到增大bs的效果,由于bn的存在只能近似不是完全等價。代碼如下:
          for idx, (images, target) in enumerate(train_loader):
              images = images.cuda()
              target = target.cuda()
              outputs = model(images)
              losses = criterion(outputs, target)

              loss = loss/accumulation_steps
              loss.backward()
              if((i+1)%accumulation_steps) == 0:
                  optimizer.step()
                  optimizer.zero_grad()

          backward是bp以及保存梯度,optimizer.step是更新weights,由于accumulation_steps,所以我們需要增加訓(xùn)練的迭代次數(shù),也就是相應(yīng)的訓(xùn)練更多的epoch。

          標(biāo)簽平滑

          LabelSmooth目前應(yīng)該算是最通用的技術(shù)了 優(yōu)點如下:

          • 可以緩解訓(xùn)練數(shù)據(jù)中錯誤標(biāo)簽的影響;
          • 防止模型過于自信,充當(dāng)正則,提升泛華性。

          但是有個缺點,使用LS后,輸出的概率值會偏小一些,這會使得如果需要考慮recall和precision,卡閾值需要更加精細。代碼如下:

          class LabelSmoothingCrossEntropy(nn.Module):
              """
              NLL loss with label smoothing.
              "
          ""
              def __init__(self, smoothing=0.1):
                  """
                  Constructor for the LabelSmoothing module.
                  :param smoothing: label smoothing factor
                  "
          ""
                  super(LabelSmoothingCrossEntropy, self).__init__()
                  assert smoothing < 1.0
                  self.smoothing = smoothing
                  self.confidence = 1. - smoothing

              def forward(self, x, target):
                  logprobs = F.log_softmax(x, dim=-1)
                  nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
                  nll_loss = nll_loss.squeeze(1)
                  smooth_loss = -logprobs.mean(dim=-1)
                  loss = self.confidence * nll_loss + self.smoothing * smooth_loss
                  return loss.mean()

          ResNet50-vd

          ResNet50vd是由張航等人所提出的,相比于ResNet50,改進點如下:

          1. 頭部的conv7x7改進為3個conv3x3,直接使用7x7會損失比較多的信息,用多個3x3來緩解。
          2. 每個stage的downsample,由(1x1 s2)->(3x3)->(1x1)修改為(1x1)->(3x3 s2)->(1x1), 同時修改shortcut從(1x1 s2)avgpool(2) + (1x1)。1x1+s2會造成信息損失,所以用3x3和avgpool來緩解。

          實驗結(jié)論:

          上面的精度是我自己跑出來的比paper中的要低一些,不過paper里面用了蒸餾,相比于R50,提升了將近2個點,推理速度和FLOPs幾乎沒有影響,所以直接用這個來替換R50了,個人感覺還算不錯,最近的業(yè)務(wù)模型都在用這個。代碼和權(quán)重在git上,可以自行取用。

          結(jié)論

          • LabelSmooth, CosineLR都可以用做是通用trick不依賴數(shù)據(jù)場景。
          • Mixup&cutmix,對數(shù)據(jù)場景有一定的依賴性,需要多次實驗。
          • AutoAug,如果有能力去搜的話,就不用看我寫的了,用就vans了。不具備搜的條件的話,如果domain和imagenet相差很多,那考慮用一下randaug,如果沒效果,autoaug這個系列可以放棄。
          • bs比較小的情況,可以試試Sycnbn和梯度累加,要適當(dāng)?shù)脑黾拥螖?shù)。


          如果覺得有用,就請分享到朋友圈吧!

          △點擊卡片關(guān)注極市平臺,獲取最新CV干貨

          公眾號后臺回復(fù)“CVPR21檢測”獲取CVPR2021目標(biāo)檢測論文下載~


          極市干貨
          神經(jīng)網(wǎng)絡(luò):視覺神經(jīng)網(wǎng)絡(luò)模型優(yōu)秀開源工作:timm庫使用方法和最新代碼解讀
          技術(shù)綜述:綜述:神經(jīng)網(wǎng)絡(luò)中 Normalization 的發(fā)展歷程CNN輕量化模型及其設(shè)計原則綜述
          算法技巧(trick):8點PyTorch提速技巧匯總圖像分類算法優(yōu)化技巧


          CV技術(shù)社群邀請函 #

          △長按添加極市小助手
          添加極市小助手微信(ID : cvmart4)

          備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測-深圳)


          即可申請加入極市目標(biāo)檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計/ReID/GAN/圖像增強/OCR/視頻理解等技術(shù)交流群


          每月大咖直播分享、真實項目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與 10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~



          覺得有用麻煩給個在看啦~  
          瀏覽 109
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  黄色电影无码 | 三级网站网址 | 欧美女操逼视频 | 中国一级操逼毛片 | 天堂成人 中文在线 |