以前理解的模型蒸餾就是模型“提純”,這樣說太寬泛了,應該說 蒸餾是“提純”的一種手段而已。
知識蒸餾具體指:讓小模型去學到大模型的知識。通俗的說,讓student模型的輸出接近(擬合)teacher模型的輸出。知識蒸餾的重點在於擬合二字,即我們要定義一個方法去衡量student模型和teacher模型的接近程度,說白了就是損失函數。必備元素為:教師模型、學生模型、損失函數。
為什么需要知識蒸餾?
因為大模型推理慢難以應用到工業界。小模型直接進行訓練又不如蒸餾得到的效果好。
相關工作介紹:
(1)Hinton在論文:Distilling the Knowledge in a Neural Network提出了知識蒸餾的方法。
損失函數:Loss = a L{soft} + (1-a) L{hard}
其中L{soft}是studentModel和TeacherModel的輸出的交叉熵,L{hard}是studentModel輸出和真實標簽的交叉熵。L{soft},我們直到TeacherModel的輸出是經過softmac處理的,指數e拉大來各個類別之間的差距,最終輸出結果特別像one-hot向量,這樣不利於studentModel的學習,因此我們希望輸出更加軟一些。因此我么我們需要修改一些softmax函數:
顯然T越大輸出越軟。這樣改完之后,對比原始softmax,梯度相當於乘了1/T^2,因此L{soft}需要再乘以T^2來與L{hard}在一個數量級上。
最后再放一張這個算法的整體框架圖:
(2)TinyBert
首先說到對Bert的蒸餾大家肯定會想到就用微調好的Bert作為TeacherModel去訓練一個StudentModel,沒錯目前就是這么干的。那么下面的問題就是我們選取什么模型作為StudentModel,這個已經有一些嘗試了,比如有人使用BiLSTM,但是更多的人還是繼續使用了Bert,只不過這個Bert會比原始的Bert小。在TinyBert中,StudentModel使用的是減少embeddingsize、hidden size和num hidden layers的小bert。
那么新的問題又來了,我們怎么初始化StudentModel?
最直接的解決方案就是隨機化,模型不都是這么訓練的嗎?但是這種效果真的好嗎?我看未必,如果沒問題那么為啥那么多人用預訓練模型?所以啊,我們需要一個比較好StudentModel的參數,確切說,我們需要一個與訓練的studentModel,那么怎么獲取一個預訓練的StudentModel,TinyBert給出的答案就是咱們再用預訓練好的Bert蒸餾出一個預訓練好的StudentModel。(是不是很繞,感覺等於沒說,要想弄明白,還是要實踐,實踐出真知)
Ok,TinyBert基本講完了,簡單總結下,TinyBert一共分為兩步:
1、用pretrained bert蒸餾一個pretrained TinyBert
2、用fine-tuned bert蒸餾一個fine-tuned TinyBert(它的初始參數就是第一步里pretrained TinyBert)
在進行蒸餾的時候,會先進行隱層蒸餾(即m<=M),然后再執行m = M+1時的蒸餾。
總結一下,TinyBert在蒸餾的時候,不僅要讓StudentModel學到最后一層的輸出,還要學到中間幾層的輸出。換言之,studentModel的某一隱層可以學到TeacherModel若干隱層的輸出。感覺蒸餾的力度比較細,我覺得可以叫做LayerBasedDistillation.
(3)BERT-OF-Theseus
這個准確的來說不是知識蒸餾,但是它確實減小了模型體積,而且思路和TinyBERT、DistillBERT都有類似。這個思路非常優雅,它通過隨機使用小模型的一層替換大模型中若干層來完成訓練。舉一個例子:假設大模型是
input->tfc1->tfc2->tfc3->tfc4->tfc5->tfc6->output,然后再定義一個小模型input->sfc1->sfc2->sfc3->output。再訓練過程中還是要訓練大模型,只是在每一步中,會隨機的將(tfc1, tfc2),(tfc3,tfc4),(tfc5,tfc6)替換sfc1, sfc2, sfc3,而且隨着訓練的進行,替換的概率不斷變大,因此最后就是在訓練一個小模型。
方式優雅,作者提供了源碼,強烈推薦大家用一用。
(4)MiniLM
1、先用TeacherModel蒸餾一個中等模型,再用中等模型蒸餾一個較小的StudentModel。只有在StudentModel很小的時候才會這么做。
2、只對最后一個隱層做蒸餾,作者認為這樣可以讓StudentModel有更大的自由空間,而且這樣對StudentModel架構的要求就變得寬松了。
3、對於最后一個隱層主要是對attention權重做學習。
相關庫的使用見如下鏈接:
https://www.cnblogs.com/SuperDun/p/12442919.html
后期會增加這一部分的實戰介紹。