一、簡(jiǎn)介
1. 中文糾錯(cuò)簡(jiǎn)介
中文糾錯(cuò)主要存在的問(wèn)題可以這樣劃分:
- 諧音字詞,如 配副眼睛-配副眼鏡
- 混淆音字詞,如 流浪織女-牛郎織女
- 字詞順序顛倒,如 伍迪艾倫-艾倫伍迪,我不會(huì)讓失望她-我不會(huì)讓她失望
- 字詞補(bǔ)全,如 愛(ài)有天意-假如愛(ài)有天意
- 形似字錯(cuò)誤,如 高梁-高粱
- 中文拼音全拼,如 xingfu-幸福
- 中文拼音縮寫(xiě),如 sz-深圳
- 語(yǔ)法錯(cuò)誤,如 想象難以-難以想象
從現(xiàn)有的技術(shù)角度,按照時(shí)間以及技術(shù)的更新時(shí)間可以這樣劃分:
- ngram模型
- 最短編輯距離
- 依存樹(shù)分析
- RNNLM
- ...
- Bert模型的橫空出世———2018年
前面的幾種方式,在網(wǎng)上可以找到一大堆說(shuō)明,這里我就不贅述了。重點(diǎn)是最后一種Bert模型。
2018年以來(lái)的NLP避不開(kāi)的一個(gè)模型就是Bert模型。全稱(chēng)是Bidirectional Encoder Representation from Transformers,它在機(jī)器閱讀理解頂級(jí)水平測(cè)試SQuAD1.1中表現(xiàn)出驚人的成績(jī):全部?jī)蓚€(gè)衡量指標(biāo)上全面超越人類(lèi),并且還在11種不同NLP測(cè)試中創(chuàng)出最佳成績(jī),包括將GLUE基準(zhǔn)推至80.4%(絕對(duì)改進(jìn)7.6%),MultiNLI準(zhǔn)確度達(dá)到86.7% (絕對(duì)改進(jìn)率5.6%)等。BERT為NLP帶來(lái)里程碑式的改變。
那么Bert模型主要解決什么問(wèn)題?
首先我們看看NLP中有哪些問(wèn)題,閱讀理解,語(yǔ)句情感分析,完形填空,判斷兩句話的相似程度,語(yǔ)法分析,包括我們這里提到的文本糾錯(cuò)。顯然,如果使用監(jiān)督學(xué)習(xí)來(lái)完成這些任務(wù),需要海量數(shù)據(jù)。作者認(rèn)為存在通用的語(yǔ)言模型,先用語(yǔ)料文章無(wú)監(jiān)督的預(yù)訓(xùn)練通用模型,然后再根據(jù)具體應(yīng)用,用 supervised 訓(xùn)練數(shù)據(jù),精加工(fine tuning)模型,使之適用于具體應(yīng)用。為了區(qū)別于針對(duì)語(yǔ)言生成的 Language Model,作者給通用的語(yǔ)言模型,取了一個(gè)名字,叫語(yǔ)言表征模型 Language Representation Model。
bert模型為什么表現(xiàn)那么好?
原因大概有兩個(gè):
-
首先是模型選得好,基本能用到的模塊都用上了。比如Transformer這種基于注意力機(jī)制的模型,誕生之初就受到了學(xué)術(shù)界工業(yè)界一致的追捧,有利于上下文內(nèi)容的學(xué)習(xí),且不會(huì)像LSTM這類(lèi)基于RNN的模型那般難以將注意力放在全文上。其次是雙向的學(xué)習(xí)機(jī)制,直觀上就會(huì)更棒。
image.png - 其次是預(yù)訓(xùn)練的學(xué)習(xí)任務(wù),它的學(xué)習(xí)任務(wù)有兩個(gè),首先是掩碼遮蔽語(yǔ)言模型學(xué)習(xí),其次是Next Sentence Prediction。這里和我們相關(guān)的只有第一個(gè),所以著重關(guān)心第一個(gè)任務(wù)。
bert模型最棒的是,預(yù)訓(xùn)練不需要我們關(guān)心,我們可以直接拿到官方給出的大數(shù)量大算力超神研究員已經(jīng)給我們預(yù)訓(xùn)練好的bert中文模型,可以拿來(lái)直接用,真是美滋滋。
Bert是如何進(jìn)行訓(xùn)練的?
bert模型的預(yù)訓(xùn)練分為兩個(gè)子任務(wù),當(dāng)然對(duì)于我們這類(lèi)糾錯(cuò)任務(wù),不涉及判斷上下文是否是相連的,其實(shí)只需要關(guān)心第一個(gè)任務(wù):掩碼遮蔽學(xué)習(xí)語(yǔ)言模型。

