1. 程式人生 > >聽說你不會調參?TextCNN的優化經驗Tricks彙總

聽說你不會調參?TextCNN的優化經驗Tricks彙總

 

前言:本篇是TextCNN系列的第三篇,分享TextCNN的優化經驗

前兩篇可見:

文字分類演算法TextCNN原理詳解(一)

TextCNN程式碼詳解(附測試資料集以及GitHub 地址)(二)

 

                               

調優模型的基本方法

    大家如果跑過模型的話,不論是demo還是實際專案,通常的情況都是先跑一次看看效果,然後針對某些效果不好的地方做一些調優,俗稱「調參狗」,調優有很多方法,基本的方法是:根據模型在測試集合的badcase 來分析有沒有共性的問題,譬如做一個文字分類,我們在訓練集上效果很好,但是測試集上,某一類的文字總是容易判斷錯誤,那麼這就屬於一個共性問題。

如何解決這種問題呢?兩種方式:

  • 從特徵的角度優化。我們可以通過做一些特徵分析等來找到有區分度的特徵來進行優化。特徵與特徵之間如何結合,如何判斷與測試結果是否有相關性,都是我們重點需要分析的。

  • 從模型結構上調整。深度學習雖然大家可能認為是一個黑盒,可解釋性差,但是不同的網路模型確實能對結果產生一些變化。我們可以從網路模型上優化,適當調整結構,再來訓練看測試的效果。不斷的迭代再調整。

     這是我們調優的基本思路和兩個著手點。如果只是按照常規的手段直接去調參,往往達不到我們想要的效果,所以通過分析bascase,可以針對性的解決問題,更加符合我們的應用場景和實際專案。如果單純的通過使用更fancy的模型來替換老模型來提高準確率,無異盲人摸像,很可能達不到我們最終想要的效果。

 


 

 具體調優方法介紹

1:明確所有類別預測錯誤的badcase 

    假設我們的任務是一個三分類的任務,其中一個類別是"movie",即判斷一個query 是不是屬於視訊。在測試集的預測結果中,有部分預測錯誤,如圖一所示

label

predict

錯誤分類原因

movie

music

標註問題

movie

book

資料分佈不平衡

movie

music

缺乏先驗知識

movie

book

過於依賴A特徵

movie

book

資料分佈不平衡

分析示例一

    從表中我們可以看到,一共有5條文字,原label是movie,預測結果與label都不相同,其中3條預測成book、2條預測成music等,這些就屬於“badcase”。除了可以統計這一個label的錯誤預測,也可以把其他類別的badcase全部統一集合,做成list來具體分析。

 

2: 分析badcse預測錯誤的共性原因

    我們把這些badcase挑出來以後,需要分析每個預測錯誤的badcase的具體原因是什麼,譬如,表中有兩條預測成book的原因是“資料分佈不一致”,這就屬於找到badcase的共性。把原始的特徵拿出來再分析,就可以分析出預測錯誤的共性是什麼。

    總結出共性原因後,按照錯誤原因的頻次從高到低排列,可以看到我們當前最需要解決的問題有哪些。假設我們一共分析出四類原因,分別是:

  • 訓練集合和測試集合部分特徵抽取方式不一致,如訓練集合是用python 來實現抽取特徵,但是部署到線上的時候是用java實現來抽取特徵,訓練和預測抽取特徵的時候不是同一套程式碼,雖然理論上兩者應該一致,但是實現的時候由於語言差異以及二次開發的差異很容易造成某一特徵在java版本和python版本有不同的結果 (佔比約40%) 

  • 最後的結果過於依賴某一特徵,比如我們的模型過於依賴A特徵,但是A 特徵的準確率只有88%左右,導致A特徵的準確率成了我們模型優化的瓶頸 (佔比約30%)

  • 泛化能力較差,比如"我要看黃渤的電影"可以判別正確,但是"我要看周星馳的電影"就判別不對 (佔比約20%)

  • 缺乏先驗知識,比如"青花瓷" 更容易出現在音樂當中, 而不是出現在baike 當中,但是我們在訓練資料當中並沒有特徵可以體現這一先驗知識(佔比約10%)

3: 針對原因,專項優化

原因一:訓練集合和測試集合部分特徵抽取方式不一致

  • 優化方法

    • 由於測試集合是使用java 程式碼進行特徵抽取以及預測的,訓練集合是用python 程式碼進行特徵抽取以及訓練的,所以我們統一了預測程式碼與測試程式碼,共用一套程式碼

    • 由於之前歷史原因,我們訓練集合與測試集合抽取特徵使用的資料來源不同,根據分析來看這種影響非常的大,本次優化使用了同一份資料來源

  • 優化結果:相對於原來的baseline,提升了0.4%

