【中文信息处理】实验三四_基于HMM的词性标注

本文介绍了如何使用HMM进行词性标注任务,包括数据集划分、参数统计、Viterbi算法实现以及评估程序。通过nltk库加载布朗语料库,将语料按4:1比例分为训练集和测试集,训练HMM模型,然后使用Viterbi算法对测试集进行词性标注,并计算准确率。实验展示了HMM在自然语言处理中的应用及其局限性。
摘要由CSDN通过智能技术生成

0、问题描述:

实验三:基于HMM的词性标注
任务:将语料分为测试集、训练集(一般比例1:4),训练集上:统计初始概率,发射概率,转移概率,估算所需的参数。

实验四:
任务1:利用Viterbi算法,实现基于HMM的词性标注。

任务2:编写评价程序,计算词性标注的准确率。


该程序的实现过程如下:

1. 使用nltk库中提供的布朗语料库加载数据集。

2. 将语料库分为训练集和测试集,比例为4:13. 定义train_hmm函数,根据训练集,统计初始概率、发射概率和转移概率,并返回这些参数。

4. 定义viterbi函数,实现Viterbi算法,对输入的句子进行词性标注,返回预测的词性序列。

5. 定义pos_tagging函数,对测试集进行词性标注,并计算准确率。

6. 调用train_hmm函数,训练HMM模型,并调用pos_tagging函数对测试集进行词性标注,最终输出准确率。

需要注意的是,由于HMM是一种生成模型,其参数的估计需要大量的数据和计算资源,
因此在实际应用中,需要对数据进行一定的预处理和降维处理,以提高模型的效率和准确率。
此外,由于HMM模型对文本的分词和词性标注是基于概率的,因此在一些特殊的语境下,可能会出现较大的错误率。

另外:训练集和数据集的理解:
假设题库有100道题目:
训练集:平时老师拿来给你练习的题目。一般比较多,假设老师拿出80道题目给你们练习
测试集:考试的时候,老师想测试你们学得咋样,所以拿出剩下的20道题给你们期末考试。
所以为啥一般训练题更多,因为训练是大量的,测试只是想看看有没有效果,所以测试一般就是少量的


1、nltk(Natural Language Toolkit)是一个用于自然语言处理的Python库,
提供了各种文本处理功能,例如分词、词性标注、命名实体识别、语义分析等等。
在本任务中,我们使用了nltk库提供的`布朗语料库作为训练和测试集`。
如果已经有了数据集,替换即可

2、sklearn.model_selection中的train_test_split函数可以将
数据集按照一定比例(或指定数量)分为训练集和测试集,方便进行模型训练和测试。

3、collections中的defaultdict是一个类,提供了默认值的字典功能,可以使得在访问不存在的键时返回一个默认值
而不是引发KeyError异常,这在处理大规模数据时非常方便。
在本任务中,我们使用defaultdict来统计标签的频率和计算概率。

import nltk
from sklearn.model_selection import train_test_split
from collections import defaultdict

# 1、加载数据集
corpus = nltk.corpus.brown.tagged_sents(tagset='universal')

# 2、将语料分为测试集和训练集
train_corpus, test_corpus = train_test_split(corpus, test_size=0.2, random_state=42)

# 3、根据训练集:统计初始概率、发射概率、转移概率
def train_hmm(tagged_corpus):
    # 统计标签频率
    tag_freq = defaultdict(int)
    for sentence in tagged_corpus:
        for word, tag in sentence:
            tag_freq[tag] += 1

    # 计算初始概率
    total_sentences = len(tagged_corpus)
    start_prob = {tag: tag_freq[tag]/total_sentences for tag in tag_freq}

    # 统计发射概率和转移概率
    emit_prob = defaultdict(lambda: defaultdict(int))
    trans_prob = defaultdict(lambda: defaultdict(int))
    for sentence in tagged_corpus:
        for i in range(len(sentence)):
            word, tag = sentence[i]
            emit_prob[tag][word] += 1
            if i == 0:
                trans_prob['start'][tag] += 1
            else:
                prev_tag = sentence[i-1][1]
                trans_prob[prev_tag][tag] += 1

    # 将频率转换为概率
    tag_list = list(tag_freq.keys())
    emit_prob = {tag: {word: count/tag_freq[tag] for word, count in emit_prob[tag].items()} for tag in tag_list}
    trans_prob = {tag1: {tag2: count/tag_freq[tag1] for tag2, count in trans_prob[tag1].items()} for tag1 in tag_list}

    return start_prob, emit_prob, trans_prob

# 4、使用Viterbi算法对测试集进行词性标注
def viterbi(sentence, start_prob, emit_prob, trans_prob):
    # 初始化
    v = [{}]
    path = {}
    for tag in start_prob:
        v[0][tag] = start_prob[tag] * emit_prob[tag].get(sentence[0], 0)
        path[tag] = [tag]

    # 递推
    for t in range(1, len(sentence)):
        v.append({})
        newpath = {}
        for tag in start_prob:
            prob, best_tag = max((v[t-1][prev_tag] * trans_prob[prev_tag].get(tag, 0) * emit_prob[tag].get(sentence[t], 0), prev_tag) for prev_tag in start_prob)
            v[t][tag] = prob
            newpath[tag] = path[best_tag] + [tag]
        path = newpath

    # 终止
    prob, best_tag = max((v[len(sentence)-1][tag], tag) for tag in start_prob)
    return path[best_tag]

# 5、对测试集进行词性标注
def pos_tagging(test_corpus, start_prob, emit_prob, trans_prob):
    total = 0
    correct = 0
    for sentence in test_corpus:
        words, tags = zip(*sentence)
        pred_tags = viterbi(words, start_prob, emit_prob, trans_prob)
        for j in range(len(tags)):
        	total += 1
        	if tags[j] == pred_tags[j]:
            	correct += 1

	accuracy = correct / total
	return accuracy
	
# 6、训练HMM模型、#对测试集进行词性标注,并计算准确率并输出
start_prob, emit_prob, trans_prob = train_hmm(train_corpus)
accuracy = pos_tagging(test_corpus, start_prob, emit_prob, trans_prob)
print('Accuracy: {:.2%}'.format(accuracy))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值