廣告行業中那些趣事系列6:BERT線上化ALBERT優化原理及項目實踐(附github)

微信公衆號:數據拾光者。願結交更多的小夥伴,一同走人生路。

摘要:BERT因爲效果好和適用範圍廣兩大優點,所以在NLP領域具有里程碑意義。實際項目中主要使用BERT來做文本分類任務,其實就是給文本打標籤。因爲原生態BERT預訓練模型動輒幾百兆甚至上千兆的大小,模型訓練速度非常慢,對於BERT模型線上化非常不友好。本篇研究目前比較火的BERT最新派生產品ALBERT來完成BERT線上化服務。ALBERT使用參數減少技術來降低內存消耗從而最終達到提高BERT的訓練速度,並且在主要基準測試中均名列前茅,可謂跑的快,還跑的好。希望對需要將BERT線上化感興趣的小夥伴有些許幫助。


目錄
01 項目背景介紹
02 從BERT到ALBERT
03 萬里第一步:先跑通模型
04 多分類任務實踐
總結




01 項目背景介紹

原生態BERT預訓練模型動輒幾百兆甚至上千兆的大小,訓練速度非常慢,對於模型線上化非常不友好。爲了實現BERT模型線上化問題,其實就是如何又快有好的訓練模型,經調研目前超火的BERT最新派生產品ALBERT項目能很好的解決上述問題。

ALBERT是由論文《ALBERT: A Lite BERT For Self-Supervised Learningof Language Representations》提出來的。通常情況下增加預訓練模型大小可以提升模型在下游任務中的性能,但是因爲“GPU/TPU內存的限制、更長的訓練時間以及意想不到的模型退化”等問題,作者提出了ALBERT模型。

論文下載地址:
https://arxiv.org/pdf/1909.11942.pdf

通俗的理解ALBERT就是參數數量更少的輕量級BERT模型。ALBERT是BERT最新派生產品,雖然輕量,但是效果並沒打折,在主要基準測試中均名列前茅。

02 從BERT到ALBERT

1. ALBERT出現背景

自從深度學習引爆計算機視覺領域之後,提升模型性能最簡單也最有效的一個方法就是增加網絡深度。下圖中拿圖片分類任務舉例,可以看出隨着網絡層數不斷增加,模型的效果也會有很大提升:

圖1 網絡層數增加模型效果提升

 


同樣的情況也出現在BERT上,隨着網絡變深變寬使得模型的效果得到提升:

圖2 BERT隨着網絡變深變寬模型效果得到提升

 


但是網絡變深變寬帶來一個顯著的問題:參數爆炸。這裏看下不同規模參數的BERT模型參數量的變“胖”之路:

圖3 BERT參數爆炸問題

 


如何做到,讓BERT不那麼“胖”,但是效果依舊好是目前學術界的研究重點,也是如何將BERT線上化的重點工作之一。這也是ALBERT要做的事情。

2. BERT“胖”在哪裏

想讓BERT變瘦,先要知道“肉”長在哪裏。BERT使用Transformer作爲特徵抽取器,這是BERT參數的來源。之前廣告行業中那些趣事系列4:詳解從配角到C位出道的Transformer很深入的剖析了Transformer,有興趣的小夥伴可以回頭看看。

Transformer的參數來源主要有大塊:第一塊是token embedding映射模塊,參數量佔比爲20%,第二塊是attention層和前向反饋層FFN,參數量佔比爲80%。

圖4 Transformer結構圖和BERT參數來源

 

3. ALBERT優化策略

策略一、對embedding參數因式分解(Factorized embedding parameterization)

BERT將詞的one-hot向量映射到高維空間,參數量是O(VXH),ALBERT則採用因式分解的方式先將詞的one-hot向量映射到低維空間(大小爲E),然後再映射回一個高維的空間(大小爲H),這樣使用的參數僅僅是O(VXE+EXH),如果E<<H的時候參數量會減少很多。這裏就一定程度上減少了上面說的BERT第一部分參數token embedding的部分。

