來(lái)源:AI人工智能初學(xué)者
作者:ChaucerG
其實(shí)圖像分類研究取得的大部分進(jìn)展都可以歸功于訓(xùn)練過(guò)程的改進(jìn),如數(shù)據(jù)增加和優(yōu)化方法的改變。但是,大多數(shù)改進(jìn)都沒(méi)有比較詳細(xì)的說(shuō)明。因此作者在本文中測(cè)試實(shí)現(xiàn)了這些改進(jìn)的方法,并通過(guò)消融實(shí)驗(yàn)來(lái)評(píng)估這些Tricks對(duì)最終模型精度的影響。作者通過(guò)將這些改進(jìn)結(jié)合在一起,同時(shí)改進(jìn)了各種CNN模型。在ImageNet上將ResNet-50的Top-1驗(yàn)證精度從75.3%提高到79.29%。同時(shí)還將證明了提高圖像分類精度會(huì)在其他應(yīng)用領(lǐng)域(如目標(biāo)檢測(cè)和語(yǔ)義分割)也可以帶來(lái)更好的遷移學(xué)習(xí)性能。
1、Introduction
近年來(lái)ImageNet的榜單一直在被刷新,從2012年的AlexNet,再到VGG-Net、NiN、Inception、ResNet、DenseNet以及NASNet;Top-1精度也從62.5%(AlexNet)->82.7%(NASNet-A);但是這么大精度的提升也不完全是由模型的架構(gòu)改變所帶來(lái)的,其中 訓(xùn)練的過(guò)程也有會(huì)起到很大的作用,比如,損失函數(shù)的改進(jìn)、數(shù)據(jù)的預(yù)處理方式的改變、以及優(yōu)化方法的選擇等;但是這也是很容易被忽略的部分,因此這篇文章在這里也會(huì)著重討論這個(gè)問(wèn)題。
2、Efficient Training
近年來(lái)硬件發(fā)展迅速,特別是GPU。因此,許多與性能相關(guān)的權(quán)衡的最佳選擇也會(huì)隨之發(fā)生變化。例如,在訓(xùn)練中使用較低的數(shù)值精度和較大的Batch/_Size更有效。
在本節(jié)中將在不犧牲模型精度的情況下實(shí)現(xiàn)低精度和大規(guī)模批量訓(xùn)練的各種技術(shù)。有些技術(shù)甚至可以提高準(zhǔn)確性和訓(xùn)練速度。
2.1、Large-batch training
Mini-Batch SGD將多個(gè)樣本分組到一個(gè)小批量中,以增加并行性,降低傳輸成本。然而,使用Large Batch-size可能會(huì)減慢訓(xùn)練進(jìn)度。對(duì)于凸優(yōu)化問(wèn)題,收斂率隨著批量大小的增加而降低。類似的經(jīng)驗(yàn)結(jié)論已經(jīng)被發(fā)表。
換句話說(shuō),在相同的epoch數(shù)量下,使用Large Batch-size的訓(xùn)練會(huì)與使用較小批次的訓(xùn)練相比,模型的驗(yàn)證精度降低。很多研究提出了啟發(fā)式搜索的方法來(lái)解決這個(gè)問(wèn)題。下面將研究4種啟發(fā)式方法,可以在單臺(tái)機(jī)器訓(xùn)練中擴(kuò)大Batch-size的規(guī)模。
1)Linear scaling learning rate
在Mini-Batch SGD中,由于樣本是隨機(jī)選取的,所以梯度下降也是一個(gè)隨機(jī)的過(guò)程。增加批量大小不會(huì)改變隨機(jī)梯度的期望,但會(huì)減小隨機(jī)梯度的方差。換句話說(shuō),大的批量降低了梯度中的噪聲,因此我們可以通過(guò)提高學(xué)習(xí)率來(lái)在梯度相反的方向上取得更大的進(jìn)展。
Goyal等人提出對(duì)于ResNet-50訓(xùn)練,經(jīng)驗(yàn)上可以根據(jù)批大小線性增加學(xué)習(xí)率。特別是,如果選擇0.1作為批量大小256的初始學(xué)習(xí)率,那么當(dāng)批量大小b變大時(shí)可以將初始學(xué)習(xí)率提高到:
2)Learning rate Warmup
在訓(xùn)練開(kāi)始時(shí),所有參數(shù)通常都是隨機(jī)值,因此離最優(yōu)解很遠(yuǎn)。使用過(guò)大的學(xué)習(xí)率可能導(dǎo)致數(shù)值不穩(wěn)定。在Warmup中,在一開(kāi)始使用一個(gè)比較小的學(xué)習(xí)率,然后當(dāng)訓(xùn)練過(guò)程穩(wěn)定時(shí)切換回初始設(shè)置的學(xué)習(xí)率base/_lr。
Goyal等人提出了一種Gradual Warmup策略,將學(xué)習(xí)率從0線性地提高到初始學(xué)習(xí)率。換句話說(shuō),假設(shè)將使用前m批(例如5個(gè)數(shù)據(jù)epoch)進(jìn)行Warmup,并且初始學(xué)習(xí)率為,那么在第批時(shí)將學(xué)習(xí)率設(shè)為i/=m。
3)Zero
一個(gè)ResNet網(wǎng)絡(luò)由多個(gè)殘差塊組成,而每個(gè)殘差塊又由多個(gè)卷積層組成。給定輸入,假設(shè)是Last Layer的輸出,那么這個(gè)殘差塊就輸出。注意,Block的最后一層可以是批處理標(biāo)準(zhǔn)化層。
BN層首先標(biāo)準(zhǔn)化它的輸入用表示,然后執(zhí)行一個(gè)scale變換。兩個(gè)參數(shù)、都是可學(xué)習(xí)的,它們的元素分別被初始化為1s和0s。在零初始化啟發(fā)式中,剩余塊末端的所有BN層初始化了。因此,所有的殘差塊只是返回它們的輸入,模擬的網(wǎng)絡(luò)層數(shù)較少,在初始階段更容易訓(xùn)練。
4)No bias decay
權(quán)值衰減通常應(yīng)用于所有可學(xué)習(xí)參數(shù),包括權(quán)值和偏差。它等價(jià)于應(yīng)用L2正則化到所有參數(shù),使其值趨近于0。但如Jia等所指出,建議僅對(duì)權(quán)值進(jìn)行正則化,避免過(guò)擬合。無(wú)偏差衰減啟發(fā)式遵循這一建議,它只將權(quán)值衰減應(yīng)用于卷積層和全連通層中的權(quán)值。其他參數(shù),包括偏差和和以及BN層,都沒(méi)有進(jìn)行正則化。
LARS提供了分層自適應(yīng)學(xué)習(xí)率,并且對(duì)大的Batch-size(超過(guò)16K)有效。本文中單機(jī)訓(xùn)練的情況下,批量大小不超過(guò)2K通常會(huì)導(dǎo)致良好的系統(tǒng)效率。
2.2、Low-precision training
神經(jīng)網(wǎng)絡(luò)通常是用32位浮點(diǎn)(FP32)精度訓(xùn)練的。也就是說(shuō),所有的數(shù)字都以FP32格式存儲(chǔ),輸入和輸出以及計(jì)算操作都是FP32類型參與的。然而,新的硬件可能已經(jīng)增強(qiáng)了新的算術(shù)邏輯單元,用于較低精度的數(shù)據(jù)類型。
例如,前面提到的Nvidia V100在FP32中提供了14個(gè)TFLOPS,而在FP16中提供了超過(guò)100個(gè)TFLOPS。如下表所示,在V100上從FP32切換到FP16后,整體訓(xùn)練速度提高了2到3倍。
盡管有性能上的好處,降低的精度有一個(gè)更窄的范圍,使結(jié)果更有可能超出范圍,然后干擾訓(xùn)練的進(jìn)展。Micikevicius等人提出在FP16中存儲(chǔ)所有參數(shù)和激活,并使用FP16計(jì)算梯度。同時(shí),F(xiàn)P32中所有的參數(shù)都有一個(gè)用于參數(shù)更新的副本。此外,損失值乘以一個(gè)比較小的標(biāo)量scaler以更好地對(duì)齊精度范圍到FP16也是一個(gè)實(shí)際的解決方案。
2.3、Experiment Results
3、Model Tweaks
模型調(diào)整是對(duì)網(wǎng)絡(luò)架構(gòu)的一個(gè)小調(diào)整,比如改變一個(gè)特定卷積層的stride。這樣的調(diào)整通常不會(huì)改變計(jì)算復(fù)雜度,但可能會(huì)對(duì)模型精度產(chǎn)生不可忽略的影響。
3.1、ResNet Tweaks
回顧了ResNet的兩個(gè)比較流行的改進(jìn),分別稱之為ResNet-B和ResNet-C。在此基礎(chǔ)上,提出了一種新的模型調(diào)整方法ResNet-D。
1)ResNet-B
ResNet-B改變的下采樣塊。觀察到路徑A中的卷積忽略了輸入feature map的四分之三,因?yàn)樗褂玫膬?nèi)核大小為1×1,Stride為2。ResNet-B切換路徑A中前兩個(gè)卷積的步長(zhǎng)大小,如圖a所示,因此不忽略任何信息。由于第2次卷積的kernel大小為3×3,路徑a的輸出形狀保持不變。
2)ResNet-C
卷積的計(jì)算代價(jià)是卷積核的寬或高的二次項(xiàng)。一個(gè)7×7的卷積比3×3的卷積的計(jì)算量更大。因此使用3個(gè)3x3的卷積替換1個(gè)7x7的卷積,如圖b所示,與第1和第2個(gè)卷積block的channel=32,stride=2,而最后卷積使用64個(gè)輸出通道。
3)ResNet-D
受ResNet-B的啟發(fā),下采樣塊B路徑上的1x1卷積也忽略了輸入feature map的3/4,因此想對(duì)其進(jìn)行修改,這樣就不會(huì)忽略任何信息。通過(guò)實(shí)驗(yàn)發(fā)現(xiàn),在卷積前增加一個(gè)平均為2x2的avg pooling層,將其stride改為1,在實(shí)踐中效果很好,同時(shí)對(duì)計(jì)算成本的影響很小。
4、Training Refinements
4.1、Cosine Learning Rate Decay
Loshchilov等人提出了一種余弦退火策略。一種簡(jiǎn)化的方法是通過(guò)遵循余弦函數(shù)將學(xué)習(xí)率從初始值降低到0。假設(shè)批次總數(shù)為T(忽略預(yù)熱階段),那么在批次T時(shí),學(xué)習(xí)率tm計(jì)算為:
可以看出,余弦衰減在開(kāi)始時(shí)緩慢地降低了學(xué)習(xí)速率,然后在中間幾乎變成線性減少,在結(jié)束時(shí)再次減緩。與step衰減相比,余弦衰減從一開(kāi)始就對(duì)學(xué)習(xí)進(jìn)行衰減,但一直持續(xù)到步進(jìn)衰減將學(xué)習(xí)率降低了10倍,從而潛在地提高了訓(xùn)練進(jìn)度。
importtorch
optim=torch.optim.lr_scheduler.CosineAnnealingLR(optimizer,T_max,eta_min=0,last_epoch=-1)
4.2、Label Smoothing
對(duì)于輸出預(yù)測(cè)的標(biāo)簽不可能像真是的label一樣真是,因此這里進(jìn)行一定的平滑策略,具體的Label Smoothing平滑規(guī)則為:
#-*-coding:utf-8-*-
"""
qi=1-smoothing(ifi=y)
qi=smoothing/(self.size-1)(otherwise)#所以默認(rèn)可以fill這個(gè)數(shù),只在i=y的地方執(zhí)行1-smoothing
另外KLDivLoss和crossentroy的不同是前者有一個(gè)常數(shù)
predict=torch.FloatTensor([[0,0.2,0.7,0.1,0],
[0,0.9,0.2,0.1,0],
[1,0.2,0.7,0.1,0]])
對(duì)應(yīng)的label為
tensor([[0.0250,0.0250,0.9000,0.0250,0.0250],
[0.9000,0.0250,0.0250,0.0250,0.0250],
[0.0250,0.0250,0.0250,0.9000,0.0250]])
區(qū)別于one-hot的
tensor([[0.,0.,1.,0.,0.],
[1.,0.,0.,0.,0.],
[0.,1.,0.,0.,0.]])
"""
importtorch
importtorch.nnasnn
fromtorch.autogradimportVariable
importmatplotlib.pyplotasplt
importnumpyasnp
classLabelSmoothing(nn.Module):
"Implementlabelsmoothing.size表示類別總數(shù)"
def__init__(self,size,smoothing=0.0):
super(LabelSmoothing,self).__init__()
self.criterion=nn.KLDivLoss(size_average=False)
#self.padding_idx=padding_idx
self.confidence=1.0-smoothing#ifi=y的公式
self.smoothing=smoothing
self.size=size
self.true_dist=None
defforward(self,x,target):
"""
x表示輸入(N,M)N個(gè)樣本,M表示總類數(shù),每一個(gè)類的概率logP
target表示label(M,)
"""
assertx.size(1)==self.size
true_dist=x.data.clone()#先深復(fù)制過(guò)來(lái)
#printtrue_dist
true_dist.fill_(self.smoothing/(self.size-1))#otherwise的公式
#printtrue_dist
#變成one-hot編碼,1表示按列填充,
#target.data.unsqueeze(1)表示索引,confidence表示填充的數(shù)字
true_dist.scatter_(1,target.data.unsqueeze(1),self.confidence)
self.true_dist=true_dist
returnself.criterion(x,Variable(true_dist,requires_grad=False))
if__name__:
#Exampleoflabelsmoothing.
crit=LabelSmoothing(size=5,smoothing=0.1)
#predict.shape35
predict=torch.FloatTensor([[0,0.2,0.7,0.1,0],
[0,0.9,0.2,0.1,0],
[1,0.2,0.7,0.1,0]])
v=crit(Variable(predict.log()),
Variable(torch.LongTensor([2,1,0])))
#Showthetargetdistributionsexpectedbythesystem.
plt.imshow(crit.true_dist)
4.3、Knowledge Distillation
在訓(xùn)練過(guò)程中增加了一個(gè)蒸餾損失,以懲罰Teacher模型和Student模型的softmax輸出之間的差異。給定一個(gè)輸入,設(shè)p為真概率分布,z和r分別為學(xué)生模型和教師模型最后全連通層的輸出。損失改進(jìn)為:
4.4、Mixup Training
在Mixup中,每次我們隨機(jī)抽取兩個(gè)例子和。然后對(duì)這2個(gè)sample進(jìn)行加權(quán)線性插值,得到一個(gè)新的sample:
其中
importnumpyasnp
importtorch
defmixup_data(x,y,alpha=1.0,use_cuda=True):
ifalpha>0.:
lam=np.random.beta(alpha,alpha)
else:
lam=1.
batch_size=x.size()[0]
ifuse_cuda:
index=torch.randperm(batch_size).cuda()
else:
index=torch.randperm(batch_size)
mixed_x=lam*x+(1-lam)*x[index,:]#自己和打亂的自己進(jìn)行疊加
y_a,y_b=y,y[index]
returnmixed_x,y_a,y_b,lam
defmixup_criterion(y_a,y_b,lam):
returnlambdacriterion,pred:lam*criterion(pred,y_a)+(1-lam)*criterion(pred,y_b)
4.5、Experiment Results
審核編輯 黃昊宇
-
人工智能
+關(guān)注
關(guān)注
1811文章
49497瀏覽量
258152 -
模型
+關(guān)注
關(guān)注
1文章
3610瀏覽量
51421
發(fā)布評(píng)論請(qǐng)先 登錄
labview軟件自帶項(xiàng)目的問(wèn)題
為什么 采集的電壓 不對(duì) 如果 ad 直接接轉(zhuǎn)換的電壓就對(duì)了
畢業(yè)設(shè)計(jì)遇到了瓶頸,求各位大大幫助
keil在編譯51項(xiàng)目和stm32項(xiàng)目的警告區(qū)別?
Android學(xué)習(xí)路上會(huì)遇到的各種瓶頸總結(jié)
激光振鏡項(xiàng)目的改進(jìn)
Programming Tricks for Higher Conversion Speeds Utilizing De
分布式項(xiàng)目開(kāi)發(fā)模型Chiefr分析

全年開(kāi)源項(xiàng)目的盤點(diǎn)和總結(jié)
機(jī)器學(xué)習(xí)模型部署到ML項(xiàng)目的過(guò)程
圖像分類任務(wù)的各種tricks
物聯(lián)網(wǎng)項(xiàng)目的原因、時(shí)間和方式

AI項(xiàng)目管理平臺(tái)有什么用
突破交付瓶頸:FPGA項(xiàng)目加速交付的“致勝密碼”

評(píng)論