那個屠榜的T5模型,現在可以在中文上玩玩了

PaperWeekly發表於2020-11-17

不知道大家對 Google 去年的屠榜之作 T5 還有沒有印象?就是那個打著“萬事皆可 Seq2Seq”的旗號、最大搞了 110 億引數、一舉重新整理了GLUE、SuperGLUE 等多個 NLP 榜單的模型,而且過去一年了,T5 仍然是 SuperGLUE [1] 榜單上的第一,目前還穩妥地拉開著第二名 2% 的差距。

然而,對於中文界的朋友來說,T5 可能沒有什麼存在感,原因很簡單:沒有中文版 T5 可用。不過這個現狀要改變了,因為 Google 最近放出了多國語言版的 T5(mT5),裡邊當然是包含了中文語言。雖然不是純正的中文版,但也能湊合著用一下。

那個屠榜的T5模型,現在可以在中文上玩玩了

▲ “萬事皆可Seq2Seq”的T5

本文將會對 T5 模型做一個簡單的回顧與介紹,然後再介紹一下如何在 bert4keras 中呼叫 mT5 模型來做中文任務。作為一個原生的 Seq2Seq 預訓練模型,mT5 在文字生成任務上的表現還是相當不錯的,非常值得一試。

一、T5

跟 BERT 一樣,T5 也是 Google 出品的預訓練模型,來自論文為 Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer,程式碼已開源。T5的理念就是“萬事皆可 Seq2Seq”,它使用了標準的 Encoder-Decoder 模型,並且構建了無監督/有監督的文字生成預訓練任務,最終將效果推向了一個新高度。

論文標題:

Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer

論文連結:

https://arxiv.org/abs/1910.10683

程式碼連結:

https://github.com/google-research/text-to-text-transfer-transformer

1.1 訓練

T5 的預訓練包含無監督和有監督兩部分。無監督部分使用的是 Google 構建的近 800G 的語料(論文稱之為 C4),而訓練目標則跟 BERT 類似,只不過改成了 Seq2Seq 版本,我們可以將它看成一個高階版的完形填空問題:

輸入:明月幾時有,[M0] 問青天,不知 [M1],今夕是何年。我欲[M2]歸去,唯恐瓊樓玉宇,高處 [M3];起舞 [M4] 清影,何似在人間。 

輸出:[M0] 把酒 [M1] 天上宮闕 [M2] 乘風 [M3] 不勝寒 [M4] 弄

而有監督部分,則是收集了常見的 NLP 監督任務資料,並也統一轉化為 SeqSeq 任務來訓練。比如情感分類可以這樣轉化:

輸入:識別該句子的情感傾向:這趟北京之旅我感覺很不錯。

輸出:正面

主題分類可以這樣轉化:

輸入:下面是一則什麼新聞?八個月了,終於又能在賽場上看到女排姑娘們了。

輸出:體育

閱讀理解可以這樣轉化:

輸入:閱讀理解:川普與拜登共同競選下一任美國總統。根據上述資訊回答問題:川普是哪國人?

輸出:美國

可以看到,這種轉化跟 GPT2、GPT3、PET 的思想都是一致的,都是希望用文字把我們要做的任務表達出來,然後都轉化為文字的預測,讀者還可以翻看舊作必須要GPT3嗎?不,BERT的MLM模型也能小樣本學習瞭解相關內容。

總的來說,在我們的內部實驗裡邊,模型夠大、資料夠多以及有監督預訓練都是 T5 成功的關鍵因素,“萬事皆可 Seq2Seq ”則提供了有效地融合這些關鍵因素的方案。

1.2 結果

T5 的主要戰績彙總如下表:

那個屠榜的T5模型,現在可以在中文上玩玩了

▲ T5的戰績彙總

除了屠了多個榜單之外,T5 還對整個訓練流程中很多可調的超引數都除錯了一遍,比如模型架構究竟用標準的 Encoder-Decoder 好還是 UniLM 那種結構好,無監督預訓練任務究竟是 BERT 的方式好還是其他方式好,隨機 Mask 的比例是不是 15% 最好,等等。

最後給出瞭如下的表格,並還很遺憾地表達了一句“其實我們覺得 T5 的實驗做得還不是很充分”,頗有一種“走別人的路,讓別人無路可走”的感覺。當然,不管怎樣,這些煉丹結果還是值得每一位要做語言模型的同學好好看看,或許能讓我們少走一些彎路。

那個屠榜的T5模型,現在可以在中文上玩玩了

▲ T5那鉅細無遺的“煉丹寶典”(點選可以看大圖)

二、mT5

至於 mT5,即 Multilingual T5,T5 的多國語言版,出自最近的論文 mT5: A massively multilingual pre-trained text-to-text transformer,程式碼已開源。這也是將多語種 NLP 任務的榜單推到了一個新高度了。當然,對我們來說,最重要的是 mT5 裡邊包含了中文,因此我們終於有機會在中文任務中嘗試下 T5 了。

