机器学习---HMM前向、后向和维特比算法的计算

1. HMM

import numpy as np# In[15]:class HiddenMarkov:def forward(self, Q, V, A, B, O, PI):  # 使用前向算法N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小alphas = np.zeros((N, M))  # alpha值T = M  # 有几个时刻,有几个观测序列,就有几个时刻for t in range(T):  # 遍历每一时刻,算出alpha值indexOfO = V.index(O[t])  # 找出序列对应的索引for i in range(N):if t == 0:  # 计算初值alphas[i][t] = PI[t][i] * B[i][indexOfO]print('alpha1(%d)=p%db%db(o1)=%f' % (i, i, i, alphas[i][t]))else:alphas[i][t] = np.dot([alpha[t - 1] for alpha in alphas], [a[i] for a in A]) * B[i][indexOfO]  # 递推()print('alpha%d(%d)=[sigma alpha%d(i)ai%d]b%d(o%d)=%f' % (t, i, t - 1, i, i, t, alphas[i][t]))# print(alphas)P = np.sum([alpha[M - 1] for alpha in alphas])  # 求和终止# alpha11 = pi[0][0] * B[0][0]    #代表a1(1)# alpha12 = pi[0][1] * B[1][0]    #代表a1(2)# alpha13 = pi[0][2] * B[2][0]   #代表a1(3)print(P)def backward(self, Q, V, A, B, O, PI):  # 后向算法N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小betas = np.ones((N, M))  # betafor i in range(N):print('beta%d(%d)=1' % (M, i))for t in range(M - 2, -1, -1):indexOfO = V.index(O[t + 1])  # 找出序列对应的索引for i in range(N):betas[i][t] = np.dot(np.multiply(A[i], [b[indexOfO] for b in B]), [beta[t + 1] for beta in betas])realT = t + 1realI = i + 1print('beta%d(%d)=[sigma a%djbj(o%d)]beta%d(j)=(' % (realT, realI, realI, realT + 1, realT + 1),end='')for j in range(N):print("%.2f*%.2f*%.2f+" % (A[i][j], B[j][indexOfO], betas[j][t + 1]), end='')print("0)=%.3f" % betas[i][t])# print(betas)indexOfO = V.index(O[0])P = np.dot(np.multiply(PI, [b[indexOfO] for b in B]), [beta[0] for beta in betas])print("P(O|lambda)=", end="")for i in range(N):print("%.1f*%.1f*%.5f+" % (PI[0][i], B[i][indexOfO], betas[i][0]), end="")print("0=%f" % P)def viterbi(self, Q, V, A, B, O, PI):N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小deltas = np.zeros((N, M))psis = np.zeros((N, M))I = np.zeros((1, M))for t in range(M):realT = t+1indexOfO = V.index(O[t])  # 找出序列对应的索引for i in range(N):realI = i+1if t == 0:deltas[i][t] = PI[0][i] * B[i][indexOfO]psis[i][t] = 0print('delta1(%d)=pi%d * b%d(o1)=%.2f * %.2f=%.2f'%(realI, realI, realI, PI[0][i], B[i][indexOfO], deltas[i][t]))print('psis1(%d)=0' % (realI))else:deltas[i][t] = np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])) * B[i][indexOfO]print('delta%d(%d)=max[delta%d(j)aj%d]b%d(o%d)=%.2f*%.2f=%.5f'%(realT, realI, realT-1, realI, realI, realT, np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])), B[i][indexOfO], deltas[i][t]))psis[i][t] = np.argmax(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A]))print('psis%d(%d)=argmax[delta%d(j)aj%d]=%d' % (realT, realI, realT-1, realI, psis[i][t]))print(deltas)print(psis)I[0][M-1] = np.argmax([delta[M-1] for delta in deltas])print('i%d=argmax[deltaT(i)]=%d' % (M, I[0][M-1]+1))for t in range(M-2, -1, -1):I[0][t] = psis[int(I[0][t+1])][t+1]print('i%d=psis%d(i%d)=%d' % (t+1, t+2, t+2, I[0][t]+1))print(I)if __name__ == '__main__':Q = [1, 2, 3]V = ['红', '白']A = [[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]B = [[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]# O = ['红', '白', '红', '红', '白', '红', '白', '白']O = ['红', '白', '红', '白']    #例子PI = [[0.2, 0.4, 0.4]]HMM = HiddenMarkov()
#    HMM.forward(Q, V, A, B, O, PI)HMM.backward(Q, V, A, B, O, PI)
#     HMM.viterbi(Q, V, A, B, O, PI)