可以通過因式分解減少參數量的原因是token embedding是上下文獨立的,通過one-hot向量轉化成dense向量。而第二部分的attention和FFN作爲隱藏層是上下文依賴的,包含更多信息。所以通過一個小於H的E做中介將詞的one-hot向量先經過一個低維的embedding矩陣,然後再映射回高維的embedding矩陣是可行的。下圖中紅色方框顯示了因式分解部分:

圖5 因式分解降低參數量

 

查看token embedding因式分解效果情況:總體來看降低了17%的模型參數,但是模型效果僅僅降低了不到1%。

圖6 因式分解降低參數量效果

 


策略二、共享層與層之間的參數(Cross-layer parameter sharing)

通過對Transformer各層參數可視化分析發現各層參數類似,都是在[CLS]token和對角線上分配更多的注意力,所以可以使用跨層的參數共享方案。

通常來說,跨層的參數共享對應Transformer編碼器中的結構有兩種方案:一種是attention模塊的參數共享,另一種是前饋神經網絡層FFN的參數共享。具體的效果如下圖所示:

圖7 使用共享參數對模型參數量和效果的影響

 

當映射到低維空間E=768時,對比不共享參數和共享FFN層的參數可以看出,參數減少了近50%,這也是導致模型效果下降的主要原因。而共享attention層的參數則對模型效果影響較小。

策略三、構建自學習任務-句子連貫性預測

通過改造NSP(Next Sentence Prediction)任務,增強網絡學習句子的連續型來提高預訓練任務。

廣告行業中那些趣事系列3:NLP中的巨星BERT重點講解了BERT模型,其中提到BERT是近幾年NLP領域傑出成果的集大成者,本身的創新主要是隨機屏蔽的語言模型Masked LM和下一句預測Next Sentence Prediction。有興趣的小夥伴可以倒回去再好好看下。

NSP任務本身是一個二分類任務,目的是預測兩句話是否是連續的語句。NSP實際包含兩個子任務,分別是主題預測和關係一致性預測。NSP任務選擇同一文檔中連續的兩個句子作爲正樣本,選擇不同文檔的句子作爲負樣本。因爲來自不同的文檔,差異性可能非常大。爲了提升模型預測連續型句子的能力,ALBERT提出了新的任務SOP(SenteceOrder Prediction),正樣本獲取方式和NSP相同,負樣本則將正樣本的語句順序顛倒。

SOP和NSP效果展示如下圖所示:

圖8 SOP和NSP效果展示

 

從圖中可以看出NSP任務無法預測SOP類任務,但是SOP可以預測NSP任務。整體來看,SOP任務的模型效果也優於NSP任務。

策略四、去掉dropout

dropout主要是爲了防止過擬合,但實際MLM一般不容易過擬合。去掉dropout還可以較少中間變量從而有效提升模型訓練過程中內存的利用率。

圖9 dropout效果影響

 

其他策略:網絡寬度和深度對模型效果的影響

1. 網絡深度是否越深越好
對比ALBERT在不同深度下的效果可以發現:隨着層數加深,不同NLP任務的模型效果是有一定提升。但是這種情況並不是絕對的,有些任務效果反而會下降。

圖10 網絡深度的影響

 

2. 網絡寬度是否越寬越好
對比深度爲3的ALBERT-large模型下不同網絡寬度的模型效果情況可以發現:模型寬度的影響和深度類似,隨着網絡寬度增加,不同NLP任務的模型效果是有一定提升。某些任務也會存在效果下降的情況。

圖11 網絡寬度的影響

 

總體來看,ALBERT的實質是使用參數減少技術來降低內存消耗從而最終達到提高BERT的訓練速度,主要優化了以下幾個方面:

  • 通過因式分解和共享層與層之間的參數減少了模型參數量,提升了參數效率;
  • 通過SOP替代NSP,增強了網絡學習句子連續性的能力,提升了自監督學習任務的能力;
  • 通過去掉dropout可以節省很多臨時變量,有效提升模型訓練過程中內存的利用率,提升了模型的效率,減少了訓練數據的規模。

03 萬里第一步:先跑通模型

