Conditional Random Field:條件隨機場,一種機器學習技術(模型)dom
CRF由John Lafferty最先用於NLP技術領域,其在NLP技術領域中主要用於文本標註,並有多種應用場景,例如:iphone
本文主要描述如何使用CRF技術來進行中文分詞。機器學習
1. CRF把分詞當作字的詞位分類問題,一般定義字的詞位信息以下:ide
2. CRF分詞的過程就是對詞位標註後,將B和E之間的字,以及S單字構成分詞函數
3. CRF分詞實例:工具
上面介紹了CRF技術思想以及如何用於分詞,下面將介紹如何在實際開發中使用CRF進行分詞工做。目前常見的CRF工具包有pocket crf, flexcrf 車crf++,目前網上也有一些它們3者之間的對比報告,我的感受crf++在易用性,穩定性和準確性等綜合方面的表現最好,同時在公司的項目開發中也一 直在使用,所以下面將概述一下crf++的使用方法(具體細節能夠到crf++官方主頁去查 閱,http://crfpp.sourceforge.net/)性能
1.安裝
編譯器要求:C++編譯器(gcc 3.0或更高)
命令:
% ./configure
% make
% su
# make install
注:只有擁有root賬號的用戶才能成功安裝。學習
2.使用
2.1訓練和測試文件的格式
訓練和測試文件必須包含多個tokens,每一個token包含多個列。token的定義可根據具體的任務,如詞、詞性等。每一個token必須寫在一行,且各列之間用空格或製表格間隔。一個token的序列可構成一個sentence,sentence之間用一個空行間隔。
最後一列是CRF用於訓練的正確的標註形式。
例如:
iphone ASCII S
是 CN S
一 CN S >> 當前token
款 CN S
不 CN B
錯 CN E
的 CN S
手 CN B
機 CN E
, PUNC S
還 CN S
能 CN S
聽 CN B
歌 CN E
。PUCN S
我上面的例子每一個token包含3列,分別爲字自己、字類型(英文數字,漢字,標點等)和詞位標記。
注意:若是每個token的列數不一致,系統將不能正確運行。
2.2準備特徵模板
使用CRF++的用戶必須本身肯定特徵模板。
1)基本模板和宏
模板文件中的每一行表明一個template。每個template中,專門的宏%x[row,col]用於肯定輸入數據中的一個token。row用於肯定與當前的token的相對行數。col用於肯定絕對行數。
如已知下面的輸入數據:
iphone ASCII S
是 CN S
一 CN S >> 當前token
款 CN S
不 CN B
錯 CN E
的 CN S
手 CN B
機 CN E
特徵模板形式爲:
# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-1,0]/%x[0,0]
U06:%x[0,0]/%x[1,0]
U07:%x[-1,0]/%x[1,0]
U08:%x[0,1]
U09:%x[-1,1]/%x[0,1]
# Bigram
B
2)模板類型
有兩種模板類型,它們可由template的第一個字符肯定。
第一種是Unigram template:第一個字符是U
這是用於描述unigram feature的模板。當你給出一個模板"U02:%x[0,0]",CRF會自動的生成一個特徵函數集合(func1 ... funcN),如:
func1 = if (output = B and feature="U02:一") return 1 else return 0
func2 = if (output = M and feature="U02:一") return 1 else return 0
func3 = if (output = E and feature="U02:一") return 1 else return 0
func4 = if (output = S and feature="U02:一") return 1 else return 0
...
funcX = if (output = B and feature="U02:的") return 1 else return 0
funcY = if (output = S and feature="U02:的") return 1 else return 0
...
一個模型生成的特徵函數的個數總數爲L*N,其中L是輸出的類別數,N是根據給定的template擴展出的unique string的數目。
第二種類型Bigram template:第一個字符是B
這 個模板用於描述bigram features。使用這個模板,系統將自動產生當前輸出token與前一個輸出token(bigram)的組合。產生的可區分的特徵的總數是 L*L*N,其中L是輸出類別數,N是這個模板產生的unique features數。當類別數很大的時候,這種類型會產生許多可區分的特徵,這將會致使訓練和測試的效率都很低下。
3)使用標識符區分相對位置
若是用戶須要區分token的相對位置時,可使用標識符。
好比在下面的例子中,宏"%x[-2,0]"和"%x[1,0]"都表明「北」,可是它們又是不一樣的「北「。
北 CN B
京 CN E
的 CN S >> 當前token
北 CN S
部 CN S
爲了區分它們,能夠在模型中加入一個惟一的標識符(U00: 或 U03:),即:
U00:%x[-2,0]
U03:%x[1,0]
在這樣的條件下,兩種模型將被認爲是不一樣的,由於他們將被擴展爲」U00:北「和」U03:北」。只要你喜歡,你可使用任何標識符,可是使用數字序號區分更頗有用,由於它們只需簡單的與特徵數相對應。
3.訓練(編碼)
使用crf_learn 命令:
% crf_learn template_file train_file model_file
其中,template_file和train_file需由使用者事先準備好。crf_learn將生成訓練後的模型並存放在model_file中。
通常的,crf_learn將在STDOUT上輸出下面的信息。還會輸出其餘的和LBFGS迭代相關的信息。
% crf_learn template_file train_file model_file
CRF++: Yet Another CRF Tool Kit
Copyright (C) 2005 Taku Kudo, All rights reserved.
reading training data:
Done! 0.32 s
Number of sentences: 77
Number of features: 32856
Freq: 1
eta: 0.0001
C(sigma^2): 10
iter=0 terr=0.7494725738 serr=1 obj=2082.968899 diff=1
iter=1 terr=0.1671940928 serr=0.8831168831 obj=1406.329356 diff=0.3248438053
iter=2 terr=0.1503164557 serr=0.8831168831 obj=626.9159973 diff=0.5542182244
其中:
iter:迭代次數
terr:和tags相關的錯誤率(錯誤的tag數/全部的tag數)
serr:與sentence相關的錯誤率(錯誤的sentence數/全部的sentence數)
obj:當前對象的值。當這個值收斂到一個肯定的值是,CRF模型將中止迭代
diff:與上一個對象值之間的相對差
有兩個主要的參數用於控制訓練條件:
-c float:使用這個選項,你能夠改變CRF的hyper-parameter。當取一個極大的C值,CRF將可能對訓練數據產生過擬合 (overfitting)現象。這個參數將會調節overfitting和underfitting之間的平衡。結果將會對參數帶來有意義的影響。使用 者能夠經過使用held-out data或者更多的通用模型的選擇方法如十字交叉驗證法(cross validation)得到最有的值。
-f NUM:這個參數用於設置特徵的cut-off閾值。CRF++訓練時只使用出現次數很多於NUM次數的特徵進行訓練。默認值爲1。當使用CRF++訓練大規模數據時,單一特徵的數量將達到數百萬,此時選擇這個參數頗有用。
這裏有一個使用這兩個參數的例子:
% crf_learn -f 3 -c 1.5 template_file train_file model_file
4.測試(解碼)
使用crf_test 命令:
% crf_test -m model_file test_files ...
其中,model_file是crf_learn建立的。在測試過程當中,使用者不須要指定template file,由於,mode file已經有了template的信息。test_file是你想要標註序列標記的測試語料。這個文件的書寫格式應該與訓練文件一致。
下面是一個crf_test輸出的例子:
% crf_test -m model test.data
Rockwell NNP B B
International NNP I I
Corp. NNP I I
's POS B B
Tulsa NNP I I
unit NN I I
..
其中,最後一列是模型估計的tag。若是第三列是標準的tag,則能夠經過簡單的比較第三列和第四列之間的差異計算出準確率。
詳細的層次(verbose level)
-v選項:將設置verbose level。默認值爲0。經過增長層次,你能夠從CRF++得到額外的信息。
層次1:
你 能夠對每一個tag使用邊緣機率(marginal probabilities)(這是一種對輸出tag的confidence measure),對輸出使用條件機率(conditional probably)(針對整個輸出的confidence measure)。
例如:
% crf_test -v1 -m model test.data| head
# 0.478113
Rockwell NNP B B/0.992465
International NNP I I/0.979089
Corp. NNP I I/0.954883
's POS B B/0.986396
Tulsa NNP I I/0.991966
...
其中,第一行的"# 0.478113"便是輸出的條件機率,並且每個輸出tag各自含有一個機率,表示形式如「B/0.992465」。
層次2:
你能夠對全部的其餘候選求邊緣機率。
例如:
% crf_test -v2 -m model test.data
# 0.478113
Rockwell NNP B B/0.992465 B/0.992465 I/0.00144946 O/0.00608594
International NNP I I/0.979089 B/0.0105273 I/0.979089 O/0.0103833
Corp. NNP I I/0.954883 B/0.00477976 I/0.954883 O/0.040337
's POS B B/0.986396 B/0.986396 I/0.00655976 O/0.00704426
Tulsa NNP I I/0.991966 B/0.00787494 I/0.991966 O/0.00015949
unit NN I I/0.996169 B/0.00283111 I/0.996169 O/0.000999975
..
N-best outputs
-n選項:使用這個選項將得到N-best結果,它根據CRF計算出的條件機率排序獲得。當選擇了N-best結果,CRF++會自動添加一行,形式爲「# N prob」,其中N是排序後的輸出結果,從0開始。prob表示output的條件機率。
須要注意的是,若是CRF++不能找到足夠的N條路徑是,它將放棄列舉N-best結果。這種狀況在所給的句子很短的狀況下常出現。
CRF++使用前向Viterbi和後向A*搜索相結合的方法。這種結合適應了n-best結果的需求。
下面是一個N-best結果的例子:
% crf_test -n 20 -m model test.data
# 0 0.478113
Rockwell NNP B B
International NNP I I
Corp. NNP I I
's POS B B
...
# 1 0.194335
Rockwell NNP B B
International NNP I I測試