LUSE: 無監督資料預訓練短文字編碼模型
1 前言
本博文字應寫之前立的Flag:基於加密技術編譯一個自己的Python直譯器,經過半個多月嘗試已經成功,但考慮到安全性問題就不公開了,有興趣的朋友私聊討論吧。
從本篇部落格開始,本人將轉化寫作模式,由話癆模式轉為極簡模式,力求三言兩語讓各位看的明白。
2 工作簡介
受到MOCO和SimCSE的啟發, 基於自監督,使用海量無監督資料(nlp_chinese_corpus),預訓練了一個專門用於短文字表徵的編碼器。該編碼器在分類任務尤其是短文字相似度任務上效果超過同級別BERT模型。該預訓練模型暫且叫LUSE.
本次實驗結果是僅在預訓練0.1輪(10萬步)情況下得到的,完全訓練後會得到更強的效果。
三層預訓練模型(torch)下載地址:
-
百度網盤:https://pan.baidu.com/s/1Do3ojovAe7VviSXdsk4mQQ 提取碼:luse
-
和彩雲(不限速): https://caiyun.139.com/m/i?1A5ChPLNDFGuW 提取碼:tFK0
程式碼地址: https://github.com/DunZhang/LUSE
預處理後的nlp_chinese_corpus下載地址: https://pan.baidu.com/s/11ddgvZ7QAbIlliJgUiau9g 提取碼:luse
使用方法:和正常BERT一樣載入使用,使用CLS作為句表徵。text_vec = transformers.BertModel()(input_id,attention_mask,token_type_ids)[1]
3 演算法詳情
演算法虛擬碼如下:
Input: sens: List[str], sen_encoder: torch.nn.Module
Output: None
aug_sens = data_augment(sens) # 資料增強, 每個句子均會增強固定數量相似句做為正例,剩餘所有句子則為負例
sens_vecs = sen_encoder.forward(sens+aug_sens) # 將所有句子編碼為句向量
scores = compute_score(sens_vecs) # 計算所有向量間的相似度值
loss = multi_positive_multi_negative_func(scores) # 基於相似度值計算loss
update(sen_encoder,loss) # 更新模型權重
3.1 資料增強
本人將資料增強分為兩類, text-level和vector-level.
text-level:字詞句層面的資料增強, 本演算法使用EDA
vector-level:句編碼層面的資料增強,可參考影像, 本演算法只使用隨機裁剪,對應NLP操作為置0,即dropout操作, SimCSE就是該方法. CV與NLP的完美融合!!!
3.2 損失函式
對於一個句子,自身和其增強而來的句子為正例,其他句子及其增強為負例. 優化目標為讓這些正例的概率最高,如果有n個正例,那麼希望這n個正例概率都很高,那就索性平分概率值1得了,讓其他負例概率都為0, 這其實就是均值不等式. 詳細推導公式和程式碼實現見本人部落格:一種基於均值不等式的Listwise損失函式
3.3 預訓練資料
預訓練資料為brightmart開源的nlp_chinese_corpus. 本人只做簡單分句和去除空白字元兩種清洗操作.然後將所有語料庫所有句子完全打散作為訓練集.最終約有1.1億個句子
3.4 訓練細節
batch_size為128, 每個句子增強8個相似問(4個EDA, 4個dropout),因此每個句子有9(8+1)個正例和(9*128-9)個負例,這變相擴大了batch_size, 也正是此原因, 本人未使用MOCO的負例佇列來增大batch_size. 忍不住再誇一波MOCO負例佇列的精巧設計,何凱明yyds.
優化器為Adam, 學習率5e-5,最大長度64(本模型只考慮短文字),短文字表徵的pooling_mode為CLS向量,有興趣的可以使用SentenceBERT, BERT-Whitening 和 SimCSE的pooling方式, 本開源專案已經提供程式碼.
GPU是租了一塊RTX3090,訓練了兩天兩夜,約12萬步,即1500萬個句子,離1.1億差的遠了,更別提多epoch了. 中途還遇上伺服器當機,不得不載入以前的模型重新訓練, 真是倒了血黴. 共花了約150塊大洋,要是訓練完一輪非得傾家蕩產不可,這就是隻預訓練三層模型且0.1輪的原因.
3.5 小技巧:同義詞搜尋加速
EDA裡最耗時操作為選取同義詞, 本人使用騰訊800萬詞向量, 使用gensim選取同義詞速度比訓練還慢, 對於窮逼是無法接受.
解決方案: 預快取同義詞詞典, 計算同義詞時不要用gensim庫, 使用faiss或milvus向量加速庫, 本人在不使用GPU的情況下僅耗時一夜就完成了快取. 句向量加速指南可以看我的部落格:[milvus和faiss安裝及其使用教程]. 或者直接用我計算好的也行,本人能開源的都開源了,就是希望有算力的同志把我的方法跑一波.
4 微調驗證
作為預訓練模型,總需要微調來證明效果的.
4.1 資料集
4個分類資料集:
資料集 | #Trian | #Dev | 任務型別 | 參考連結 |
---|---|---|---|---|
NLPCC情感分類 | 8000 | 2000 | 2分類 | https://www.luge.ai/ |
微博情感分類 | 99988 | 20000 | 2分類 | https://github.com/SophonPlus/ChineseNlpCorpus |
購物網站評論情感分類 | 52774 | 10000 | 2分類 | https://github.com/SophonPlus/ChineseNlpCorpus |
今日頭條新聞分類 | 53360 | 10000 | 15分類 | https://github.com/CLUEbenchmark/CLUE |
6個相似度資料集:
資料集 | #Train | #Dev | 參考連結 |
---|---|---|---|
LCQMC(哈工大通用聊天資料集) | 238766 | 8802 | http://icrc.hitsz.edu.cn/Article/show/171.html |
ADAT(基於Adversarial Attack的問題等價性判別比賽資料集) | 36210 | 9027 | / |
ATEC(螞蟻金服相似度資料集) | 81981 | 20496 | / |
CHIP(平安醫療中文的疾病問答資料) | 16000 | 4000 | / |
COVID(新冠句對) | 8747 | 2001 | https://aistudio.baidu.com/aistudio/datasetdetail/48492 |
CCKS(微眾銀行智慧客服問句匹配大賽) | 80000 | 20000 | / |
沒有連結的資料集可以自行搜尋, 由於微調資料集可能設計到一些版權問題, 開源專案裡就不再放出.
為了簡化操作只使用dev評估.
4.2 微調方法
對於分類資料集,使用交叉熵微調
對於相似度資料集,由於預訓練模型為短文字編碼器, 將兩個句子一起輸入做0/1分類是不合適的. 做法是單獨對兩個句子進行編碼,計算餘弦相似度並歸一化至0-1之間作為概率值, 然後最大似然求解.
同時考慮到低計算資源情況, 訓練又分為全部微調和固定bert訓練上層神經網路兩種.
4.3 評價指標
分類資料集使用ACC和F1
相似度資料集使用Spearman相關係數
4.4 基線模型
哈工大的RBT3
4.4 實驗結果
分類實驗結果(ACC / F1):
NLPCC情感分類 | 微博情感分類 | 購物網站評論情感分類 | 今日頭條新聞分類 | |
---|---|---|---|---|
ACC / F1 | ACC / F1 | ACC / F1 | ACC / F1 | |
RBT3-TrainBERT | 0.786 / 0.784 | 0.979 / 0.979 | 0.945 / 0.945 | 0.554 / 0.538 |
LUSE-TrainBERT | 0.791 / 0.789 | 0.979 / 0.979 | 0.944 / 0.944 | 0.556 / 0.541 |
RBT3-FreezeBERT | 0.720 / 0.720 | 0.864 / 0.864 | 0.873 / 0.873 | 0.445 / 0.416 |
LUSE-FreezeBERT | 0.740 / 0.740 | 0.804 / 0.804 | 0.888 / 0.888 | 0.482 / 0.460 |
文字相似度實驗結果(Spearman):
ADAT | ATEC | CCKS微眾銀行 | CHIP | COVID | LCQMC | |
---|---|---|---|---|---|---|
RBT3-TrainBERT | 0.633 | 0.086 | 0.785 | 0.624 | 0.703 | 0.642 |
LUSE-TrainBERT | 0.636 | 0.210 | 0.796 | 0.634 | 0.692 | 0.650 |
RBT3-FreezeBERT | 0498 | 0.070 | 0.432 | 0.308 | 0.507 | 0.280 |
LUSE-FreezeBERT | 0.556 | 0.200 | 0.675 | 0.527 | 0.653 | 0.497 |
行名解釋, RBT3代表使用的是哈工大的RBT3模型,LUSE代表本人預訓練的模型.
TrainBERT代表微調時整體訓練耗時但效果好, FreezeBERT代表凍結BERT訓練上層神經網路,省時省力但效果差些.
實驗結論: 專門針對短文字編碼預訓練的模型確實可以取得更好的效果, 尤其是在短文字相似度任務上
5 總結
LUSE模型是一個優缺點非常明顯的模型, 成也預訓練任務敗也預訓練任務.
LUSE模型在需要進行短文字編碼的任務上能取得較好的效果,即便只訓練了0.1輪,效果也很明顯.
但是缺點同樣突出, 由於其預訓練任務, 使其適用場景變得很小, 在其他任務上LUSE怕是無能為力了, 估計在二分類的短文字相似度任務上,LUSE都未必效果好,後續可以做實驗看下.
即便如此, 本人構想還是對的,基於無監督資料, 藉助對比學習, 還是可以預訓練出優質文字編碼模型的, 挺好奇為什麼SimCSE的作者不預訓練一個文字編碼模型.
影像的好多東西都可以借鑑到NLP中,NLPer需要定期關注影像領域的最新進展.
6 TODOList
- MOCO負例佇列或許可以一試
- 能否基於GAN做vector-level的資料增強
- 使用百GB級別資料預訓練一次大模型
- 和MLM-Loss做交叉訓練
- 文字相似度微調模型可以嘗試Sentence-BERT的方式
- alignment和uniformity驗證無監督句向量效果
7 FAQ
Q: 為什麼就放出了一個沒完全訓練的小模型?
A: 窮
Q: 後續還會放出新的預訓練模型嗎?
A: 會的, 一定會的. 該預訓練任務本人會一直嘗試下去的, 但是要等到顯示卡回落到正常價格之後(萬惡的虛擬貨幣)
Q: 與simbert以及RoFormer-sim相比如何?
A: 沒有可比性,有監督對無監督就是降維打擊. 中文資料任務完全可以用SimBERT替代LUSE預訓練模型.
Q:接上一問題,那LUSE預訓練模型的意義何在呢?
A:如果沒有有監督資料怎麼辦?如果資料脫敏了怎麼辦? 本文主要探索無監督資料預訓練短文字編碼模型的可能性.
Q:EDA和dropout資料增強,那個更有用?
A:沒錢做消融實驗了,中庸了, 兩個都用. 個人猜測兩個都起正面作用, dropout可能會更強些, 畢竟simcse論文效果很好
Q:為什麼實驗結果的好多F1和ACC一樣了?
A:其實不一樣,只是取了前三位恰好一樣罷了
8 致謝
特別感謝 資料集nlp_chinese_corpus, 沒有資料集一切免談.
還要感謝SimCSE和MOCO,正是這兩篇論文激發本人嘗試LUSE的興致.