HMM分词

作者: lwyaoshen | 来源:发表于2018-05-20 20:14 被阅读0次

    模型

    HMM的典型模型是一个五元组:
    StatusSet: 状态值集合
    ObservedSet: 观察值集合
    TransProbMatrix: 转移概率矩阵
    EmitProbMatrix: 发射概率矩阵
    InitStatus: 初始状态分布

    基本假设

    HMM模型的三个基本假设如下:
    有限历史性假设:
    P(Status[i]|Status[i-1],Status[i-2],… Status[1]) = P(Status[i]|Status[i-1])
    齐次性假设(状态和当前时刻无关):
    P(Status[i]|Status[i-1]) = P(Status[j]|Status[j-1])
    观察值独立性假设(观察值只取决于当前状态值):
    P(Observed[i]|Status[i],Status[i-1],…,Status[1]) = P(Observed[i]|Status[i])

    五元组

    2.3.1 状态值集合(StatusSet)

    为(B, M, E, S): {B:begin, M:middle, E:end, S:single}。分别代表每个状态代表的是该字在词语中的位置,B代表该字是词语中的起始字,M代表是词语中的中间字,E代表是词语中的结束字,S则代表是单字成词。

    给你一个隐马尔科夫链的例子。
    可以标注为:
    给/S 你/S 一个/BE 隐马尔科夫链/BMMMME 的/S 例子/BE 。/S
    

    观察值集合(ObservedSet)

    为就是所有汉字(东南西北你我他…),甚至包括标点符号所组成的集合。
    状态值也就是我们要求的值,在HMM模型中文分词中,我们的输入是一个句子(也就是观察值序列),输出是这个句子中每个字的状态值。

    初始状态概率分布(InitStatus )

    B  -0.26268660809250016
    E  -3.14e+100
    M  -3.14e+100
    S  -1.4652633398537678
    
    

    数值是对概率值取【对数】之后的结果(可以让概率【相乘】的计算变成对数【相加】)。其中-3.14e+100作为负无穷,也就是对应的概率值是0。
    也就是句子的第一个字属于{B,E,M,S}这四种状态的概率。

    转移概率矩阵(TransProbMatrix )

    【有限历史性假设】

    转移概率是马尔科夫链。Status(i)只和Status(i-1)相关,这个假设能大大简化问题。所以,它其实就是一个4x4(4就是状态值集合的大小)的二维矩阵。矩阵的横坐标和纵坐标顺序是BEMS x BEMS。(数值是概率求对数后的值)

    发射概率矩阵(EmitProbMatrix )

    【观察值独立性假设】
    P(Observed[i], Status[j]) = P(Status[j]) * P(Observed[i]|Status[j])
    其中,P(Observed[i]|Status[j])这个值就是从EmitProbMatrix中获取。

    使用Viterbi算法

    这五元的关系是通过一个叫Viterbi的算法串接起来,ObservedSet序列值是Viterbi的输入,而StatusSet序列值是Viterbi的输出,输入和输出之间Viterbi算法还需要借助三个模型参数,分别是InitStatus, TransProbMatrix, EmitProbMatrix。

    定义变量
    二维数组 weight[4][15],4是状态数(0:B,1:E,2:M,3:S),15是输入句子的字数。比如 weight[0][2] 代表 状态B的条件下,出现’硕’这个字的可能性。

    二维数组 path[4][15],4是状态数(0:B,1:E,2:M,3:S),15是输入句子的字数。比如 path[0][2] 代表 weight[0][2]取到最大时,前一个字的状态,比如 path[0][2] = 1, 则代表 weight[0][2]取到最大时,前一个字(也就是明)的状态是E。记录前一个字的状态是为了使用viterbi算法计算完整个 weight[4][15] 之后,能对输入句子从右向左地回溯回来,找出对应的状态序列。

    B:-0.26268660809250016
    E:-3.14e+100
    M:-3.14e+100
    S:-1.4652633398537678
    
    且由EmitProbMatrix可以得出
    
    Status(B) -> Observed(小)  :  -5.79545
    Status(E) -> Observed(小)  :  -7.36797
    Status(M) -> Observed(小)  :  -5.09518
    Status(S) -> Observed(小)  :  -6.2475
    
    所以可以初始化 weight[i][0] 的值如下:
    
    weight[0][0] = -0.26268660809250016 + -5.79545 = -6.05814
    weight[1][0] = -3.14e+100 + -7.36797 = -3.14e+100
    weight[2][0] = -3.14e+100 + -5.09518 = -3.14e+100
    weight[3][0] = -1.4652633398537678 + -6.2475 = -7.71276
    
    注意上式计算的时候是相加而不是相乘,因为之前取过对数的原因。
    
    
    
    //遍历句子,下标i从1开始是因为刚才初始化的时候已经对0初始化结束了
    for(size_t i = 1; i < 15; i++)
    {
        // 遍历可能的状态
        for(size_t j = 0; j < 4; j++) 
        {
            weight[j][i] = MIN_DOUBLE;
            path[j][i] = -1;
            //遍历前一个字可能的状态
            for(size_t k = 0; k < 4; k++)
            {
                double tmp = weight[k][i-1] + _transProb[k][j] + _emitProb[j][sentence[i]];
                if(tmp > weight[j][i]) // 找出最大的weight[j][i]值
                {
                    weight[j][i] = tmp;
                    path[j][i] = k;
                }
            }
        }
    }
    
    
    

    确定边界条件和路径回溯
    边界条件如下:
    对于每个句子,最后一个字的状态只可能是 E 或者 S,不可能是 M 或者 B。
    所以在本文的例子中我们只需要比较 weight[1(E)][14] 和 weight[3(S)][14] 的大小即可。

    在本例中:
    weight[1][14] = -102.492;
    weight[3][14] = -101.632;
    所以 S > E,也就是对于路径回溯的起点是 path[3][14]。

    回溯的路径是:
    SEBEMBEBEMBEBEB
    倒序一下就是:
    BE/BE/BME/BE/BME/BE/S
    所以切词结果就是:
    小明/硕士/毕业于/中国/科学院/计算/所

    相关文章

      网友评论

          本文标题:HMM分词

          本文链接:https://www.haomeiwen.com/subject/ibntjftx.html