• 开源自然语言处理工具包hanlp中CRF分词实现详解


     

     CRF简介

    CRF是序列标注场景中常用的模型,比HMM能利用更多的特征,比MEMM更能抵抗标记偏置的问题。

    [gerative-discriminative.png] 

    CRF训练

    这类耗时的任务,还是交给了用C++实现的CRF++。关于CRF++输出的CRF模型,请参考《CRF++模型格式说明》。 

    CRF解码

    解码采用维特比算法实现。并且稍有改进,用中文伪码与白话描述如下:

    首先任何字的标签不仅取决于它自己的参数,还取决于前一个字的标签。但是第一个字前面并没有字,何来标签?所以第一个字的处理稍有不同,假设第0个字的标签为X,遍历X计算第一个字的标签,取分数最大的那一个。

    如何计算一个字的某个标签的分数呢?某个字根据CRF模型提供的模板生成了一系列特征函数,这些函数的输出值乘以该函数的权值最后求和得出了一个分数。该分数只是“点函数”的得分,还需加上“边函数”的得分。边函数在本分词模型中简化为f(s,s),其中s’为前一个字的标签,s为当前字的标签。于是该边函数就可以用一个4*4的矩阵描述,相当于HMM中的转移概率。

    实现了评分函数后,从第二字开始即可运用维特比后向解码,为所有字打上BEMS标签。 

    实例

    还是取经典的“商品和服务”为例,首先HanLPCRFSegment分词器将其拆分为一张表:

     

    null表示分词器还没有对该字标注。

    代码

    上面说了这么多,其实我的实现非常简练:

     

     

     

    标注结果

    标注后将table打印出来:

     

    最终处理

    BEMS该合并的合并,得到:

    [商品/null, /null, 服务/null]

    然后将词语送到词典中查询一下,没查到的暂时当作nx,并记下位置(因为这是个新词,为了表示它的特殊性,最后词性设为null),再次使用维特比标注词性:

    [商品/n, /cc, 服务/vn]

    新词识别

    CRF对新词有很好的识别能力,比如:

    CRFSegment segment = new CRFSegment();

    segment.enablePartOfSpeechTagging(true);

    System.out.println(segment.seg("你看过穆赫兰道吗"));

    输出

    CRF标注结果

      S   

      S   

      S   

      B   

      M   

      M   

      E   

      S   

    [/rr, /v, /uguo, 穆赫兰道/null, /y]

    null表示新词。

  • 相关阅读:
    select option 下拉多选单选bootstrap插件使用总结
    bootstrap-dialog的使用
    display的table和cell外加table-layout:fixed等分布局,外加换行,word-wrap:break-word
    css样式实现字体删除线效果
    递归实现遍历二叉树
    童晶老师的游戏开发课程作业--实时时钟的实现
    张宵 20201120-1 每周例行报告
    张宵 20201112-1 每周例行汇报
    20201105-1 每周例行报告
    张宵 20201029-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/adnb34g/p/10441625.html
Copyright © 2020-2023  润新知