大模型如火如荼的今天,不學點語言模型(LM)相關的技術實在是說不過去了。只不過由於過往專案用到LM較少,所以學習也主要停留在直面——動眼不動手的水平。Huggingface(HF)也是現在搞LM離不開的工具了。
出於專案需要,以及實踐出真知的想法,在此記錄一下第一次使用HF和微調ERNIE-gram的過程。
- 開始的開始
- 模型選擇
- 如何使用選好的模型
- 怎麼微調
- 模型定義
- 訓練流程
- 參考
開始的開始
HF已經做的很好了。但是對於第一次上手實操LM的我來說,還是有點陌生的。上手時有幾個問題是一直困擾我的:
- HF上這麼多模型,我該用哪一個?
- 每個LM的主要作用是對文字進行Embedding,可我的任務是句子對相似性計算,這該怎麼搞?
- 我想在自己的資料上繼續微調模型,該怎麼做?
模型選擇
簡單描述一下我的任務:給定兩個句子,判斷兩個句子的語義是否等價
。
從NLP的角度出發,這是一類STS(Semantic Textual Similarity)任務,本質是在比較兩個文字的語義是否相似。透過檢索,找到了一些相關的比賽,例如問題匹配的比賽和相關的模型,這裡簡單羅列一下:
- 千言資料集:問題匹配魯棒性。
- 千言-問題匹配魯棒性評測基線。
- Quora Question Pairs。
- ATEC學習賽:NLP之問題相似度計算。
- 第三屆魔鏡杯大賽—— 語義相似度演算法設計。
- LCQMC通用領域問題匹配資料集。
- [Chinese-BERT-wwm]。
透過以上資料,我大致確定了我要使用的模型——ERNIE-Gram[1]。
如何使用選好的模型
首先,我找到了ERNIE-Gram的程式碼倉庫[2]。程式碼裡開源了模型的結構以及微調的程式碼,相對來說還是比較齊全的。但是有一個最不方便的地方——它是用飛漿寫的(不是說飛漿不好,只是一直以來都用pytorch)。當然,很快我又找到了pytorch版的ERNIE-Gram,並且在HF找到了ERNIE-Gram模型。如果我知道怎麼使用HF,那麼或許我可以很快開始我的微調了,可惜沒有如果。
那怎麼使用HF上的模型,在自己的資料上進行微調呢?
找到了一篇比較合適的參考資料[3],其中介紹瞭如何在HF中呼叫ERNIE模型:
from transformers import BertTokenizer, ErnieModel
tokenizer = BertTokenizer.from_pretrained("nghuyong/ernie-1.0-base-zh")
model = ErnieModel.from_pretrained("nghuyong/ernie-1.0-base-zh")
根據這個,我發現透過HF使用某個模型的方法是從transformers
庫中匯入對應的模型和工具即可。那麼,我只需要找到對應的模型名和工具,然後以此作為基座,再新增一些可訓練層就可以了?
分析dir(transformers)
看看都有哪些和Ernie相關的類:
d = dir(transformers)
dd = [e for e in d if 'ernie' in e.lower()]
len(dd) # 26
print(dd)
# ====
['ERNIE_M_PRETRAINED_CONFIG_ARCHIVE_MAP', 'ERNIE_M_PRETRAINED_MODEL_ARCHIVE_LIST', 'ERNIE_PRETRAINED_CONFIG_ARCHIVE_MAP', 'ERNIE_PRETRAINED_MODEL_ARCHIVE_LIST', 'ErnieConfig', 'ErnieForCausalLM', 'ErnieForMaskedLM', 'ErnieForMultipleChoice', 'ErnieForNextSentencePrediction', 'ErnieForPreTraining', 'ErnieForQuestionAnswering', 'ErnieForSequenceClassification', 'ErnieForTokenClassification', 'ErnieMConfig', 'ErnieMForInformationExtraction', 'ErnieMForMultipleChoice', 'ErnieMForQuestionAnswering', 'ErnieMForSequenceClassification', 'ErnieMForTokenClassification', 'ErnieMModel', 'ErnieMPreTrainedModel', 'ErnieMTokenizer', 'ErnieModel', 'ErniePreTrainedModel', 'models.ernie', 'models.ernie_m']
為了更好了解每個類是幹啥的,直接上transformers
庫來看各個類的介紹[4]。很快啊,我就發現ErnieForSequenceClassification
很適合我的任務:
圖中的GLUE(General Language Understanding Evaluation )[5]是一系列評測任務集合,顯然,我的任務屬於Similarity那一類。
很好,大致可以確定該怎麼使用HF上的Ernie-Gram模型來完成我的任務了(可惜沒有對應的示例)。
怎麼微調
在實操之前,對於在預訓練好的模型上進行微調,我的想法是:把預訓練模型包起來,新增一個分類層,學習分類層的引數就可以了。
但是如果我選擇了ErnieForSequenceClassification
,透過原始碼可以發現該類其實是在ErnieModel
的基礎上新增了一個分類層,那我是否直接載入模型後,選擇訓練哪些引數就可以了呢?
其實,廣義的來說,這等價於一個問題:在HuggingFace中如何微調模型?[6][7][8]。
其實,微調和平常的模型訓練沒有太大區別,只不過需要載入預訓練好的模型,以及利用現成的工具搭建訓練流程,其中主要涉及到的就兩點:模型的定義、訓練流程的搭建。
模型定義
由於transformers
中已經定義好了很多模型,如果某個完全符合要求,那就可以直接使用了。根據自己的需求,選擇凍結和訓練哪些引數就可以了。
但是有些時候只是用預訓練的模型作為自己模型的一部分,這個時候就需要我們做一些額外的工作了——把預訓練模型作為一塊積木,搭建我們自己的模型。正如ErnieForSequenceClassification
所做的一樣。
訓練流程
訓練流程類似。可以重頭自己搭建訓練流程,或者使用transformes
自帶的Trainer
介面。
這裡直接參考HF的教程即可:Fine-tuning a model with the Trainer API、自己搭建訓練流程。
參考
ERNIE-Gram: Pre-Training with Explicitly N-Gram Masked Language Modeling for Natural Language Understanding, NAACL-HLT, 2021. ↩︎
ernie-gram. ↩︎
試試在transformers中呼叫ERNIE. ↩︎
Hugging Face Ernie Doc`` ↩︎
GLUE: A MULTI-TASK BENCHMARK AND ANALYSIS PLATFORM FOR NATURAL LANGUAGE UNDERSTANDING, ICLR, 2019. ↩︎
Hugging Face 的 Transformers 庫快速入門(四):微調預訓練模型. ↩︎
HuggingFace | 在HuggingFace中如何微調模型. ↩︎
FINE-TUNING A PRETRAINED MODEL. ↩︎