NLPCC:預訓練在小米的推理優化落地

導讀: 本文主要分享 小米AI實驗室NLP團隊NLPCC輕量級語言模型比賽 上的經驗,以及我們在預訓練模型推理優化上所作的工作和達到的實際落地後的效果。此次分享的目的是幫助大家快速進入比賽,以及瞭解工業界中使用 BERT 之類的大型預訓練模型時進行推理的相關優化手段。

01 背景介紹

首先和大家說一下比賽的背景和預訓練模型中存在的問題。

1. NLP中的預訓練

隨着BERT的推出和發展,預訓練模型成爲目前工業界和比賽使用最廣泛的模型。目前在各大NLP任務SOTA榜單上排前幾名都是大型的預訓練模型,比如原生BERT或者它的一些變體。

預訓練模型的應用分爲兩個階段,先進行預訓練階段 ( pre-training ),然後進行微調階段 ( fine-tuning )。預訓練階段利用大規模的無監督預料,通常大於100g的量級,加上特定的無監督任務進行訓練。用來預訓練的任務有,經典的NSP ( next sentence predict )、MLM ( masked language model )、以及一些變體,如阿里發佈的Structural language model。另外在預訓練階段時,embedding層的使用方式也有很多,比如NEZHA以及XLNET使用的相對位置編碼。Pretrain階段一般比較消耗計算資源,一般都是在大量的GPU集羣上進行運算,並且計算很長的時間才能得到一個比較好的結果。

相對於複雜預訓練任務,下游的微調任務就比較簡單了。在預訓練好的模型的基礎上,只需要添加較少的網絡參數,並在在下游有監督數據上進行少量的訓練,就可以得到很不錯的成果,這也是預訓練技術能夠被大量使用的基礎條件。

2. 效率問題

然而就像天下沒有免費的午餐一樣,預訓練技術在帶來好處的同時也存在一些問題,這其中最爲凸顯的恐怕是效率問題了。

微軟在發佈TuringNLG模型的同時發佈了這種圖,從上圖我們可以看到在BERT發佈到現在,自然語言模型參數量的發展是指數型增大的,從BERT的1億參數量、到GPT2的10億、然後TuringNLG的100億。模型變大帶來的效率問題可以從訓練和推理兩個方面來體現。

在訓練階段,一個好的模型需要大量的語料支持,通常爲了得到一個不錯的模型,需要使用100g以上的訓練數據。同時爲了支持如此規模的數據集,使模型能擬合出不錯的效果,就需要使用大量昂貴的GPU資源。而在推理階段,大模型的推理時間比較長,那如何在高併發業務線上使用大模型,並且保證推理服務的性能 ( 比如服務延遲99分位數 ) 成爲一個難題。由此可見,在預訓練模型應用時必須考慮性價比,在效果提升和成本預算之間做一個合適的權衡。

3. 解決方向

針對這些效率上的問題,衍生出兩個比較清晰的解決方向和思路。

第一種方法是小模型或蒸餾,小模型是指參數特別少的模型,比如在NLPCC小模型比賽中聚焦的小於12M參數的模型。蒸餾是將訓練好的BERT類大模型的能力遷移到較小的模型中,目前業界聚焦的任務是將12層的BERT-base模型蒸餾到6層的BERT上,並保證較少的性能損失。這種方法的主要優勢是資源佔用率比較少,適用於線上的高併發業務;並且通過一些方法能夠實現與大模型類似的效果。

第二種方法是對大模型的優化,具體來說是指優化大模型在單張GPU上所能承受的最大流量,即吞吐量。這種方法的優勢是效果較好,比較適合低併發業務。

02 NLPCC預訓練小模型比賽經驗分享

1. 比賽介紹

比賽要求的小模型必須是小於12M參數的預訓練模型,即1/9的BERT-base大小,最後在四個下游任務中測試模型效果並進行打分。評測涉及任務有:指代消歧 ( CLUEWSC2020 )、分類任務 ( CSL論文關鍵詞識別 )、命名實體識別 ( CLUENER2020 ) 以及閱讀理解 ( CMRC 2018 )。其中,指代消歧任務用的是小數據集 ( 1.2k左右 ),其餘任務所用數據集大小爲萬級別。在小數據集上微調模型,尤其是小預訓練模型,是比較影響模型效果的,後面我們會介紹這方面所做工作,希望能夠對讀者有所幫助。