隐马尔可夫模型是一个统计模型,用于描述由隐藏的状态序列和对应的观测序列组成的系统。在这

个模型中,隐藏的状态是无法直接观测到的,而只能通过观测序列来进行推断。

前向算法(Forward Algorithm):前向算法用于计算在给定观测序列下每个时间步长处于特定状态

的概率。前向算法利用动态规划的思想,通过递推计算每个时间步的前向概率。前向概率

(alpha)的计算公式为:alpha[t][j] = sum(alpha[t-1][i] * A[i][j] * B[j][O[t]]) for i in range(N)

其中,alpha[t][j]表示在时间步t处于状态j的概率,A[i][j]表示从状态i转移到状态j的概率,B[j]

[O[t]]表示在状态j下观测到序列中的第t个观测的概率。

后向算法(Backward Algorithm):后向算法用于计算在给定观测序列下每个时间步从特定状态开始

的概率。后向算法同样利用动态规划的思想,通过递推计算每个时间步的后向概率。后向概率

(beta)的计算公式为: beta[t][i] = sum(A[i][j] * B[j][O[t+1]] * beta[t+1][j]) for j in range(N),其

中,beta[t][i]表示在时间步t从状态i开始的概率,A[i][j]表示从状态i转移到状态j的概率,B[j][O[t+1]]

表示在状态j下观测到序列中的第t+1个观测的概率,beta[t+1][j]表示在时间步t+1处于状态j的概率。

维特比算法(Viterbi Algorithm):维特比算法用于找到在给定观测序列下最可能的隐藏状态序列。

维特比算法利用动态规划的思想,通过递推计算每个时间步的最大概率和对应的状态。维特比算法

中使用的两个变量是delta和psi,分别表示到达某个状态的最大概率和之前的最优状态。 delta[t][j]

= max(delta[t-1][i] * A[i][j] * B[j][O[t]]) for i in range(N)

psi[t][j] = argmax(delta[t-1][i] * A[i][j]) for i in range(N)

其中,delta[t][j]表示在时间步t到达状态j的最大概率,psi[t][j]表示在时间步t到达状态j时的最优前一

个状态,argmax表示取最大值的索引。

