CRF++
( 空格分隔): nlp
[TOC]
http://x-algo.cn/index.php/2016/02/29/crf-name-entity-recognition/#i
使用說明
安裝
CRF++官網: https://taku910.github.io/crfpp/#tips
注意windows和linux下載的版本不同
example 包含 basenp,chunking,JapaneseNE,seg。前兩個是英文數據,后兩個是日文數據。第一個應該是命名實體識別,第二個應該是分詞,第三個應該是日文命名實體識別,第四個不清楚。windows: 可以選擇example里的某個例子做測試,比如選chunking。將crf_learn.exe;crf_test.exe;libcrfpp.dll三個文件復制到到,含有exec.sh;template;test.data;train.data的文件夾(chunking)里。cmd,cd進入該文件夾
(目的:保持數據文件和代碼文件處于同一目錄下,減少輸入文件路徑)
使用參考教程:
Windows下CRF++分詞實踐及Python分詞效果評測
命名實體識別參考教程:
[1] http://blog.csdn.net/felomeng/article/details/4367250
[2] 人民日報:http://blog.csdn.net/cuixianpeng/article/details/42171615注意:
務必記得每行的訓練數據的標注必須要加上開頭的B_、I_等等。
否則sgd在訓練過程中,雖然accuracy一直會增長,但是precision和recall將一直是0.
template
模板說明: http://www.hankcs.com/nlp/the-crf-model-format-description.html
jieba 結巴分詞和詞性標注:
http://www.mamicode.com/info-detail-1889910.html
訓練模型
不帶參數:
crf_learn template_file train_file model_file
這個訓練過程的時間、迭代次數等信息會輸出到控制臺上如果想保存這些信息,我們可以將這些標準輸出流到文件上,命令格式如下:
crf_learn template_file train_file model_file > train_info_file
-
帶參數
crf_learn -a CRF-L2 -c 4.0 -f 3 -p 4 template train.data model
-a CRF-L2 or CRF-L1 規范化算法選擇。默認是CRF-L2。一般來說L2算法效果要比L1算法稍微好一點,雖然L1算法中非零特征的數值要比L2中大幅度的小。 -c float 這個參數設置CRF的hyper-parameter。c的數值越大,CRF擬合訓練數據的程度越高。這個參數可以調整過度擬合和不擬合之間的平衡度。這個參數可以通過交叉驗證等方法尋找較優的參數。 -f NUM 這個參數設置特征的cut-off threshold。CRF++使用訓練數據中至少NUM次出現的特征。默認值為1。當使用CRF++到大規模數據時,只出現一次的特征可能會有幾百萬,這個選項就會在這樣的情況下起到作用。 -p NUM 如果電腦有多個CPU,那么那么可以通過多線程提升訓練速度。NUM是線程數量。 -f, --freq=INT 使用屬性的出現次數不少于INT(默認為1) -m, --maxiter=INT 設置INT為LBFGS的最大跌代次數(默認10k) -c, --cost=FLOAT 設置FLOAT為代價參數,過大會過度擬合(默認1.0) -e, --eta=FLOAT 設置終止標準FLOAT(默認0.0001) -C, --convert 將文本模式轉為二進制模式 -t, --textmodel 為調試建立文本模型文件 -a, --algorithm=(CRF|MIRA) 選擇訓練算法,CRF-L2 or CRF-L1,默認為CRF-L2 -p, --thread=INT 線程數(默認1),利用多個CPU減少訓練時間 -H, --shrinking-size=INT 設置INT為最適宜的跌代變量次數(默認20) -v, --version 顯示版本號并退出 -h, --help 顯示幫助并退出
測試
- 不帶參數:
crf_test -m model_file test_files
與crf_learn類似,輸出的結果放到了標準輸出流上 - 而這個輸出結果是最重要的預測結果信息(測試文件的內容+預測標注),同樣可以使用重定向,將結果保存下來,命令行如下:
crf_test -m model_file test_files >> result_file
- 帶參數:
crf_test -v1 -m model test.data| head
有兩個參數-v和-n都是顯示一些信息的,
-v,可以顯示預測標簽的概率值
-n,可以顯示不同可能序列的概率值,對于準確率,召回率,運行效率,沒有影響
評估結果
安裝 perl strawberry 64bit for windows
下載 conlleval.pl
運行命令:
perl conlleval.pl <result.txt
result.txt是待評估的文件,是crf測試集輸出的結果注意:
conlleval.pl中代碼my $delimiter = " "; # field delimiter
要求待評估的文件,必須是以空格作為分隔符,否則運行命令出錯:
conlleval: unexpected number of features in line XXX XX XX
參考說明:http://www.52ml.net/2463.html解決方法1:將conlleval.pl中的空格分隔符改為tab,即:
my $delimiter = "[空格]"
替換為my $delimiter = "[tab]"
解決方法2:將result.txt中的tab分隔符改為空格
實驗結果
Windows 10 , python 2.7
處理步驟:
- 原始語料處理
一句一行
*可選:去除{{time:}}等標記- 打標簽 BMEUNS
- 切分訓練集和測試集
- 調整crf++的template
- 訓練,調參
- 測試
- 評估
word+POS+Tag(B/M/E/U/NS)
- 去掉了原始語料中的{{time:}}等符號 , pos+tag
娃哈哈 nz B
集團 n E
在 p NS
黔 j U
發展 vn NS
近十年 l U
, x NS
見證 v NS
了 ul NS
貴州 ns U
發展 vn NS
取得 v NS
的 uj NS
巨大 a NS
成績 n NS
。 x NS
- template
# 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]
U10:%x[-2,1]
U11:%x[-1,1]
U12:%x[0,1]
U13:%x[1,1]
U14:%x[2,1]
U15:%x[-2,1]/%x[-1,1]
U16:%x[-1,1]/%x[0,1]
U17:%x[0,1]/%x[1,1]
U18:%x[1,1]/%x[2,1]
U20:%x[-2,1]/%x[-1,1]/%x[0,1]
U21:%x[-1,1]/%x[0,1]/%x[1,1]
U22:%x[0,1]/%x[1,1]/%x[2,1]
U23:%x[0,1]
# Bigram
B
Done!179.61 s
POS+dictionary
- userDic
浙江在線紹興 100 nr
福美來三代啟停版 100 nr
搜狗 100 nr
岳飛 100 nr
搜狐 100 nr
- 原始語料未作清洗,POS+tag
娃 nz B
哈 nz I
哈 nz I
集 n O
團 n O
} x O
} x O
在 p O
{ x O
{ x O
l eng O
o eng O
c eng O
a eng O
t eng O
i eng O
o eng O
n eng O
: x O
黔 j O
} x O
} x O
發 vn O
展 vn O
- template 同上
Done!70.12 s
分詞沒有添加詞典
template同上
娃 nz B
哈 nz I
哈 nz I
集 n O
團 n O
} x O
} x O
在 p O
{ x O
{ x O
l eng O
o eng O
c eng O
a eng O
t eng O
i eng O
o eng O
n eng O
: x O
黔 j O
} x O
} x O
發 vn O
展 vn O
???詞性標注和前面加載了詞典一樣
Done!88.84 s
強行修改標簽
noSeg , 詞性POS
娃 POS B
哈 POS I
哈 POS I
集 POS I
團 POS I
} POS 0
} POS 0
在 POS 0
{ POS 0
{ POS 0
l POS 0
o POS 0
c POS 0
a POS 0
t POS 0
i POS 0
o POS 0
n POS 0
: POS 0
黔 POS B
} POS 0
} POS 0
發 POS 0
展 POS 0
template同上
Done!175.85 s
noPOS+template
娃 B
哈 I
哈 I
集 I
團 I
} 0
} 0
在 0
{ 0
{ 0
l 0
o 0
c 0
a 0
t 0
i 0
o 0
n 0
: 0
黔 B
} 0
} 0
發 0
展 0
設置template
# Unigram
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
B
結果:
Done!77.47 s
總結
feature | time | precision | recall | FB1 |
---|---|---|---|---|
c_noPOS-BIO | 175.85s | 86.46% | 82.18% | 84.26 |
c_noPOS+template-BIO | 77.47s | 86.73% | 84.16% | 85.43 |
c_POS(noDic)-BIO | 88.84 | 92.08% | 92.08% | 92.08 |
c_POS+dic-BIO | 70.12s | 98.96% | 98.73% | 98.85 |
w_POS(noDic)-BMEUNs | 179.61s | 99.80% | 99.52% | 99.66 |
c_表示一字一行處理的, w表示一詞一行
疑問
添加詞典與否事實上結果一樣,上文的結果不相同是因為強行對訓練集和測試集對的BIO標簽進行了修改,命名實體的完全是BI。如果自動分詞,粒度較細,實體標簽不一定完全正確。
- 修改標簽以后,92.08
n eng 0
a eng 0
m eng 0
e eng 0
: x 0
浙 nr B
江 nr I
在 nr I
線 nr I
杭 nr I
州 nr I
} x 0
} x 0
- 沒有修改標簽,98.85
n eng O
a eng O
m eng O
e eng O
: x O
浙 ns B
江 ns I
在 b O
線 b O
杭 ns B
州 ns I
} x O
} x O
- 預料中給定的NER是否是NER?
{{location:河北省邯鄲市火車站過街天橋南約100米}}的路西,十幾個男子圍成一團,氣氛很是熱烈。
{{product_name:嘻嘻MACWE書包中學生女雙肩包男女背包韓版潮學院風旅行包帆布電腦包}}{{product_name:http://t.cn/8sSfk0S}}
嘻嘻{{company_name:MACWE}}書包中學生女雙肩包男女背包{{location:韓}}版潮學院風旅行包帆布電腦包{{product_name:http://t.cn/8sSfk0S}}