用一句話來總結這個比賽,小模型的效果真的很差嗎?我們直接來看比賽的結果。

其中,第一條我們提交的BERT-base的參考。可以看到相較於BERT模型,小模型在分類、NER以及閱讀理解任務上都可以將差距縮小到1.5%以內。而在wsc任務上由於數據集太小,導致微調時效果的抖動非常大效果會略差一點,而實際中很少有這麼小的數據集。

2. 經驗分享

接下來主要介紹一下我們的解決方案。在直接預訓練小模型和蒸餾的方式選擇上,我們採用了前者。

我們在比賽中所做的工作主要分爲了3個方面,首先是數據。我們一共收集了160g的原始中文語料,並剔除了一些口語、表情、微博段子、網絡流行用語比較多的語料,最終篩選出35g+相對通用的語料。爲了快速得到實驗結果,我們在輸入長度上採用了256的大小,同時也正在嘗試512的長度,以便在閱讀理解等需要更長的句子輸入的任務上得到更好一點的效果。

在模型方面,我們選用了6層的高瘦模型,並通過以下公式選擇對應的Hidden size和Vocab size來保證模型參數總量小於12M。

大概介紹一下訓練細節,我們使用了8張V100卡;採用了混合精度的方法;優化器爲lamb優化器;batch size大概爲14400,並每過十幾步累積一次梯度;預訓練任務選用了wwm-MLM。沒有選用NSP任務的原因是,我們在測試MLM + NSP任務訓練時出現了收斂較慢的現象,原因仍有待分析。最終訓練結果是MLM loss達到了1.5 ~ 1.8之間,同時我們發現當loss到1.8左右時,分類任務和NER任務對應的表現已經很好了;繼續訓練當loss來到1.5附近時,閱讀理解任務的效果提升較大,而分類任務和NER任務的表現開始有一些抖動。

遇到的問題

同時我們分享兩個在比賽過程中遇到的問題。

第一個是模型訓練時的梯度爆炸,具體是每當loss收斂到1.5附近時就會出現梯度爆炸的問題。再排除了數據中的問題後,最終我們找到的解決方法是將初始的學習率調小,之後再沒有遇到同樣的問題。

第二個問題是,我們再嘗試微軟發佈的Bert of theseus蒸餾方式時,發現該方法在本次小模型比賽中取得的效果不好,原因是使用該方法時Hidden Size不能改變,因此必須壓縮層數來達到參數量的限制。同時,我們嘗試用小的Hidden Size預訓練一個模型,再去蒸餾一個12M的模型。可能是受限於Teacher模型的效果限制,得到的結果是不好的。

3. 後續嘗試

同時,在比賽快結束的時候我們總結性的提出一些後續可以繼續嘗試的思路。

注:NLPCC比賽結束後,我們又嘗試了一個數據增強和簡單的蒸餾方法,目前在WSC和CLUENER兩個任務上已經超過了bert-base的效果,並且排在了小模型排行榜第一名,詳見如下:

以上就是這次NLPCC小模型比賽的經驗分享,下面將分享一下大模型推理服務的優化以及在小米的落地情況。

03 大模型推理效率及在小米的優化落地

1. 相關知識和現狀

爲了方便大家閱讀,我們先介紹兩個工程上評價服務的指標。

爲什麼要介紹這兩個指標,是因爲線上服務要在短時間內接受大量的請求,爲了滿足使用者的體驗以及維護公司利益,必須要保證較高的可用性。

我們再來看一下在用大模型推理時,用一張T4卡能達到的最大QPS。如果模型用的是BERT base,句子計算長度設定爲16,那麼最大的QPS大概是100,這時P99已經比較高了,如果QPS設定爲150服務將變得不可用;同時,如果模型是BERT-large,在同樣的句子長度下,模型根本無法運行。在這種情況下假設有一個日活1000w+的服務要上線,QPS對應要求爲2000,並使用BERT-base作計算推理。那麼我們計算了一下,一共需要20張T4卡來滿足需求,並且P99延遲會大於90ms,這是一個非常大的資源浪費。

