CRF分词和隐马尔克夫模型分词,数据实验

隐马尔可夫模型是一个五元组<S,O,A,B,π>:

S:状态集合:即所有可能的状态s1,s2,…,sn所组成的集合。

O:观察序列:即实际存在的一个状态的有向序列,如状态o1,o2,…,on,注意状态是存在顺序的。

A:状态转移分布,即S中各元素中,两两之间转移的概率值。比如当前是s2,下一个状态是s9的转移概率为s2,9(小于1)。

B:每种状态出现的概率分布。

π:初始的状态分布

HMM模型有三个主要用途,没有例子可能比较难于理解,分词示例:

1.       参数学习

模型没有建立前,有已经分好词的部分语料。利用现有语料训练模型,得到各参数的值。我们使用最简单的HMM(设S由四种状态构成:词头,词中、词尾、单字成词),可以这样做:

假如训练语料有两句话:

我 爱 你 程序员。

他们 两个 人 是 半斤八两。

a.       O是观察序列,本例中,就是:“我、爱、你、程、序、员、他、们、两、个、人、是、半、斤、八、两”这16个字。

b.      S由四种状态构成:词头(如“程”),词中(如“序”)、词尾(如“员”)、单字成词(如“爱”、“你”)

c.       A即由一个状态转移到另一个状态的概率集合,本例共有8种状态

                                                               i.      单字成词->单字成词,如a我单单=1“我”后面一定是单字成词

                                                             ii.      单字成词->词头,如a我单头=0“我”后面一定不是词头,而a你单头=1

                                                            iii.      词头->词中

                                                           iv.      词头->词尾

                                                               i.            词中->词尾

                                                             ii.            词中->词中

                                                            iii.            词尾->词头

                                                           iv.            词尾->单字成词

d.      B由各状态的概率分布构成,如b我单=1(“我”一定单字成词)。

e.      π由初始状态的概率构成,此例中为π我=1/2(以“我”开头的概率为1/2),π他=1/2(以“他”开头的概率为1/2)。

2.       评价问题

以上面一个问题的参数为基础,评估第一句话:我 爱 你 程序员。

“我”开头的概率为π我=1/2,“我”转移到“爱”的概率为a我单=1,“爱”到“你”的概率为a单单=1,“你”到“程”的概率为a单头=1, “你”到“序”的概率为a头中=1,“序”到“员”的概率为a中尾=1,而本例(因为字太少,每个字只出现一次)中所有的b都为1,所以该句的概率为:

Pv=π我*b我单 *a我单单* b爱单*a爱单单*b你单 *a你单头* b程头*a程头中*b序中 *a序中尾* b员尾

注:至于数值越界等非原理问题这里就不详解了,请大家自己找资料。

3.       分词问题

比如还以第一个问题的参数为基础,来解码还没有分词的句子:我爱人是程序员。

因为首字是“我”,所以是“他”的情况被排除。

π我=1/2,

“我”后面是单字的概率为1,a我单=1(即只能是单字),其它情况的概率为0

“爱”后面是单字的概率为1,a爱单=1,其它情况的概率为0

“人”后面是单字的概率为1,a人单=1,其它情况的概率为0

“是”后面是词头的概率为1,a是头=1,其它情况的概率为0

“程”后面是词中的概率为1,a程中=1,其它情况的概率为0

“序”后面是词尾的概率为1,a序尾=1,其它情况的概率为0

所有分词的可能性是很多的,需要采用动态规划的算法,这里就不详述了,只给出其中三种可能作为示例:

a.       “我”为开头,“爱”是单字成词,“人”是单字成词,“是”是单字成词,“程”是词头,“序”是词中,“员”是词尾:

P1= π我*b我单*a我单单*b爱单*a爱单单*b人单*a人单单*b是单*a是单头*b程头*a程头中*b序中*a序中尾*b员尾

=1/2*1*1*1*1*1*1*1*1*1*1*1*1*1=1/2

b.      “我”为开头,“爱”是词头,“人”是词尾,“是”是单字成词,“程”是词头,“序”是词中,“员”是词尾:

