前言
網(wǎng)絡(luò)層內(nèi)在參數(shù)
使用 3x3 卷積
使用 cbr 組合
嘗試不同的權(quán)重初始化方法
圖片尺寸與數(shù)據(jù)增強(qiáng)
batch size 設(shè)定
學(xué)習(xí)率參數(shù)設(shè)定
優(yōu)化器選擇
模型 finetune
模型可視化
參考資料
前言所謂超參數(shù),即不是通過(guò)學(xué)習(xí)算法本身學(xué)習(xí)出來(lái)的,需要作者手動(dòng)調(diào)整(可優(yōu)化參數(shù))的參數(shù) (理論上我們也可以設(shè)計(jì)一個(gè)嵌套的學(xué)習(xí)過(guò)程,一個(gè)學(xué)習(xí)算法為另一個(gè)學(xué)習(xí)算法學(xué)出最優(yōu)超參數(shù)),卷積神經(jīng)網(wǎng)絡(luò)中常見(jiàn)的超參數(shù)有: 優(yōu)化器學(xué)習(xí)率、訓(xùn)練 Epochs
數(shù)、批次大小 batch_size
、輸入圖像尺寸大小。
一般而言,我們將訓(xùn)練數(shù)據(jù)分成兩個(gè)不相交的子集,其中一個(gè)用于學(xué)習(xí)參數(shù),另一個(gè)作為驗(yàn)證集,用于估計(jì)訓(xùn)練中或訓(xùn)練后的泛化誤差,用來(lái)更新超參數(shù)。
用于學(xué)習(xí)參數(shù)的數(shù)據(jù)子集通常仍被稱為訓(xùn)練集(不要和整個(gè)訓(xùn)練過(guò)程用到的更大的數(shù)據(jù)集搞混)。 用于挑選超參數(shù)的數(shù)據(jù)子集被稱為驗(yàn)證集(validation set
)。 通常,80%
的訓(xùn)練數(shù)據(jù)用于訓(xùn)練,20%
用于驗(yàn)證。因?yàn)轵?yàn)證集是用來(lái) “訓(xùn)練” 超參數(shù)的,所以驗(yàn)證集的誤差通常會(huì)比訓(xùn)練集誤差小 ,驗(yàn)證集會(huì)低估泛化誤差。完成所有超參數(shù)優(yōu)化后,需要使用測(cè)試集估計(jì)泛化誤差 。
網(wǎng)絡(luò)層內(nèi)在參數(shù)在設(shè)計(jì)網(wǎng)絡(luò)架構(gòu)的時(shí)候,我們通常需要事先指定一些網(wǎng)絡(luò)架構(gòu)參數(shù),比如:
卷積層(convlution
)參數(shù) : 卷積層通道數(shù)、卷積核大小、卷積步長(zhǎng)。池化層(pooling
)參數(shù) : 池化核大小、步長(zhǎng)等。權(quán)重參數(shù)初始化 ,常用的初始化方法有 Xavier
,kaiming
系列;或者使用模型 fintune
初始化模型權(quán)重參數(shù)。網(wǎng)絡(luò)深度 (這里特指卷積神經(jīng)網(wǎng)絡(luò) cnn),即 layer
的層數(shù);網(wǎng)絡(luò)的深度一般決定了網(wǎng)絡(luò)的表達(dá)(抽象)能力,網(wǎng)絡(luò)越深學(xué)習(xí)能力越強(qiáng)。網(wǎng)絡(luò)寬度 ,即卷積層通道(channel
)的數(shù)量,也是濾波器 (3 維)的數(shù)量;網(wǎng)絡(luò)寬度越寬,代表這一層網(wǎng)絡(luò)能學(xué)習(xí)到更加豐富的特征。這些參數(shù)一般在設(shè)計(jì)網(wǎng)絡(luò)架構(gòu)時(shí)就已經(jīng)確定下來(lái)了,參數(shù)的取值一般可以參考經(jīng)典 paper
和一些模型訓(xùn)練的經(jīng)驗(yàn)總結(jié),比如有以下經(jīng)驗(yàn):
使用 3x3 卷積 卷積層是 cnn
的主流組件,比如提取圖像特征的 backbone
網(wǎng)絡(luò)中,其卷積層的卷積核大小大部分都是 。比如 vgg 和 resnet 系列網(wǎng)絡(luò)具體參數(shù)表如下所示。
Vgg 和 resnet 參數(shù)表 使用 cbr 組合在 cnn
模型中,卷積層(conv
)一般后接 bn
、relu
層,組成 cbr
套件。BN
層(batch normalization,簡(jiǎn)稱 BN
,批規(guī)范化層)很重要,是卷積層、激活函數(shù)層一樣都是 cnn
模型的標(biāo)配組件 ,其不僅加快了模型收斂速度,而且更重要的是在一定程度緩解了深層網(wǎng)絡(luò)的一個(gè)難題“梯度彌散”,從而使得訓(xùn)練深層網(wǎng)絡(luò)模型更加容易和穩(wěn)定 。
另外,模型訓(xùn)練好后,模型推理時(shí)的卷積層和其后的 BN
層可以等價(jià)轉(zhuǎn)換為一個(gè)帶 bias
的卷積層(也就是通常所謂的“吸BN”),其原理參考深度學(xué)習(xí)推理時(shí)融合BN,輕松獲得約5%的提速 。
對(duì)于 cv 領(lǐng)域的任務(wù),建議無(wú)腦用 ReLU
激活函數(shù)。
# cbr 組件示例代碼 def convbn_relu (in_planes, out_planes, kernel_size, stride, pad, dilation) : return nn.Sequential( nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=dilation if dilation > 1 else pad, dilation=dilation, bias=False ), nn.BatchNorm2d(out_planes), nn.ReLU(inplace=True ) )
嘗試不同的權(quán)重初始化方法嘗試不同的卷積核權(quán)重初始化方式。目前常用的權(quán)重初始化方法 有 Xavier
和 kaiming
系列,pytorch 在 torch.nn.init
中提供了常用的初始化方法函數(shù),默認(rèn)是使用 kaiming
均勻分布函數(shù): nn.init.kaiming_uniform_()
。
pytorch框架默認(rèn)是使用 kaiming
均勻分布函數(shù) 下面是一個(gè)使用 kaiming_normal_
(kaiming 正態(tài)分布)設(shè)置卷積層權(quán)重初始化的示例代碼。
import torchimport torch.nn as nn# 定義一個(gè)卷積層 conv = nn.Conv2d(in_channels=3 , out_channels=16 , kernel_size=3 , stride=1 , padding=1 )# 使用He初始化方式設(shè)置卷積層的權(quán)重 nn.init.kaiming_normal_(conv.weight, mode='fan_out' , nonlinearity='relu' )
使用不同的卷積層權(quán)重初始化方式,會(huì)有不同的輸出效果。分別使用 xavier_normal_
和 xavier_normal_
初始化權(quán)重,并使一個(gè)輸入圖片經(jīng)過(guò)一層卷積層,其輸出效果是不同的,對(duì)比圖如下所示:
不同權(quán)重初始化方式效果對(duì)比圖 圖片尺寸與數(shù)據(jù)增強(qiáng)1,在顯存滿足的情況下,一般輸入圖片尺寸越大,模型精度越高 !
2,送入到模型的訓(xùn)練數(shù)據(jù)一定要充分打亂(shuffle
) ,這樣在使用自適應(yīng)學(xué)習(xí)率算法的時(shí)候,可以避免某些特征集中出現(xiàn),而導(dǎo)致的有時(shí)學(xué)習(xí)過(guò)度、有時(shí)學(xué)習(xí)不足,使得下降方向出現(xiàn)偏差的問(wèn)題。同時(shí),信息論(information theor)中也曾提到: “從不相似的事件中學(xué)習(xí)總是比從相似事件中學(xué)習(xí)更具信息量”。
另外,為了方便做實(shí)驗(yàn)對(duì)比,建議設(shè)定好隨機(jī)數(shù)種子 ! 并且,模型每輪(epoch
)訓(xùn)練進(jìn)行前將訓(xùn)練數(shù)據(jù)集隨機(jī)打亂(shuffle
),確保模型不同輪數(shù)相同批次“看到”的數(shù)據(jù)是不同的。
3,數(shù)據(jù)增強(qiáng)(圖像增強(qiáng))的策略必須結(jié)合具體任務(wù)來(lái)設(shè)計(jì) !數(shù)據(jù)增強(qiáng)的手段有多種,常見(jiàn)的如下(除了前三種以外,其他的要慎重考慮):
翻轉(zhuǎn) + 旋轉(zhuǎn)(旋轉(zhuǎn)和翻轉(zhuǎn)其實(shí)是保證了數(shù)據(jù)特征的旋轉(zhuǎn)不變性能被模型學(xué)習(xí)到,卷積層面的方法可以參考論文 ACNet
) batch size 設(shè)定 背景知識(shí)深度學(xué)習(xí)中經(jīng)??吹?epoch、 iteration 和 batchsize,這三個(gè)名字的區(qū)別如下:
batch size
:批大小。在深度學(xué)習(xí)中,一般采用 SGD 訓(xùn)練,即每次訓(xùn)練在訓(xùn)練集中取 batch_size 個(gè)樣本訓(xùn)練;iteration
:1 個(gè) iteration 等于使用 batch_size 個(gè)樣本訓(xùn)練一次;epoch
:1 個(gè) epoch 等于使用訓(xùn)練集中的全部樣本訓(xùn)練一次; batch size 定義batch
一般被翻譯為批量,設(shè)置 batch size
的目的讓模型在訓(xùn)練過(guò)程中每次選擇批量的數(shù)據(jù)來(lái)進(jìn)行處理。batch size
的直觀理解就是一次訓(xùn)練所選取的樣本數(shù) 。
batch size
的大小會(huì)影響模型的收斂速度和優(yōu)化程度。同時(shí)其也直接影響到 GPU
內(nèi)存的使用情況,如果你的 GPU
內(nèi)存(顯存)不大,該數(shù)值最好設(shè)置小一點(diǎn),否則會(huì)出現(xiàn)顯存溢出的錯(cuò)誤。
選擇合適大小的 batch sizebatch size
是所有超參數(shù)中最好調(diào)的一個(gè),也是應(yīng)該最早確定下來(lái)的超參數(shù),其設(shè)置的原則就是,batch size
別太小,也別太大,取中間合適值為宜 ,通常最好是 2 的 n 次方,如 16, 32, 64, 128。在常見(jiàn)的 setting(~100 epochs),batch size 一般不會(huì)低于 16
。
設(shè)置為 2 的 n 次方的原因:計(jì)算機(jī)的 gpu 和 cpu 的 memory 都是 2 進(jìn)制方式存儲(chǔ)的,設(shè)置 2 的 n 次方可以加快計(jì)算速度。
batch size
太小和太大的問(wèn)題:
batch size
太?。好看斡?jì)算的梯度不穩(wěn)定,引起訓(xùn)練的震蕩比較大,很難收斂。batch size
太大: 雖然大的 batch size 可以減少訓(xùn)練時(shí)間,即收斂得快,但深度學(xué)習(xí)的優(yōu)化 (training loss 降不下去)和泛化 (generalization gap 很大)都會(huì)出問(wèn)題。(結(jié)論來(lái)源論文-Accurate, Large Minibatch SGD:
Training ImageNet in 1 Hour)有論文指出 LB
(Large batch size)之所以出現(xiàn) Generalization Gap
問(wèn)題,是因?yàn)?LB
訓(xùn)練的時(shí)候更容易收斂到 sharp minima
,而 SB
(Small batch size)則更容易收斂到 flat minima
,并且 LB
還不容易從這些 sharp minima
中出來(lái),另外,作者認(rèn)為關(guān)于 batch size
的選擇是有一個(gè)閾值的,一旦超過(guò)這個(gè)閾值,模型的質(zhì)量會(huì)退化,網(wǎng)絡(luò)的準(zhǔn)確度大幅下降。
Flat_and_Sharp_Minima 參考論文來(lái)源 On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima [1] ,該論文主要探究了深度學(xué)習(xí)中一個(gè)普遍存在的問(wèn)題——使用大的 batchsize 訓(xùn)練網(wǎng)絡(luò)會(huì)導(dǎo)致網(wǎng)絡(luò)的泛化性能下降(文中稱之為Generalization Gap)。
另外:
合適的 batch size 范圍和訓(xùn)練數(shù)據(jù)規(guī)模、神經(jīng)網(wǎng)絡(luò)層數(shù)、單元數(shù)都沒(méi)有顯著的關(guān)系。 合適的 batch size 范圍主要和收斂速度、隨機(jī)梯度噪音有關(guān)。 參考知乎問(wèn)答-怎么選取訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)的Batch size? [2]
學(xué)習(xí)率和 batch size 關(guān)系batch size
和學(xué)習(xí)率有緊密聯(lián)系,我們知道深度學(xué)習(xí)模型多采用批量隨機(jī)梯度下降算法進(jìn)行優(yōu)化,隨機(jī)梯度下降算法的原理如下:
是批量大小(batchsize), 是學(xué)習(xí)率(learning rate)。從隨機(jī)梯度下降算法(SGD),可知道除了梯度本身,這兩個(gè)因子直接決定了模型的權(quán)重更新,從優(yōu)化本身來(lái)看它們是影響模型性能收斂最重要的參數(shù)。
學(xué)習(xí)率(learning rate
)直接影響模型的收斂狀態(tài),batch size
則影響模型的泛化性能 ,兩者又是分子分母的直接關(guān)系,相互也可影響,因此這一次來(lái)詳述它們對(duì)模型性能的影響。
參考來(lái)源-【AI不惑境】學(xué)習(xí)率和batchsize如何影響模型的性能? [3]
學(xué)習(xí)率參數(shù)設(shè)定 背景知識(shí)反向傳播指的是計(jì)算神經(jīng)?絡(luò)參數(shù)梯度的?法??偟膩?lái)說(shuō),反向傳播依據(jù)微積分中的鏈?zhǔn)椒▌t,沿著從輸出層到輸?層的順序,依次計(jì)算并存儲(chǔ)?標(biāo)函數(shù)有關(guān)神經(jīng)?絡(luò)各層的中間變量以及參數(shù)的梯度。
前向傳播:輸入層-->輸出層;反向傳播:輸出層-->輸入層。
什么是學(xué)習(xí)率現(xiàn)階段的所有深度神經(jīng)網(wǎng)絡(luò)的參數(shù)都是由 BP
(反向傳播)算法訓(xùn)練得到的,而 BP
算法是基于梯度下降(gradient desent
)策略,以目標(biāo)的負(fù)梯度方向?qū)?shù)進(jìn)行調(diào)整的 ,以下公式描述了這種關(guān)系。
new_weight = existing_weight — learning_rate * gradient
更細(xì)致點(diǎn),權(quán)重參數(shù)更新公式如下。
這里套用吳恩達(dá)機(jī)器學(xué)習(xí)課程的梯度下降公式,也可參考《機(jī)器學(xué)習(xí)》書(shū)中的公式 (5.6),雖然表達(dá)式寫(xiě)法不一樣,但其意義是一樣的。
式中 是學(xué)習(xí)率參數(shù) , 是待更新的權(quán)重參數(shù)。學(xué)習(xí)率范圍為 控制著算法每一輪迭代中更新的步長(zhǎng),很明顯可得,若學(xué)習(xí)率太大則容易振蕩導(dǎo)致不收斂,太小則收斂速度又會(huì)過(guò)慢(即損失函數(shù)的變化速度過(guò)慢) 。雖然使用低學(xué)習(xí)率可以確保我們不會(huì)錯(cuò)過(guò)任何局部極小值,但也意味著我們將花費(fèi)更長(zhǎng)的時(shí)間來(lái)進(jìn)行收斂,特別是在被困在高原區(qū)域的情況下。
采用小學(xué)習(xí)速率(頂部)和大學(xué)習(xí)速率(底部)的梯度下降 采用小學(xué)習(xí)速率(頂部)和大學(xué)習(xí)速率(底部)的梯度下降。圖來(lái)源:Coursera 上吳恩達(dá)(Andrew Ng)的機(jī)器學(xué)習(xí)課程。
因此可以說(shuō),學(xué)習(xí)速率是指導(dǎo)我們?nèi)绾瓮ㄟ^(guò)損失函數(shù)的梯度調(diào)整網(wǎng)絡(luò)權(quán)重的重要超參數(shù) !
如何設(shè)置學(xué)習(xí)率訓(xùn)練 CNN 模型,如何設(shè)置學(xué)習(xí)率有兩個(gè)原則可以遵守:
模型訓(xùn)練開(kāi)始時(shí)的初始學(xué)習(xí)率不宜過(guò)大 ,cv
類模型以 0.01
和 0.001
為宜; 模型訓(xùn)練過(guò)程中,學(xué)習(xí)率應(yīng)隨輪數(shù)(epochs
)增加而衰減 。 除以上固定規(guī)則的方式之外,還有些經(jīng)驗(yàn)可以參考 :
對(duì)于圖像分類任務(wù),使用 finetune
方式訓(xùn)練模型,訓(xùn)練過(guò)程中,凍結(jié)層的不需要過(guò)多改變參數(shù),因此需要設(shè)置較小的學(xué)習(xí)率,更改過(guò)的分類層則需要以較大的步子去收斂,學(xué)習(xí)率往往要設(shè)置大一點(diǎn)。(來(lái)源-pytorch 動(dòng)態(tài)調(diào)整學(xué)習(xí)率 [4] ) 尋找理想學(xué)習(xí)率或診斷模型訓(xùn)練學(xué)習(xí)率是否合適時(shí)也可借助模型訓(xùn)練曲線(learning curve)的幫助。下圖展示了不同大小的學(xué)習(xí)率下?lián)p失函數(shù)的變化情況,圖來(lái)自于 cs231n
。 不同學(xué)習(xí)率下訓(xùn)練損失值隨訓(xùn)練輪數(shù)增加呈現(xiàn)的狀態(tài) 以上是理論分析,但在實(shí)際應(yīng)用中,以 pytorch
框架為例,pyTorch
提供了六種學(xué)習(xí)率調(diào)整方法,可分為三大類,分別是:
有序調(diào)整 :按照一定規(guī)律有序進(jìn)行調(diào)整,這一類是最常用的,分別是等間隔下降(Step
),
按需設(shè)定下降間隔(MultiStep
),指數(shù)下降(Exponential
)和 CosineAnnealing
。這四種方法的調(diào)整時(shí)機(jī)都是人為可控的,也是訓(xùn)練時(shí)常用到的。自適應(yīng)調(diào)整 : 如依據(jù)訓(xùn)練狀況伺機(jī)調(diào)整 ReduceLROnPlateau
方法。該法通過(guò)監(jiān)測(cè)某一指標(biāo)的變化情況,當(dāng)該指標(biāo)不再怎么變化的時(shí)候,就是調(diào)整學(xué)習(xí)率的時(shí)機(jī),因而屬于自適應(yīng)的調(diào)整。自定義調(diào)整 : 自定義調(diào)整 Lambda
。Lambda 方法提供的調(diào)整策略十分靈活 ,我們可以為不同的層設(shè)定不同的學(xué)習(xí)率調(diào)整方法,這在 fine-tune 中十分有用,我們不僅可為不同的層設(shè)定不同的學(xué)習(xí)率,還可以為其設(shè)定不同的學(xué)習(xí)率調(diào)整策略,簡(jiǎn)直不能更棒了!常見(jiàn)的學(xué)習(xí)率調(diào)整方法有:
lr_scheduler.StepLR
: 等間隔調(diào)整學(xué)習(xí)率。調(diào)整倍數(shù)為 gamma
倍,調(diào)整間隔為 step_size
。lr_scheduler.MultiStepLR
: 按設(shè)定的間隔調(diào)整學(xué)習(xí)率。適合后期使用,通過(guò)觀察 loss 曲線,手動(dòng)定制學(xué)習(xí)率調(diào)整時(shí)機(jī)。lr_scheduler.ExponentialLR
: 按指數(shù)衰減調(diào)整學(xué)習(xí)率,調(diào)整公式:lr_scheduler.CosineAnnealingLR
: 以余弦函數(shù)為周期,并在每個(gè)周期最大值時(shí)重新設(shè)置學(xué)習(xí)率。lr_scheduler.ReduceLROnPlateau
: 當(dāng)某指標(biāo)不再變化(下降或升高),調(diào)整學(xué)習(xí)率(非常實(shí)用的策略)。lr_scheduler.LambdaLR
: 為不同參數(shù)組設(shè)定不同學(xué)習(xí)率調(diào)整策略。學(xué)習(xí)率調(diào)整方法類的詳細(xì)參數(shù)及類方法定義,請(qǐng)參考 pytorch 官方庫(kù)文檔-torch.optim [5] 。
注意,PyTorch 1.1.0
之后版本,學(xué)習(xí)率調(diào)整策略的設(shè)定必須放在優(yōu)化器設(shè)定的后面! 構(gòu)建一個(gè)優(yōu)化器,首先需要為它指定一個(gè)待優(yōu)化的參數(shù)的可迭代對(duì)象,然后設(shè)置特定于優(yōu)化器的選項(xiàng),比如學(xué)習(xí)率、權(quán)重衰減策略等。
在 PyTorch 1.1.0 之前,學(xué)習(xí)率調(diào)度器應(yīng)該在優(yōu)化器更新之前被調(diào)用;1.1.0 以打破 BC 的方式改變了這種行為。如果在優(yōu)化器更新(調(diào)用 optimizer.step())之前使用學(xué)習(xí)率調(diào)度器(調(diào)用 scheduler.step()),后果是將跳過(guò)學(xué)習(xí)率調(diào)度的第一個(gè)值。
使用指數(shù)級(jí)衰減的學(xué)習(xí)率調(diào)整策略的模板代碼如下。
import torchvision.models as modelsimport torch.optim as optim model = models.resnet50(pretrained=False ) optimizer = optim.SGD(model.parameters(), lr=0.01 , momentum=0.9 ) # 構(gòu)建優(yōu)化器,lr 是初始學(xué)習(xí)率 scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9 ) # 設(shè)定學(xué)習(xí)率調(diào)整策略 for epoch in range(20 ): for input, target in dataset: optimizer.zero_grad() output = model(input) loss = loss_fn(output, target) loss.backward() optimizer.step() scheduler.step() print_lr(is_verbose=true) # pytorch 新版本可用,1.4及以下版本不可用
優(yōu)化器選擇 優(yōu)化器定義優(yōu)化器(優(yōu)化算法)優(yōu)化的是神經(jīng)元參數(shù)的取值 。優(yōu)化過(guò)程如下:假設(shè) 表示神經(jīng)網(wǎng)絡(luò)中的參數(shù), 表示在給定的參數(shù)取值下,訓(xùn)練數(shù)據(jù)集上損失函數(shù)的大?。òㄕ齽t化項(xiàng)),則優(yōu)化過(guò)程即為尋找某一參數(shù) ,使得損失函數(shù) 最小。
在完成數(shù)據(jù)預(yù)處理、數(shù)據(jù)增強(qiáng),模型構(gòu)建和損失函數(shù)確定之后,深度學(xué)習(xí)任務(wù)的數(shù)學(xué)模型也就確定下來(lái)了,接下來(lái)自然就是選擇一個(gè)合適的優(yōu)化器(Optimizer
)對(duì)該深度學(xué)習(xí)模型進(jìn)行優(yōu)化(優(yōu)化器選擇好后,選擇合適的學(xué)習(xí)率調(diào)整策略也很重要)。
如何選擇適合不同ml項(xiàng)目的優(yōu)化器選擇優(yōu)化器的問(wèn)題在于沒(méi)有一個(gè)可以解決所有問(wèn)題的單一優(yōu)化器 。實(shí)際上,優(yōu)化器的性能高度依賴于設(shè)置。所以,優(yōu)化器選擇的本質(zhì)其實(shí)是: 哪種優(yōu)化器最適合自身項(xiàng)目的特點(diǎn)?
深度卷積神經(jīng)網(wǎng)絡(luò)通常采用隨機(jī)梯度下降類型的優(yōu)化算法進(jìn)行模型訓(xùn)練和參數(shù)求解。最為常用且經(jīng)典的優(yōu)化器算法是 (基于動(dòng)量的)隨機(jī)梯度下降法 SGD(stochastic gradient descent)
和 Adam
法,其他常見(jiàn)的優(yōu)化器算法有 Nesterov
型動(dòng)量隨機(jī)下降法、Adagrad
法、Adadelta
法、RMSProp
法。
優(yōu)化器的選擇雖然沒(méi)有通用的準(zhǔn)則,但是也還是有些經(jīng)驗(yàn)可以總結(jié)的:
SGD
是最常見(jiàn)的神經(jīng)網(wǎng)絡(luò)優(yōu)化方法,收斂效果較穩(wěn)定,但是收斂速度過(guò)慢。Adam
等自適應(yīng)學(xué)習(xí)率算法對(duì)于稀疏數(shù)據(jù)具有優(yōu)勢(shì),且且收斂速度很快,但是收斂效果不穩(wěn)定(容易跳過(guò)全局最優(yōu)解)。下表 1 概述了幾種優(yōu)化器的優(yōu)缺點(diǎn),通過(guò)下表可以嘗試找到與數(shù)據(jù)集特征、訓(xùn)練設(shè)置和項(xiàng)目目標(biāo)相匹配的優(yōu)化器。
某些優(yōu)化器在具有稀疏特征的數(shù)據(jù)上表現(xiàn)出色,而其他優(yōu)化器在將模型應(yīng)用于以前未見(jiàn)過(guò)的數(shù)據(jù)時(shí)可能表現(xiàn)更好。一些優(yōu)化器在大批量(batch_size
設(shè)置較大)下工作得很好,而而另一些優(yōu)化器會(huì)在泛化不佳的情況下收斂到極小的最小值。
Summary of popular optimizers highlighting their strengths and weaknesses 表格來(lái)源 Which Optimizer should I use for my ML Project? [6]
網(wǎng)絡(luò)上有種 tricks
是將 SGD
和 Adam
組合使用,先用 Adam
快速下降,再用 SGD
調(diào)優(yōu)。但是這種策略也面臨兩個(gè)問(wèn)題: 什么時(shí)候切換優(yōu)化器和切換后的 SGD 優(yōu)化器使用什么樣的學(xué)習(xí)率?論文 SWATS
Improving Generalization Performance by Switching from Adam to SGD [7] 給出了答案,感興趣的讀者可以深入閱讀下 paper
。
PyTorch 中的優(yōu)化器以 Pytorch
框架為例,PyTorch 中所有的優(yōu)化器(如: optim.Adadelta、optim.SGD、optim.RMSprop 等)均是 Optimizer
的子類,Optimizer 中也定義了一些常用的方法:
step(closure)
: 執(zhí)行一步權(quán)值更新, 其中可傳入?yún)?shù) closure(一個(gè)閉包)。state_dict()
: 獲取模型當(dāng)前的參數(shù),以一個(gè)有序字典形式返回,key 是各層參數(shù)名,value 就是參數(shù)。load_state_dict(state_dict)
: 將 state_dict 中的參數(shù)加載到當(dāng)前網(wǎng)絡(luò),常用于模型 finetune
。add_param_group(param_group)
: 給 optimizer 管理的參數(shù)組中增加一組參數(shù),可為該組參數(shù)定制 lr, momentum, weight_decay 等,在 finetune 中常用。優(yōu)化器設(shè)置和使用的模板代碼如下:
# optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) # 指定每一層的學(xué)習(xí)率 optim.SGD([ {'params' : model.base.parameters()}, {'params' : model.classifier.parameters(), 'lr' : 1e-3 } ], lr=1e-2 , momentum=0.9 )for input, target in dataset: optimizer.zero_grad() output = model(input) loss = loss_fn(output, target) loss.backward() optimizer.step()
優(yōu)化器的算法原理可以參考花書(shū)第八章內(nèi)容,Pytorch
框架優(yōu)化器類的詳細(xì)參數(shù)及類方法定義,請(qǐng)參考 pytorch 官方庫(kù)文檔-torch.optim [8] 。
模型 finetune一般情況下,我們?cè)谧錾疃葘W(xué)習(xí)任務(wù)時(shí),backbone
一般會(huì)用 imagenet
的預(yù)訓(xùn)練模型的權(quán)值參數(shù)作為我們自定義模型的初始化參數(shù),這個(gè)過(guò)程稱為 finetune
,更廣泛的稱之為遷移學(xué)習(xí)。fintune 的本質(zhì)其實(shí)就是,讓我們有一個(gè)較好的權(quán)重初始化值 。模型 finetune
一般步驟如下:
獲取預(yù)訓(xùn)練模型的權(quán)重(如 imagenet
); 使用預(yù)訓(xùn)練模型權(quán)重初始化我們的模型,即加載預(yù)訓(xùn)練模型權(quán)重參數(shù)。 模型 finetune
一般有兩種情況:
直接使用 imagenet
的 resnet50
預(yù)訓(xùn)練模型權(quán)重當(dāng)作特征提取器,只改變模型最后的全連接層。代碼示例如下: import torchimport torchvision.models as models model = models.resnet50(pretrained=True )#遍歷每一個(gè)參數(shù),將其設(shè)置為不更新參數(shù),即凍結(jié)模型所有參數(shù) for param in model.parameters(): param.requires_grad = False # 只替換最后的全連接層, 改為訓(xùn)練10類,全連接層requires_grad為T(mén)rue model.fc = nn.Linear(2048 , 10 ) print(model.fc) # 這里打印下全連接層的信息 # 輸出結(jié)果: Linear(in_features=2048, out_features=10, bias=True)
使用自定義模型結(jié)構(gòu),保存某次訓(xùn)練好后比較好的權(quán)重用于后續(xù)訓(xùn)練 finetune
,可節(jié)省模型訓(xùn)練時(shí)間,示例代碼如下: import torchimport torchvision.models as models# 1,保存模型權(quán)重參數(shù)值 # 假設(shè)已經(jīng)創(chuàng)建了一個(gè) net = Net(),并且經(jīng)過(guò)訓(xùn)練,通過(guò)以下方式保存模型權(quán)重值 torch.save(net.state_dict(), 'net_params.pth' )# 2,加載模型權(quán)重文件 # load(): Loads an object saved with :func:`torch.save` from a file pretrained_dict = torch.load('net_params.pth' )# 3,初始化模型 net = Net() # 創(chuàng)建 net net_state_dict = net.state_dict() # 獲取已創(chuàng)建 net 的 state_dict # (可選)將 pretrained_dict 里不屬于 net_state_dict 的鍵剔除掉: pretrained_dict_new = {k: v for k, v in pretrained_dict.items() if k in net_state_dict}# 用預(yù)訓(xùn)練模型的參數(shù)字典 對(duì) 新模型的參數(shù)字典 net_state_dict 進(jìn)行更新 net_state_dict.update(pretrained_dict_new)# 加載需要的預(yù)訓(xùn)練模型參數(shù)字典 net.load_state_dict(net_state_dict)
更進(jìn)一步的模型 finetune
,可以為不同網(wǎng)絡(luò)層設(shè)置不同的學(xué)習(xí)率,請(qǐng)參考《PyTorch_tutorial_0.0.5_余霆嵩》第二章。
模型 finetune
是屬于遷移學(xué)習(xí)技術(shù)的一種。
模型可視化 參考資料[1] On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima: https:///pdf/1609.04836.pdf
[2] 怎么選取訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)的Batch size?: https://www.zhihu.com/question/61607442
[3] 【AI不惑境】學(xué)習(xí)率和batchsize如何影響模型的性能?: https://zhuanlan.zhihu.com/p/64864995
[4] pytorch 動(dòng)態(tài)調(diào)整學(xué)習(xí)率: http:///index.php/archives/32/
[5] torch.optim: https://pytorch.org/docs/stable/optim.html#torch.optim.Optimizer
[6] Which Optimizer should I use for my ML Project?: https://www./post/which-optimizer-should-i-use-for-my-machine-learning-project
[7] Improving Generalization Performance by Switching from Adam to SGD: https:///abs/1712.07628
[8] torch.optim: https://pytorch.org/docs/stable/optim.html#torch.optim.Optimizer
[9] 怎么選取訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)的Batch size?: https://www.zhihu.com/question/61607442
[10] batch size設(shè)置技巧: https://blog.51cto.com/u_15485092/5464376
[11] 如何選擇適合不同ML項(xiàng)目的優(yōu)化器: https://www./articles/2021-01-05-9
[12] 理解深度學(xué)習(xí)中的學(xué)習(xí)率及多種選擇策略: https://www./articles/understanding-learning-rates
[13] 知乎問(wèn)答-深度學(xué)習(xí)調(diào)參有哪些技巧?: https://www.zhihu.com/question/25097993
[14] pytorch 學(xué)習(xí)筆記-3.2 卷積層: https://pytorch./3-mo-xing-gou-jian/3.2-juan-ji-ceng#juan-ji-wang-luo-shi-li