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

文章介绍了自然语言处理课程中的HMM模型,包括其在序列数据建模和预测中的应用,以及HMM的评估、解码和学习问题。通过使用1998人民日报词性标注语料库训练模型,文章详细展示了HMM的模型参数估计过程,如初始概率向量、转移矩阵的计算,并使用维特比算法进行解码。然而,由于HMM的两个强假设在实际应用中可能不成立,导致词性标注准确率不理想,提出了使用RNN等深度学习模型作为改进方案。
摘要由CSDN通过智能技术生成

一、作业头

这个作业属于哪个课程自然语言处理
这个作业要求在哪里http://t.csdn.cn/67O2W
我在这个课程的目标是掌握自然语言处理的基本技术和理论;了解自然语言处理的研究现状和发展趋势;能够运用自然语言处理技术解决实际问题;具备自主学习和探索的能力。
这个作业在那个具体方面帮助我实现目标提高了自主学习能力,能锻炼自己运用自然语言处理技术解决实际问题
参考文献http://t.csdn.cn/VNrVDhttp://t.csdn.cn/u6dMr

二、HMM介绍

HMM模型是一种统计模型,主要应用于序列数据的建模和预测,由一个隐藏的马尔可夫过程和一个可观测的输出过程组成。
HMM模型有三个基本问题:评估问题、解码问题和学习问题。评估问题是计算给定HMM模型和观测数据的联合概率,解码问题是找到最有可能对应的状态序列,而学习问题则是通过观测数据来估计HMM模型的参数。

三、HMM的模型参数

1.数据处理

利用“1998人民日报词性标注语料库”进行模型的训练。
将每个句子预处理成下面的格式: [(word,tag), … , (word,tag)]

2.模型训练

根据数据估计HMM的模型参数:全部的词性集合Q,全部的词集合V ,初始概率向量PI ,词性到词性的转移矩阵A ,词性到词的转移矩阵B 。 可以采用频率估计概率的方法计算模型参数,但需要进一步采用拉普拉斯平滑处理。
在这里插入图片描述
代码如下:

# 统计words和tags
words = set()
tags = set()
for words_with_tag in sentences:
    for word_with_tag in words_with_tag:
        word, tag = word_with_tag
        words.add(word)
        tags.add(tag)
words = list(words)
tags = list(tags)
# 统计 词性到词性转移矩阵A 词性到词转移矩阵B 初始向量pi
# 先初始化
A = {tag: {tag: 0 for tag in tags} for tag in tags}
B = {tag: {word: 0 for word in words} for tag in tags}
pi = {tag: 0 for tag in tags}
# 统计A,B
for words_with_tag in sentences:
    head_word, head_tag = words_with_tag[0]
    pi[head_tag] += 1
    B[head_tag][head_word] += 1
    for i in range(1, len(words_with_tag)):
        A[words_with_tag[i-1][1]][words_with_tag[i][1]] += 1
        B[words_with_tag[i][1]][words_with_tag[i][0]] += 1
# 拉普拉斯平滑处理并转换成概率
sum_pi_tag = sum(pi.values())
for tag in tags:
    pi[tag] = (pi[tag] + 1) / (sum_pi_tag + len(tags))
    sum_A_tag = sum(A[tag].values())
    sum_B_tag = sum(B[tag].values())
    for next_tag in tags:
        A[tag][next_tag] = (A[tag][next_tag] + 1) / (sum_A_tag + len(tags))
    for word in words:
        B[tag][word] = (B[tag][word] + 1) / (sum_B_tag + len(words))

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

维特比算法的简单的说就是提前终止了不可能路径。具体而言,在每一步遍历全部的K个节点,对于每一个节点继续遍历可能来源于上一步的K个节点,只保留上一步K个节点中概率大的路径,裁剪其余的K-1条路径。所以时间复杂度降低到O(K²T),相比指数级的暴力枚举,这是可接受的。

def decode_by_viterbi(sentence):
    words = sentence.split()
    sen_length = len(words)
    T1 = [{tag: float('-inf') for tag in tags} for i in range(sen_length)]
    T2 = [{tag: None for tag in tags} for i in range(sen_length)]
    # 先进行第一步
    for tag in tags:
        T1[0][tag] = math.log(pi[tag]) + math.log(B[tag][words[0]])
    # 继续后续解码
    for i in range(1, sen_length):
        for tag in tags:
            for pre_tag in tags:
                current_prob = T1[i-1][pre_tag] + math.log(A[pre_tag][tag]) + math.log(B[tag][words[i]])
                if current_prob > T1[i][tag]:
                    T1[i][tag] = current_prob
                    T2[i][tag] = pre_tag
    # 获取最后一步的解码结果
    last_step_result = [(tag, prob) for tag, prob in T1[sen_length-1].items()]
    last_step_result.sort(key=lambda x: -1*x[1])
    last_step_tag = last_step_result[0][0]
    # 向前解码
    step = sen_length - 1
    result = [last_step_tag]
    while step > 0:
        last_step_tag = T2[step][last_step_tag]
        result.append(last_step_tag)
        step -= 1
    result.reverse()
    return list(zip(words, result))

五、词性标注结果

结果不太理想(根据文献HMM一般中文词性标注的准确率能够达到85%以上 )
原因:主要是两个强假设在实际中是不成立的
解决方案:隐变量不仅仅跟前一个状态的隐变量有关,同时当前观测变量也不仅 仅跟当前的隐变量有关,可以尝试用深度学习中RNN等模型解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值