P1= π我*b我单*a我单头*b爱头*a爱头尾*b人尾*a人尾单*b是单*a是单头*b程头*a程头中*b序中*a序中尾*b员尾

=1/2*1*0*0*0*0*0*1*1*1*1*1*1*1=0

c.       “我”为开头,“爱”是词头,“人”是词中,“是”是词尾,“程”是词头,“序”是词中,“员”是词尾:

P1= π我*b我单*a我单头*b爱头*a爱头尾*b人中*a人中尾*b是尾*a是尾头*b程头*a程头中*b序中*a序中尾*b员尾

=1/2*1*0*0*0*0*0*0*0*1*1*1*1*1=0

本人实现的隐马分词器下载(仅供参考):

http://download.csdn.net/source/1133534

内含实验报告等文件,便于读者理解程序的编写思想。



CRF分词:

中文分词的方法非常多,基于词库是最基本的,但是当前各大互联网公司基本上不会仅仅依赖于词库的分词,一般以机器学习的分词为主,词库分词的方式为辅。在很久以前,我提过利用隐马尔科夫模型进行中文分词,条件随机场其实是隐马尔科夫模型的一次升级版本,网上有很多关于条件随机场模型的分词,但是基本上很难看懂,也许是论文的缘故,那些作者习惯了一上来就是一堆复杂的公式,我也看了一些,获取有些作者自己都没搞懂,就弄了一篇论文。本文从实践的角度,提供一种基于条件随机场模型的中文分词解决方案。

      第一步:准备语料库。

      首先,你必须得准备一个已经分好词的语料库,用于机器学习,如下图所示:

     条件随机场分词1    

      第二步:初步语料库特征学习

      和隐马尔科夫模型一样,条件随机场也是基于学习字的状态来进行状态分析的,对于一个字来说,它有4个状态,分别是:词头(Begin)、词中(Middle)、词尾(End)、单字成词(Single),简称B,M,E,S。

      因此需要把第一步的语料库,分析出每一个字的状态,例如:“收益”需要改进为:“收|B 益|E”, 通过将语料库的每一个分好的词,添加其状态信息,如下图所示:

      条件随机场分词2

      第三步:特征学习

      有了第二步的初步学习,第三步就相对容易多了,特征学习是整个过程中非常重要的部分,在进行特征学习之前,必须弄清楚一个问题,要学习哪些特征?如下:

      1. 这一个字一共在语料库中出现的次数是多少?例如“我”字一共出现了256次。

      2. 这一个字,出现为词头(B)、词中(M)、词尾(E)、单字成词(S)的概率是多少?即为在256出现“我”字的时候,“我”作为词头的概率是多少,词中的概率是多少,依次类推。

      3. 这一个字,当为词头(B)的时候,它转移到下一个词的状态概率是多少?每一个字都有属于自己的状态,但是这个字的后面一个字,也有属于自己的状态,那么当前字的状态,到下一个字的状态(或许是B、M、E、S之一)的概率是多少。例“我”字,当“我”的状态为B的时候,后面跟的字中,状态为B的为0个,状态为M的为10个,状态为E的为20个,状态为S的0个。依次统计“我”的状态为M、E、S的时候,下一字的状态。此过程俗称:状态转移概率计算。此项会形成一个4X4的矩阵。

      截至前面三个特征学习,也许你会感觉与隐马尔科夫模型的方式没有太大区别,但是从理论上研究,条件随机场的准确率一定是高于隐马尔科夫模型的。是因为条件随机场会学习上下文关系,也就是多计算了,当一个字出现的时候,它的前一个字是什么,后一个字是什么,这个概率是多少,也就是我们第四个特征学习。

     4. 这一个字出现的时候,后面字出现的是什么,概率为多少?例如当状态为B的“我”,下一个字是“们”的概率为67.9%,例如状态为S的“我”,上一个字是“的”的概率为21%,下一个字是“爱”的概率为17.8%等等,记录每一个字在四种状态下上下文关系,是非常重要的一步。这一步中,我们仅仅记录了上一个字和下一个字的上下文关系,条件允许的情况下,我们可以记录上两个字和下两个字的上下文关系。

     利用代码,就是如下示例:

