CRF简介
Conditional Random Field(CRF):条件随机场,一种机器学习模型
CRF由John Lafferty最早用于NLP技术领域,其在NLP技术领域中主要用于文本标注,并有多种应用场景,例如:
l 分词(标注字的词位信息,由字构词)
l 词性标注(标注分词的词性,例如:名词,动词,助词)
l 命名实体识别(识别人名,地名,机构名,商品名等具有一定内在规律的实体名词)
CRF与其他分词方法的比较
CRF VS 词典统计分词
- 基于词典的分词过度依赖词典和规则库,因此对于歧义词和未登录词的识别能力较低;其优点是速度快,效率高
- CRF代表了新一代的机器学习技术分词,其基本思路是对汉字进行标注即由字构词(组词),不仅考虑了文字词语出现的频率信息,同时考虑上下文语境,具备较好的学习能力,因此其对歧义词和未登录词的识别都具有良好的效果;其不足之处是训练周期较长,运营时计算量较大,性能不如词典的分词
CRF VS HMM,MEMM
- 首先,CRF,HMM(隐马模型),MEMM(最大熵隐马模型)都常用来做序列标注的建模,像分词、词性标注,以及命名实体标注
- 隐马模型一个最大的缺点就是由于其输出独立性假设,导致其不能考虑上下文的特征,限制了特征的选择
- 最大熵隐马模型则解决了隐马的问题,可以任意选择特征,但由于其在每一节点都要进行归一化,所以只能找到局部的最优值,同时也带来了标记偏见的问题,即凡是训练语料中未出现的情况全都忽略掉
- 条件随机场则很好的解决了这一问题,他并不在每一个节点进行归一化,而是所有特征进行全局归一化,因此可以求得全局的最优值。
CRF分词原理
(1)CRF把分词当做字的词位分类问题,通常定义字的词位信息如下:
l 词首,常用B表示
l 词中,常用M表示
l 词尾,常用E表示
l 单子词,常用S表示
按是否在该位置断词,字的词位信息也可以简单划分为两类:
l 断字,常用I表示 ,说明此字之后应该跟词分界符,即此字是词的最后一个字。
l 非断字,常用B表示 ,说明此字之后不跟词分界符。
(2) CRF分词的过程
对词位标注后,将B和E之间的字,以及S单字构成分词。
或者在第二中分类方法中,在断字的后面添加词分界符。
(3) CRF分词实例:
- 原始例句:我们都是中国人。
- CRF标注后:我/B们/I都/I是/I中/B国/B人/I。/I
- 分词结果:我们 都 是 中国人 。
使用CRF++进行中文分词
CRF++简介
CRF++是一个用c++实现的CRF开源工具包,在CRF++官方主页可以下载到源码和可运行文件(http://crfpp.sourceforge.net/)。在官方网址上也可以看到使用细节。其使用过程为:
(1) 准备符合输入格式训练和测试数据;
(2) 准备特征模板;
(3) 训练;
(4) 测试。
训练和测试文件的格式
训练和测试文件必须包含多个tokens,每个token包含多个列,且每个token的列数必须一致。token的定义可根据具体的任务,如词、词性等。每个token必须写在一行,且各列之间用空格或制表格间隔。一个token的序列可构成一个sentence,sentence之间用一个空行间隔。最后一列是CRF用于训练的正确的标注形式。
例如下面的例子中每个token包含3列,分别为字本身、字类型(英文数字,汉字,标点等)和词位标记。
我 CN I
是 CN I
中 CN B
国 CN B
人 CN I
, PUCN I
And En I
you EN I
? PUCN I
特征模板
因为CRF++设计为一个泛用的工具,使用者必须事先指定特征模板(template_file),该文件描述了训练和测试时会用到的特征。
# 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] 当前字的字类型和下个字的字类型和下下个字的字类型
# Bigram
B
训练
调用crf_learn.exe对训练数据进行训练,使用crf_learn 命令:
>crf_learn template_file train_file model_file
其中,template_file和train_file需由使用者事先准备好。crf_learn将生成训练后的模型并存放在model_file中。
训练文件的格式:
總 CN B
辦 CN B
事 CN B
處 CN I
…
测试
% crf_test -m model_file test_files …
其中,model_file是crf_learn创建的。在测试过程中,使用者不需要指定template file,因为,mode file已经有了template的信息。test_file是你想要标注序列标记的测试语料。
测试文件的格式:
可以和训练文件一样(含分词答案,可以评估效果),或少掉最后一列(只预测分词,不能评估),为:
大 CN
陸 CN
考 CN
古 CN …
评估
调用conlleval.pl(crf++官方网站提供下载)对预测结果文件进行评估。
> perl conlleval.pl < test_result.txt
本项目实验结果:P值:93.14%;R值:92.54%;F值:92.84%
分词还是相当准确的!
将来的工作
考虑与其他的NPL项目结合,做中文自然语言处理的高级应用。例如,结合web文档聚类项目,做一个中文的聚类搜索引擎。
简单的系统流程如下:
先获取搜索的结果页面,可以爬虫实现或者早期可以从baidu,google等搜索网站直接捕获搜索结果页面;然后对结果页面进行中文分词;接着利用SVM计算结果页面直接的相似度;最后利用聚类算法(比如Ncut谱聚类)对结果网页聚类,将聚类结果展现给网络用户。
请教一下大牛:> perl conlleval.pl < test_result.txt 为什么我用这个命令,竟然报错,训练和测试的例子都是从你的例子拷贝的,conlleval: unexpected number of features in line ? h I B
perl conlleval.pl < test_result.txt 是对你的预测结果进行评估,其中conlleval.pl 是peal写的评估程序,test_result.txt 的格式要求是四列,如下:為 CN I I了 CN I I要 CN I I準 CN B B備 CN I I聯 CN B B考 CN I I, PUCN I I其中,最后一列是模型预测的tag。如果第三列是标准的tag(该列对测试结果没有影响,只是为了比较标准tag和估计tag),则可以通过简单的比较第三列和第四列之间的差别计算出准确率。