原因二:過於依賴效果不佳的特徵

  • 優化方法

    • 在全連線層 增加dropout層,設定神經元隨機失活的比例為0.3,即keep_rate= 0.7

    • 在資料預處理的時候,隨機去掉10%的A特徵

  • 優化結果

    • 針對方法1,效果提升了0.11%,可以認為在這裡隨機扔掉30%的所有特徵(包括A特徵),讓訓練結果與A特徵不強相關

    • 針對方法2,效果提升了0.29%,因為我們只是過於依賴A特徵,並沒有過分依賴其他特徵,故只在資料預處理的隨機去掉10%的A特徵,更有針對性的

原因三:泛化能力差

  • 優化方法:增加槽位抽取:針對部分query, 增加槽位抽取的處理,比如將"黃渤", "周星馳" 等對映為aritist. 這樣此類query, 模型見到的都是 我要看artist的電影,不存在缺乏泛化能力的問題. 瓶頸在於槽位抽取的準確率。

  • 優化結果:沒有單獨實驗, 增加槽位抽取後共同實驗,分析badcase發現此類問題基本解決

原因四:缺乏先驗知識

  • 優化方法:引入200萬外部詞表以及 計算”青花瓷“在整體語料中出現在其他類別的頻率來部分解決這個問題

  • 優化結果:模型提升了0.5%

4.模型調優實操

1) 模型優化術語說明

在我們下面行文中,會有一些術語,為了方便說明我們先提前解釋一下

  • baseline: 最開始的實驗結果, 後續所有的實驗結果,都會和baseline的結果進行對比,來體現每一次實驗優化的提升

  • baseline diff:相比baseline的結果, 我們實驗的提升有多少

  • 測試集acc:即我們的模型在測試集合的準確率

  • epoch :一個epoch 表示將將所有訓練樣本學習一遍

  • iteration(step)或者叫迭代步數: 表示執行一次iteration或者(step) 更新一次引數。每執行一次iteration 都需要一個batch size 的資料進行學習,學習完一個batch size 的資料,更新一次引數, 下面的所有實驗 迭代步數全部為26萬步

  • batch size: 迭代一次需要的樣本量,下面的實驗,batch size 全部設定為64

  • 舉例說明:exampleNums(樣本數) = 100000, epoch = 64, batch size = 64, 那麼iteration = 100000

2) 模型優化過程說明

實驗BaseLine

無論是論文還是日常的工作,最首要一點是跑出baseline 即我們實驗的起點,我們本次的baseline 即不對textCNN的網路結構做任何調整在我們測試集合的準確率

 

實驗0 baseline 測試基本引數在測試集合的表現

修改內容

測試集acc

迭代步數

baseline diff

無任何修改

85.14%

26w

0

 

優化實驗一:修改embedding_dim長度

Embeddinga_dim :128, 即將我們的query 對映成向量的時候,向量本身的維度

引數調整:我們將query 初始化成embedding的時候,修改了embed_dim 從128降低到64,相比於baseline 並沒有明顯的提升,降低了0.17%,在這裡我們希望瞭解不同的向量維度對最後的實驗結果的影響

 

實驗一 修改測試embed_dim 長度對最後結果的影響

修改內容

測試集acc

迭代步數

baseline diff

修改  embed_dim 128 -> 64

84.97%

26w

-0.17%

 

優化實驗二:在全連線層增加dropout層,keep_rate = 0.7

keep rate 是dropout 的一個引數即:表示本層要保留多少比例神經單元

引數調整:我們在前面的分析當中發現,badcase 與A 特徵高度相關,於是在最後的全連結層增加dropout,並將keep_rate 設定為0.7,即隨機丟掉30%的資料,相比baseline有0.11%的提升

 

 

實驗二 在全連線層增加dropout 層,keep_rate = 0.7

修改內容

測試集acc

迭代步數

baseline diff

在全連線層增加dropout層, keep_rate = 0.7

85.25%

26w

+0.11%

 

 

優化實驗三:在全連線層增加dropout層,keep_rate = 0.5

引數調整:在實驗二的基礎上,我們希望測試丟掉更多的資料,是否會有更加明顯的提升,發現反而降低了0.04%,原因待進一步探究

實驗三 在全連線層增加dropout 層,keep_rate = 0.5

修改內容

測試集acc

迭代步數

baseline diff

在全連線層增加dropout層, keep_rate = 0.5

85.09%

26w

-0.04%

優化實驗四:隨機去掉10%A特徵資訊

引數調整:在實驗三的基礎上,進一步思考其實我們只是過於依賴A特徵, 並沒有過分依賴其他特徵,故只在資料預處理的時候,隨機去掉10%的A特徵,相比baseline 提升0.29%

實驗四 隨機去掉10% A特徵 打分

修改內容

測試集acc

迭代步數

baseline diff

在資料增廣的時候,設定概率值, 如果 隨機數小於0.1就不輸出所有A特徵資訊, 如果隨機數高於該概率值就輸出打分資訊

85.43%

26w

+0.29%