論文標題:

mT5: A massively multilingual pre-trained text-to-text transformer

論文連結:

https://arxiv.org/abs/2010.11934

程式碼連結:

https://github.com/google-research/multilingual-t5

2.1 T5.1.1

總的來說,mT5 跟 T5 一脈相承的,整體基本一樣,但在模型結構方面,mT5 用的是 T5.1.1方案,在此對它做個基本的介紹。

很多人都不知道的是,自從在去年 10 月釋出後,T5 在今年還經歷了一次低調的小升級,具體細節可以檢視 Github [2] 連結,官方把升級前的 T5 稱為 T5.1.0,而升級後的叫做 T5.1.1。

它主要的改動來自論文 GLU Variants Improve Transformer [3],主要是借用了Language Modeling with Gated Convolutional Networks [4] 的 GLU(Gated Linear Unit)來增強 FFN 部分的效果。具體來說,原來 T5 的 FFN 為(T5 沒有 Bias):

那個屠榜的T5模型,現在可以在中文上玩玩了

現在改為了:

那個屠榜的T5模型,現在可以在中文上玩玩了

也就是把 relu 啟用的第一個變化層改為了 gelu 啟用的門控線性單元,這樣 FFN 層增加了 50% 引數,但是從論文效果看效果明顯增加。

此外,T5.1.1 還對 Embedding 層做了改動,原來在 T5.1.0 中,Encoder 和 Decoder 的Embedding 層、Decoder 最後預測機率分佈的 Softmax 層都是共享同一個 Embedding 矩陣的。

現在 T5.1.1 只讓 Encoder 和 Decoder 的 Embedding 層共享,而 Decoder 最後預測機率分佈的 Softmax 層則用了一個獨立的 Embedding 矩陣,當然這會讓引數量大大增加,但 Google 的結論說這樣做效果會更好,其結論被總結在最近的論文Rethinking embedding coupling in pre-trained language models [5] 中。還有最後一點改動,T5.1.1 在預訓練階段去掉了 Dropout,而只有在下游微調階段才使用 Dropout

經過這些調整後,Google 重新訓練並開放了全系列的 T5.1.1 模型,其下載地址可以在剛才的 Github 連結找到,注意 T5.1.1 只做了無監督預訓練,但效果依然相當出色。由於 T5.1.1 提升明顯,所以 mT5 也就繼續使用了 T5.1.1 結構了

2.2 結果

mT5 其實就是重新構建了多國語言版的資料集 mC4,然後使用 T5.1.1 方案訓練了一波,技術路線上沒有什麼明顯的創新。關於訓練細節,大家觀察下原論文就好,論文其實也不長,畢竟 T5 已經把路都給鋪好了。

至於 mT5 的戰績,主要就是集中在下面這張表內了:

那個屠榜的T5模型,現在可以在中文上玩玩了

▲ mT5的“戰績”

讀者可能會有疑問,這種多國語言版的該用什麼方式評測?簡單的話,我們可以直接在此基礎上 finetune 一個跨語種的機器翻譯任務,看看效果的提升。

但事實上,對於多國語言版模型,研究人員更關心的是它在跨語種任務上的 Zero Shot 表現,說白了,就是同一種任務,在一個語種上進行 finetune,其模型能不能直接用於其餘語種?這也是上圖中“Cross-lingual zero-shot transfer(models fine-tuned on English data only)”的含義了,可以看到,mT5 的表現還是相當出色的。

三、實踐

終於到了大家喜聞樂見的實踐時間了,這裡我們簡單介紹一下在 bert4keras 上使用 mT5 模型來做中文文字生成任務的流程和技巧。bert4keras 從 0.9.1 版本開始支援呼叫 mT5 模型,如果要進行下述實驗的讀者,請先將 bert4keras 升級到 0.9.1 版或以上。

Github連結:

https://github.com/bojone/t5_in_bert4keras

## 基本

用bert4keras把mT5模型載入到keras中的基本程式碼為:

# 模型路徑
config_path = '/root/kg/bert/mt5/mt5_small/t5_config.json'
checkpoint_path = '/root/kg/bert/mt5/mt5_small/model.ckpt-1000000'
spm_path = '/root/kg/bert/mt5/sentencepiece.model'

# 載入分詞器
tokenizer = SpTokenizer(spm_path, token_start=None, token_end='</s>')

# 載入模型
t5 = build_transformer_model(
    config_path=config_path,
    checkpoint_path=checkpoint_path,
    model='t5.1.1',
    return_keras_model=False,
    name='T5',
)

encoder = t5.encoder
decoder = t5.decoder
model = t5.model

可以看到跟在 bert4keras 中載入 BERT 沒太大區別,其中 t5_config.json 的構建了 model.ckpt-1000000 的下載在 Github 上有詳細介紹,大家請移步去看。完整程式碼(訓練和解碼細節)在 Github 上也可以找到,這裡就不展開了。

