簡介
PaddleClas是PaddlePaddle最近開源的圖像分類代碼庫,裏面包括了目前比較常用的分類模型,ResNet、HRNet、DenseNet、ResNeXt等,配置文件裏也提供了這些模型的訓練腳本,總共大概是117個模型,當然pretrained model權重文件也都給出來了,github地址在這裏:https://github.com/PaddlePaddle/PaddleClas
模型庫其實還是比較豐富,不過裏面最吸引人的可能還是ImageNet1k val數據集上**top1 acc 82.4%**的ResNet50-Vd預訓練模型,這個是224的圖像分類情況下得到的,也是目前開源的精度最高的ResNet50系列模型。
這個模型主要是基Paddle自研的SSLD這個知識蒸餾方案得到的,全稱是:Simple Semi-supervised Label Distillation,當然僅僅用ImageNet1k數據是很難做到這個高的指標的,PaddleClas裏面引入了ImageNet22k數據集,並且對數據進行了抽樣選擇訓練,這裏主要是說下82.4%的指標實現思路,主要參考了PaddleClas的蒸餾文檔:https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/advanced_tutorials/distillation/distillation.md
預訓練模型可以從這裏下載:https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/models/models_intro.md
帶ssld後綴的模型都是使用SSLD知識蒸餾方案得到的模型。
SSLD知識蒸餾策略
2.1 簡介
SSLD的流程圖如下圖所示。
數據還是毋庸置疑地有效,要想提升精度,額外數據是必須的。
首先從ImageNet22k中挖掘出了近400萬張圖片,與ImageNet-1k訓練集整合在一起,得到了一個新的包含500萬張圖片的數據集。然後,將學生模型與教師模型組合成一個新的網絡,該網絡分別輸出學生模型和教師模型的預測分佈,與此同時,固定教師模型整個網絡的梯度,而學生模型可以做正常的反向傳播。最後,將兩個模型的logits經過softmax激活函數轉換爲soft label,並將二者的soft label做JS散度作爲損失函數,用於蒸餾模型訓練。這裏其實PaddleClas也開源了79%地MobileNetV3 large模型,主要也是以這個模型蒸餾爲例,給出了一些消融實驗結論。
-
教師模型的選擇。在進行知識蒸餾時,如果教師模型與學生模型的結構差異太大,蒸餾得到的結果反而不會有太大收益。相同結構下,精度更高的教師模型對結果也有很大影響。相比於79.12%的ResNet50_vd教師模型,使用82.4%的ResNet50_vd教師模型可以帶來0.4%的絕對精度收益(
75.6%->76.0%
)。 -
改進loss計算方法。分類loss計算最常用的方法就是cross entropy loss,實驗發現,在使用soft label進行訓練時,相對於cross entropy loss,KL div loss對模型性能提升幾乎無幫助,但是使用具有對稱特性的JS div loss時,在多個蒸餾任務上相比cross entropy loss均有0.2%左右的收益(
76.0%->76.2%
),SSLD中也基於JS div loss展開實驗。 -
更多的迭代輪數。蒸餾的baseline實驗只迭代了120個epoch。實驗發現,迭代輪數越多,蒸餾效果越好,最終迭代了360epoch,精度指標可以達到77.1%(
76.2%->77.1%
)。 -
無需數據集的真值標籤,很容易擴展訓練集。SSLD的loss在計算過程中,僅涉及到教師和學生模型對於相同圖片的處理結果(經過softmax激活函數處理之後的soft label),因此即使圖片數據不包含真值標籤,也可以用來進行訓練並提升模型性能。該蒸餾方案的無標籤蒸餾策略也大大提升了學生模型的性能上限(
77.1%->78.5%
)。 -
ImageNet1k蒸餾finetune。僅使用ImageNet1k數據,使用蒸餾方法對上述模型進行finetune,最終仍然可以獲得0.4%的性能提升(
75.8%->78.9%
)。
指標上升情況大概如下
數據選擇
-
ImageNet22k數據包含1400W張圖像,如果全部用來訓練的話,訓練成本太高,因此PaddleClas裏面參考了FaceBook之前的一個做法,用大模型去預測所有圖片,這個大模型是包含1000類的圖像分類模型(ImageNet 1k)對於每一個類別,都找到得分Top-k的圖片,這樣總共可以找到1000k張圖片,再和ImageNet1k 訓練集融合在一起,組成最後的500W張圖片的訓練集。
-
在這裏需要注意的是,因爲引入了新的數據,因此爲了防止引入的新數據中包含ImageNet1k val的數據,因此需要對數據進行去重。PaddleClas裏面是使用了SIFT特徵相似度匹配的方法進行去重,防止添加的ImageNet22k數據集中包含ImageNet1k val的數據,但是這塊去重的代碼目前還沒有開源。
實驗部分
- PaddleClas的蒸餾策略爲
大數據集訓練+ImageNet1k蒸餾finetune
的策略。選擇合適的教師模型,首先在挑選得到的500萬數據集上進行訓練,然後在ImageNet1k訓練集上進行finetune,最終得到蒸餾後的學生模型。 - 在這裏PaddleClas裏也給出了實驗的超參,有了數據,按照這個超參,是可以復現給出的精度的。主要的實驗有以下幾組。
教師模型的選擇
爲了驗證教師模型和學生模型的模型大小差異和教師模型的模型精度對蒸餾結果的影響,PaddleClas提供了幾組實驗。訓練策略統一爲:cosine_decay_warmup,lr=1.3, epoch=120, bs=2048
,學生模型均爲從頭訓練。
Teacher Model | Teacher Top1 | Student Model | Student Top1 |
---|---|---|---|
ResNeXt101_32x16d_wsl | 84.2% | MobileNetV3_large_x1_0 | 75.78% |
ResNet50_vd | 79.12% | MobileNetV3_large_x1_0 | 75.60% |
ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
從表中可以看出
教師模型結構相同時,其精度越高,最終的蒸餾效果也會更好一些。
教師模型與學生模型的模型大小差異不宜過大,否則反而會影響蒸餾結果的精度。
因此最終在蒸餾實驗中,對於ResNet系列學生模型,使用ResNeXt101_32x16d_wsl
作爲教師模型;對於MobileNet系列學生模型,使用蒸餾得到的ResNet50_vd
作爲教師模型。
大數據蒸餾
基於PaddleClas的蒸餾策略爲大數據集訓練+imagenet1k finetune
的策略。
針對從ImageNet22k挑選出的400萬數據,融合imagenet1k訓練集,組成共500萬的訓練集進行訓練,具體地,在不同模型上的訓練超參及效果如下。
Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
---|---|---|---|---|---|---|
MobileNetV1 | 360 | 3e-5 | 4096/8 | 1.6 | cosine_decay_warmup | 77.65% |
MobileNetV2 | 360 | 1e-5 | 3072/8 | 0.54 | cosine_decay_warmup | 76.34% |
MobileNetV3_large_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 78.54% |
MobileNetV3_small_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 70.11% |
ResNet50_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 82.07% |
ResNet101_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 83.41% |
ImageNet1k訓練集finetune
對於在大數據集上訓練的模型,其學習到的特徵可能與ImageNet1k數據特徵有偏,因此在這裏使用ImageNet1k數據集對模型進行finetune。finetune的超參和finetune的精度收益如下。
Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
---|---|---|---|---|---|---|
MobileNetV1 | 30 | 3e-5 | 4096/8 | 0.016 | cosine_decay_warmup | 77.89% |
MobileNetV2 | 30 | 1e-5 | 3072/8 | 0.0054 | cosine_decay_warmup | 76.73% |
MobileNetV3_large_x1_0 | 30 | 1e-5 | 2048/8 | 0.008 | cosine_decay_warmup | 78.96% |
MobileNetV3_small_x1_0 | 30 | 1e-5 | 6400/32 | 0.025 | cosine_decay_warmup | 71.28% |
ResNet50_vd | 60 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 82.39% |
ResNet101_vd | 30 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 83.73% |
實驗過程中的一些問題
- 在蒸餾的過程中,有一些地方和正常模型訓練的思路還是有些出入的,在這裏也需要注意一下其中的一些細節。
bn的計算方法
- 在預測過程中,batch norm的平均值與方差是通過加載預訓練模型得到(設其模式爲test mode)。在訓練過程中,batch norm是通過統計當前batch的信息(設其模式爲train mode),與歷史保存信息進行滑動平均計算得到,在蒸餾任務中,PaddleClas裏提到,通過train mode,即教師模型的bn實時變化的模式,去指導學生模型,比通過test mode蒸餾,得到的學生模型性能更好一些,下面是一組實驗結果。因此在該蒸餾方案中,均使用train mode去得到教師模型的soft label。
Teacher Model | Teacher Top1 | Student Model | Student Top1 |
---|---|---|---|
ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 75.84% |
模型名字衝突問題的解決辦法
- 在蒸餾過程中,如果遇到命名衝突的問題,如使用ResNet50_vd蒸餾ResNet34_vd,此時直接訓練,會提示相同variable名稱不匹配的問題,此時可以通過給學生模型或者教師模型中的變量名添加名稱的方式解決該問題,如下所示。在訓練之後也可以直接根據後綴區分學生模型和教師模型各自包含的參數。
def net(self, input, class_dim=1000):
student = ResNet34_vd(postfix_name="_student")
out_student = student.net( input, class_dim=class_dim )
teacher = ResNet50_vd()
out_teacher = teacher.net( input, class_dim=class_dim )
out_teacher.stop_gradient = True
return out_teacher, out_student
- 訓練完成後,可以通過批量重名的方式修改學生模型的參數,以上述代碼爲例,批量重命名的命令行如下。
cd model_final # enter model dir
for var in ./*_student; do cp "$var" "../student_model/${var%_student}"; done # batch copy and rename
應用
- PaddleClas中的這個知識蒸餾方案有2個用途
- 進一步提升模型效果,同時無標籤數據也可以利用起來了
- 蒸餾的預訓練模型也可以用在其他視覺任務裏,作爲pretrain,進一步提升效果。
- 更多的實際應用可以參考這裏:https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/advanced_tutorials/distillation/distillation.md