import numpy as np# In[15]:class HiddenMarkov:def forward(self, Q, V, A, B, O, PI):  # 使用前向算法N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小alphas = np.zeros((N, M))  # alpha值T = M  # 有几个时刻,有几个观测序列,就有几个时刻for t in range(T):  # 遍历每一时刻,算出alpha值indexOfO = V.index(O[t])  # 找出序列对应的索引for i in range(N):if t == 0:  # 计算初值alphas[i][t] = PI[t][i] * B[i][indexOfO]print('alpha1(%d)=p%db%db(o1)=%f' % (i, i, i, alphas[i][t]))else:alphas[i][t] = np.dot([alpha[t - 1] for alpha in alphas], [a[i] for a in A]) * B[i][indexOfO]  # 递推()print('alpha%d(%d)=[sigma alpha%d(i)ai%d]b%d(o%d)=%f' % (t, i, t - 1, i, i, t, alphas[i][t]))# print(alphas)P = np.sum([alpha[M - 1] for alpha in alphas])  # 求和终止# alpha11 = pi[0][0] * B[0][0]    #代表a1(1)# alpha12 = pi[0][1] * B[1][0]    #代表a1(2)# alpha13 = pi[0][2] * B[2][0]   #代表a1(3)print(P)def backward(self, Q, V, A, B, O, PI):  # 后向算法N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小betas = np.ones((N, M))  # betafor i in range(N):print('beta%d(%d)=1' % (M, i))for t in range(M - 2, -1, -1):indexOfO = V.index(O[t + 1])  # 找出序列对应的索引for i in range(N):betas[i][t] = np.dot(np.multiply(A[i], [b[indexOfO] for b in B]), [beta[t + 1] for beta in betas])realT = t + 1realI = i + 1print('beta%d(%d)=[sigma a%djbj(o%d)]beta%d(j)=(' % (realT, realI, realI, realT + 1, realT + 1),end='')for j in range(N):print("%.2f*%.2f*%.2f+" % (A[i][j], B[j][indexOfO], betas[j][t + 1]), end='')print("0)=%.3f" % betas[i][t])# print(betas)indexOfO = V.index(O[0])P = np.dot(np.multiply(PI, [b[indexOfO] for b in B]), [beta[0] for beta in betas])print("P(O|lambda)=", end="")for i in range(N):print("%.1f*%.1f*%.5f+" % (PI[0][i], B[i][indexOfO], betas[i][0]), end="")print("0=%f" % P)def viterbi(self, Q, V, A, B, O, PI):N = len(Q)  # 状态序列的大小M = len(O)  # 观测序列的大小deltas = np.zeros((N, M))psis = np.zeros((N, M))I = np.zeros((1, M))for t in range(M):realT = t+1indexOfO = V.index(O[t])  # 找出序列对应的索引for i in range(N):realI = i+1if t == 0:deltas[i][t] = PI[0][i] * B[i][indexOfO]psis[i][t] = 0print('delta1(%d)=pi%d * b%d(o1)=%.2f * %.2f=%.2f'%(realI, realI, realI, PI[0][i], B[i][indexOfO], deltas[i][t]))print('psis1(%d)=0' % (realI))else:deltas[i][t] = np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])) * B[i][indexOfO]print('delta%d(%d)=max[delta%d(j)aj%d]b%d(o%d)=%.2f*%.2f=%.5f'%(realT, realI, realT-1, realI, realI, realT, np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])), B[i][indexOfO], deltas[i][t]))psis[i][t] = np.argmax(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A]))print('psis%d(%d)=argmax[delta%d(j)aj%d]=%d' % (realT, realI, realT-1, realI, psis[i][t]))print(deltas)print(psis)I[0][M-1] = np.argmax([delta[M-1] for delta in deltas])print('i%d=argmax[deltaT(i)]=%d' % (M, I[0][M-1]+1))for t in range(M-2, -1, -1):I[0][t] = psis[int(I[0][t+1])][t+1]print('i%d=psis%d(i%d)=%d' % (t+1, t+2, t+2, I[0][t]+1))print(I)if __name__ == '__main__':Q = [1, 2, 3]V = ['红', '白']A = [[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]B = [[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]# O = ['红', '白', '红', '红', '白', '红', '白', '白']O = ['红', '白', '红', '白']    #例子PI = [[0.2, 0.4, 0.4]]HMM = HiddenMarkov()
#    HMM.forward(Q, V, A, B, O, PI)
#    HMM.backward(Q, V, A, B, O, PI)HMM.viterbi(Q, V, A, B, O, PI)

前向算法(Forward Algorithm):前向算法用于计算给定观测序列下每个时刻的前向概率

(alpha),表示在当前时刻观测到特定状态的概率。通过递推计算,利用前一时刻的前向概率和

状态转移概率、发射概率来计算当前时刻的前向概率。数学公式:alpha[i][t] = PI[t][i] * B[i]

[indexOfO],其中alpha[i][t]表示在时刻t处于状态i的前向概率,PI[t][i]表示初始状态概率,B[i]

[indexOfO]表示在状态i观测到观测序列的概率。

后向算法(Backward Algorithm):后向算法用于计算给定观测序列下每个时刻的后向概率

(beta),表示从当前时刻开始,在未来时刻观测到特定状态的概率。通过递推计算,利用后一时

刻的后向概率和状态转移概率、发射概率来计算当前时刻的后向概率。数学公式:beta[i][t] = Σ(A[i]

[j] * B[j][indexOfO] * beta[j][t+1]),其中beta[i][t]表示在时刻t处于状态i的后向概率,A[i][j]表示状态i

转移到状态j的概率,B[j][indexOfO]表示在状态j观测到观测序列的概率。

维特比算法(Viterbi Algorithm):维特比算法用于找到给定观测序列下最可能的隐藏状态序列,

即根据观测序列推断出最可能的隐藏状态路径。通过动态规划的方式,利用状态转移概率、发射概

率和初始状态概率,计算每个时刻每个状态的最大概率值和对应的前一个状态。数学公式:delta[i]

