条件随机场(CRF)及CRF++安装使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq575379110/article/details/71125258

  这个,终于到了要解决命名实体识别的问题,搞自然语言处理,貌似这个绕不开的。CRF,传统的干这活的利器,听名字就是高大上。既然绕不开,那就整整吧。

  CRF是用来标注和划分序列结构数据的概率化结构模型。言下之意,就是对于给定的输出,标识序列Y和观测序列X,条件随机场通过定义条件概率P(Y | X),而不是联合概率分布P(X, Y)来描述模型。
  很清楚了,这是个判别模型。
  CRF也可以看做一个无向图模型或者马尔可夫随机场。
  任何一个概念,都要从定义着手:

  设G = (V, E)为一个无向图,V为结点集合,E为无向边的结合。Y = {Yv | v ∈ V},即V中的每个结点对应于一个随机变量Yv,其取值范围为可能的标记集合{y}。如果以观察序列X为条件,每一个随机变量Yv都满足以下马尔可夫特性:p(Yv | X, Yw, w ≠ v) = p(Yv | X, Yw, w ~ v),其中,w ~ v表示两个结点在图G中是邻近结点。那么(X,Y)为一个条件随机场。

  从定义中能得出啥来呢?
  CRF考虑一件东西,不但要考虑自身,还要考虑周围的情况。举个例子,我们做命名实体识别,例句:“Google的总部在硅谷”。我们知道地址是“硅谷”,其他位置的词对我们识别“硅谷”有啥帮助呢?例如,“硅谷”前面是“在”,是不是这个字后面经常接地址呢?“在”前面的词是不是应该是名词?这样的综合考虑,就是CRF中的特征选择或者叫特征模板。
  简要的说,CRF算法,需要解决三个问题:
  1、特征的选择
  在CRF中,很重要的工作就是找特征函数,然后利用特征函数来构建特征方程。在自然语言处理领域,特征函数主要是指一个句子 s,词在句子中的位置 i,当前词的标签 l_{i},前一个词的标签 l_{i-1}。
  2、参数训练
  在每一个特征函数之前,都有一个参数,也就是训练它们的权重。CRF的参数训练,可以采用梯度下降法。
  3、解码
  解码问题,如果来一个句子,遍历所有可能的分割,会导致计算量过大。因此,可以采用类似viterbi这样的动态规划算法,来提高效率。
  这里介绍的比较简略,我当时看CRF的资料,发现国外写的都比较浅显易懂,文末放链接。


  下面介绍CRF++的使用。
  首先吐槽一下自己的智商,我在linux上安装好crf++后,因为提示信息比较奇怪,自己没见过,所以一直以为没安装好,各种Google和Baidu,结果白花了两天时间,真是心疼和郁闷。
  我就不贴图了,这个按照官网的说明,一步步走下去,只要没出ERROR这样的信息,就是成功了。
  如果不放心的话,那就按照官网的例子,跑跑证明一下。
  我用的版本是CRF++-0.58,应该是最新的,很久不更新了。按照说明安装就好。

  根据上面CRF的介绍,我们列举了CRF要解决的三个问题:  

  1. 特征模板
  2. 参数训练
  3. 解码

    下面依次介绍CRF++如何解决这三个问题。
    1、特征模板:
    CRF++解决这个问题,是编写template文件,数据格式(实体,标注)如下:

Input: Data
He        PRP  B-NP
reckons   VBZ  B-VP
the       DT   B-NP << CURRENT TOKEN
current   JJ   I-NP 
account   NN   I-NP

  以current token为基准,用%x[0,0]这些数字组合来表示相应实体位置:

template expanded feature
%x[0,0] the
%x[0,1] DT
%x[-1,0] reckons
%x[-2,1] PRP
%x[0,0]/%x[0,1] the/DT
ABC%x[0,1]123 ABCDT123

  
  模板类型有两种,比较常用的是Unigram template(单字特征),以U开头。比如,我们使用”U01:%x[0,1]“为模板,CRF++会自动的生成一系列的特征函数:
  

func1 = if (output = B-NP and feature="U01:DT") return 1 else return 0
func2 = if (output = I-NP and feature="U01:DT") return 1 else return 0
func3 = if (output = O and feature="U01:DT") return 1  else return 0
....
funcXX = if (output = B-NP and feature="U01:NN") return 1  else return 0
funcXY = if (output = O and feature="U01:NN") return 1  else return 0
...

  看起来好多式子啊,会生成多少个呢?
  CRF++的原理,就是生成L * N个式子,L是输出的可能个数,N是相应位置上可能的个数。上面的”U01:%x[0,1]“,N就是在[0,1]这个位置上有多少个可能性,再乘以输出值(例如“B-NP”)的可能性。
  这个仔细思考一下就好。

  CRF++生成所有的特征函数,而训练的就是这些特征函数前面的权重参数。

  还有一个模板类型是“Bigram template”(双字特征),以“B”开头。和Unigram template的区别在于输出Unigram template输出的是单个输出标签,Bigram template输出的是两个输出标签,则Bigram template的输出可能性为L*L*N。这个容易出现计算膨胀,所以,用Unigram template的多。

2、参数训练

  这个问题,CRF++封装的比较好了,直接使用命令:

%crf_learn template train.data model

3、解码

% crf_test -m model test.data

  剩下的2, 3两个问题还是比较简单的了。


参考文献:

展开阅读全文

没有更多推荐了,返回首页