值得一提的是,對於中文來說,tokenizer 給出的結果是帶有詞的,即對於中文來說 mT5 是以詞為單位的,只不過詞顆粒度會比較少。這進一步說明了我們之前的工作提速不掉點:基於詞顆粒度的中文 WoBERT [6] 的改進方向是正確的。

3.1 中文

相信大多數讀者多數都只關心中文任務,部分讀者可能也會關心英文任務,應該鮮有讀者會關心中英文以外的任務了。然而,mT5 涵蓋了 101 種語言,總詞表有 25 萬,而且它採用的 T5.1.1結構的 Softmax 還不共享引數,這就導致了 Embedding 層佔用了相當多的引數量。

比如 mT5 small 的引數量為 3 億,其中 Embedding 相關的就佔了 2.5 億,關鍵是裡邊的大部分引數我們都用不上,純粹是不必要的浪費。因此,對於主要關心中文任務的我們來說,有必要精簡一下這個 Embedding 層了。

對模型的精簡很簡單,只需要在兩個 Embedding 矩陣中刪除不需要的行就行了,關鍵在於如何決定要保留的 token,以及如何得到一個精簡後的 sentencepiece 模型。

決定要保留的 token,簡單來想就是把中文的 token 保留下來,但是也不只是中文,英文的也要保留一部分,看上去似乎只是一個正規表示式的問題,實際上沒那麼簡單,用英文字母的也不一定是英語,用中文字的也不一定是中文,這是個讓人糾結的事情。

於是筆者想了另外一個辦法:用這個 25 萬 token 的 tokenizer 對筆者收集的幾十 G 中文語料分詞,統計分詞結果,然後按照詞頻選擇前面的部分(最後保留了 3 萬多個 token)。這樣雖然費時一些,但是比較靠譜,能確保把我們比較需要的 token 保留下來。決定詞表後,就要修改得到一個新的 sentencepiece 模型,這也有點麻煩,但最終經過搜尋後還是把這個事情解決了,處理方法都分享在 Github 上。

經過這樣處理後,要構建新的模型,則只需要多加三行程式碼 keep_tokens 相關的程式碼,所需要的視訊記憶體就大大降低,並且中文生成的效果基本不變了:

# 模型路徑
config_path = '/root/kg/bert/mt5/mt5_base/t5_config.json'
checkpoint_path = '/root/kg/bert/mt5/mt5_base/model.ckpt-1000000'
spm_path = '/root/kg/bert/mt5/sentencepiece_cn.model'
keep_tokens_path = '/root/kg/bert/mt5/sentencepiece_cn_keep_tokens.json'

# 載入分詞器
tokenizer = SpTokenizer(spm_path, token_start=None, token_end='</s>')
keep_tokens = json.load(open(keep_tokens_path))

# 載入模型
t5 = build_transformer_model(
    config_path=config_path,
    checkpoint_path=checkpoint_path,
    keep_tokens=keep_tokens,
    model='t5.1.1',
    return_keras_model=False,
    name='T5',
)

encoder = t5.encoder
decoder = t5.decoder
model = t5.model

3.2 效果

最後,大家應該是關心折騰了這麼久,生成效果究竟有沒有提升,有沒有使用的價值?這樣說吧,用 mT5 small 版本 finetune 出來的 CSL 標題生成模型,BLEU 指標能持平基於 WoBERT 的 UniLM 模型,並且解碼速度快 130%;而用 mT5  base 版本 finetune 出來的 CSL 標題生成模型,指標能超過基於 WoBERT 的 UniLM 模型 1% 以上,並且解碼速度也能快 60%。

那個屠榜的T5模型,現在可以在中文上玩玩了

說白了,確實是又快又好。至於裝置要求,平時跑過 BERT base 的同學,基本都應該能跑起 mT5 small/base 版,甚至 large 版也可以嘗試一下,至於 XL 和 XXL,那就比較難搞了,建議還是放棄吧。

更多的驚喜,還是大家自己去挖掘吧。對了,順便需要提醒一下,微調 T5 模型的時候,學習率要比微調 BERT大10 倍以上才行(即  級別,BERT 一般是  級別),這是兩者模型架構差異決定的。

四、小結

本文回顧了一下 Google 去年釋出的 T5 模型,然後介紹了最近釋出的多國語言版的 mT5,最後介紹瞭如何在 bert4keras 中微調 mT5 來做中文任務,結果顯示 mT5 在中文生成上有著很不錯的表現,值得做文字生成任務的同學一試。


參考文獻


[1] https://super.gluebenchmark.com/

[2] https://github.com/google-research/text-to-text-transfer-transformer/blob/master/released_checkpoints.md

[3] https://arxiv.org/abs/2002.05202

[4] https://arxiv.org/abs/1612.08083

[5] https://arxiv.org/abs/2010.12821

[6] https://kexue.fm/archives/7758

相關文章