目錄
前言
1. 不同蒸餾算法資源占用
2. 不動態調整蒸餾損失
2.1? 訓練定量化結果
2.1 訓練結果可視化結果
3. 動態調整蒸餾損失權重及實驗分析
3.1 余弦衰減和指數衰減
3.2 CWD蒸餾損失
3.3 MGD蒸餾損失
3.4 AT蒸餾損失
3.5 SKD和PKD蒸餾損失
4. 調權重心得總結
5. 待驗證
前言
? ? ? ?YOLOv8源碼修改(5)- YOLO知識蒸餾(上)添加蒸餾代碼,以yolov8-pose為例進行知識蒸餾
????????接上文,我們已經加好了yolo蒸餾訓練的必要代碼,但并不意味著知識蒸餾就有用。我總結了以下一些可能有影響的因素:
(1)蒸餾算法的選擇。最常用的CWD、MGD等知識蒸餾算法,論文中MGD的性能就要好過CWD。
(2)蒸餾算法的超參設置。以MGD為例,alpha_mgd的權重設置,lambda_mgd的權重設置等等,不同的參數設置會取得不同效果,MGD的論文里也寫了,他的最佳經驗值,是夠能在我們自己的數據集上取得最好呢?
(3)蒸餾損失權重的設置。這點我認為是最重要的。因為所有蒸餾算法都繞不開,尤其對于yolo來說,yolo基于檢測最基本的loss有box_loss、cls_loss和dfl_loss,如果是obb、seg、pose等任務,還會引入其他的loss。如果蒸餾損失過大,勢必會導致其中一些較小的loss“失效”。
(4)數據集本身的質量。以COCO2017人體關鍵點為例,里面有些人需要預測出,有些人不需要預測出(我認為是標注錯誤、或者漏標)。但模型可能有別的“思考”,比如,只預測出屬于“前景”的人,而“背景”的人不預測。大模型(m號以上)可以區分這種細粒度的區別,但小模型不行,因此就表現為中間層顯著的特征差異,這時候知識蒸餾就明顯了。而我數據清洗后,幾乎沒有漏標和錯標,只要是人就預測出,這種特征可能相對簡單,小模型(s號,n號可能還是不行)已經足夠表示,所以再用知識蒸餾,這時效果就不明顯了。
(5)教師模型和學生模型的差異。這里的差異不僅表現為中間層維度的差異,還可能是架構的差異,比如用yolov11m去蒸餾yolov8s,從一個維度映射到另一個維度,這種特征映射真的能形成等效表達嗎?以及還有性能上的差異,教師模型比學生模型優秀多少,才能讓學生模型有一個穩定提升。
(6)蒸餾代碼實現的細節。我主要還是參考了paddleDetection中的yolo蒸餾實現,其中對特征用了均值歸一化,如果換成一個可學習的BN層是否會更好,還有中間相同維度特征的映射,是否還要再加入一個相同維度的1D卷積?
?經過大量調試訓練后,我得出的心得:
? ? ? ? 對于實際落地的yolo訓練而言(寫論文不在其中),一個好的蒸餾算法應該只有一個參數,就是“損失權重”,最多再加一個影響不大的可調節參數。
? ? ? ? 根據動態調整訓練過程中的損失權重,我發現:不同蒸餾算法的影響可能沒有那么大,只要損失權重調整的好,都可以取得一個不錯的訓練結果。
1. 不同蒸餾算法資源占用
? ? ? ? 下面是我訓練時候記錄的資源占用情況,可以看到MGD訓練時間比其他的多了1小時,這些算法大都要生成中間特征,以進行一系列操作,因此顯存占用大。
? ? ? ? 所以,經過我的調整測試,我一般選擇AT來做蒸餾,實現簡單,資源占用少,關鍵還有效。除非準確度有要求,才考慮其他的蒸餾算法。
2. 不動態調整蒸餾損失
2.1? 訓練定量化結果
????????首先,還是問問神奇的GPT,蒸餾損失大小怎么調整,他是這樣告訴我的:
? ? ? ? 可調節的占比范圍大概在0.1-0.8之間,然后如下圖綠色框中所示,觀察一下yolov8s-pose的幾類損失,發現box_loss和dfl_loss很小加起來才等于其他3個損失。所以,我就想蒸餾損失應該控制在20%~30%之間(絕對數值在1.0~2.0之間),這樣占比剛好取個平均值。
? ? ? ? 基于上面這樣設置參數,本文直接進行了實驗,得到了以下結果:
? ? ? ? 如上圖,僅CWD取得比較明顯的效果,MGD僅次于CWD。于是,我們就有疑問:這和論文中的結果不對啊。MGD是后發的論文,里面明明還寫了自己效果比CWD好的。
? ? ? ? 此外,我們還容易發難:這個AT是什么鬼,不僅沒正面作用,還產生負面效果了,難道是這個蒸餾算法實現不對,或者就是個rubbish算法,打著“attention”的旗號水論文,根本沒有普適性?
????????而經過我對訓練過程分析,發現恰恰相反,AT是所有算法中收斂最快的,尤其在前50輪的訓練,基本要比正常訓練高1~2%的點。那就又有疑問了:假設我們從50輪起訓練,不加任何蒸餾損失,我AT訓練得到的模型,應該有一個更好的起點(各項指標都高),那么最終獲取的模型,至少不應該比其他蒸餾算法訓練得到的差吧?
? ? ? ? 因此,我也做了一些可視化分析。
2.1 訓練結果可視化結果
? ? ? ? 每10輪,記錄一下驗證的結果(B表示檢測框,P表示關鍵點):
? ? ? ? 根據上面的圖表,我很很如看到AT在開始是瑤瑤領先的,收斂速度很快。但是在50輪之后就不行了。那只有一個原因,訓練后期,AT的蒸餾損失對模型優化是負面影響。
? ? ? ? 因此,我用余弦衰減來對AT蒸餾損失進行加權,最終得到以下變化:
? ? ? ? 根據上圖,很容易發現,進行衰減加權后,整個訓練過程中,取得的性能都要優于直接使用的性能。最終,pose的mAP50:95取得66.8(超正常訓練的66.5),也說明知識蒸餾產生了一些效果。
3. 動態調整蒸餾損失權重及實驗分析
? ? ? ? 使用余弦衰減、指數衰減后損失權重的可視化分析。這里沒有使用“溫度”這個參數來調整損失大小,是因為相比分類,檢測、關鍵點等損失調整要困難很多,直接用權重加權會簡單很多。
3.1 余弦衰減和指數衰減
? ? ? ? 也可以引入warmup,因為前期損失過大,不過用了以后,似乎沒啥用。
????????這兩種衰減方式的選擇,主要是看損失需不需要快速衰減,比如AT后期沒用,可能需要衰減快一點,就用指數衰減,其他可以用余弦衰減。具體還是要根據自己的訓練過程中,蒸餾損失下降的特性以及產生的影響去調整。
指數衰減:
余弦衰減:
????????衰減的預設參數的代碼寫在了distillation.py中YOLOv8DistillationLoss類的get_kd_weight方法中:
3.2 CWD蒸餾損失
? ? ? ? 如下圖,最初用BN來歸一化的版本的,下井很快,20輪后比例就穩定在0.11,總統而言,該算法損失下降速度和yolov8-pose的一致,可能不需要加權重,只需要調整比例。
? ? ? ? 加權后下降,如下圖,精度反而掉了0.3%,參數還需要調整一下。
3.3 MGD蒸餾損失
? ? ? ? MGD的蒸餾損失在后期占比還提升了,說明下降過慢,對應后期性能增加也變慢了。
? ? ? ? 我設置最終權重衰減到0.1,不過訓練結果好像也沒有提升,也沒有下降。經過多次實驗,我發現只要權重不是設置太高或者太低,該方法都能產生效果,是魯棒性比較好的一個方法。
3.4 AT蒸餾損失
? ? ? ? AT的下降趨勢看起和CWD類似,但是比例卻不同,損失占比一致在20%左右,可能太高了,但是前期收斂快也是真的快,是唯一一個能在20輪的時候就讓原始損失到6.5的,比其他算法快了10輪。
? ? ? ? 加權后,衰減到0,衰減好像過快了,導致后期就是沒進行知識蒸餾的訓練。所以這部分參數還得再調試。
3.5 SKD和PKD蒸餾損失
????????這兩種算法不會實際用,僅做實驗參考。
SKD:2.1中訓練效果變差,有原因,就是這個損失在后期占比越來越高,影響原始損失的下降了。
PKD:中規中矩,沒啥特點,類似CWD,要用估計也優先用CWD。
4. 調權重心得總結
? ? ? ? 我會優先選擇AT,因為實現簡單,資源消耗少,訓練時間也不會變長。實際訓練的想法就是但求無錯,最好有功。
? ? ? ? 求魯棒性選擇MGD,算法對參數設置(用論文中的就行)沒那么敏感,多多少少會有些效果。
? ? ? ? 求結果選擇CWD,只要參數調的好,效果比MGD還好。
? ? ? ? 初始權重調整:將蒸餾損失與原始損失的初始比例調整到15%~25%,最終比例調整到5%~15%,可能是一個比較好的設置。
? ? ? ? 如果教師模型性能遠超學生模型(比如yolov8m-pose蒸餾yolov8n-pose),那么參數設置可以沒那么嚴格,因為我在做m蒸n時,參數直接用的m蒸s的,根本沒調,結果也能提升2.5%~2.8%。
5. 待驗證
? ? ? ? 優于時間有限,目前驗證的結論如上。大家可以多嘗試,分享下調參經驗。
? ? ? ? 還可以采用多種/多階段的知識蒸餾方式,比如AT+MGD,開始設置9:1權重,最后設置1:9權重,因為AT開始效果好,MGD后期效果好一些,可以多嘗試。