因爲實際項目中主要是識別中文,所以主要是使用ALBERT中文版本ALBERT_zh,項目的github地址:https://github.com/brightmart/albert_zh

記得之前看過一個圖片很有意思,能很好的描述此刻我的心情:

圖12 第一步先跑通模型

 

對於我這種“拿來主義者”來說,再牛逼的模型第一步永遠都是先跑通它,至於優化的先放一放。跑通它不僅能提升自信心,最實際的作用就是能快速實現項目上線。因爲我需要完成文本分類任務,所以通過上面的github地址下載項目後,在集羣上跳轉到albert_zh目錄下,執行sh run_classifier_lcqmc.sh命令即可跑起來。因爲項目沒有句子分類任務,只有個類似的句子關係判斷任務,所以先跑通這個任務,後期再根據這個任務的代碼來改就行了。

run_classifier_lcqmc.sh腳本中總體分成兩大塊,第一塊是模型運行的準備工作,第二塊就是模型運行。下面是模型的第一塊,其中涉及獲取數據、預訓練模型、設備以及模型相關的參數等等。

圖13 模型運行準備工作

 

第二塊就是負責模型運行,主要就是python運行程序的指令以及需要的相關參數配置。

圖14 模型運行

 


總結下,這裏重點講了如何運行成功ALBERT_zh本身提供的一個句子關係判斷任務。這個demo是和我們實際項目中文本分類任務很相似的任務,下面就是通過改造這個腳本以及執行的代碼來完成我們的實際項目文本分類。

04 多分類任務實踐

項目改造的github地址如下:https://github.com/wilsonlsm006/albert_zh

將原項目fork下來,這裏我增加了兩個文件run_classifier_multiclass.sh和run_classifier_multiclass.py。這是用來執行文本分類的任務腳本以及代碼。改造的原理其實也比較簡單,這裏大致講解下。

項目原來提供的句子關係判斷任務的數據格式是:id,text_a,text_b,label,任務其實就是來判斷兩句話到底有沒有關係。正樣本舉例如下:

text_a:成龍大哥代言的一刀傳奇好玩麼?
text_b:成龍大哥還代言過其他傳奇麼?
label:1

負樣本則可能是這樣的:
text_a:成龍大哥代言的一刀傳奇好玩麼?
text_b:成都市內哪個景點最好玩?
label:0

通過上面兩個正負樣本的例子大家應該能瞭解什麼是句子關係判斷任務,其實就是有監督學習的分類任務。我們實際項目主要通過BERT來做文本分類,識別一句話屬於哪個標籤,對應到上面的任務其實就是隻有text_a,label。因爲任務類型一致,所以修改代碼的策略就是重點分析有text_b的代碼的部分。具體腳本和代碼修改就是上面說的兩個文件,有需要的小夥伴自取。這裏需要注意的是原來的數據文件是tsv格式,我這邊是csv格式,數據輸入有點點不同,模型其他的都沒動。


總結

實際項目中需要將BERT線上化需要使模型又快又好的訓練,所以經過調研使用目前BERT最新的派生產品ALBERT。ALBERT通過因式分解和共享層與層之間的參數減少了模型參數量,提升了參數效率;通過SOP替代NOP,增強了網絡學習句子的連續性的能力,提升了自監督學習任務的能力;通過去掉dropout可以節省很多臨時變量,有效提升模型訓練過程中內存的利用率,提升了模型的效率,減少了訓練數據的規模。最後將項目中的句子關係判斷任務改造成我們實際項目中的文本分類任務用於實際業務需求。可以說是有理論,幫助小夥伴們理解ALBERT爲啥訓練快了,效果還不錯。也有實踐,如果需要使用ALBERT做文本分類任務,直接用我改造好的腳本和代碼跑起來就行。

喜歡本類型文章的小夥伴可以關注我的微信公衆號:數據拾光者。有任何干貨我會首先發布在微信公衆號,還會同步在知乎、頭條、簡書、csdn等平臺。也歡迎小夥伴多交流。如果有問題,可以在微信公衆號隨時Q我哈。

 

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