[t] = max(delta[t-1][j] * A[j][i]) * B[i][indexOfO],其中delta[i][t]表示在时刻t处于状态i的最大概率值,

A[j][i]表示状态j转移到状态i的概率,B[i][indexOfO]表示在状态i观测到观测序列的概率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/470915.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 2024-02-16 开源项目日报 Top9

根据Github Trendings的统计,今日(2024-02-16统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4TypeScript项目3Rust项目3Jupyter Notebook项目1JavaScript项目1 Black:不妥协的Pytho…

五、DataX源码分析、性能参数优化

DataX源码分析 一、总体流程二、程序入口1.datax.py2.com.alibaba.datax.core.Engine.java3.切分的逻辑并发数的确认 3.调度3.1 确定组数和分组算法3.2 数据传输 三、DataX性能优化1.关键参数2.优化:提升每个 channel 的速度3.优化:提升 DataX Job 内 Ch…

npm使用国内淘宝镜像(最新地址)

目录 前言 一、命令配置 二、使用cnpm安装 三、常见包地址 四、总结 往期回顾 前言 我们前端程序员在使用国外的镜像源速度很慢并且容易下载失败,有时候需要尝试多次才有可能下载成功,很麻烦,但是可以切换为国内镜像源,下…

【Java多线程】Thread类的基本用法

目录 Thread类 1、创建线程 1.1、继承 Thread,重写run 1.2、实现 Runnable,重写run 1.3、使用匿名内部类,继承 Thread,重写run 1.4、使用匿名内部类,实现 Runnable,重写run 1.5、使用 lambda 表达式…

基于四叉树的图像分割算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ........................................................... Imgs(dx 1 : dx R1, dy 1 …

搜索专项---双端队列广搜模型

文章目录 电路维修 一、电路维修OJ链接 本题思路: #include <bits/stdc.h>#define x first #define y secondtypedef std::pair<int,int> PII;constexpr int N510;int n,m; char g[N][N]; int dist[N][N]; bool st[N][N]; std::deque<PII> dq;char cs[] &q…

vscode运行C/C++时候cmd.exe界面显示

写了一些命令行传参的程序&#xff0c;需要终端输入参数&#xff0c;默认是输出结果显示在它自己的终端界面 Code-runner: Run In Terminal 打勾就行 效果&#xff1a;

机器学习2---逻辑回归(基础准备)

逻辑回归是基于线性回归是直线分的也可以做多分类 ## 数学基础 import numpy as np np.pi # 三角函数 np.sin() np.cos() np.tan() # 指数 y3**x # 对数 np.log10(10) np.log2(2) np.e np.log(np.e) #ln(e)# 对数运算 # log(AB) log(A) logB np.log(3*4)np.log(3)np.log(4) #…

【AIGC】Stable Diffusion的采样器入门

在 Stable Diffusion 中&#xff0c;采样器&#xff08;Sampler&#xff09;是指用于生成图像的一种技术或方法&#xff0c;它决定了模型如何从潜在空间中抽样并生成图像。采样器在生成图像的过程中起着重要作用&#xff0c;影响着生成图像的多样性、质量和创造性。以下是对 St…

C++动态规划-线性dp算法

莫愁千里路 自有到来风 CSDN 请求进入专栏 X 是否进入《C专栏》? 确定 目录 线性dp简介 斐波那契数列模型 第N个泰波那契数 思路&#xff1a; 代码测试&#xff1a; 三步问题 思路&#xff1a; 代码测试&#xff1a; 最小花费爬楼梯 思路…

具有集中目录服务器的 P2P 工作方式

P2P 工作方式概述 在 P2P 工作方式下&#xff0c;所有的音频/视频文件都是在普通的互联网用户之间传输。 具有集中目录服务器的 P2P 工作方式 Napster 最早使用 P2P 技术&#xff0c;提供免费下载 MP3 音乐。 Napster 将所有音乐文件的索引信息都集中存放在 Napster 目录服务…

【Pygame手册02/20】pygame模块display控制窗口和屏幕

目录 一、说明二、pygame.display接口函数2.1 函数表格2.2 pygame.display的功能 三、详细的函数调用3.1 pygame.display.init()3.2 pygame.display.quit()3.3 pygame.display.get_init()3.4 pygame.display.set_mode()3.5 pygame.display.get_surface()3.6 pygame.display.fl…