【學習筆記】text summary_4_oov和word repetition問題
OOV問題及其常用解決方法
什麼是oov問題?
在encoder-decoder結構中,需要通過固定的詞典對平行語料進行表示,詞典大小一般控制在30k-60k;因此希望減少詞表的大小,從而提高時間和空間效率。
同時還希望文字長度儘可能的短,因為文字長度的增加會降低效率並增加神經模型傳遞資訊所需的距離(LSTM),文字越長資訊丟失的可能性越大。這就導致了很多未登入詞(OOV)和罕見詞(Rare Words)。 另外,新詞每時每刻都可能被創造出來,這些新詞顯然也不在詞彙表中,也是屬於未登入詞的一種。
傳統解決方案
傳統方法在解決oov問題時,主要有:
- 增加詞典長度(enlarge vocabulary)
- 直接忽略(Ingore)
- UNK替代
該方法在一定程度上能夠消除oov的影響,但是作用非常的有限。尤其是在一些NLP任務中,OOV詞可能具有極重要的意義。例如,在情感分類問題中,OOV詞彙中可能包含表達positive或者negative的情感詞。 - 字元表示(Individual Characters)
- 特徵雜湊(Feature Hashing)
雜湊表示並不是特地為解決oov問題而設計的演算法。該方法引入到nlp解決oov問題,只是盲目的認為雜湊碰撞(hash collision)能在有些時候讓模型work。當前,很多時候,該方法能夠起到一定的作用。 - 拼寫檢查(spell check)
基於sub-word的解決方案
上述解決方案是一些比較古老的、傳統的解決方案;而隨著研究的加深,提出了一些基於子詞(sub word)的解決方案(當然,也已經不怎麼用)。
- 字詞生成(sub word generation)
對於一個詞來說,採取它長度為3-6的n-gram片語來表示該詞彙。
經過該處理後,可能得到大量(且唯一)的n-grams表示,因此進一步應用雜湊的方式,將其進行轉換
經過hash後的詞彙表,能將每一個n-gram表示為1-B之間的整數。
- BPE方法(Byte Pair Encoding)
step1.準備⾜夠⼤的訓練語料
step2.確定期望的subword詞表⼤⼩
step3.將單詞拆分為字元序列並在末尾新增字尾“ </ w>”,統計單詞頻率。本階段的subword的粒度是字元。 例如,“ low”的頻率為5,那麼我們將其改寫為“ l o w </ w>”:5
step4.統計每⼀個連續位元組對的出現頻率,選擇最⾼頻者合併成新的subword
step5. 重複第4步直到達到第2步設定的subword詞表⼤⼩或下⼀個最⾼頻的位元組對出現頻率為1 - WordPiece
step1.準備⾜夠⼤的訓練語料
step2.確定期望的subword詞表⼤⼩
step3.將單詞拆分成字元序列
step4.基於第3步資料訓練語⾔模型
step5.從所有可能的subword單元中選擇加⼊語⾔模型後能最⼤程度地
增加訓練資料概率的單元作為新的單元
step6.重複第5步直到達到第2步設定的subword詞表⼤⼩或概率增量低
於某⼀閾值 - Unigram Language Model
step1.準備⾜夠⼤的訓練語料
step2.確定期望的subword詞表⼤⼩
step3.給定詞序列優化下⼀個詞出現的概率
step4.計算每個subword的損失
step5.基於損失對subword排序並保留前X%。為了避免OOV,建議保留字元級的單元
step6.重複第3⾄第5步直到達到第2步設定的subword詞表⼤⼩或第5步的結果不再變化
基於指標生成網路的解決方案
當前較為主流解決oov問題的方法是基於指標生成的方法。因此,本位重點介紹該方法。
指標生成網路(Pointer Network Generate, PGN)是基於注意力機制和Pointer Network改進的產物。
注意力機制下的seq2seq模型
注意力機制及其在seq2seq模型發揮的作用,此處不再重述,在seq2seq模型中,已做更具體說明。大體流程圖如下:
注意力機制下的seq2seq模型可以關注原文字中的相關單詞,並依據概率分佈生成新單詞。
Pointer Network
Pointer network 實際上是Seq2Seq模型中encoder 和decoder的擴充套件,主要解決的問題是輸出的字典長度不固定問題(輸出序列的詞長度會隨著輸入序列長度的改變而改變的問題的)。
因此,引出了Pointer Network模型。這種網路結構和seq2seq模型相似,其不同點主要在於:1. 在序列到序列模型中,每一步的預測目標的種類是固定的,但是在 Ptr-Net 中是可變的;2. 在 Ptr-Net 中,通過注意機制來選擇(指向)輸入序列中的一個來作為輸出。即:它不預測輸出是什麼,而是預測輸出(decoder)應該對應輸入(encoder)所在的位置。
Pointer Network Generator
pointer network預測結果完全來在輸入,即encoder部分;而seq2seq模型的輸出,完全來自依據decoder的概率分佈,生成的內容。因此,Pointer Network Generator結合了兩個模型的長處,既具備seq2seq模型的生成能力,又具備Pointer Network的複製能力(複製原文詞彙)。其整體流程如下:
從流程圖中可以看出,該模型最終得到的概率分佈由兩部分構成:Attention分佈和詞彙表分佈,並做了加權平均。
如何權衡一個詞應該是生成的還是複製的?即由其權重\(P_{gen}\)和\(1 - P_{gen}\)共同決定。其中\(P_{gen}\)計算方法如下:
\(p_{gen} = \sigma(w_{h^*}^T h_t^* + w_s^Ts_t + w_x^Tx_t + b_{ptr})\)。其中,\(h^*\) \(s_t\)來自seq2seq模型的輸出。最終概率分佈表示如下:
\(P(w) = p_{gen}P_{vocab}(w) + (1 - p_{gen}) \sum_{i:w_i=w} a_i^t\)
其中 \(a_i^t\) 表示的是原文件中的詞。我們可以看到解碼器一個詞的輸出概率有其是否拷貝是否生成的概率和決定。當一個詞不出現在常規的單詞表上時 \(P_{vocab}(w)\) 為0,當該詞不出現在文件中\(\sum_{i:w_i=w} a_i^t\)為0。
repetition問題及解決方法
指標生成網路(Pointer-Generator-Network)的創新點主要由兩個方面:
- 該通過指向(pointer)從源文字中複製單詞,有助於準確地複製資訊,同時保留通過生成器產生新單詞的能力;
- 使用coverage機制來跟蹤已總結的內容,防止重複。
Coverage Mechanism
Coverage Mechanism是將先前時間步的注意力權重加到一起,得到所謂的覆蓋向量\(c_t\)(coverage vector)。用先前的注意力權重,來影響當前注意力權重的決策,這樣就避免在同一位置重複,從而避免重複生成文字。計算方法如下:
\(c^t = \sum_{t'=0}^{t-1}a^{t'}\)
最終得到的注意力權重計算方式如下:
\(e_i^t = v^T tanh(W_{h}h_i + W_{s}s_t + w_{c}c_i^t + b_{attn})\)
為coverage vector新增損失coverage loss,其計算方式為:
\(covloss_{t} = \sum_{i}min(a_i^t, c_i^t)\)
因此,最終的損失函式為:
\(loss_t = -logP(w_t^*) + \lambda \sum_{i}min(a_i^t, c_i^t)\)
文字摘要在工業中的應用案例
Multi-Source Pointer-Generator Network
該文主要關注電商平臺上的商品摘要的生成。這種摘要與傳統的句子摘要有一定的區別和侷限,即商品摘要無法容忍事實細節的錯誤或關鍵資訊的丟失。因此本文提出了商品摘要的兩個限制:
- 不介紹無關資訊
- 保留關鍵資訊(如品牌和商品名稱)
因此,作者在原PGN的基礎上,提出了帶新知識編碼器的多源指標網路來解決這個問題。
超引數調參及常用編碼經驗等問題
手動調參總結
編碼
• 將各個引數的設定部分集中在⼀起。如果引數的設定分佈在程式碼的各個地⽅,
那麼修改的過程想必會⾮常痛苦。
• 可以輸出模型的損失函式值以及訓練集和驗證集上的準確率
• 可以考慮設計⼀個⼦程式,可以根據給定的引數,啟動訓練並監控和週期性儲存評估結果。再由⼀個主程式,分配引數以及並⾏啟動⼀系列⼦程式。
復現
• 建議先參考相關論⽂,以論⽂中給出的引數作為初始引數。⾄少論⽂中的引數,是個不差的結果。
• 如果找不到參考,那麼只能⾃⼰嘗試了。可以先從⽐較重要,對實驗結果影響⽐較⼤的引數開始,同時固定其他引數,得到⼀個差不多的結果以後,在這個結果的基礎上,再調其他引數。例如學習率⼀般就⽐正則值,dropout值重要的話,學習率設定的不合適,不僅結果可能變差,模型甚⾄會⽆法收斂。
• 如果實在找不到⼀組引數讓模型收斂。那麼就需要檢查,是不是其他地⽅出了問題,例如模型實現,資料等等。
實驗加速
• 對訓練資料進⾏取樣。例如原來100W條資料,先採樣成1W,進⾏實驗看看。
• 減少訓練類別。例如⼿寫數字識別任務,原來是10個類別,那麼我們可以先在2個類別上訓練,看看結果如何。
HP Range
• 建議優先在對數尺度上進⾏超引數搜尋。
⽐較典型的是學習率和正則化項,我們可以從諸如0.001 0.01 0.1 1 10,以10為階數進⾏嘗試。因為他們對訓練的影響是相乘的效果。不過有些引數,還是建議在原始尺度上進⾏搜尋,例如dropout值: 0.3 0.5 0.7)。
實驗次數
• learning rate: 1 0.1 0.01 0.001, ⼀般從1開始嘗試。很少見learning rate⼤於10的。學習率⼀般要隨著訓練進⾏衰減。衰減係數⼀般是0.5。衰減時機,可以是驗證集準確率不再上升時,或固定訓練多少個週期以後。不過更建議使⽤⾃適應梯度的辦法,例如adam,adadelta,rmsprop等,這些⼀般使⽤相關論⽂提供的預設值即可,可以避免再費勁調節學習率。對RNN來說,有個經驗,如果RNN要處理的序列⽐較長,或者RNN層數⽐較多,那麼learning rate⼀般⼩⼀些⽐較好,否則有可能出現結果不收斂,甚⾄Nan等問題。
• ⽹絡層數: 先從1層開始。
• 每層結點數: 16 32 128,超過1000的情況⽐較少見。超過1W的從來沒有見過。
• batch size: 128上下開始。batch size值增加,的確能提⾼訓練速度。但是有可能收斂結果變差。如果視訊記憶體⼤⼩允許,可以考慮從⼀個⽐較⼤的值開始嘗試。因為batch size太⼤,⼀般不會對結果有太⼤的影響,⽽batch size太⼩的話,結果有可能很差。
• clip c(梯度裁剪): 限制最⼤梯度,其實是value = sqrt(w12+w22….),如果value超過了閾值,就算⼀個衰減繫系數,讓value的值等於閾值: 5,10,15
• dropout: 0.5
• L2正則:1.0,超過10的很少見。
• 詞向量embedding⼤⼩:128,256
• 正負樣本⽐例: 這個是⾮常忽視,但是在很多分類問題上,又⾮常重要的引數。很多⼈往往習慣使⽤訓練資料中預設的正負類別⽐例,當訓練資料⾮常不平衡的時候,模型很有可能會偏向數⽬較⼤的類別,從⽽影響最終訓練結果。除了嘗試訓練資料預設的正負類別⽐例之外,建議對數⽬較⼩的樣本做過取樣,例如進⾏複製。提⾼他們的⽐例,看看效果如何,這個對多分類問題同樣適⽤。
• 在使⽤mini-batch⽅法進⾏訓練的時候,儘量讓⼀個batch內,各類別的⽐例平衡,這個在影象識別等多分類任務上⾮常重要。
loss不下降問題
• train loss 不斷下降,test loss不斷下降,說明⽹絡仍在學習;
• train loss 不斷下降,test loss趨於不變,說明⽹絡過擬合;
• train loss 趨於不變,test loss不斷下降,說明資料集100%有問題;
• train loss 趨於不變,test loss趨於不變,說明學習遇到瓶頸,需要減⼩學習率或批量數⽬;
• train loss 不斷上升,test loss不斷上升,說明⽹絡結構設計不當,訓練超引數設定不當,資料集經過清洗等問題
自動調參
窮舉搜尋
代理模型(surrogate model)
工具
tensorflow自動調參參考
pytorch自動調參參考
autoML 平臺
https://github.com/tensorflow/adanet
https://github.com/h2oai/h2o-3