對(duì)于一句話,隨機(jī)遮蔽其中15%的文字,其中大部分遮蔽的文字用符號(hào)[MASK]表示,少部分用隨機(jī)一個(gè)漢字表示。這樣模型學(xué)習(xí)遇到[MASK]就會(huì)主動(dòng)學(xué)習(xí)上下文內(nèi)容,得到被遮蔽的[MASK]應(yīng)該的表示,同時(shí),對(duì)于錯(cuò)別字,因?yàn)橹勒鎸?shí)標(biāo)簽的真實(shí)字,所以模型也要學(xué)習(xí)通過(guò)上下文語(yǔ)義,糾正這個(gè)文字。
瞅瞅,這可不就和我們的糾錯(cuò)任務(wù)完美契合了嘛。
當(dāng)然機(jī)器可不知道人類(lèi)漢字的表達(dá)方式,首先要做的是對(duì)漢字進(jìn)行word embedding,將其轉(zhuǎn)為機(jī)器可以理解可以計(jì)算的向量表示。在bert中,語(yǔ)句的wordEmbedding也是不簡(jiǎn)單的。

不僅僅包括漢字自身(或者英文,總之就是人類(lèi)自己能夠理解的語(yǔ)言)轉(zhuǎn)換為向量(Token Embedding);語(yǔ)句位置屬于第一條語(yǔ)句,還是第二條語(yǔ)句,也要轉(zhuǎn)為段落向量(Segment Embedding);文字的具體在第幾位也要轉(zhuǎn)換為位置向量(Position Embedding)。然后將這三者結(jié)合起來(lái),就得到既包含語(yǔ)言信息又包含位置信息的向量了。
2. 本文簡(jiǎn)介
回歸到這篇論文,這是一篇中文糾錯(cuò)模型,來(lái)自今日頭條公司。論文使用了一個(gè)錯(cuò)別字檢測(cè)器detector和錯(cuò)別字糾正器corrector兩個(gè)模型串聯(lián)的方式進(jìn)行錯(cuò)別字的檢測(cè)和糾正。

其中錯(cuò)別字檢測(cè)器使用了一個(gè)普通的Bi-GRU網(wǎng)絡(luò),而錯(cuò)別字糾正器使用了業(yè)界的Bert encoder模塊。

其中e_mask是符號(hào)'[MASK]'的embedding表示,而e_i是原始漢字的embedding表示。pi為detector檢測(cè)為錯(cuò)別字的概率。所以這就是softMasked的含義。
二、模型結(jié)構(gòu)
1. Detector檢測(cè)錯(cuò)別字

網(wǎng)絡(luò)結(jié)構(gòu)如上圖所示,比較明確。detection網(wǎng)絡(luò)是一個(gè)bi-GRU網(wǎng)絡(luò),輸入為語(yǔ)句通過(guò)embedding之后的向量表示[max_length,hidden_size],其中max_length為語(yǔ)句的長(zhǎng)度,一般會(huì)按照實(shí)際語(yǔ)句的最大值進(jìn)行填充,比如512,但是實(shí)際訓(xùn)練的時(shí)候,考慮到訓(xùn)練效率可以設(shè)置的短一點(diǎn),因?yàn)橐话愕恼Z(yǔ)句也就是50字以內(nèi)。輸出是每個(gè)漢字的錯(cuò)別字概率。
2. Corrector糾正錯(cuò)別字