复制代码
/**
     * Feature for each word.
     * 
     * @author liufanping
     *
     */
    private static class Feature {

        /**
         * The State transition matrix
         */
        private Double[][] transfer;

        /**
         * The observation sequence transition matrix
         */
        private Double[] status;

        /**
         * The predecessor State
         */
        private TreeMap<Integer, Double> preStatus;

        /**
         * The next status
         */
        private TreeMap<Integer, Double> nextStatus;

        /**
         * Total count.
         */
        private int cnt;

        ... ...

    }
复制代码

     上面代码中需要注意两个事项:

     1. 每一个字都会有这样一个特征类,可以利用一个哈希表,key存字,value存其特征。

     2. 记录前后上下文的preStatus ,key是上一个字和当前字状态的组合,nextStatus,key是下一个字和当前字状态的组合,例如当前字是“我”,当前字的状态是B,下一个字可能是“们”,在nextStatus中,key就是“们_B”的哈希值,value均是出现这种情况的概率。

     我相信从语料库中学习这四个特征,应该不是一件很难的事情,自己根据描述完善代码即可。

     第四步:开始分词

     既然特征已经训练好了,怎么去给一个句子分词呢?例如用户输入“希腊的经济结构较特殊”,怎么就可以进行分词了呢?其实很简单,下面就是数学计算了。

     1. 将“希腊的经济结构较特殊”变成字符数组。即“希”、“腊”、“的”、“经”、“济”、“结”、“构”、“较”、“特”、“殊”。

     2. 取出每一个字对应特征(第三步产生的内容)。

     现在每一个字的特征以及取出来了,后面怎么办呢?我们先分析下,我们其实就是在给每一个字确定它是B、M、E、S四个状态中的哪一种,因此可以绘制一个矩阵。

     条件随机场分词3

     到这里,既然是矩阵,而且是求矩阵里面的一个路径,那么很容易想到维特比算法。到这里,我们只需要计算出“希”字在B、M、E、S的状态值,后面就游刃而解。

     我们设定矩阵中的值为S, S[字][当前状态]=MAX(P[上一个字任何状态][当前状态]*S[上一个字][任何一个状态])+W[前(后)一个字_当前状态][当前字]+R[当前状态概率]  (备注:R是特征二,P是特征三,W前是特征四的上文部分,W后是特征四的下文部分)

     例如“腊”字,在为状态B上的值为:S[腊][B]=MAX(P[B][B]*S[希][B],P[M][B]*S[希][M],P[E][B]*S[希][E],P[S][B]*S[希][S])+W前[希_B][腊]+W后[的_B][腊]+R[B],同理可以计算S[腊][M],S[腊][E],S[腊][S]。

     依次类推,可以计算出后面其它字的情况。由于“希”字出现在首字,不存在其它状态转移到其状态的概率,因此,S[希][B]=W前[_B][希]+W后[腊_B][希]+R[B],依次计算出“希”字其它值。

     上面过程,希望反复用研究下,研究透后,你会发现很简单,通过计算会得到如下矩阵:

    条件随机场分词4

    看到这里,你似乎已经看到分词的结果了,在矩阵中所有值的后面,都有一个小括号,里面存放的是路径,也就是这个值是通过上一个的哪一个值过来的(因为有计算max的过程,就会有路径选择),记录下来之后,以便于路径回溯。

    当得到这个矩阵之后,我们只需要将“殊”中的最大值取出,即为1.1867对应状态是End,来自上一字的状态0,也就是“特”字的Begin,再次查看“特”字来自于上一个字“较”的Single。因此,判别状态如下

    “希/B 腊/E 的/S 经/B 济/E 结/B 构/E 较/S 特/B 殊/E”

    翻译成分词结果就是“希腊 的 经济 结构 较 特殊”。

    完成的实现分词过程,如果你对此项有点模糊,建议看下维特比算法。

    写到最后,我也要感谢您能够看到最后,这是比较简单的一种利用条件随机场进行分词的方式,复杂的,可以在这个基础上进行优化升级。

    诚挚的谢意!



CRF++分词实验,采用JAVA。源码和数据如下:

http://download.csdn.net/download/luozhipeng2011/8872241


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值