這個系列會針對NLP比賽,經典問題的解決方案進行梳理並給出程式碼復現~也算是找個理由把程式碼從TF搬運到torch。Chapter1是CCF BDC2019的賽題:金融資訊負面及主體判定,屬於實體關聯的情感分類任務,相關程式碼實現以及Top方案梳理詳見ClassisSolution/fin_new_entity。資料lookalike如下
賽題本身已經對金融網路文字進行了實體抽取,跳過了金融實體抽取的步驟,只需要對已抽取出的實體判斷文字是否描述了該金融實體的負面資訊。只看問題本身和屬性級情感分類問題有些類似,例如電商領域需要從評論中抽取產品多個屬性各自的正負面評價,像價格[低]但是質量[差],可以得到價格和質量兩個屬性分別的正面和負面情緒。不過難點上有所不同,屬性情感識別上,不同屬性的評價詞會有比較顯著的差異,在金融實體中,因為實體本身多是並列關係,需要學習更復雜的上下文差異。
比賽的效果評估採用綜合F1,分別計算句子級別的情感分類F1和實體級別的F1。整體任務F1=0.4句子F1+0.6實體F1。不過官網已經不能提交測試集評估,因此下面方案嘗試我從訓練集切了20%的樣本來做效果評估
梳理了下Top方案的差異,主要在以下幾個方面:預處理,實體處理方式,多工,繼續預訓練
文字是爬取的新聞,html標籤比較多。不過不是抽取類任務所以我只過濾了一些高頻的標籤和pattern,沒有做的非常細緻,在分類任務上基本不會有太大的影響。
def text_preprocess(s):
if not s:
return s
s = full2half(s)
s = re.sub('\{IMG:.?.?.?\}', ' ', s) # 圖片
s = re.sub(re.compile(r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'), ' ', s) # 網址
s = re.sub(re.compile('<.*?>'), '', s) # 網頁標籤
s = re.sub(r'&[a-zA-Z0-9]{1,4}', ' ', s) #   > &type &rdqu ....
s = re.sub('^\?+', '', s) # 問號開頭直接刪除
s = re.sub('\?{2,}', ' ', s) # 中間出現多餘1個問號用空格替代
s = re.sub('^#', '', s) # 井號開頭直接刪除
s = re.sub('#+', ' ', s) # 井號在中間用空格分隔
s = re.sub('\[超話\]', ' ', s) # 超話刪除
return s
長文書處理一般是截斷,段落或者句子過Encoder再在上游融合。因為要預測實體是否負面,主需要保留實體周圍的上下文即可。並且賽題文字中有部分是前半段講實體1,後半段講實體2,且情緒不同,如果使用全文字預測反而會增加混淆度。因此選擇根據實體位置進行文字截斷,定位實體首次出現的位置,如果位置>max_seq_len,則擷取實體周圍的上下文作為樣本。這裡我直接簡單粗暴地擷取了前後250個字,更優的方案還是按句子切分,定位到實體出現的句子,擷取前後的完整句子,保證語意的通順,在實體發現的案例中我做了這種處理。
相比直接拼接標題和正文,可以針對標題和正文的重合度(編輯距離),判斷標題是否有資訊補充,如果沒有可以選擇只保留正文。我嘗試後對效果影響不大,不過會適當降低文字長度,以及優化文字的語意通順度。在醫療文字分類中,處理患者主訴,和醫生病例文字時嘗試過這個方案,會有一定的效果提升
雖然問題本身看起來很像一個pipeline問題,先判斷句子是否負面,再定位負面句子中哪些實體為負面。但其實可以被簡化成一個屬性(實體)情感分類問題,只需要對樣本進行下重構,把一條文字中每個實體是否負面的判別問題,拆分成多條樣本,每個樣本只預測一個實體是否負面。當預測一個實體時,文字中其他實體屬於伴隨實體。方案的主要差異在於如何處理待預測實體和伴隨實體
都是實體,為什麼需要區別對待呢?
個人認為待預測實體比伴隨實體更需要學到'負面實體出現的上下文'這個資訊,而伴隨實體的作用更多是提示模型這些span本身是實體,也就是金融領域知識的引入。兩種待預測實體的標識方案,效果上差不多,我更傾向於特殊標識的方案,因為這個方案能引入更多的位置資訊。兩種伴隨實體的處理方案中,把伴隨實體作為一路輸入的效果更好,所以我感覺伴隨實體的span資訊更重要,降低對預測實體的影響這一點可能沒有那麼重要。
方案 | F1_entity | F1_sentence | F1 |
---|---|---|---|
Format1:雙輸入,1為待預測實體,2為title+text,伴隨實體用[O]替換 | 93.8% | 94.5% | 94.1% |
Format2:單輸入,title+text, 用[E]標記待預測實體,伴隨實體用[O]替換 | 93.5% | 94.6% | 93.9% |
Format3:雙輸入,1為伴隨實體拼接,2title+text,帶預測實體用[E]標記 | 94.5% | 95% | 94.7% |
雖然把pipeline任務簡化成了屬性分類,但是句子級別的情感資訊依舊是建模中可以嘗試引入的優化點。如果能識別句子非負則實體全部非負,如果句子為負則實體為負的概率更高。因此可以嘗試引入更簡單的句子級別的情感分類作為一路輔助任務。句子和實體共用文字Encoder,同時各自的頭分別學習各自的label,效果上句子級別的F1提升比較明顯。
方案 | F1_entity | F1_sentence | F1 |
---|---|---|---|
Format3:雙輸入,1為伴隨實體拼接,2title+text,帶預測實體用[E]標記 | 94.5% | 95% | 94.7% |
Format4: Format3基礎上加入多工同時學習實體+句子負面 | 94.8% | 95.5% | 95.1% |
在Bert手冊中Bert不完全手冊8. 預訓練不要停!Continue Pretraining我們聊過繼續預訓練正規化。考慮賽題本身是金融領域,因此可以嘗試用任務樣本繼續預訓練(TAPT)來進行效果優化。
不過這裡和原始論文不同的是,我調整了繼續預訓練的任務目標。把樣本中抽取出來的實體詞加入了分詞器,在Whole Word MASK的基礎上補充了金融實體粒度的詞資訊,進行實體和全詞掩碼的繼續預訓練,訓練了10個epoch。然後再進行以上的多工學習,整體還會有微小0.1個點的F1提升,這個提升我懷疑是波動哈哈哈....畢竟樣本這麼小,你想要啥自行車~
方案 | F1_entity | F1_sentence | F1 |
---|---|---|---|
Format4: Format3基礎上加入多工同時學習實體+句子負面 | 94.8% | 95.5% | 95.1% |
Format5:Format4基礎上加入TAPT | 95.0% | 95.6% | 95.2% |
除此之外top方案中還有MRC之類的方案,我們在其他的多分類任務中再做嘗試。這裡的方案梳理更多是對模型結構,建模正規化,資料處理方案的討論,像Ensemble,不同預訓練模型選擇一類的細節,大家感興趣可以去看Repo中梳理的Top方案~