如何理解隐马尔可夫模型 分词中的向后算法

如何用简单易懂的例子解释隐马尔可夫模型? - 知乎10736被浏览626232分享邀请回答blog.csdn.net/ppn0290121. 赌场风云(背景介绍)最近一个赌场的老板发现生意不畅,于是派出手下去赌场张望。经探子回报,有位大叔在赌场中总能赢到钱,玩得一手好骰子,几乎是战无不胜。而且每次玩骰子的时候周围都有几个保镖站在身边,让人不明就里,只能看到每次开局,骰子飞出,沉稳落地。老板根据多年的经验,推测这位不善之客使用的正是江湖失传多年的"偷换骰子大法”(编者注:偷换骰子大法,用兜里自带的骰子偷偷换掉均匀的骰子)。老板是个冷静的人,看这位大叔也不是善者,不想轻易得罪他,又不想让他坏了规矩。正愁上心头,这时候进来一位名叫HMM帅哥,告诉老板他有一个很好的解决方案。不用近其身,只要在远处装个摄像头,把每局的骰子的点数都记录下来。然后HMM帅哥将会运用其强大的数学内力,用这些数据推导出1. 该大叔是不是在出千?2. 如果是在出千,那么他用了几个作弊的骰子? 还有当前是不是在用作弊的骰子。3. 这几个作弊骰子出现各点的概率是多少?天呐,老板一听,这位叫HMM的甚至都不用近身,就能算出是不是在作弊,甚至都能算出别人作弊的骰子是什么样的。那么,只要再当他作弊时,派人围捕他,当场验证骰子就能让他哑口无言。2. HMM是何许人也?在让HMM开展调查活动之前,该赌场老板也对HMM作了一番调查。HMM(Hidden Markov Model), 也称隐性马尔可夫模型,是一个概率模型,用来描述一个系统隐性状态的转移和隐性状态的表现概率。系统的隐性状态指的就是一些外界不便观察(或观察不到)的状态,
比如在当前的例子里面, 系统的状态指的是大叔使用骰子的状态,即{正常骰子, 作弊骰子1, 作弊骰子2,...}隐性状态的表现也就是,
可以观察到的,由隐性状态产生的外在表现特点。这里就是说, 骰子掷出的点数. {1,2,3,4,5,6}HMM模型将会描述,系统隐性状态的转移概率。也就是大叔切换骰子的概率,下图是一个例子,这时候大叔切换骰子的可能性被描述得淋漓尽致。很幸运的,这么复杂的概率转移图,竟然能用简单的矩阵表达, 其中a_{ij}代表的是从i状态到j状态发生的概率当然同时也会有,隐性状态表现转移概率。也就是骰子出现各点的概率分布,
(e.g. 作弊骰子1能有90%的机会掷到六,作弊骰子2有85%的机会掷到'小’). 给个图如下,隐性状态的表现分布概率也可以用矩阵表示出来,把这两个东西总结起来,就是整个HMM模型。这个模型描述了隐性状态的转换的概率,同时也描述了每个状态外在表现的概率的分布。总之,HMM模型就能够描述扔骰子大叔作弊的频率(骰子更换的概率),和大叔用的骰子的概率分布。有了大叔的HMM模型,就能把大叔看透,让他完全在阳光下现形。3. HMM能干什么!总结起来HMM能处理三个问题,3.1 解码(Decoding)解码就是需要从一连串的骰子中,看出来哪一些骰子是用了作弊的骰子,哪些是用的正常的骰子。比如上图中,给出一串骰子序列(3,6,1,2..)和大叔的HMM模型, 我们想要计算哪一些骰子的结果(隐性状态表现)可能对是哪种骰子的结果(隐性状态).3.2学习(Learning)学习就是,从一连串的骰子中,学习到大叔切换骰子的概率,当然也有这些骰子的点数的分布概率。这是HMM最为恐怖也最为复杂的招数!!3.3 估计(Evaluation)估计说的是,在我们已经知道了该大叔的HMM模型的情况下,估测某串骰子出现的可能性概率。比如说,在我们已经知道大叔的HMM模型的情况下,我们就能直接估测到大叔扔到10个6或者8个1的概率。4. HMM是怎么做到的?4.1 估计估计是最容易的一招,在完全知道了大叔的HMM模型的情况下,我们很容易就能对其做出估计。现在我们有了大叔的状态转移概率矩阵A,B就能够进行估计。比如我们想知道这位大叔下一局连续掷出10个6的概率是多少? 如下这表示的是,在一开始隐性状态(s0)为1,也就是一开始拿着的是正常的骰子的情况下,这位大叔连续掷出10个6的概率。现在问题难就难在,我们虽然知道了HMM的转换概率,和观察到的状态V{1:T}, 但是我们却不知道实际的隐性的状态变化。好吧,我们不知道隐性状态的变化,那好吧,我们就先假设一个隐性状态序列,
假设大叔前5个用的是正常骰子, 后5个用的是作弊骰子1. 好了,那么我们可以计算,在这种隐性序列假设下掷出10个6的概率.这个概率其实就是,隐性状态表现概率B的乘积.但是问题又出现了,刚才那个隐性状态序列是我假设的,而实际的序列我不知道,这该怎么办。好办,把所有可能出现的隐状态序列组合全都试一遍就可以了。于是,R就是所有可能的隐性状态序列的集合。的嗯,现在问题好像解决了,我们已经能够通过尝试所有组合来获得出现的概率值,并且可以通过A,B矩阵来计算出现的总概率。但是问题又出现了,可能的集合太大了, 比如有三种骰子,有10次选择机会, 那么总共的组合会有3^10次...这个量级O(c^T)太大了,当问题再大一点时候,组合的数目就会大得超出了计算的可能。所以我们需要一种更有效的计算P(V(1:T)概率的方法。比如说如下图的算法可以将计算P(V1:T)的计算复杂度降低至O(cT).有了这个方程,我们就能从t=0的情况往前推导,一直推导出P(V1:T)的概率。下面让我们算一算,大叔掷出3,2,1这个骰子序列的可能性有多大(假设初始状态为1, 也就是大叔前一次拿着的是正常的骰子)?4.2 解码(Decoding)解码的过程就是在给出一串序列的情况下和已知HMM模型的情况下,找到最可能的隐性状态序列。用数学公式表示就是,
(V是Visible可见序列, w是隐性状态序列, A,B是HMM状态转移概率矩阵)(公式太多,请具体看我博客中的推导)然后又可以使用估计(4.1)中的前向推导法,计算出最大的P(w(1:T),
V(1:T)).在完成前向推导法之后,再使用后向追踪法(Back
Tracking),对求解出能令这个P(w(1:T), V(1:T))最大的隐性序列.这个算法被称为维特比算法(Viterbi Algorithm).4.3 学习(Learning)学习是在给出HMM的结构的情况下(比如说假设已经知道该大叔有3只骰子,每只骰子有6面),计算出最有可能的模型参数.(公式太多,请具体看我博客中的推导)5. HMM 的应用以上举的例子是用HMM对掷骰子进行建模与分析。当然还有很多HMM经典的应用,能根据不同的应用需求,对问题进行建模。但是使用HMM进行建模的问题,必须满足以下条件,1.隐性状态的转移必须满足马尔可夫性。(状态转移的马尔可夫性:一个状态只与前一个状态有关)2. 隐性状态必须能够大概被估计。在满足条件的情况下,确定问题中的隐性状态是什么,隐性状态的表现可能又有哪些.HMM适用于的问题在于,真正的状态(隐态)难以被估计,而状态与状态之间又存在联系。5.1 语音识别语音识别问题就是将一段语音信号转换为文字序列的过程.
在个问题里面隐性状态就是: 语音信号对应的文字序列而显性的状态就是: 语音信号.HMM模型的学习(Learning): 语音识别的模型学习和上文中通过观察骰子序列建立起一个最有可能的模型不同. 语音识别的HMM模型学习有两个步骤:1. 统计文字的发音概率,建立隐性表现概率矩阵B2. 统计字词之间的转换概率(这个步骤并不需要考虑到语音,可以直接统计字词之间的转移概率即可)语音模型的估计(Evaluation): 计算"是十四”,"四十四"等等的概率,比较得出最有可能出现的文字序列.5.2 手写识别这是一个和语音差不多,只不过手写识别的过程是将字的图像当成了显性序列.5.3 中文分词“总所周知,在汉语中,词与词之间不存在分隔符(英文中,词与词之间用空格分隔,这是天然的分词标记),词本身也缺乏明显的形态标记,因此,中文信息处理的特有问题就是如何将汉语的字串分割为合理的词语序。例如,英文句子:you
should go to kindergarten now 天然的空格已然将词分好,只需要去除其中的介词“to”即可;而“你现在应该去幼儿园了”这句表达同样意思的话没有明显的分隔符,中文分词的目的是,得到“你/现在/应该/去/幼儿园/了”。那么如何进行分词呢?主流的方法有三种:第1类是基于语言学知识的规则方法,如:各种形态的最大匹配、最少切分方法;第2类是基于大规模语料库的机器学习方法,这是目前应用比较广泛、效果较好的解决方案.用到的统计模型有N元语言模型、信道—噪声模型、最大期望、HMM等。第3类也是实际的分词系统中用到的,即规则与统计等多类方法的综合。”[1]5.4 HMM实现拼音输入法拼音输入法,是一个估测拼音字母对应想要输入的文字(隐性状态)的过程(比如, ‘pingyin’ -& 拼音)参考:3.3K157 条评论分享收藏感谢收起隐马尔可夫模型——Viterbi算法
参考博客:
先用一句话来简单描述一下:给出一个观测序列o1,o2,o3 …,我们希望找到观测序列背后的隐藏状态序列s1, s2, s3,
…;Viterbi以它的发明者名字命名,正是这样一种由动态规划的方法来寻找出现概率最大的隐藏状态序列(被称为Viterbi路径)的算法。
Markov随机过程具有如下的性质:在任意时刻,从当前状态转移到下一个状态的概率与当前状态之前的那些状态没有关系,即只与“现在”有关,而与“过去”无关。所以,我们可以用一个状态转移概率矩阵来描述它。假设我们有n个离散状态S1,
S2,…Sn,我们可以构造一个矩阵A,矩阵中的元素aij表示从当前状态Si下一时刻迁移到Sj状态的概率。
但是在很多情况下,Markov模型中的状态是我们观察不到的。例如,容器与彩球的模型:有若干个容器,每个容器中按已知比例放入各色的彩球(这样,选择了容器后,我们可以用概率来预测取出各种彩球的可能性);我们做这样的实验,实验者从容器中取彩球——先选择一个容器,再从中抓出某一个球,只给观察者看球的颜色;这样,每次取取出的球的颜色是可以观测到的,即o1,
o2,…,但是每次选择哪个容器是不暴露给观察者的,容器的序列就组成了隐藏状态序列S1,
S2,…Sn。这是一个典型的可以用HMM描述的实验。
HMM有几个重要的任务,其中之一就是期望通过观察序列来猜测背后最有可能的隐藏序列。在上面的例子中,就是找到我们在实验中最有可能选择到的容器序列。Viterbi正是用来解决这个问题的算法。HMM另外两个任务是:a)
给定一个HMM,计算一个观测序列出现的可能性;b)已知一个观测序列,HMM参数不定,如何优化这些参数使得观测序列的出现概率最大。解决前一个问题可以用与Viberbi结构非常类似的Forward算法来解决(实际上在下面合二为一),而后者可以用Baum-Welch/EM算法来迭代逼近。
用一个例子来说明Viterbi算法。
假设你有一个朋友在外地,每天你可以通过电话来了解他每天的活动。他每天只会做三种活动之一——Walk, Shop,
Clean。你的朋友从事哪一种活动的概率与当地的气候有关,这里,我们只考虑两种天气——Rainy,
Sunny。我们知道,天气与运动的关系如下:
P(o|state)
例如,在下雨天出去散步的可能性是0.1。
而天气之前互相转换的关系如下,(从行到列)
p(state—&next_state)
例如,从今天是晴天而明天就开始下雨的可能性是0.4 。
同时为了求解问题我们假设初始情况:通话开始的第一天的天气有0.6的概率是Rainy,有0.4概率是Sunny。OK,现在的问题是,如果连续三天,你发现你的朋友的活动是:Walk-&Shop-&Clean(观测序列);那么,如何判断你朋友那里这几天的天气(隐藏状态序列)是怎样的?
解决这个问题的python伪代码如下:
def forward_viterbi(y, X, sp, tp, ep):
for state in X:
## prob. V. path V. prob.
T[state] = (sp[state], [state], sp[state])
for output in y:
for next_state in X:
&&& total =
&&& argmax =
&&& valmax =
source_state in X:
(prob, v_path, v_prob) = T[source_state]
p = ep[source_state][output] * tp[source_state][next_state]
v_prob *= p
total += prob
if v_prob & valmax:
&&&&&&&&&&&
argmax = v_path + [next_state]
&&&&&&&&&&&
valmax = v_prob
U[next_state] = (total, argmax, valmax)
## apply sum/max to the final states:
argmax = None
valmax = 0
for state in X:
(prob, v_path, v_prob) = T[state]
total += prob
if v_prob & valmax:
&&& argmax =
&&& valmax =
return (total, argmax, valmax)几点说明:
算法对于每一个状态要记录一个三元组:(prob, v_path,
v_prob),其中,prob是从开始状态到当前状态所有路径(不仅仅
是最有可能的viterbi路径)的概率加在一起的结果(作为算法附产品,它可以输出一个观察序列在给定HMM下总的出现概率,即forward算法的输出),v_path是从开始状态一直到当前状态的viterbi路径,v_prob则是该路径的概率。
算法开始,初始化T (T是一个Map,将每一种可能状态映射到上面所说的三元组上)
三重循环,对每个一活动y,考虑下一步每一个可能的状态next_state,并重新计算若从T中的当前状态state跃迁到next_state概率会有怎样的变化。跃迁主要考虑天气转移(tp[source_state][next_state])与该天气下从事某种活动(ep[source_state][output])的联合概率。所有下一步状态考虑完后,要从T中找出最优的选择viterbi路径——即概率最大的viterbi路径,即上面更新Map
U的代码U[next_state] = (total, argmax, valmax)。
算法最后还要对T中的各种情况总结,对total求和,选择其中一条作为最优的viterbi路径。
算法输出四个天气状态,这是因为,计算第三天的概率时,要考虑天气转变到下一天的情况。
通过程序的输出可以帮助理解这一过程:{p=p(observation|state)*p(state—&next_state)}
observation=Walk
next_state=Sunny
state=Sunny
triple=(0.144,Sunny-&,0.144)
state=Rainy
triple=(0.018,Rainy-&,0.018)
U[Sunny]=(0.162,Sunny-&Sunny-&,0.144)
next_state=Rainy
state=Sunny
triple=(0.096,Sunny-&,0.096)
state=Rainy
triple=(0.042,Rainy-&,0.042)
U[Rainy]=(0.138,Sunny-&Rainy-&,0.096)
observation=Shop
next_state=Sunny
state=Sunny
triple=(0.02916,Sunny-&Sunny-&,0.02592)
state=Rainy
triple=(0.01656,Sunny-&Rainy-&,0.01152)
U[Sunny]=(0.04572,Sunny-&Sunny-&Sunny-&,0.02592)
next_state=Rainy
state=Sunny
triple=(0.01944,Sunny-&Sunny-&,0.01728)
state=Rainy
triple=(0.03864,Sunny-&Rainy-&,0.02688)
U[Rainy]=(0.05808,Sunny-&Rainy-&Rainy-&,0.02688)
observation=Clean
next_state=Sunny
state=Sunny
triple=(0.0027432,Sunny-&Sunny-&Sunny-&,0.0015552)
state=Rainy
triple=(0.008712,Sunny-&Rainy-&Rainy-&,0.004032)
U[Sunny]=(0.0114552,Sunny-&Rainy-&Rainy-&Sunny-&,0.004032)
next_state=Rainy
state=Sunny
triple=(0.0018288,Sunny-&Sunny-&Sunny-&,0.0010368)
state=Rainy
triple=(0.020328,Sunny-&Rainy-&Rainy-&,0.009408)
U[Rainy]=(0.0221568,Sunny-&Rainy-&Rainy-&Rainy-&,0.009408)
triple=(0.033612,Sunny-&Rainy-&Rainy-&Rainy-&,0.009408)所以,最终的结果是,朋友那边这几天最可能的天气情况是Sunny-&Rainy-&Rainy-&Rainy,它有0.009408的概率出现。而我们算法的另一个附带的结论是,我们所观察到的朋友这几天的活动序列:Walk-&Shop-&Clean在我们的隐马可夫模型之下出现的总概率是0.033612。
附:c++主要代码片断
void forward_viterbi(const
vector&string& & ob,
viterbi_triple_t & vtriple)
map&string,
double&& sp =
map&string, map&string,
double& & & tp =
transition_
map&string, map&string,
double& & & ep =
// initialization
InitParameters();
map&string, viterbi_triple_t&
for (vector&string&::iterator it
= states.begin();
it != states.end();
viterbi_triple_
foo.prob = sp[*it];
foo.vpath.push_back(*it);
foo.vprob = sp[*it];
map&string, viterbi_triple_t&
double total = 0;
vector&string&
double valmax = 0;
double p = 0;
(vector&string&::const_iterator itob
= ob.begin(); itob != ob.end(); ++itob)
cout && “observation=”
U.clear();
for (vector&string&::iterator
itNextState = states.begin();
itNextState != states.end();
++itNextState)
cout && “\tnext_state=”
&& *itNextState
total = 0;
argmax.clear();
valmax = 0;
for (vector&string&::iterator
itSrcState = states.begin();
itSrcState != states.end();
++itSrcState)
cout && “\t\tstate=”
&& *itSrcState
viterbi_triple_t foo = T[*itSrcState];
p = ep[*itSrcState][*itob] *
tp[*itSrcState][*itNextState];
cout && “\t\t\tp=”
foo.prob *=
foo.vprob *=
cout && “\t\t\ttriple=”
total += foo.
if (foo.vprob & valmax)
foo.vpath.push_back(*itNextState);
argmax = foo.
valmax = foo.
U[*itNextState] = viterbi_triple_t(total, argmax,
cout && “\tUpdate U["
&& *itNextState
&& U[*itNextState]
T.swap(U);
total = 0;
argmax.clear();
valmax = 0;
for (vector&string&::iterator
itState = states.begin();
itState != states.end();
++itState)
viterbi_triple_t foo = T[*itState];
total += foo.
if (foo.vprob & valmax)
argmax.swap(foo.vpath);
valmax = foo.
vtriple.prob =
vtriple.vpath =
vtriple.vprob =
cout && “final triple=”
&& vtriple
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。对经典隐马尔可夫模型学习算法的改进_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
对经典隐马尔可夫模型学习算法的改进
上传于|0|0|文档简介
&&对经典隐马尔可夫模型学习算法的改进
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
你可能喜欢隐马尔可夫模型的前向算法(java实现),今天奉上
时间: 23:38:49
&&&& 阅读:203
&&&& 评论:
&&&& 收藏:0
标签:&&&&&& 隐马尔可夫模型的前向算法(手动实现),今天奉上,由于研究生期间,实现的时候没有多加注释,这里为了让更好的人进入自然语言处理领域,特此,将前向算法奉上,具体公式可参考52nlp的HMN系列博客。&&&&&& 参考了大部分网站公式和借鉴。在此表示感谢。&&&&& 后向算法和维特比算法,后续更新。&HMM类:&&1&package&.hmm.&&2&&&3&import&.hmm.bean.HMMH&&4&&&5&/**&&6&&*&实现了&HMM(隐马尔可夫模型,&Hidden&Markov&Models)的&前向(Forward),&后向(Backward),&&7&&*&前向-后向(Baum-Welch)算法&这里均计算对数概率(将乘法转换为加法)&&8&&*&&HMM五元素:λ=(N,&M,&A,&B,&pi)&&&9&&*&&N:隐藏状态数&hidden&states&&10&&*&&M:观测状态数&observed&states&&11&&*&&A:&状态转移矩阵&transition&matrix&&12&&*&&B:发射矩阵&emission&matrix&&13&&*&&pi:初始隐状态向量&initial&state&vector&14&&*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&P(q_t|q_t-1)&15&&*&隐藏状态:&q1&——&q2&——&&……——&q_t-1——&q_t——&——&q_T&16&&*&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&|&17&&*&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&|&&&&&&&&&&&&&&&&&&&&&&&&&&|&18&&*&&显示状态:O1&&&&&&&&&&&&O2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&O_t-1&&&&&&&&O_t&&&&&&&&&&&&&&&&&&&&O_T&19&&*&&隐数目——N个;显数目——M个&20&&*/&21&public&class&HMM&{&22&&&&&/**&23&&&&&&*&隐藏状态名称列表——在获取最优隐藏状态序列时需要&24&&&&&&*&如enum&Box&{one,&two,&three};&//&隐藏状态(箱子编号)&25&&&&&&*/&26&&&&&public&String[]&&27&&&&&/**&28&&&&&&*&观察状态名称列表——在根据观测索引获取获取观测序列时需要&29&&&&&&*&enum&Color&{red,&yellow,&blue,&green};&//&观察状态(观测到的颜色值)&30&&&&&&*/&31&&&&&public&String[]&&32&&&&&&33&&&&&public&int&N;&34&&&&&/**&35&&&&&&*&&观测状态数&observed&states&36&&&&&&*&&观测状态名称叫syms&37&&&&&&*/&38&&&&&public&int&M;&39&&&&&/**&40&&&&&&*&隐藏状态转移矩阵&41&&&&&&*&logA[&i&][&j&]&=&log(P(&i&-&&j&))&表示从i状态转移到&j&状态的概率——取自然对数&42&&&&&&*/&43&&&&&public&double[][]&logA;&44&&&&&/**&45&&&&&&*&发射矩阵(混淆矩阵)&46&&&&&&*&logB[&i&][Ot]&=&log(P(emit&Ot&in&state&i))&表示状态&i&下发射出&Ot&的概率——Ot为第t时刻的显示序列单号&47&&&&&&*/&48&&&&&public&double[][]&logB;&49&&&&&/**&50&&&&&&*&初始状态概率分布——每个隐藏状态发生的概率&51&&&&&&*/&52&&&&&public&double[]&logPI;&53&&&&&&54&&&&&/**&55&&&&&&*&观察到的序列&56&&&&&&*/&57&&&&&//public&int[]&O;//如yellow&red&blue&yellow&green&这些在enum&Color&{red,yellow,blue,green&}的索引位置&58&&&&&&59&&&&&public&HMM(){}&60&&&&&&61&&&&&public&&HMM(int&N,&int&M){&62&&&&&&&&&this.N=N;&63&&&&&&&&&this.M=M;&64&&&&&&&&&this.logA=new&double[N][N];&65&&&&&&&&&this.logB=new&double[N][M];&66&&&&&&&&&this.logPI=new&double[N];&67&&&&&&&&&for(int&i=0;&i&N;&i++){&68&&&&&&&&&&&&&for(int&j=0;&j&N;&j++){&69&&&&&&&&&&&&&&&&&this.logA[&i&][&j&]&=&Double.NEGATIVE_INFINITY;&70&&&&&&&&&&&&&}&71&&&&&&&&&&&&&for(int&j=0;&j&M;&j++){&72&&&&&&&&&&&&&&&&&this.logB[&i&][&j&]=Double.NEGATIVE_INFINITY;&73&&&&&&&&&&&&&}&74&&&&&&&&&&&&&this.logPI[&i&]&=&Double.NEGATIVE_INFINITY;&75&&&&&&&&&}&76&&&&&}&77&&&&&&78&&&&&/**&79&&&&&&*&(已经有具体HMM的各个参数情况下调用)&80&&&&&&*&@param&state隐藏状态名称&81&&&&&&*&&&&&&&&&&&&enum&Box&{one,two,three&}&82&&&&&&*&&@param&syms&观测状态名称&83&&&&&&*&&&&&&&&&&&&enum&Color&{red,yellow,blue,green}&84&&&&&&*&@param&A&85&&&&&&*&&&&&&&&&&&&隐藏状态的转移矩阵&86&&&&&&*&&&&&&&&&&&&&&&&&&&&&&&&&1&&&&&&&&&&&&&2&&&&&&&&&&&3&87&&&&&&*&&&&&&&&&&&&&&&&&&&&&&one&&&&&&&&two&&&&&&&&three&88&&&&&&*&&&&&&&&&&&one&&{0.500,&&&0.375,&&&0.125}&89&&&&&&*&&&&&&&&&&&two&&{0.250,&&&0.125,&&&0.625},&90&&&&&&*&&&&&&&&&&&three{0.250,&&&0.375,&&&0.375}&91&&&&&&*&@param&B&从隐藏状态——观察状态的发射矩阵(混淆矩阵)&92&&&&&&*&&&&&&&&&&&&&&&&&&&&&&&&&&&&0&&&&&&&&1&&&&&&&&&2&&&&&&&&3&93&&&&&&*&&&&&&&&&&&&&&&&&&&&&&&&&&red&yellow&blue&&green&94&&&&&&*&&&&&&&&&&&&one&&&&&{0.60,&&0.20,&&0.15,&&0.05},&95&&&&&&*&&&&&&&&&&&&two&&&&&{0.25,&&0.25,&&0.25,&&0.25},&96&&&&&&*&&&&&&&&&&&&three&&{0.05,&&0.10,&&0.35,&&0.50}&97&&&&&&*/&98&&&&&public&HMM(double[][]&A,&double[][]&B,&double[]&PI){&99&&&&&&&&&this.N=A.100&&&&&&&&&this.M=B[0].101&&&&&&&&&this.logA=new&double[N][N];102&&&&&&&&&this.logB=new&double[N][M];103&&&&&&&&&this.logPI=new&double[N];104&&&&&&&&&for(int&i=0;&i&N;&i++){105&&&&&&&&&&&&&for(int&j=0;&j&N;&j++){106&&&&&&&&&&&&&&&&&this.logA[&i&][&j&]&=&Math.log(&A[&i&][&j&]&);107&&&&&&&&&&&&&}108&&&&&&&&&&&&&for(int&j=0;&j&M;&j++){109&&&&&&&&&&&&&&&&&this.logB[&i&][&j&]=Math.log(&B[&i&][&j&]&);110&&&&&&&&&&&&&}111&&&&&&&&&&&&&this.logPI[&i&]&=&Math.log(&PI[&i&]&);112&&&&&&&&&}113&&&&&}114&&&&&115&&&&&/**116&&&&&&*&打印转移矩阵117&&&&&&*/118&&&&&public&void&printA()&{119&&&&&&&&&System.out.println("转移矩阵:");120&&&&&&&&&for&(int&i&=&1;&i&&&N;&i++)&{121&&&&&&&&&&&&&for&(int&j&=&1;&j&&&N;&j++){122&&&&&&&&&&&&&&&&&System.out.print(HMMHelper.fmtlog(logA[i][j]));123&&&&&&&&&&&&&}124&&&&&&&&&&&&&System.out.println();125&&&&&&&&&}126&&&&&}127&128&&&&&/**129&&&&&&*&打印发射矩阵130&&&&&&*/131&&&&&public&void&printB()&{132&&&&&&&&&System.out.println("发射矩阵:");133&&&&&&&&&for&(int&i&=&1;&i&&&N;&i++)&{134&&&&&&&&&&&&&for&(int&j&=&1;&j&&&N;&j++){135&&&&&&&&&&&&&&&&&System.out.print(HMMHelper.fmtlog(logB[i][j]));136&&&&&&&&&&&&&}137&&&&&&&&&&&&&System.out.println();138&&&&&&&&&}139&&&&&}140&&&&&141&&&&&142&}View Code&Forward类:&&1&package&.hmm.&2&&3&import&.hmm.bean.HMMH&4&import&.util.TCMM&5&&6&/**&7&&*&前向算法:&8&&*&目的:&9&&*&1、先计算前向变量矩阵10&&*&2、再用前向变量矩阵&来&计算一个观测序列的概率11&&*&@author&aool12&&*/13&public&class&Forward&extends&HMM{14&&&&&public&int[]&O;//观测序列observe//如yellow&red&blue&yellow&green&这些在enum&Color&{red,yellow,blue,green&}的索引位置15&16&&&&&public&double[][]&&//前向变量矩阵17&&&&&18&&&&&public&Forward(double[][]&A,&double[][]&B,&double[]&PI,&int[]&O){19&&&&&&&&&super(A,&B,&PI);20&&&&&&&&&this.O=O;21&&&&&}22&&&&&23&&&&&/**24&&&&&&*&【计算前向变量矩阵】25&&&&&&*&在时间&t&的条件下,hmm输出观察序列O(1)O(2)...O(t)且该时间t下的隐藏状态为s_i(第i个隐藏状态,共N种隐藏状态)的概率26&&&&&&*&alpha[&t&][&i&]&=&alpha_t(&i&)&=&log(P(O(1)O(2)...O(t),&q_t=s_i&|&λ))27&&&&&&*/28&&&&&public&void&CalculateForeMatrix(){29&&&&&&&&&int&T&=&O.30&&&&&&&&&alpha&=&new&double[&T&][&N&];//每一时刻(每行)上&可能出现的多个状态的发生的前向变量概率31&&&&&&&&&//1、初始化,计算初始时刻(直觉上的第1时刻)所有状态的局部概率32&&&&&&&&&for&(int&i&=&0;&i&&&N&;&i++){33&&&&&&&&&&&&&alpha[&0&][&i&]&=&logPI[&i&]&+&logB[&i&][&O[&0&]&];34&&&&&&&&&}35&&&&&&&&&//2、归纳,递归计算每个时间点的局部概率36&&&&&&&&&for&(int&t&=&1;&t&&&T;&t++){//从(直觉上的第2时刻)即t=1(下标从0开始)观测值算起——第时间t下开始循环37&&&&&&&&&&&&&for&(int&i&=&0;&i&&&N;&i++)&{//在时间t下,对于每个状态s_i——计算到时间t+1的前向变量概率38&&&&&&&&&&&&&&&&&double&sum&=&Double.NEGATIVE_INFINITY;&//&=&log(0)39&&&&&&&&&&&&&&&&&for&(int&j&=&0;&j&&&N;&j++){//到第&j&种隐状态下的累计概率40&&&&&&&&&&&&&&&&&&&&&sum&=&TCMMath.logplus(&sum,&alpha[t&-&1][&j&]&+&logA[&j&][&i&]);41&&&&&&&&&&&&&&&&&}42&&&&&&&&&&&&&&&&&alpha[&t&][&i&]&=&logB[&i&][&O[&t&]&]&+&//在&【t&时刻】&下&输出观察序列&O1O2……Ot(已知观测序列的局部)&且位于第&i&种隐藏状态发生的概率43&&&&&&&&&&&&&}44&&&&&&&&&}45&&&&&}46&&&&&47&&&&&/**48&&&&&&*&【计算观测序列的概率】——前提是先计算前向变量矩阵49&&&&&&*&P(&O&|&μ&)&=&∑alpha_T(&i&)&(求和上界N,求和下界i=1)50&&&&&&*&@return&返回的结果是概率的自然对数51&&&&&&*&计算&t=T&时刻下输出观察序列&O0……OT(已经观测序列的局部)且位于第&T&状态下发生的概率52&&&&&&*/53&&&&&public&double&logProb()&{54&&&&&&&&&//3.终止,观察序列的概率等于最终时刻(&T&)所有局部概率之和55&&&&&&&&&double&sum&=&Double.NEGATIVE_INFINITY;&//&=&log(0)56&&&&&&&&&int&T&=&O.57&&&&&&&&&for&(int&i&=&0;&i&&&N;&i++){58&&&&&&&&&&&&&sum&=&TCMMath.logplus(sum,&alpha[&T-1&][&i&]);//下标从0开始59&&&&&&&&&}60&&&&&&&&&return&61&&&&&}62&&&&&63&&&&&/**64&&&&&&*&打印前向变量矩阵65&&&&&&*/66&&&&&public&void&print()&{67&&&&&&&&&for&(int&j&=&0;&j&&&N;&j++)&{68&&&&&&&&&&&&&for&(int&i&=&0;&i&&&alpha.&i++){69&&&&&&&&&&&&&&&&&System.out.print(HMMHelper.fmtlog(alpha[&i&][&j&]));70&&&&&&&&&&&&&}71&&&&&&&&&&&&&System.out.println();72&&&&&&&&&}73&&&&&}74&}&测试类:&&1&package&.hmm.&2&&3&import&.hmm.bean.HMMH&4&&5&public&class&Demo1&{&6&&&&&enum&Box&{one,&two,&three};&//&隐藏状态(箱子编号)&7&&&&&enum&Color&{red,&yellow,&blue,&green};&//&观察状态(观测到的颜色值)&8&&9&&&&&public&static&void&main(String[]&args)&{10&&&&&&&&&test();11&&&&&}12&13&&&&&public&static&void&test()&{14&&&&&&&&&//&状态转移矩阵15&&&&&&&&&double[][]&A&=&{&16&&&&&&&&&&&&&&&&&{&0.500,&0.375,&0.125&},&17&&&&&&&&&&&&&&&&&{&0.250,&0.125,&0.625&},&18&&&&&&&&&&&&&&&&&{&0.250,&0.375,&0.375&}&};19&&&&&&&&&//&发射矩阵20&&&&&&&&&double[][]&B&=&{&21&&&&&&&&&&&&&&&&&{&0.60,&0.20,&0.15,&0.05&},&22&&&&&&&&&&&&&&&&&{&0.25,&0.25,&0.25,&0.25&},&23&&&&&&&&&&&&&&&&&{&0.05,&0.10,&0.35,&0.50&}&};24&&&&&&&&&25&&&&&&&&&&&//&初始概率向量26&&&&&&&&&&&double[]&PI&=&{&0.63,&0.17,&0.20&};27&&&&&&&&&28&&&&&&&&&//&观察序列29&&&&&&&&&int[]&O&=&{&Color.yellow.ordinal(),&Color.red.ordinal(),&Color.blue.ordinal(),&Color.yellow.ordinal(),Color.green.ordinal()&};30&&&&&&&&&System.out.println("初始概率向量:{"+PI[0]+"&"+PI[1]+"&"+PI[2]+"}");31&&&&&&&&&System.out.println("隐藏状态序列:{"+Box.one+"&"+Box.two+"&"+Box.three+"}");32&&&&&&&&&System.out.println("观测序列:{"+Color.yellow+"&"+Color.red+"&"+Color.blue+"&"+Color.yellow+"&"+Color.green+"}");33&&&&&&&&&34&&&&&&&&&/**35&&&&&&&&&&*&前向算法测试——求解观察序列的概率36&&&&&&&&&&*/37&&&&&&&&&Forward&foreward=new&Forward(A,&B,&PI,&O);38&&&&&&&&&foreward.CalculateForeMatrix();//计算前向变量矩阵39&&&&&&&&&System.out.println(&HMMHelper.fmtlog(&foreward.logProb()&)&);//计算观测序列O的概率40&&&&&&&&&41&&&&&&&&&/**42&&&&&&&&&&*&后向算法测试43&&&&&&&&& */ 47&&& }48&}&标签:
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 隐马尔可夫模型 的文章

 

随机推荐