優化實驗五:限制高頻query權重

引數調整:我們在實驗的時候,會對資料資料重取樣,使之符合一定的分佈,在重取樣的時候,我們限制了部分query的權重,相比baseline 提升0.03%,這個的目的是增加資料的多樣性

實驗五 限制高頻query 權重

修改內容

測試集acc

迭代步數

baseline diff

在資料增廣的時候,限制高頻query

85.17%

26w

+0.03%

優化實驗六:隨機去掉20%A特徵

引數調整:在實驗四的基礎上,在資料預處理的時候,隨機去掉20%的A特徵,相比baseline 提升0.28%, 並沒有優於隨機去掉10%,最終選擇隨機去掉10%A特徵

實驗六 隨機去掉20% A 特徵

修改內容

測試集acc

迭代步數

baseline diff

在資料增廣的時候,設定概率值, 如果 隨機數小於0.2就不輸出A特徵, 如果隨機數高於該概率值就輸出A 特徵

85.42%

26w

+0.28%

優化實驗七:隨機去掉10%A特徵,使用一致的特徵抽取方式

引數調整:在實驗四的基礎上,我們分析了測試集合與訓練集合特徵抽取不一致的來源,統一來源,相比baseline 提升了0.64%

 

實驗七 隨機去掉10% A特徵 使用一致的特徵抽取方式

修改內容

測試集acc

迭代步數

baseline diff

在資料增廣的時候,設定概率值, 如果 隨機數小於0.1就不輸出A特徵, 如果隨機數高於該概率值就輸出A特徵

85.78%

26w

+0.64%

 

優化實驗八:隨機去掉10% A 特徵,使用一致的特徵抽取方式,引入B特徵

引數調整:在實驗七的基礎上,我們進一步分析出B特徵對badcase 有很好的區分度,將B特徵引入訓練,相比baseline 提升了1.14%

 

實驗八 隨機去掉10% A 特徵 使用一致的特徵抽取方式,引入B特徵

修改內容

測試集acc

迭代步數

baseline diff

在資料增廣的時候,設定概率值, 如果隨機數小於0.1就不輸出A特徵, 如果隨機數高於該概率值就輸出A特徵,訓練與測試集合使用一致的特徵抽取方式,額外引入B特徵

86.28%

26w

+1.14%

 


 

 總結

   這篇文章主要總結了文字分類演算法TextCNN調優的方法,先給大家分享了下一般基本做調優我們會採取什麼方法——找到badcase,分析共性問題。

分析共性問題後,可以從模型和特徵兩個方面去優化。在這裡我們以文字分類為例,針對具體出現的badcase,我們總結了四個原因:

  • 抽取方式差異

  • 過於依賴某個特徵

  • 泛化能力差

  • 缺乏先驗知識

    這些問題可能不僅僅在文字分類這個領域中出現,在其他的應用場景中也可能會出現。那麼,具體如何優化呢,我們做了八個實驗來解決問題:其中實驗五,實驗八是從資料層面來優化模型,其餘的都是從模型方面來優化

  • 實驗一:我們通過修改embedding_dim長度希望瞭解不同的向量維度對最後的實驗結果的影響,發現embedding_dim 降低到64會對最後結果有比較明顯的影響,下次要實驗一下embedding dim 到512 會不會對實驗結果有提升

  • 實驗二:在全連線層增加dropout 層,keep_rate = 0.7,隨機丟掉30%,來降低最後結果與A特徵相關性

  • 實驗三:在全連線層增加dropout 層,keep_rate = 0.5,隨機丟掉50%,來降低最後結果與A特徵相關性

  • 實驗四:只在資料預處理的時候,隨機去掉10%的A特徵,相比baseline 提升0.29%

  • 實驗五:對資料資料重取樣,在重取樣的時候,限制了部分query的權重,相比baseline 提升0.03%,目的是增加資料的多樣性,提升了0.03%

  • 實驗六:在實驗四的基礎上,隨機去掉20%的A特徵,相比baseline 提升0.28%, 並沒有優於隨機去掉10%,最終選擇隨機去掉10%A特徵

  • 實驗七:在實驗四的基礎上,統一來源,相比baseline 提升了0.64%

  • 實驗八:在實驗七的基礎上,將B特徵引入訓練,相比baseline 提升了1.14%

    大家不要覺得這些實驗很多覺得很麻煩,其實在實際工作中,通常來說,最有效的方法是:分析badcase,引入更有區分度的特徵,如果你的專案效果不好,再試試引入dropout等等。具體的引數如何調整,是根據具體的專案而定,但是不管如何優化,都要先跑baseline。在baseline的基礎上再進行優化。其次快速迭代實驗,做好實驗記錄也是非常有必要的

 

    希望這一次的優化經驗總結能對大家有所幫助,下一篇會給大家講解訓練好的textcnn模型如何部署上線,實際應用於工業場景