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}}