一个有味道的男人's profileSecure's SpacePhotosBlogListsMore Tools Help

Blog


    March 06

    基于CRF的中文分词(转载)

    CRF简介

    Conditional Random Field:条件随机场,一种机器学习技术(模型)

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

    • 分词(标注字的词位信息,由字构词)
    • 词性标注(标注分词的词性,例如:名词,动词,助词)
    • 命名实体识别(识别人名,地名,机构名,商品名等具有一定内在规律的实体名词)

    本文主要描述如何使用CRF技术来进行中文分词

    CRF VS 词典统计分词

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

    CRF VS HMM,MEMM

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

    CRF分词原理

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

    • 词首,常用B表示
    • 词中,常用M表示
    • 词尾,常用E表示
    • 单子词,常用S表示

    2. CRF分词的过程就是对词位标注后,将B和E之间的字,以及S单字构成分词

    3. CRF分词实例:

    • 原始例句:我爱北京天安门
    • CRF标注后:我/S 爱/S 北/B 京/E 天/B 安/M 门/E
    • 分词结果:我/爱/北京/天安门

    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

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://securelvlan.spaces.live.com/blog/cns!C60FD6EABDDFC877!1322.trak
    Weblogs that reference this entry
    • None