2. 優化效果

開門見山的說,在優化後同樣一張T4卡上可以達到什麼樣的效果呢?大家可以看下錶中QPS和對應的P99表現,當QPS最大達到3000時,P99的延遲仍然保持在40ms以下。

如果大家爲了追求更好的效果使用BERT-large模型,使用相同的推理優化方法能夠達到的數據如下表,極限QPS大概是800左右。

總結一下優化效果,優化前如果BERT-base模型要放在線上推理,需要使用20張T4來滿足需求。優化後可以將數量縮減到1張,一共節約了19倍的成本。

3. 實現方案

下面來介紹一下我們的優化方案。

簡單來說分爲三個:

  • 第一個是Tensorflow Serving提供的Batching功能,該方法能夠提升n倍的服務性能;
  • 第二個是FP16的量化,可以提升2倍服務性能;
  • 第三個是NVIDIA開源的Faster Transformer庫。

Tensorflow Serving Batching所做的是將多個請求合併在一起進行計算,這樣可以利用GPU的並行性能。之所以能這樣做是因爲GPU在計算一定量的batch所消耗的時間和計算單挑所用時間相差不多。具體的原理是服務端在規定好的一段時間裏持續接收請求並放入隊列等待,如果請求數達到規定的數量或者隊列等待時間超過規定時間,再進行推理運算。另外一個經驗是在使用TF-Serving Batching時,服務端做Padding會用隨機數填充,所以建議大家在Client端做Padding。

在用FP16優化中,我們使用了TensorCore來做加速,將模型圖中FP32精度的節點全部轉換爲FP16,從而降低模型推理需要計算的運算量 ( 每秒浮點運算次數TFLOPs )。在BERT-base上實驗,這種方法很穩定,損失基本上控制在萬分位,是一個非常值得使用的方法。

第三個方法是用Fast Transformer,大家感興趣可以去github瞭解源碼。我們在這基礎上所做的工作是,將Fast Transformer集成到Tensorflow Serving上,並且支持對可變長度輸入的處理等等。大家可以訪問英偉達的github主頁瞭解更多。

4. 線上效果

前面在評測這些優化方法時用到的數據都是壓測數據,那麼在真實線上業務的表現怎麼樣呢,我們用小愛同學的閒聊業務來舉例說明。

這個任務是一個問答排序問題,比如用戶問"你喜歡維尼小熊嘛",這時對應的答案可能有好多種,按照先檢索後排序的方法,需要對輸入和每個回答計算一個相似度。我們使用的方案是Pointwise的BERT二分類,使用的模型爲6層的BERT,輸入長度爲32,輸入爲Query+Reply,輸出爲0-1的相關性。下面是服務的優化效果,我們一共分爲了三個版本,在使用了這三種優化方法後成功的將13張GPU壓縮到了3張GPU,並且P99從200ms+降到了35ms,效果還是比較明顯的。

04 總結

我們的分享就結束了,一共講了三個部分,先分享了我們在NLPCC小模型比賽上的經驗,然後介紹了預訓練推理優化在小米的相關落地,最後感謝賽事主辦方CLUE&NLPCC提供這樣一次賽事。

今天的分享就到這裏,謝謝大家。

作者介紹

趙羣,小米高級軟件工程師

2014年碩士畢業於中國人民大學,同年加入微軟Bing廣告組。2017年加入小米AI實驗室NLP應用組,參與了閒聊機器人在小米小愛同學的搭建與落地,現聚焦在預訓練通用優化方向。

本文來自 DataFunTalk

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzU1NTMyOTI4Mw==&mid=2247502777&idx=2&sn=ebc2ccc9997a45732b4244cfbb35f63f&chksm=fbd779d5cca0f0c3ecca9fa6d2c736e8f1c497116c2157e0da23f0db19fb46df2f84b5096fbc&scene=27#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章