這一部分的輸入是softmasking的結(jié)果,根據(jù)上面Detector給出的錯(cuò)別字的概率,動(dòng)態(tài)的給錯(cuò)別字按照錯(cuò)誤概率進(jìn)行遮蔽。
將中間層的embedding輸出輸入到bert模型中,輸出結(jié)果首先和輸入的embedding求和疊加(殘差結(jié)構(gòu)),最后再通過(guò)一個(gè)softmax層得到最終結(jié)果。
e = self.embedding(input_ids=input_ids, token_type_ids=segment_ids)
p = self.detector(e)
e_ = p * self.mask_e + (1-p) * e
_, _, _, _, _, head_mask, encoder_hidden_states, encoder_extended_attention_mask= self._init_inputs(input_ids, input_mask)
h = self.corrector(e_, attention_mask=encoder_extended_attention_mask, head_mask=head_mask, encoder_hidden_states=encoder_hidden_states, encoder_attention_mask=encoder_extended_attention_mask)
h = h[0] + e
out1 = self.linear(h)
out2 = self.softmax(out1)
這個(gè)過(guò)程也可以用論文畫(huà)出的圖給出,我覺(jué)得如果理解了我上面畫(huà)的圖,這個(gè)圖還是比較好理解的~

三、損失函數(shù)
損失函數(shù)由兩個(gè)部分組成,detector的損失函數(shù)以及糾正器的損失函數(shù)。其中,detector因?yàn)檩敵鰹槎蹈怕剩該p失函數(shù)采用二元交叉熵?fù)p失函數(shù)。糾正器輸出為多元交叉熵?fù)p失.兩個(gè)損失函數(shù)按照固定比例進(jìn)行加權(quán)得到最終的損失函數(shù)。需要注意的是,因?yàn)閐etector是一個(gè)二分類(lèi)的網(wǎng)絡(luò),其實(shí)是比較好訓(xùn)練的。因此gama權(quán)重應(yīng)該盡量大一些,也可以先用較小值訓(xùn)練好detector網(wǎng)絡(luò)之后,后期用大gama值訓(xùn)練corrector網(wǎng)絡(luò)。

在實(shí)際使用的時(shí)候,對(duì)檢測(cè)器直接使用nn.BCELoss()即可,對(duì)于糾正器則按照實(shí)際的情況使用損失函數(shù)

四、實(shí)驗(yàn)效果
效果很好,需要注意到bert模型進(jìn)行finetune之后的效果也不差,但是我現(xiàn)在還不是很清楚bert模型直接finetune的話,訓(xùn)練數(shù)據(jù)應(yīng)該怎么標(biāo)注,暫且先放在這里,以后補(bǔ)上。

實(shí)際使用的話,git上有兩份開(kāi)源代碼,地址如下:
其中第一份代碼,我自己嘗試使用大約800萬(wàn)優(yōu)質(zhì)訓(xùn)練集進(jìn)行訓(xùn)練,在corrector準(zhǔn)確率為30%的時(shí)候,loss就不下降了,嘗試修改過(guò)學(xué)習(xí)率和損失函數(shù)的參數(shù)都沒(méi)有什么效果。暫時(shí)沒(méi)有看出什么問(wèn)題,先擱置一下。
后面一份代碼的問(wèn)題比較大,需要好好修改之后運(yùn)行。在我自己生成的數(shù)據(jù)集上(600萬(wàn)),跑出的結(jié)果為detector的召回率0.649,精確率0.837;corrector網(wǎng)絡(luò)效果不佳,訓(xùn)練到后期無(wú)法收斂,大概的Accuracy只有59.5%,無(wú)法達(dá)到論文提到的精度,還需要再仔細(xì)琢磨一下問(wèn)題出在哪里。
