这里采用的手写维特比算法进行词性标注

我们也可以选择第三方的库进行计算

https://github.com/jmschrei/yahmm

import nltk
import sys
from nltk.corpus import brown
"""
做这个之前 首先我们要知道 我们知道什么  要求什么
第一步
我们需要根据 给定的语料库  进行学习hmm模型的 (A,B,π)
A 是状态转移矩阵  在我们词库之中  就是tag之间转移的概率矩阵
对整个语料进行统计    P(ti | t{i-1}) = count(t{i-1}, ti) / count(t{i-1})   计算t(i-1)到 ti的转移概率 就是ti在t(i-1)后面的个数/  T(i-1)tag的总数
B是每个隐藏状态到可见状态的概率分布  就是在tag下出现这个可见状态的概率  也就是在Tag下出现这个单词的概率
这个在整个语料库之中也可以统计
P(wi | ti) = count(wi, ti) / count(ti)  等于  tag1下所有的单词 /tag的数量的单词 π 是初始概率  就是在0时刻  statr  到每个tag的概率   这个在语料库中也可以统计 等于  start-tag1的数量 /  所有start到tag的数量根据语料库 计算出模型所有的参数  (A,B,π)
就可以利用hmm的模型求解三种问题
1.根据hmm模型  用遍历算法 求出  发生这个可见状态链条概率是多少
可以求出发生这个可见状态的可能性是多大2.第2个问题就是我们这里词性标注要解决的问题
给出一个模型(A,B,π)  可见状态链  也就一句话  求出 隐藏状态链 也就是单词的词性 
维特比算法 动态规划求解  也可以用第三方的库 将参数 (A,b,π)带入求和 我们这里是自己实现这个算法 求和3。第三种问题这个例子中我们无关  
说的是模型的参数(A.B.π)不确定  根据我们出现的可见状态 不断调整 求出发生这个可见状态最大可能性 
这个模型的参数是什么 在词性标注的应用就是  给出一句话   然后给出一个隐藏状态链tag  判断一下匹配度
给出一句话  求出每个单词的词性 """"""
预处理词库
这里需要的预处理是  给词加上开始和结束符合
brown 里面的句子都是自己标注好了的,形式如下:(i.NOUN),(LOVE,VERB),(YOU,NOUN)
我们用
(START,START)(END.END)
的格式做开始和结束的标注
下载语料库   
"""
#nltk.download('brown')brown_tags_words=[]
for sent in brown.tagged_sents():#加上开头brown_tags_words.append(("START","START"))#省略tag  只去tag前2个字母brown_tags_words.extend([(tag[:2],word) for (word,tag) in sent])#结尾加上结束符合brown_tags_words.append(("END","END"))print(brown_tags_words[0])
#('START', 'START')"""
词统计
这里计算的是 模型参数B
这个时候,我们要把我们所有的词库中拥有的单词与tag之间的关系,做个简单粗暴的统计。也就是我们之前说过的:P(wi | ti) = count(wi, ti) / count(ti)你可以自己一个个的loop全部的corpus,当然,这里NLTK给了我们做统计的工具,
(这属于没有什么必要的hack,装起逼来也不X,所以,大家想自己实现,可以去实现,不想的话,就用这里提供的方法)
"""
# conditional frequency distribution
cfd_tagwords = nltk.ConditionalFreqDist(brown_tags_words)
# conditional probability distribution
cpd_tagwords = nltk.ConditionalProbDist(cfd_tagwords, nltk.MLEProbDist)
"""
好,现在我们看看平面统计下来的结果:
可以拿到每个tag到 单词的概率 也就是可见状态的分布概率  模型参数B
动词duck的概率  JJ new的概率 
"""
print("The probability of an adjective (JJ) being 'new' is", cpd_tagwords["JJ"].prob("new"))
print("The probability of a verb (VB) being 'duck' is", cpd_tagwords["VB"].prob("duck"))
"""
The probability of an adjective (JJ) being 'new' is 0.01472344917632025
The probability of a verb (VB) being 'duck' is 6.042713350943527e-05
""""""
计算模型参数 A  隐藏状态的转移矩阵 
这里面我们也把start 到各个tag的概率也一起计算了  也就是我们这次统计 计算了
2个参数  一个是A 一个是π初始概率  
好,接下来,按照课上讲的,还有第二个公式需要计算:P(ti | t{i-1}) = count(t{i-1}, ti) / count(t{i-1})这个公式跟words没有什么卵关系。它是属于隐层的马科夫链。所以 我们先取出所有的tag来。
"""brown_tags = [tag for (tag, word) in brown_tags_words ]
# count(t{i-1} ti)
# bigram的意思是 前后两个一组,联在一起
cfd_tags= nltk.ConditionalFreqDist(nltk.bigrams(brown_tags))
# P(ti | t{i-1})
cpd_tags = nltk.ConditionalProbDist(cfd_tags, nltk.MLEProbDist)"""
好的,可以看看效果了:
"""
print("If we have just seen 'DT', the probability of 'NN' is", cpd_tags["DT"].prob("NN"))
print( "If we have just seen 'VB', the probability of 'JJ' is", cpd_tags["VB"].prob("DT"))
print( "If we have just seen 'VB', the probability of 'NN' is", cpd_tags["VB"].prob("NN"))
"""
DT 转移到NN的概率
VB到DT的概率
VB到NN的 概率 
If we have just seen 'DT', the probability of 'NN' is 0.5057722522030194
If we have just seen 'VB', the probability of 'JJ' is 0.016885067592065053
If we have just seen 'VB', the probability of 'NN' is 0.10970977711020183
""""""
下面可以根据语料计算出来的Hmm 模型 进行词性标注求解第2类问题 
可以根据维特比算法进行计算  也可以用第三方面实现的库进行计算  YAhMm进行计算
我们这里采用的是自己实现算法
https://github.com/jmschrei/yahmm
第三方实现库
""""""一些有趣的结果:
那么,比如, 一句话,"I want to race", 一套tag,"PP VB TO VB"他们之间的匹配度有多高呢?其实就是:P(START) * P(PP|START) * P(I | PP) *P(VB | PP) * P(want | VB) *P(TO | VB) * P(to | TO) *P(VB | TO) * P(race | VB) *P(END | VB)
"""
prob_tagsequence = cpd_tags["START"].prob("PP") * cpd_tagwords["PP"].prob("I") * \cpd_tags["PP"].prob("VB") * cpd_tagwords["VB"].prob("want") * \cpd_tags["VB"].prob("TO") * cpd_tagwords["TO"].prob("to") * \cpd_tags["TO"].prob("VB") * cpd_tagwords["VB"].prob("race") * \cpd_tags["VB"].prob("END")print( "The probability of the tag sequence 'START PP VB TO VB END' for 'I want to race' is:", prob_tagsequence)
#The probability of the tag sequence 'START PP VB TO VB END' for 'I want to race' is: 1.0817766461150474e-14"""
根据hmm进行词性标注环节
Viterbi 的实现
如果我们手上有一句话,怎么知道最符合的tag是哪组呢?
首先,我们拿出所有独特的tags(也就是tags的全集)
"""
distinct_tags = set(brown_tags)
sentence = ["I", "want", "to", "race" ]
sentlen = len(sentence)"""
接下来,开始维特比:从1循环到句子的总长N,记为i每次都找出以tag X为最终节点,长度为i的tag链动态规划  从第一个开始算
"""
viterbi = [ ]
"""
同时,还需要一个回溯器:从1循环到句子的总长N,记为i把所有tag X 前一个Tag记下来。
"""
backpointer = [ ]
first_viterbi = { }
first_backpointer = { }
for tag in distinct_tags:# don't record anything for the START tagif tag == "START": continuefirst_viterbi[ tag ] = cpd_tags["START"].prob(tag) * cpd_tagwords[tag].prob( sentence[0] )first_backpointer[ tag ] = "START"print(first_viterbi)
print(first_backpointer)"""
以上,是所有的第一个viterbi 和第一个回溯点。接下来,把楼上这些,存到Vitterbi和Backpointer两个变量里去
first_viterbi
这个变量记录的是 每个tag下是这个单词的概率  那么动态规划的原理  这里可以取出  当前概率最大的一个tag作为tag
然后存到backpoint之中
{'CS': 0.0, 'QL': 0.0, 'NP': 1.7319067623793952e-06, 'IN': 0.0, 'AP': 0.0, 'NI': 3.3324520848931064e-07, '(-': 0.0, ')-': 0.0,
'CC': 0.0, 'WD': 0.0, 'END': 0.0, 'NR': 0.0, 'CD': 0.0, '*': 0.0, '(': 0.0, 'DT': 0.0, 'RP': 0.0, 'WQ': 0.0, ':': 0.0, 'WP': 0.0, "''": 0.0,
'--': 0.0, 'AT': 0.0, "'": 0.0, 'DO': 0.0, 'PN': 0.0, ',-': 0.0, 'NN': 1.0580313619573935e-06, ')': 0.0, 'AB': 0.0, 'RB': 0.0, 'HV': 0.0,
'``': 0.0, '*-': 0.0, ',': 0.0, 'JJ': 0.0, 'FW': 0.0, 'PP': 0.014930900689060006, 'TO': 0.0, 'MD': 0.0, 'EX': 0.0, '.-': 0.0, '.': 0.0,
'UH': 0.0, 'RN': 0.0, 'WR': 0.0, 'VB': 0.0, ':-': 0.0, 'BE': 0.0, 'OD': 0.0}
first_backpointer
{'CS': 'START', 'QL': 'START', 'NP': 'START', 'IN': 'START', 'AP': 'START', 'NI': 'START', '(-': 'START', ')-': 'START',
'CC': 'START', 'WD': 'START', 'END': 'START', 'NR': 'START', 'CD': 'START', '*': 'START', '(': 'START', 'DT': 'START',
'RP': 'START', 'WQ': 'START', ':': 'START', 'WP': 'START', "''": 'START', '--': 'START', 'AT': 'START', "'": 'START', 'DO':
'START', 'PN': 'START', ',-': 'START', 'NN': 'START', ')': 'START', 'AB': 'START', 'RB': 'START', 'HV': 'START', '``': 'START',
'*-': 'START', ',': 'START', 'JJ': 'START', 'FW': 'START', 'PP': 'START', 'TO': 'START', 'MD': 'START', 'EX': 'START',
'.-': 'START', '.': 'START', 'UH': 'START', 'RN': 'START', 'WR': 'START', 'VB': 'START', ':-': 'START', 'BE': 'START', 'OD': 'START'}
"""viterbi.append(first_viterbi)
backpointer.append(first_backpointer)
#全部存起来 """
我们可以先看一眼,目前最好的tag是啥:
也就是把第一个单词所有tag的情况下的概率都算出来  然后取最大值 作为第一个tag的值
"""
currbest = max(first_viterbi.keys(), key = lambda tag: first_viterbi[ tag ])
print( "Word", "'" + sentence[0] + "'", "current best two-tag sequence:", first_backpointer[ currbest], currbest)
#Word 'I' current best two-tag sequence: START PP"""
就是这样  我们一个单词一个单词往下算 每次都找到最大的那个概率  然后作为tag链 序列
好的一些都清晰了我们开始loop:
"""
for wordindex in range(1, len(sentence)):this_viterbi = { }this_backpointer = { }prev_viterbi = viterbi[-1]for tag in distinct_tags:# START没有卵用的,我们要忽略if tag == "START": continue# 如果现在这个tag是X,现在的单词是w,# 我们想找前一个tag Y,并且让最好的tag sequence以Y X结尾。# 也就是说# Y要能最大化:# prev_viterbi[ Y ] * P(X | Y) * P( w | X)best_previous = max(prev_viterbi.keys(),key = lambda prevtag: \prev_viterbi[ prevtag ] * cpd_tags[prevtag].prob(tag) * cpd_tagwords[tag].prob(sentence[wordindex]))this_viterbi[ tag ] = prev_viterbi[ best_previous] * \cpd_tags[ best_previous ].prob(tag) * cpd_tagwords[ tag].prob(sentence[wordindex])this_backpointer[ tag ] = best_previous# 每次找完Y 我们把目前最好的 存一下currbest = max(this_viterbi.keys(), key = lambda tag: this_viterbi[ tag ])print( "Word", "'" + sentence[ wordindex] + "'", "current best two-tag sequence:", this_backpointer[ currbest], currbest)# 完结# 全部存下来viterbi.append(this_viterbi)backpointer.append(this_backpointer)"""
找END,结束:
"""# 找所有以END结尾的tag sequence
prev_viterbi = viterbi[-1]
best_previous = max(prev_viterbi.keys(),key = lambda prevtag: prev_viterbi[ prevtag ] * cpd_tags[prevtag].prob("END"))prob_tagsequence = prev_viterbi[ best_previous ] * cpd_tags[ best_previous].prob("END")# 我们这会儿是倒着存的。。。。因为。。好的在后面
best_tagsequence = [ "END", best_previous ]
# 同理 这里也有倒过来
backpointer.reverse()"""
最终:回溯所有的回溯点此时,最好的tag就是backpointer里面的current best
"""current_best_tag = best_previous
for bp in backpointer:best_tagsequence.append(bp[current_best_tag])current_best_tag = bp[current_best_tag]best_tagsequence.reverse()
print( "The sentence was:", end = " ")
for w in sentence: print( w, end = " ")
print("\n")
print( "The best tag sequence is:", end = " ")
for t in best_tagsequence: print (t, end = " ")
print("\n")
print( "The probability of the best tag sequence is:", prob_tagsequence)"""
Word 'I' current best two-tag sequence: START PP
Word 'want' current best two-tag sequence: PP VB
Word 'to' current best two-tag sequence: VB TO
Word 'race' current best two-tag sequence: IN NN
The sentence was: I want to race The best tag sequence is: START PP VB IN NN END The probability of the best tag sequence is: 5.71772824864617e-14
"""

hmm进行英文词性标注相关推荐

  1. Stanford-corenlp 英文词性标注

    一.环境配置 1.下载官网的NLP相关包 将下载下来的stanford-corenlp-full-2018-02-27解压并将下载英文的jar文件 stanford-english-corenlp-2 ...

  2. 基于HMM的中文词性标注 POSTagging

    文章目录 1. 词性标注 1.1 概念 1.2 任务 1.3 预处理 1.4 初步统计预览 2. 最大概率模型 2.1 训练 2.2 预测 2.3 结果评估 2.4 结果可视化 3. 二元隐马尔科夫B ...

  3. nltk英文词性标注

    需要用nltk.download()下载punkt和averaged_preceptron_tagger import nltk words = nltk.word_tokenize('And now ...

  4. 4.2 英文分词及词性标注

    转载自: https://datartisan.gitbooks.io/begining-text-mining-with-python/content/%E7%AC%AC4%E7%AB%A0%20% ...

  5. NLP-文本处理:词性标注【使用成熟的第三方工具包:中文(哈工大LTP)、英文()】【对分词后得到的“词语列表”进行词性标注,词性标注的结果用于依存句法分析、语义角色标注】

    词性: 语言中对词的一种分类方法,以语法特征为主要依据.兼顾词汇意义对词进行划分的结果, 常见的词性有14种, 如: 名词, 动词, 形容词等. 顾名思义, 词性标注(Part-Of-Speech t ...

  6. 【NLP Tool -- NLTK】NLTK进行英文情感分析、分词、分句、词性标注(附代码)

    NLP Tool 系列文章 NLP--Jieba中文文本--关键词提取.自定义词典.分词.词性标注 NLP--NLTK英文文本--情感分析.分词.分句.词性标注 工具介绍 NLTK,Natural L ...

  7. 统计机器学习方法 for NLP:基于HMM的词性标注

    前言 最近在重刷李航老师的<统计机器学习方法>尝试将其与NLP结合,通过具体的NLP应用场景,强化对书中公式的理解,最终形成「统计机器学习方法 for NLP」的系列.这篇将介绍隐马尔可夫 ...

  8. 【python】TXT文本数据清洗和英文分词、词性标注

    去除空行 def clean_line(raw_file_name, save_file_name):with open(raw_file_name, 'r+') as f_r, open(save_ ...

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

    NLP作业01:请利用HMM实现词性标注 目录 NLP作业01:请利用HMM实现词性标注 一.作业头 二.对HMM模型进行介绍 三. 估计HMM的模型参数 四.基于维特比算法进行解码 五. 词性标注结 ...

  10. 史上最详细最容易理解的HMM文章

    分类 隐马尔科夫模型 HMM(隐马尔科夫模型)是自然语言处理中的一个基本模型,用途比较广泛,如汉语分词.词性标注及语音识别等,在NLP中占有很重要的地位.网上关于HMM的介绍讲解文档很多,我自己当时开 ...

最新文章

  1. jquery实现返回顶部按钮和scroll滚动功能[带动画效果] 转载
  2. 2017-11-15 软件包 java.io学习
  3. 【Qt】undefined reference to `vtable for xxx’
  4. 书摘---创业36条军规1:创业是怎么回事
  5. switch 的性能提升了 3 倍,我只用了这一招!
  6. win8+sdk8+vs2012+freeglut+glew开发opengl
  7. sql查询初学者指南_面向初学者SQL Server查询执行计划–聚集索引运算符
  8. extjs 如何将局部的变量变为全局变量
  9. javascript教程现有Web App模式的问题以及挑战
  10. model.load_state_dict(checkpoint[‘state_dict‘]) KeyError: ‘state_dict‘
  11. 计算机232接口接线图,rs232串口接线图
  12. python编程基础及应用 重庆大学出版社_大学计算机基础与应用
  13. 1那智机器人主电连接
  14. 问题解决逻辑:深度和广度谁应该优先?
  15. 解决:“证书错误,导航已阻止”
  16. QT mindmap
  17. PSQLException: An I/O error occurred问题排查
  18. De-Sim示例分析(三)SIR传染病模型
  19. springboot之shiro
  20. 【HCIE-RS 天梯路】NDP

热门文章

  1. 【历史上的今天】5 月 19 日:Java 之父诞生;中国首家互联网公司成立;CP/M 操作系统发明者出生
  2. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并输出其因子。
  3. 一小时建立数据分析平台
  4. Vue引入百度地图增加导航功能
  5. 解决执行HiveSQL时,报could not be cleaned up的错误
  6. Linux---带你区分根目录 和 家目录
  7. Newton牛顿法(二)| 收敛性和收敛速度 +初值的选取方法
  8. HDU - 5773 - The All-purpose Zero 【必做题目之LIS+++贪贪贪贪心】
  9. 刘文智《产品经理深入浅出》培训课程笔记
  10. 微信公众号文章阅读数和点赞数采集接口