文章目录
1.概述
隐马尔可夫模型(HMM)是可用于标注问题的统计学习模型,描述由隐藏的马尔科夫链随机生成观测序列的过程,属于生成模型,被认为是解决大多数自然语言处理问题最快速、有效的方法;20世纪70年代被应用在语音处理上,后被广泛应用在汉语自动分词、词性标注、统计机器翻译等方面。 本次主要介绍基于HMM的Viterbi算法进行分词。
2.理论描述
2.1 HMM五元组
HMM是一个五元组(O,S,A,B,O):
- O: {o1…ot}(ObservedSet)观测值集合,观测序列;
- S: {s1…sv}(StatusSet)状态值集合,隐序列;
- aij = p(sj|si):(TransProbMatrix)转移概率矩阵;
- bij = p(oj|si): (EmitProbMatrix);发射概率矩阵;
- 〇0:(InitStatus)初始状态分布,有些还有终止状态;
状态序列的每个状态值仅取决于前面有限个状态,这种状态序列就是马尔可夫链。
隐马尔可夫模型就是像这种由一个隐藏的马尔可夫链随机生成的不可观测的状态序列,再由各个状态生成一个观测而产生观测随机序列的过程。
HMM可以用于估算隐藏于表面事件背后的事件的概率。 在词性标注中,词串可视为可观察序列,词的词性可视为隐序列 。
PS:如果你了解EM算法的话,会发现“状态序列是隐藏的,观测序列是可观测的”这个条件和EM算法面临问题的条件有些像,即,“只知道结果,却不知道每个结果从哪个过程中得出”。于是这里要说一句:“隐马尔科夫模型”只是模型,它不是算法,这个不要弄混了,而可应用到这个模型的算法之一就是EM算法。
2.2 HMM三个基本问题及三个假设
估计问题(概率计算):给定一个马尔科夫模型M=(A,B),如何有效的计算出某个观测序列O出现的概率,及计算P(O|M)(A表示转移概率,B表示发射概率)。
解码问题(预测问题):给定一个观测序列O和一个HMM模型M,寻找最好的隐序列Q以便更好地解释观测值。
学习问题():依据给定的观测序列O以及HMM模型中的状态集合,学习最佳HMM参数模型A和B。
1.有限历史性假设:也就是马尔科夫链的n=1。即Status(i)只和Status(i-1)相关,这个假设能大大简化问题P(Status[i]|Status[i-1],Status[i-2],… Status[1]) = P(Status[i]|Status[i-1])
2.齐次性假设(状态和当前时刻无关)😛(Status[i]|Status[i-1]) = P(Status[j]|Status[j-1])
3.观察值独立性假设:观察值只取决于当前状态值,P(Observed[i], Status[j]) = P(Status[j]) * P(Observed[i]|Status[j])
2.3 解决问题算法
第一个问题:前向-后向算法(一种动态规划算法)
第二个问题:Viterbi算法实际上是最优路径算法的一种。在HMM的解码问题中,我们可以使用穷举法把所有可能的隐序列的概率都计算出来,这样最优解自然就出来了,但是缺点也很明显,即计算量太大。Viterbi算法的主要思想是寻找局部最优路径,即寻找所有序列中在t时刻以状态j终止的最大概率,所对应的路径为部分最优路径。依据最后一个时刻中概率最高的状态,通过回溯找其路径中的上一个最大部分最优路径,从而找到整个最优路径,而不用穷举所有的状态。这样就比计算整个的排列组合的次数要小得多。穷举的时间复杂度为O(mn),而Viterbi是多次对链中的一个小分布穷举,时间复杂度为O(m*n)。(一种动态规划算法)
第三个问题:如果状态序列已知,那用最大似然估计就好了,但HMM的状态序列未知,即含有隐变量,所以要使用Baum-welch算法(其实其本质就是EM算法)
主要介绍第二种,使用Viterbi算法进行中文分词及词性标注
基于统计 主要思想把每个词看做是由词的最小单位的各个字组成,如果相连的字在不同文本中出现的次数越多,就证明这相连的字很可能就是一个词。
3 整体过程
模型生成过程
观测序列的生成
输入:隐马尔科夫模型λ=(A,B,π),观测序列长度T;
输出:观测序列O=(O1,O2,…,OT)。
过程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nUzPAsKi-1596089566514)(/uploads/zhishifenxiang/images/m_93790759a4dff7145f5f16e8d8204c59_r.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mDRcJEDR-1596089566517)(/uploads/zhishifenxiang/images/m_2a30ed43aee615fe519eab2223f98c73_r.png)]
3.1 简单的分词过程
隐含马尔可夫模型(HMM)是将分词作为字在句子中的序列标注任务来实现的。其基本思路是:每个字在构造一个特定词语时都占据着一个特定的位置即词位,一般采用四结构词位:B(词首),M(词中),E(词尾)和S(单独成词)。比如:
‘中文/分词/是/文本处理/不可或缺/的/一步/!’,
标注后的形式:
‘中/B 文/E 分/B 词/E 是/S 文/B 本/M 处/M 理/E 不/B 可/M 或/M 缺/E 的/S 一/B 步/E !/S’
。
分词的主要过程
1.使用已经分好词的训练集去训练HMM模型,计算频数得到HMM的三要素(初始状态概率,状态转移概率和发射概率)
2.使用Viterbi算法以及训练好的三个概率矩阵,将待分词的句子转换为’BMES’类型的状态序列。
3.根据已经求出的状态序列,划分句子进行分词。
五元组在分词的过程中各自的意义
(StatusSet:)状态值集合:[B, M, E, S],{B:begin, M:middle, E:end, S:single},分别代表的是该字在词语中的位置,B代表该字是词语中起始字,M代表是词语中中间字,E代表是词语中结束字,S则代表是单字成词。
(ObservedSet)观测值集合:所有语料库中包含标点符号组成的集合。状态值也就是我们要求的值,在HMM模型中文分词中,我们的输入是一个句子(也就是观察值序列),输出是这个句子中每个字的状态值。
初始状态概率分布(InitStatus):句子的第一个字属于{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的算法串接起来,observations序列值是Viterbi的输入,而states序列值是Viterbi的输出,输入和输出之间Viterbi算法还需要借助三个模型参数,分别是InitStatus,TransProbMatrix,EmitProbMatrix。
4.应用方式
4.1 简单的中文分词
1.使用已经分好词的训练集去训练HMM模型,计算频数得到HMM的三要素(初始状态概率,状态转移概率和发射概率)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LcI8TCFJ-1596089566518)(/uploads/zhishifenxiang/images/m_b530325d8aaa5e677c15f109d4c1e968_r.png)]
2.使用Viterbi算法以及训练好的三个概率矩阵,将待分词的句子转换为’BMES’类型的状态序列。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bJsLSjJf-1596089566519)(/uploads/zhishifenxiang/images/m_cad34e9502cb212a93c3f26db40aee80_r.png)]
3.Viterbi求最大概率序列
根据已经求出的状态序列,划分句子进行分词。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sl7l31yv-1596089566520)(/uploads/zhishifenxiang/images/m_6513c50351aa8312198777ffff8bdc95_r.png)]
分词
最后测试结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBuQvJQl-1596089566522)(/uploads/zhishifenxiang/images/m_71231b2b4f3c29d51019da2357788b3d_r.png)]
加载训练参数,读取模型,分词
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oDyvOKk-1596089566522)(/uploads/zhishifenxiang/images/m_7a21b1af637f331c9048ce805bce5365_r.png)]
4.2 词性标注问题
1、对词性标注问题进行提炼:词性标注本质上是一个分类问题,对于句子中的每一个单词W,找到一个合适的词类类别T,也就是词性标记,不过词性标注考虑的是整体标记的好坏,既整个句子的序列标记问题;
2、抽象为数学模型:对于分类问题,有很多现成的数学模型和框架可以套用,譬如HMM、最大熵模型、条件随机场、SVM等等;
5.jieba分词中的HMM
5.1 中文分词的介绍
分词的特点:
1.词是最小的能够独立活动的有意义的语言成分
2.汉语是以字位单位,不像西方语言,词与词之间没有空格之类的标志指示词的边界
3.分词问题为中文文本处理的基础性工作,分词的好坏对后面的中文信息处理起关键作用
分词的难点:
1. 分词规范,词的定义还不明确 (《统计自然语言处理》宗成庆)
2. 歧义切分问题,交集型切分问题,多义组合型切分歧义等
结婚的和尚未结婚的 =>
结婚/的/和/尚未/结婚/的
结婚/的/和尚/未/结婚/的
3. 未登录词问题有两种解释:一是已有的词表中没有收录的词,二是已有的训练语料中未曾出现过的词,第二种含义中未登录词又称OOV(Out of Vocabulary)。对于大规模真实文本来说,未登录词对于分词的精度的影响远超歧义切分。一些网络新词,自造词一般都属于这些词。
jieba分词的策略:
1. 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
2. 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
3. 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法
jieba中对于未登录词问题,通过–cut–DAG 函数我们可以看出这个函数前半部分用 calc 函数计算出了初步的分词,而后半部分就是就是针对上面例子中未出现在语料库的词语进行分词了。由于基于频度打分的分词会倾向于把不能识别的词组一个字一个字地切割开,所以对这些字的合并就是识别OOV的一个方向,–cut–DAG定义了一个buf 变量收集了这些连续的单个字,最后把它们组合成字符串再交由 finalseg.cut 函数来进行下一步分词。
def __cut_DAG(self, sentence):
DAG = self.tokenizer.get_DAG(sentence)
route = {}
self.tokenizer.calc(sentence, DAG, route)
x = 0
buf = ''
N = len(sentence)
while x < N:
y = route[x][1] + 1
l_word = sentence[x:y]
if y - x == 1:
buf += l_word
else:
if buf:
if len(buf) == 1:
yield pair(buf, self.word_tag_tab.get(buf, 'x'))
elif not self.tokenizer.FREQ.get(buf):
recognized = self.__cut_detail(buf)
for t in recognized:
yield t
else:
for elem in buf:
yield pair(elem, self.word_tag_tab.get(elem, 'x'))
buf = ''
yield pair(l_word, self.word_tag_tab.get(l_word, 'x'))
x = y
if buf:
if len(buf) == 1:
yield pair(buf, self.word_tag_tab.get(buf, 'x'))
elif not self.tokenizer.FREQ.get(buf):
recognized = self.__cut_detail(buf)
for t in recognized:
yield t
else:
for elem in buf:
yield pair(elem, self.word_tag_tab.get(elem, 'x'))
6.应用代码
HMM不只用于中文分词,如果把 S 换成句子,O 换成语音信号,就变成了语音识别问题,如果把 S 换成中文,O 换成英文,就变成了翻译问题,如果把 S 换成文字,O 换成图像,就变成了文字识别问题,此外还有词性标注等等问题。
中文分词 https://github.com/hiyoung123/ChineseSegmentation
jiaba分词 https://github.com/fxsjy/jieba/
This is some text!