使用CRF进行中文分词

期末做了一个中文分词项目,利用条件随机场(CRF)进行分词。稍微总结一下:

CRF简介

Conditional Random FieldCRF):条件随机场,一种机器学习模型

CRFJohn Lafferty最早用于NLP技术领域,其在NLP技术领域中主要用于文本标注,并有多种应用场景,例如:

 

l         分词(标注字的词位信息,由字构词)

l         词性标注(标注分词的词性,例如:名词,动词,助词)

l         命名实体识别(识别人名,地名,机构名,商品名等具有一定内在规律的实体名词)

 CRF与其他分词方法的比较

CRF VS 词典统计分词

  • 基于词典的分词过度依赖词典和规则库,因此对于歧义词和未登录词的识别能力较低;其优点是速度快,效率高
  • CRF代表了新一代的机器学习技术分词,其基本思路是对汉字进行标注即由字构词(组词),不仅考虑了文字词语出现的频率信息,同时考虑上下文语境,具备较好的学习能力,因此其对歧义词和未登录词的识别都具有良好的效果;其不足之处是训练周期较长,运营时计算量较大,性能不如词典的分词

CRF VS HMMMEMM

  • 首先,CRFHMM(隐马模型)MEMM(最大熵隐马模型)都常用来做序列标注的建模,像分词、词性标注,以及命名实体标注
  • 隐马模型一个最大的缺点就是由于其输出独立性假设,导致其不能考虑上下文的特征,限制了特征的选择
  • 最大熵隐马模型则解决了隐马的问题,可以任意选择特征,但由于其在每一节点都要进行归一化,所以只能找到局部的最优值,同时也带来了标记偏见的问题,即凡是训练语料中未出现的情况全都忽略掉
  • 条件随机场则很好的解决了这一问题,他并不在每一个节点进行归一化,而是所有特征进行全局归一化,因此可以求得全局的最优值。

CRF分词原理

(1)CRF把分词当做字的词位分类问题,通常定义字的词位信息如下:

l         词首,常用B表示

l         词中,常用M表示

l         词尾,常用E表示

l         单子词,常用S表示

 

按是否在该位置断词,字的词位信息也可以简单划分为两类:

l         断字,常用I表示 ,说明此字之后应该跟词分界符,即此字是词的最后一个字。

l         非断字,常用B表示 ,说明此字之后不跟词分界符。

 

(2) CRF分词的过程

对词位标注后,将BE之间的字,以及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的序列可构成一个sentencesentence之间用一个空行间隔。最后一列是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_filetrain_file需由使用者事先准备好。crf_learn将生成训练后的模型并存放在model_file中。

训练文件的格式:

CN   B

CN   B

CN   B

CN   I


测试

% crf_test -m model_file test_files …
其中,model_filecrf_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文档聚类项目,做一个中文的聚类搜索引擎。

简单的系统流程如下:

先获取搜索的结果页面,可以爬虫实现或者早期可以从baidugoogle等搜索网站直接捕获搜索结果页面;然后对结果页面进行中文分词;接着利用SVM计算结果页面直接的相似度;最后利用聚类算法(比如Ncut谱聚类)对结果网页聚类,将聚类结果展现给网络用户。



 

此条目发表在科研路分类目录。将固定链接加入收藏夹。

2 Responses to 使用CRF进行中文分词

  1. 小鱼说道:

    请教一下大牛:> perl conlleval.pl < test_result.txt 为什么我用这个命令,竟然报错,训练和测试的例子都是从你的例子拷贝的,conlleval: unexpected number of features in line ? h I B

  2. 少伟说道:

    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),则可以通过简单的比较第三列和第四列之间的差别计算出准确率。

留下评论