NLP作业01:请利用HMM实现词性标注

本文介绍了HMM的基本概念,如模型参数和常见例子,详细讲解了HMM的模型参数估计过程,并通过维特比算法进行解码示例,应用于词性标注问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、作业头

二、什么是HMM

常见的例子 

三、估计HMM的模型参数

四、基于维特比算法进行解码

维特比算法

代码

五、词性标注结果


一、作业头

这个作业属于那个课程自然语言处理
这个作业要求在哪里http://t.csdn.cn/f0hUe
我在这个课程的目标是学习自然语言处理技术,完善专业技术
这个作业在那个具体方面帮助我实现目标了解HMM模型和学习词性标注
参考文献

https://blog.youkuaiyun.com/Daycym/article/details/89331220

https://blog.youkuaiyun.com/sharic_song/article/details/105319961

https://blog.youkuaiyun.com/weixin_62231629/article/details/127051385

https://blog.youkuaiyun.com/chunyun0716/article/details/52963748

https://blog.youkuaiyun.com/sinat_33741547/article/details/78867039

二、什么是HMM

隐马尔可夫模型(Hidden Markov Model,HMM)是统计模型,它用来描述一个含有隐含未知参数的马尔可夫过程。

常见的例子 

抛硬币
假设小明有两个硬币A、B,这两个硬币的正反面的概率是不一样的,我们假设A硬币正面的概率为0.6,B硬币正面的概率为0.7,那么如果我们在未来6次的硬币抛掷过程中,得到如下的结果:

硬币(Z)    A    B    B    A    B    A
结果(x)    正    反    正    正    反    正
这种时候就会存在三个问题:

第一次即初始投的硬币是A还是B?
若知道前一次投的硬币的种类,那后一次硬币是A还是B?
每次投掷硬币时,结果是正面还是反面?
针对第一个问题,那么就有一个初始的概率P(π),它决定了第一个位置是A还是B,然后假设确定了初始的位置为A,那么我们就需要知道第一次投掷硬币的结果是正还是反,这就是一个生成概率P(A),然后呢我们还得知道第二次硬币是A还是B,假设是B,那么就有一个P(B|A)的转移概率。这就是HMM模型的三个参数。
针对我们上面的投掷硬币的问题,HMM模型的三个参数为(π,A,B)


其中π代表第一个位置P(A)=0.3,P(B)=0.7
A代表转移矩阵P(A|A)=0.3, P(B|A)=0.5, P(A|B)=0.4, P(B|B)=0.6
B代表生成矩阵P(正|A)=0.4,P(反|A)=0.6,P(正|B)=0.2,P(反|B)=0.8

三、估计HMM的模型参数

参数估计问题:给定一个观察序列O=O1O2…OTO=O1O2…OT,如何调节模型μ=(A,B,π)μ=(A,B,π)的参数,使得P(O|μ)P(O|μ)最大化:

模型的参数是指构成 μμ的 πi,aij,bj(k)πi,aij,bj(k)。本文的前序两节讲的EM算法就是为了解决模型参数的最大化问题。其基本思想是,初始时随机地给模型参数赋值,该赋值遵循模型对参数的限制,例如,从某一状态出发的所有转移概率之和为1.给模型参数赋初值后,得到模型 μ0μ0, 然后根据 μ0μ0可以得到模型中隐变量的期望值。例如,从 μ0μ0得到某一状态到另一状态的期望次数,用期望次数来替代实际次数,这样可以得到模型参数的重新估计值,由此得到新的模型 μ1μ1。然后重复上述过程,直到参数收敛于最大似然估计值。

Hidden_states = ('Healthy', 'Fever') # 隐状态集合
 
Observations_states = ('normal', 'cold', 'dizzy') # 观测状态集合
 
Start_probability = {'Healthy': 0.6, 'Fever': 0.4} # 表示病人第一次到访时医生认为其所处的HMM状态,他唯一知道的是病人倾向于是健康的(可以理解为这是基于一个对大众身体信息的了解得出的初始状态)
 
Hidden_transition_probability = { # 隐马尔可夫链中身体状态的状态转移概率,我们能够看到,当天健康的人,第二天有30%的概率会发烧
   'Healthy' : {'Healthy': 0.7, 'Fever': 0.3},
   'Fever' : {'Healthy': 0.4, 'Fever': 0.6},
   }
 
