ACL2020 | FastBERT:放飞BERT的推理速度
FastBERT
自從BERT問世以來,大多數NLP任務的效果都有了一次質的飛躍。BERT Large在GLUE test上甚至提升了7個點之多。但BERT同時也開啟了模型的“做大做深”之路,普通玩家根本訓不起,高端玩家雖然訓得起但也不一定用得起。
所以BERT之后的發展也比較清晰,一部分壕大佬們繼續搞預訓練提升效果,當你對BERT Large望而卻步的時候,又出了GPT2,又雙出了威震天Megatron-LM,又雙叒出了T5,又雙叒叕出了DeepSpeed。。。每次都是照著一個數量級去加,剩下的人只能默默觀望,翻翻《顯存不夠,如何訓練大型神經網絡?》看哪個trick可以用上。
另一部分大佬著力于給BERT瘦身提升速度。比如剪枝,剪掉多余的連接、多余的注意力頭、甚至LayerDrop[1]直接砍掉一半Transformer層;再比如量化,把FP32改成FP16或者INT8;還有蒸餾,用一個學生模型來學習大模型的知識,不僅要學logits,還要學attention score。。。
然而,大部分減肥方法都會帶來精度的下降。剪枝會直接降低模型的擬合能力,量化雖然有提升但也有瓶頸,蒸餾的不確定性最大,很難預知你的BERT教出來怎樣的學生。
但!是!
昨天刷到了一篇讓我眼前一亮的文章《FastBERT: a Self-distilling BERT with Adaptive Inference Time》[2],是北大+騰訊+北師大的ACL2020。作者提出了一種新的inference速度提升方式,相比單純的student蒸餾有更高的確定性,且可以自行權衡效果與速度,簡單實用。
后臺回復【0409】獲取論文PDF噢~
FastBERT
模型結構
FastBERT的創新點很容易理解,就是在每層Transformer后都去預測樣本標簽,如果某樣本預測結果的置信度很高,就不用繼續計算了。論文把這個邏輯稱為樣本自適應機制(Sample-wise adaptive mechanism),就是自適應調整每個樣本的計算量,容易的樣本通過一兩層就可以預測出來,較難的樣本則需要走完全程。
那么問題來了,用什么去預測中間層的結果呢?作者的解決方案是給每層后面接一個分類器,畢竟分類器比Transformer需要的成本小多了:
注:FLOPs (floating point operations)是Tensorflow中提供的浮點數計算量統計
于是模型的整體結構就呼之欲出了:
作者將原BERT模型稱為主干(Backbone),每個分類器稱為分支(Branch)。
要注意的是,這里的分支Classifier都是最后一層的分類器蒸餾來的,作者將這稱為自蒸餾(Self-distillation)。就是在預訓練和精調階段都只更新主干參數,精調完后freeze主干參數,用分支分類器(圖中的student)蒸餾主干分類器(圖中的teacher)的概率分布。
之所以叫自蒸餾,是因為之前的蒸餾都是用兩個模型去做,一個模型學習另一個模型的知識,而FastBERT是自己(分支)蒸餾自己(主干)的知識。值得注意的是,蒸餾時需要freeze主干部分,保證pretrain和finetune階段學習的知識不被影響,僅用brach 來盡可能的擬合teacher的分布。
那為什么不直接用標注數據訓分支分類器呢?因為直接訓效果不好唄(攤手~下面是作者在消融實驗給出的結果:
可以看到,非蒸餾的結果沒有蒸餾要好。個人認為是合理的,因為這兩種方式在精調階段的目標不一樣。非自蒸餾是在精調階段訓練所有分類器,目標函數有所改變,迫使前幾層編碼器抽取更多的任務feature。但BERT強大的能力與網絡深度的相關性很大,所以過早地判斷不一定準確,致使效果下降。
同時,使用自蒸餾還有一點重要的好處,就是不再依賴于標注數據。蒸餾的效果可以通過源源不斷的無標簽數據來提升。
模型訓練與推理
了解模型結構之后,訓練與推理也就很自然了。只比普通的BERT模型多了自蒸餾這個步驟:
Pre-training:同BERT系模型是一樣的,網上那么多開源的模型也可以隨意拿來~
Fine-tuning for Backbone:主干精調,也就是給BERT加上分類器,用任務數據訓練,這里也用不到分支分類器,可以盡情地優化
Self-distillation for branch:分支自蒸餾,用無標簽任務數據就可以,將主干分類器預測的概率分布蒸餾給分支分類器。這里使用KL散度衡量分布距離,loss是所有分支分類器與主干分類器的KL散度之和
Adaptive inference:自適應推理,及根據分支分類器的結果對樣本進行層層過濾,簡單的直接給結果,困難的繼續預測。這里作者定義了新的不確定性指標,用預測結果的熵來衡量,熵越大則不確定性越大:
效果
對于每層分類結果,作者用“Speed”代表不確定性的閾值,和推理速度是正比關系。因為閾值越小 => 不確定性越小 => 過濾的樣本越少 => 推理速度越慢。
模型最終在12個數據集(6個中文的和6個英文的)上的表現還是很好的:
可以看到,在Speed=0.2時速度可以提升1-10倍,且精度下降全部在0.11個點之內,甚至部分任務上還有細微提升。相比之下HuggingFace的DistillBERT的波動就比較劇烈了,6層模型速度只提升2倍,但精度下降最高會達到7個點。
總結
FastBERT是一個在工程上十分實用的模型,通過提前輸出簡單樣本的預測結果,減少模型的計算負擔,從而提高推理速度。雖然每層都多了一個分類器,但分類器的計算量也比Transformer小了兩個數量級,對速度影響較小。后續的分支自蒸餾也設計的比較巧妙,可以利用無監督數據不斷提升分支分類器的效果。
另外,Sample-wise adaptive mechanism和Self-distillation這兩個idea也是在本文首次提出,相信會起到拋玉引玉的作用,衍生更多此類工作。論文本身也還有一些想象空間,比如分別優化每層分類器,因為在主干被freeze的情況下各個分支是獨立的;或者自蒸餾unfreeze主干,再加上數據自蒸餾一把,說不定還會有性能提升。
值得一提的是,本文的一作劉偉杰(北大)正是K-BERT[3]的作者,那也是一篇我很喜歡的文章,把知識融入到BERT的方式比較優雅,真心期待作者有更多的idea~
最后再回來夸一下,FastBERT著實很實用,而且完全不會影響到手頭調好的BERT,只需要蒸餾幾個淺層分類器,再把判斷機制加上就可以了。而且比起不太穩定的蒸餾來說放在線上也更有底,穩穩的幸福。
唯一的遺憾是源碼要在文章發表時才會放出來,一起去催更吧~
https://github.com/autoliuweijie/FastBERT
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的ACL2020 | FastBERT:放飞BERT的推理速度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性代数应该这样讲(三)-向量2范数与模
- 下一篇: 算法岗SSP offer收割指南!