使用 CRF 做中文分词
使用 CRF 做中文分詞
概要
注:以上實(shí)現(xiàn)只針對(duì)中文分詞任務(wù)。
1. 簡(jiǎn)述 CRF
注,以下內(nèi)容需要一定的學(xué)習(xí)成本,如有不適請(qǐng)?zhí)料乱还?jié)(實(shí)戰(zhàn)中學(xué)習(xí))。但,建議先大概學(xué)一下理論!
學(xué)習(xí) CRF 的路線:
- 概率有向圖模型 --> 貝葉斯網(wǎng)絡(luò)
- 概率無(wú)向圖模型 --> 馬爾科夫隨機(jī)場(chǎng)
- 概率無(wú)向圖模型的因子分解(考慮如何表示聯(lián)合概率),不求證明但求理解
- 資料
- 從零學(xué)習(xí)Belief Propagation算法1
- 從零學(xué)習(xí)Belief Propagation算法2
- 邏輯斯蒂回歸 非常簡(jiǎn)單,它能讓我們了解什么是 對(duì)數(shù)線性模型(CRF也是哦)
- 最大熵模型
- 本質(zhì),模型的學(xué)習(xí)過(guò)程就是求解最大熵模型的過(guò)程
- 也就是,在滿(mǎn)足所有約束條件下,模型最后學(xué)到的是熵最大的,最公平的
- 最后,學(xué)習(xí)使用 改進(jìn)的迭代尺度法 優(yōu)化ME(后面 CRF 的學(xué)習(xí)也使用這個(gè)方法)
- 資料
- 《統(tǒng)計(jì)學(xué)習(xí)方法》第六章
- 從三個(gè)點(diǎn)學(xué)習(xí) HMM (其實(shí) CRF MEM 類(lèi)似)–> 學(xué)習(xí)過(guò)程中一定要牢記這三點(diǎn)
- 概率問(wèn)題(數(shù)學(xué)問(wèn)題)
- 學(xué)習(xí)問(wèn)題(學(xué)習(xí)模型)
- 預(yù)測(cè)問(wèn)題(利用模型)–> 維特比算法
- HMM 的兩個(gè)假設(shè)
- 馬爾科夫性假設(shè)
- 觀測(cè)獨(dú)立性假設(shè):任意時(shí)刻的觀測(cè)只依賴(lài)該時(shí)刻的狀態(tài),與其他觀測(cè)以及狀態(tài)無(wú)關(guān)(☆,注意與 CRF MEMM 的不同)
- MEMM 的問(wèn)題 --> 標(biāo)注偏執(zhí)(CRF,解決了此問(wèn)題)
- 資料
- 《統(tǒng)計(jì)學(xué)習(xí)方法》第十章
- 【中文分詞】最大熵馬爾可夫模型MEMM
- 重點(diǎn)回顧 馬爾科夫隨機(jī)場(chǎng)
- 資料
- 從零學(xué)習(xí)Belief Propagation算法2
- CRF 通俗的說(shuō),就是條件概率分布構(gòu)成一個(gè)馬爾科夫隨機(jī)場(chǎng);
- CRF 參數(shù)化形式,由它的定義結(jié)合概率無(wú)向圖的因子分解可得;
- 可能會(huì)發(fā)現(xiàn)其與 ME 的形式,有幾分相似,但它們的思想不一樣(CRF 做序列標(biāo)注,ME 做分類(lèi));
- 接下來(lái)從三個(gè)點(diǎn)學(xué)習(xí) CRF
- 概率問(wèn)題(重點(diǎn)關(guān)注求期望,在學(xué)習(xí)算法要用到)
- 學(xué)習(xí)問(wèn)題(已學(xué),改進(jìn)的迭代尺度法)
- 解碼問(wèn)題(已學(xué),維特比算法)
- 資料
- 《統(tǒng)計(jì)學(xué)習(xí)方法》第十一章
- 【中文分詞】條件隨機(jī)場(chǎng)CRF
學(xué)習(xí)過(guò)程中可能對(duì)一些符合表示產(chǎn)生歧義,后面的中文分詞應(yīng)用會(huì)有解釋。
學(xué)完后,可能還有點(diǎn)迷糊,不要緊,通過(guò)下面做中文分詞的應(yīng)用便能完全懂了!
2. 問(wèn)題描述
我們的目標(biāo)是:中文分詞!OK,接下來(lái)分析此任務(wù)。
白 B // 第一列,等待分詞的輸入序列;第二列,標(biāo)記序列(即分詞結(jié)果) 菜 E 清 B // B,表示詞的開(kāi)始 燉 E // M,表示詞的中間 白 B // E,表示詞的結(jié)束 蘿 M // S, 表示單字成詞 卜 E 是 S 什 B 么 E 味 B 道 E ? S這里,把中文分詞視為序列標(biāo)注問(wèn)題。即,給每個(gè)字打上標(biāo)簽,由這些標(biāo)簽描述了分詞結(jié)果。上面是“白菜清燉白蘿卜是什么味道?”的分詞結(jié)果。從注釋中可以看到,一共有 4 個(gè)標(biāo)簽。
通常,我們稱(chēng)等待分詞的語(yǔ)句輸入序列(或稱(chēng)為觀測(cè)序列);而稱(chēng)分詞結(jié)果為輸出序列(或稱(chēng)為標(biāo)記序列、狀態(tài)序列)。所以,我們的目標(biāo)(中文分詞)可以描述為:在給定觀測(cè)序列 XXX 下,找到概率最大的標(biāo)記序列 YYY。
怎么解決呢?CRF的思想是:首先,假設(shè)條件分布 P(Y∣X)P(Y|X)P(Y∣X) 可構(gòu)成馬爾科夫隨機(jī)場(chǎng)(即每個(gè)狀態(tài)只受相鄰狀態(tài)或輸入序列的影響);然后,我們通過(guò)訓(xùn)練(統(tǒng)計(jì))可以確定此分布;最后,序列標(biāo)注問(wèn)題(如中文分詞)是在給定條件隨機(jī)場(chǎng) P(Y∣X)P(Y|X)P(Y∣X) 和輸入序列 XXX 求條件概率最大的標(biāo)記序列 Y?Y^{*}Y?。可以看到,最后變?yōu)橐粋€(gè)動(dòng)態(tài)規(guī)劃問(wèn)題(DP)。
在我們繼續(xù)進(jìn)行下去之前,需要線性鏈CRF的參數(shù)化形式(想要了解如何得到的該形式,請(qǐng)參考概率無(wú)向圖的因子分解)
P(Y∣X)=1Z(X)exp(∑i,kλktk(yi?1,yi,X,i)+∑i,lμlsl(yi,x,i))P(Y|X)=\frac{1}{Z(X)}exp(\sum_{i,k}\lambda_kt_k(y_{i-1},y_i,X,i)+\sum_{i,l}\mu_ls_l(y_i,x,i))P(Y∣X)=Z(X)1?exp(i,k∑?λk?tk?(yi?1?,yi?,X,i)+i,l∑?μl?sl?(yi?,x,i))
其中,tkt_ktk? sls_lsl? 分別為 轉(zhuǎn)移特征、狀態(tài)特征,而 λk\lambda_kλk? μl\mu_lμl? 為它們對(duì)應(yīng)的權(quán)重(學(xué)習(xí)問(wèn)題就是去學(xué)習(xí)這些權(quán)重)。而 Z(X)Z(X)Z(X) 是規(guī)范化因子,求和是在所有可能的輸出序列上進(jìn)行(如何理解這句話,其實(shí)就是遍歷 YYY 的全排列,比如這里一共有 4句子長(zhǎng)度4^{句子長(zhǎng)度}4句子長(zhǎng)度 個(gè)可能)
Z(X)=∑Yexp(∑i,kλktk(yi?1,yi,X,i)+∑i,lμlsl(yi,x,i))Z(X) = \sum_Yexp(\sum_{i,k}\lambda_kt_k(y_{i-1},y_i,X,i)+\sum_{i,l}\mu_ls_l(y_i,x,i))Z(X)=Y∑?exp(i,k∑?λk?tk?(yi?1?,yi?,X,i)+i,l∑?μl?sl?(yi?,x,i))
可以看到,Z(X)Z(X)Z(X) 起到的是全局歸一化,而在 MEMM 中只使用了局部歸一化,所以出現(xiàn)局部偏執(zhí)問(wèn)題。
在下一節(jié),我們將關(guān)注 狀態(tài)特征 與 轉(zhuǎn)移特征。
3. 構(gòu)建特征函數(shù)
在線性鏈CRF參數(shù)化形式中,未知的只有特征與對(duì)應(yīng)參數(shù)(或稱(chēng)為權(quán)重),而參數(shù)是在學(xué)習(xí)問(wèn)題中關(guān)注的,所以只剩下特征了。怎樣定義或構(gòu)建特征呢?
我們的目標(biāo)是:中文分詞!所以,針對(duì)中文分詞任務(wù)我們有獨(dú)特的特征構(gòu)造方式(借鑒于CRF++)。首先,明確特征函數(shù)的含義:它描述是否滿(mǎn)足指定特征,滿(mǎn)足返回1否則返回0;再來(lái)看特征模板
# Unigram --> 構(gòu)造狀態(tài)特征的模板 U00:%x[-2,0] U01:%x[-1,0] U02:%x[0,0] U03:%x[1,0] U04:%x[2,0] U05:%x[-2,0]/%x[-1,0]/%x[0,0] U06:%x[-1,0]/%x[0,0]/%x[1,0] U07:%x[0,0]/%x[1,0]/%x[2,0] U08:%x[-1,0]/%x[0,0] U09:%x[0,0]/%x[1,0]# Bigram --> 構(gòu)造轉(zhuǎn)移特征的模板 B我們的特征有兩種形式:狀態(tài)特征 & 轉(zhuǎn)移特征。下面結(jié)合特征模板分別介紹這兩種特征。
狀態(tài)特征函數(shù) sl(yi,X,i))s_l(y_i,X,i))sl?(yi?,X,i)) ,它的輸入為當(dāng)前狀態(tài)、整個(gè)觀測(cè)序列以及當(dāng)前位置。上面特征模板中 U01~U09 用于生成狀態(tài)特征。以 U00:%x[-2,0] 為例,-2 代表取觀測(cè)序列中相對(duì)當(dāng)前位置的倒數(shù)第2個(gè),0 在此處無(wú)意義。所以,用 U00~U09 做模板在 我愛(ài)我的祖國(guó)。 第3個(gè)位置下可構(gòu)建的狀態(tài)特征為
我 愛(ài) 我 <-- 當(dāng)前處于此位置 的 祖 國(guó) # 下面為生成的狀態(tài)特征 U00:我 U01:愛(ài) U02:我 U03:的 U04:祖 U05:我/愛(ài)/我 U06:愛(ài)/我/的 U07:我/的/祖 U08:愛(ài)/我 U09:我/的 注:每行代表 4 個(gè)狀態(tài)特征,因?yàn)檫@里有 4 標(biāo)簽(BMES)。所以,這里一共產(chǎn)生 40 個(gè)狀態(tài)特征。 注:請(qǐng)注意,這只是在第 3 個(gè)位置下產(chǎn)生的。轉(zhuǎn)移特征 tk(yi?1,yi,X,i)t_k(y_{i-1},y_i,X,i)tk?(yi?1?,yi?,X,i),它的輸入為上一狀態(tài)、當(dāng)前狀態(tài)、整個(gè)觀測(cè)序列以及當(dāng)前位置。上面特征模板中,B 表示生成所有的轉(zhuǎn)移特征。因而,一共可產(chǎn)生 16 種轉(zhuǎn)移特征(無(wú)視觀測(cè)序列)。它們?yōu)?/p> BB --> 表示從上一個(gè)狀態(tài) B 轉(zhuǎn)移到當(dāng)前狀態(tài) B BM BE BS MB MM ME MS EB EM EE ES SB SM SE SS
OK,了解了這兩種特征的構(gòu)造過(guò)程,我們便可以通過(guò)掃描訓(xùn)練集來(lái)構(gòu)建大量的特征(注意,轉(zhuǎn)移特征固定為16個(gè))。我的 25M 訓(xùn)練集下,大約可以生成 560w+ 個(gè)特征函數(shù)(只取頻率大于等于3的)。
下面看程序中如何定義特征,首先看 Feature 類(lèi)
import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger;/*** @author iwant* @date 19-6-13 09:31* @desc 特征函數(shù)*/ public class Feature implements Serializable, Cloneable {// 特征函數(shù)數(shù)字標(biāo)識(shí)private int id;// 特征函數(shù)標(biāo)識(shí)(含特征函數(shù)的內(nèi)容) --> 比如,featureId="U00:我"private String featureId; // 出現(xiàn)頻率 --> 數(shù)組大小為 4 ,從這里可以看出一個(gè)該類(lèi)對(duì)象對(duì)應(yīng) 4 個(gè)狀態(tài)特征private AtomicInteger[] freqs = new AtomicInteger[4];// 權(quán)重 --> 數(shù)組大小為 4 ,從這里可以看出一個(gè)該類(lèi)對(duì)象對(duì)應(yīng) 4 個(gè)狀態(tài)特征// 注:對(duì)應(yīng)四個(gè)標(biāo)記(BMES)private double[] weights = new double[4];public Feature(int id, String featureId) {this.id = id;this.featureId = featureId;for (int i = 0; i < weights.length; i++)this.freqs[i] = new AtomicInteger();}public Feature(String featureId) {this(-1, featureId);}}從注釋中我們可以看到,一個(gè)Feature 對(duì)象包含 4 個(gè)狀態(tài)特征。
我們把所有的特征放在一個(gè) Map<String,Feature> 集合中,其中 key 即 featureId 便于后續(xù)查找某一特征,而 value 自然就是對(duì)應(yīng)的 Feature 對(duì)象了。
注:因這里的轉(zhuǎn)移特征無(wú)視觀測(cè)序列,所以在用 Feature 對(duì)象描述轉(zhuǎn)移特征時(shí),一個(gè)對(duì)象對(duì)應(yīng)一個(gè)轉(zhuǎn)移特征。因而此時(shí)規(guī)定對(duì)象中的數(shù)組只有下標(biāo) 0 處有意義。
這里就不列出掃描訓(xùn)練集構(gòu)造所有特征函數(shù)的代碼,具體請(qǐng)?jiān)谠创a中 Utils.java 中查找。
有了特征函數(shù)我們便可關(guān)注參數(shù)了,也就是下一節(jié)中學(xué)習(xí)算法做的事。
4. CRF 學(xué)習(xí)算法
首先,我們需要明確學(xué)習(xí)的是什么。在線性鏈CRF的參數(shù)化形式中原有兩個(gè)未知,一個(gè)是特征函數(shù)另一個(gè)是參數(shù)(亦稱(chēng)為權(quán)重)。在上一節(jié),我們已經(jīng)構(gòu)造了所有的特征函數(shù)。所以現(xiàn)在只剩下它們對(duì)應(yīng)的參數(shù)就可以確定模型了。自然而然,CRF 學(xué)習(xí)的目標(biāo)就是更新這些參數(shù)!
至于如何更新這些參數(shù),是這一小節(jié)的重點(diǎn)。前面已經(jīng)提到,我們將會(huì)使用改進(jìn)的迭代尺度法來(lái)優(yōu)化CRF。
可能你會(huì)問(wèn)為什么這么學(xué)習(xí)。首先要明確我們已知訓(xùn)練數(shù)據(jù)集,由此可知經(jīng)驗(yàn)概率分布 P~(X,Y)\tilde{P}(X,Y)P~(X,Y) (統(tǒng)計(jì)學(xué)習(xí)的最基本假設(shè))。現(xiàn)在求條件分布,便可以通過(guò) 極大化 訓(xùn)練數(shù)據(jù)的 對(duì)數(shù)似然函數(shù) 來(lái)求模型參數(shù)。改進(jìn)的迭代尺度法通過(guò)迭代的方法不斷優(yōu)化對(duì)數(shù)似然函數(shù)改變量的下界,達(dá)到極大化對(duì)數(shù)似然函數(shù)的目的。通俗地講,為了求條件分布,數(shù)學(xué)家給我們提供了一個(gè)NB的工具 – 極大化對(duì)數(shù)似然函數(shù),這樣就變成了優(yōu)化問(wèn)題。針對(duì)該優(yōu)化問(wèn)題呢,數(shù)學(xué)家經(jīng)過(guò)對(duì)原函數(shù)不斷放縮、求導(dǎo)給我們推導(dǎo)出了許多優(yōu)化算法,改進(jìn)的迭代尺度法(IIS)便是其中一個(gè),其他的還有 擬牛頓法 梯度下降法 等等。(注:這里不再詳述推導(dǎo)過(guò)程。感興趣的,可以參考《統(tǒng)計(jì)學(xué)習(xí)方法》第六章)
說(shuō)個(gè)題外話,再來(lái)談?wù)劄槭裁碈RF學(xué)習(xí)算法學(xué)習(xí)的是參數(shù)。我們還可以這么理解,由不同的參數(shù)可以定義不同的模型。所有的參數(shù)可能構(gòu)成了 模型空間(或稱(chēng)為 模型集合)。學(xué)習(xí)算法的目的就是在模型空間中找尋最能擬合訓(xùn)練數(shù)據(jù)的模型。
迭代尺度法的基本思想:我們有種方法能夠使得對(duì)數(shù)似然函數(shù)每次增加一點(diǎn)點(diǎn),所以我們可以不斷地使用(迭代)該方法慢慢的增大對(duì)數(shù)似然函數(shù)。總有那么一個(gè)時(shí)刻,它會(huì)收斂,于是達(dá)到了極大化對(duì)數(shù)似然函數(shù)的目的。
OK,是時(shí)候看算法描述
下面將結(jié)合中文分詞任務(wù)解釋上面的算法描述。
不難發(fā)現(xiàn)整個(gè)算法中最難的就是步驟(a)中的方程求解。怎么求,公式11.41、11.44已經(jīng)說(shuō)明了。下面以公式11.41為例來(lái)說(shuō)明。
- 先要明確它是針對(duì)轉(zhuǎn)移特征的,且 δk\delta_kδk? 只針對(duì)下標(biāo)為 kkk 這一轉(zhuǎn)移特征;
- 再來(lái)看 SSS,它是一個(gè)常數(shù),是一個(gè)足夠大的特征總數(shù)。這里,我們每次訓(xùn)練都要選一批句子,而每個(gè)句子都有個(gè)特征總數(shù)(即該句子滿(mǎn)足的狀態(tài)特征與轉(zhuǎn)移特征總數(shù)),足夠大的特征總數(shù)可以為這些特征總數(shù)中最大的那個(gè)。
- 再來(lái)看 Ep~[tk]E_{\tilde{p}}[t_k]Ep~??[tk?] ,表示在經(jīng)驗(yàn)概率分布下 P~(X,Y)\tilde{P}(X,Y)P~(X,Y),轉(zhuǎn)移特征函數(shù) tkt_ktk? 的期望值。聽(tīng)起來(lái)很高大上,其實(shí)就是統(tǒng)計(jì)該特征函數(shù)在當(dāng)前批量句子中出現(xiàn)的次數(shù);
- 最后有 Ep[tk]E_{p}[t_k]Ep?[tk?] ,表示特征函數(shù)在經(jīng)驗(yàn)分布為 P~(X)\tilde{P}(X)P~(X) 下關(guān)于聯(lián)合分布 P(X,Y)P(X,Y)P(X,Y) 的數(shù)學(xué)期望。公式 (11.42) 說(shuō)明了怎么求。但是相當(dāng)繁瑣!我們需要知道 alphaalphaalpha MMM β\betaβ。
- 先來(lái)解釋公式11.42,最外面的求和是針對(duì)所有的句子(比如,我實(shí)現(xiàn)時(shí)每次訓(xùn)練要用 500 個(gè)句子);從 1~n+1 的求和是遍歷一個(gè)句子(注意一個(gè)句子的長(zhǎng)度為 n);最里面的求和是針對(duì)所有的“前后狀態(tài)”(在中文分詞任務(wù)中,有4中標(biāo)簽,所以一共有16個(gè)前后狀態(tài));
- MMM (參考《統(tǒng)計(jì)學(xué)習(xí)方法》公式11.23)
Mi(X)=[exp(∑k=1K(∑i,kλktk(yi?1,yi,X,i)+∑i,lμlsl(yi,x,i)))]M_i(X)=[exp(\sum_{k=1}^K(\sum_{i,k}\lambda_kt_k(y_{i-1},y_i,X,i)+\sum_{i,l}\mu_ls_l(y_i,x,i)))]Mi?(X)=[exp(k=1∑K?(i,k∑?λk?tk?(yi?1?,yi?,X,i)+i,l∑?μl?sl?(yi?,x,i)))]
- alphaalphaalpha (參考《統(tǒng)計(jì)學(xué)習(xí)方法》公式11.28)
αiT(X)=αi?1T(X)Mi(X)\alpha_i^T(X)=\alpha_{i-1}^T(X)M_i(X)αiT?(X)=αi?1T?(X)Mi?(X)
- betabetabeta (參考《統(tǒng)計(jì)學(xué)習(xí)方法》公式11.31)
βi(X)=Mi+1(X)βi+1(X)\beta_i(X)=M_{i+1}(X)\beta_{i+1}(X)βi?(X)=Mi+1?(X)βi+1?(X)
- 注意,在計(jì)算它們是要注意下標(biāo)!每個(gè)句子都要計(jì)算 alphaalphaalpha MMM β\betaβ 一次。
上面只是理解計(jì)算過(guò)程,而在具體的實(shí)現(xiàn)中需要優(yōu)秀的設(shè)計(jì)來(lái)提高性能。比如,我們的特征有幾百萬(wàn)個(gè),每次訓(xùn)練要遍歷這么多特征?顯然,這樣行不通。我們能不能率先找出該批量句子中所含有的特征?再比如,考慮這一系列的計(jì)算過(guò)程那些能用多線程?
這些設(shè)計(jì)很吃個(gè)人的經(jīng)驗(yàn),建議在 先弄懂算法流程后,再設(shè)計(jì),最后動(dòng)手。大家先自己想想怎么設(shè)計(jì),看看有沒(méi)有奇淫技巧。如果沒(méi)想到,可以看看我的代碼(篇幅有限,就不再描述我是如何實(shí)現(xiàn)的了)。我的肯定不是最好的,但還能湊合。
5. CRF 預(yù)測(cè)算法
最后的預(yù)測(cè)算法,用于解決解碼問(wèn)題,說(shuō)白了就是能夠?qū)斎氲木渥舆M(jìn)行分詞。
現(xiàn)在已經(jīng)有條件隨機(jī)場(chǎng) P(Y∣X)P(Y|X)P(Y∣X)(由上面得到的)以及輸入序列(句子),要求條件概率最大的輸出序列(標(biāo)記序列)Y?Y^*Y?。最后會(huì)發(fā)現(xiàn)這就是一個(gè)最優(yōu)路徑問(wèn)題,要用到 動(dòng)態(tài)規(guī)劃。此處便用的是著名的 維特比算法。
具體過(guò)程不打算寫(xiě)了。請(qǐng)參考《統(tǒng)計(jì)學(xué)習(xí)方法》中的 206 頁(yè)。很簡(jiǎn)單的!書(shū)中已經(jīng)給出遞歸公式,實(shí)現(xiàn)時(shí)按照公式來(lái)即可。
6. 結(jié)果
我是在 人民日?qǐng)?bào)語(yǔ)料(2014版) 語(yǔ)料上做的實(shí)驗(yàn)。模型大約訓(xùn)練了一個(gè)半小時(shí),最后的準(zhǔn)確率為 94.20%。還算可以。
[INFO] 開(kāi)始初始化! [INFO] 開(kāi)始解析特征模板... [INFO] 特征模板解析完畢! [INFO] 開(kāi)始加載模型... [INFO] 一共加載了 5656572 個(gè)特征! [INFO] 初始化完畢! [INFO] 評(píng)測(cè)使用的文件:data/save/test.data ! [INFO] 結(jié)果將會(huì)保存在:data/save/result.data ! [INFO] 分詞已結(jié)束,正在評(píng)估準(zhǔn)確率... [INFO] 評(píng)測(cè)結(jié)果如下:wTotal: 2042582sTotal: 47884wError: 118489, 5.80% --> 94.20%sError: 29377, 61.35%代碼(Github)
總結(jié)
以上是生活随笔為你收集整理的使用 CRF 做中文分词的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: rk3288_5.1_BOX 调整HDM
- 下一篇: SocksCap64全局代理设置教程