Hidden_observations_probability = {    # 原来叫emission_probability。这里表示病人每天的感觉的可能性。即,如果他是一个健康人,有50%的可能会感觉正常,40%觉得冷,10%觉得头晕
   'Healthy' : {'normal': 0.5, 'cold': 0.4, 'dizzy': 0.1},
   'Fever' : {'normal': 0.1, 'cold': 0.3, 'dizzy': 0.6},
   }

# Helps visualize the steps of Viterbi.
def print_dptable(V): # 打印dp矩阵
    print ("    "),
    for i in range(len(V)): 
        print("%7d" % i)
    print()

    for y in V[0].keys():
        print ("%.5s: " % y)
        for t in range(len(V)):
            print ("%.7s" % ("%f" % V[t][y]))
        print()

def viterbi(obs, states, start_p, trans_p, h2o_p): # Viterbi算法
    V = [{}]
    path = {}

    # Initialize base cases (t == 0)
    for y in states:
        V[0][y] = start_p[y] * h2o_p[y][obs[0]]
        path[y] = [y]

    # Run Viterbi for t > 0
    for t in range(1,len(obs)):
        V.append({})
        newpath = {}

        for y in states:
            (prob, state) = max([(V[t-1][y0] * trans_p[y0][y] * h2o_p[y][obs[t]], y0) for y0 in states])
            V[t][y] = prob
            newpath[y] = path[state] + [y]

        # Don't need to remember the old paths
        path = newpath

    print_dptable(V)
    (prob, state) = max([(V[len(obs) - 1][y], y) for y in states])
    return (prob, path[state])

def example():
    return viterbi(Observations_states,
                   Hidden_states,
                   Start_probability,
                   Hidden_transition_probability,
                   Hidden_observations_probability)
print(example())

四、基于维特比算法进行解码

维特比算法

与穷举法不同,维特比算法是基于动态规划思想的隐马尔科夫模型解法。动态规划原理提到,假设存在一条最优路径,那么将该路径切分成N段,那么这N段小路径都分别是该环境下的最优路径,否则就存在着其他未知小路径,能组成一个比最优路径还更好的路径,这显然不成立。

基于上述原理,我们只需要从时刻t=1开始,递归的计算子安时刻t状态为i的各条部分路径的最大概率,直至得到时刻t=T的状态为i的各条路径的最大概率,便可以得到最优路径。

代码

假设连续观察3天的海藻湿度为(Dry,Damp,Soggy),求这三天最可能的天气情况。

#-*- coding:utf-8 -*-
import numpy as np
def viterbi(trainsition_probability,emission_probability,pi,obs_seq):

    #转换为矩阵进行计算
    trainsition_probability=np.array(trainsition_probability)
    emission_probability=np.array(emission_probability)
    pi=np.array(pi)

    #定义要返回的矩阵
    F = np.zeros((Row, Col))

    #初始状态
    F[:,0]=pi*np.transpose(emission_probability[:,obs_seq[0]])


    for t in range(1,Col):
        list_max=[]
        for n in range(Row):
            list_x=list(np.array(F[:,t-1])*np.transpose(trainsition_probability[:,n]))

            #获取最大概率
            list_p=[]
            for i in list_x:
                list_p.append(i*10000)
            list_max.append(max(list_p)/10000)

        F[:, t] = np.array(list_max) * np.transpose(emission_probability[:,obs_seq[t]])

    return F


if __name__ == '__main__':
    #隐藏状态
    invisible=['Sunny','Cloud','Rainy']
    #初始状态
    pi=[0.63,0.17,0.20]
    #转移矩阵
    trainsition_probability=[[0.5,0.375,0.125],
                             [0.25,0.125,0.625],
                             [0.25,0.375,0.375]]
    #发射矩阵
    emission_probability=[[0.6,0.2,0.15,0.05],
                          [0.25,0.25,0.25,0.25],
                          [0.05,0.10,0.35,0.5]]
    #最后显示状态
    obs_seq=[0,2,3]

    #最后返回一个Row*Col的矩阵结果
    Row = np.array(trainsition_probability).shape[0]
    Col = len(obs_seq)

    F=viterbi(trainsition_probability, emission_probability, pi, obs_seq)

    print F

五、词性标注结果

[[ 0.378     0.02835        0.00070875]
[ 0.0425    0.0354375    0.00265781]
[ 0.01        0.0165375    0.01107422]]

每列代表Dry,Damp,Soggy的概率,每行代表Sunny,Cloud,Rainy,所以可以看出最大概率的天气为{Sunny,Cloud,Rainy}。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值