机器学习---概率图模型(概率计算问题)

1. 直接计算法

给定模型和观测序列,计算观测序列O出现的概率。最直接

的方法是按概率公式直接计算.通过列举所有可能的长度为T的状态序列,求各个状

态序列 I 与观测序列的联合概率,然后对所有可能的状态序列求和,得


状态序列的概率是

对固定的状态序列,观测序列的概率是

,O和I同时出现的联合概率为

。然后,对所有可能的状态序列I求和,得到观测序列O的概率

,即但是,利用公式计算

量很大,是阶的,这种算法不可行。

2. 前向算法

首先定义前向概率。给定隐马尔可夫模型λ,定义到时刻 t 部分观测序列为,且

状态为q1的概率为前向概率,记作。可以递推地求得前向概率α(i)

及观测序列概率

算法:(观测序列概率的前向算法)输入:隐马尔可夫模型λ,观测序列O;输出:观测序列概率P

(O|λ)。

初值:

递推:对

终止:

如上图所示,前向算法实际是基于“状态序列的路径结构”递推计算P(O|λ)的算法。前向算法高

效的关键是其局部计算前向概率,然后利用路径结构将前向概率“递推”到全局,得到P(O|λ).

具体地,在时刻t=1,计算α1(i)的N个值(i=1,2,···,N);在各个时刻t=1,2,···,T-1,

计算αt+1(i)的N个值(i=1,2,···.,N),而且每个αt+1(i)的计算利用前一时刻N个αt(j),减少计

算量的原因在于每一次计算直接引用前一个时刻的计算结果,避免重复计算。这样,利用前向概率

计算P(O|λ)的计算量是阶的,而不是直接计算的阶。

前向算法的复杂度:

所以利用前向算法计算的计算量是阶的,当N=3,T=100时,

原始算法:大约需要10^(50)次运算;前向算法:计算次数小于2000次

前向算法Python实现分析:

import numpy as np  
  
def forward_algorithm(obs, states, start_p, trans_p, emit_p):  
    """  
    obs: 观察序列  
    states: 隐藏状态集合  
    start_p: 初始状态概率  
    trans_p: 状态转移概率  
    emit_p: 发射概率  
    """  
      
    T = len(obs)  
    N = len(states)  
      
    # 初始化alpha  
    alpha = np.zeros((T, N))  
    alpha[0, :] = start_p * emit_p[:, obs[0]]  
      
    # 递推计算alpha  
    for t in range(1, T):  
        for n in range(N):  
            alpha[t, n] = sum(alpha[t-1, :] * trans_p[:, n]) * emit_p[n, obs[t]]  
      
    # 计算观察序列的概率  
    P = sum(alpha[-1, :])  
      
    return P, alpha  
  
# 示例  
obs = [0, 1, 0]  # 观察序列  
states = [0, 1]  # 隐藏状态集合  
start_p = [0.6, 0.4]  # 初始状态概率  
trans_p = [[0.7, 0.3], [0.4, 0.6]]  # 状态转移概率  
emit_p = [[0.1, 0.9], [0.9, 0.1]]  # 发射概率  
  
P, alpha = forward_algorithm(obs, states, start_p, trans_p, emit_p)  
print(f"观察序列的概率: {P}")

3. 后向算法

后向概率:给定隐马尔可夫模型λ,定义在时刻t状态为q1的条件下,从t+1到T的部分观测序列为

的概率为后向概率,记作

可以用递推的方法求得后向概率βt(i)及观测序列概率P(O|λ)。

观测序列概率的后向算法:

输入:隐马尔可夫模型λ,观测序列O;输出:观测序列概率P(O|λ)。

,对

后向算法Python实现分析:

import numpy as np  
  
def backward_algorithm(obs, states, start_p, trans_p, emit_p):  
    """  
    obs: 观察序列  
    states: 隐藏状态集合  
    start_p: 初始状态概率 (虽然后向算法本身不使用这个参数,但为了完整性仍然包括在参数列表中)  
    trans_p: 状态转移概率  
    emit_p: 发射概率  
    """  
      
    T = len(obs)  # 观察序列的长度  
    N = len(states)  # 隐藏状态的数量  
      
    # 初始化beta  
    beta = np.ones((T, N))  
      
    # 从观察序列的倒数第二个元素开始递推计算beta  
    for t in range(T - 2, -1, -1):  
        for n in range(N):  
            beta[t, n] = np.dot(beta[t + 1, :] * emit_p[:, obs[t + 1]], trans_p[n, :])  
      
    # 计算观察序列的概率  
    # 注意:这里我们实际上计算的是所有可能路径的概率之和,  
    # 但由于我们只需要这个总和,因此不需要显式地计算每个路径的概率。  
    # 初始状态概率start_p在后向算法中并不直接用于计算观察序列的概率,  
    # 但我们可以利用最后一步的beta和初始的发射概率来计算整个观察序列的概率。  
    # 这是一种不太常见的做法,因为我们通常使用前向-后向算法来计算概率,  
    # 该算法结合了前向和后向概率以避免数值下溢问题。  
    # 然而,为了这个示例的完整性,我们将展示如何使用beta来计算概率。  
    # 请注意,这种方法可能不是数值上最稳定的。  
      
    # 正确的做法是使用前向-后向算法中的一个步骤来计算概率,如下:  
    # P = sum(forward_probs[-1] * backward_probs[0]) (其中forward_probs和backward_probs是归一化的)  
    # 但在这个例子中,我们只实现后向算法,所以我们将使用一种简化的方法(可能不是最优的)。  
      
    # 计算最后一步的"后向概率"(未归一化)  
    last_step_backward = np.dot(beta[0, :] * emit_p[:, obs[0]], start_p)  
      
    # 由于我们没有计算前向概率,我们不能简单地通过前向和后向概率的乘积来归一化。  
    # 因此,我们将依赖这样一个事实:对于正确的模型参数,后向算法计算的beta应该使得下面的求和接近1(但不是严格的1,因为数值误差)。  
    # 在实际应用中,应该使用前向-后向算法来确保正确的归一化。  
      
    # 近似计算观察序列的概率(这不是标准做法,仅用于演示目的)  
    P = np.sum(last_step_backward)  
      
    return P, beta  
  
# 示例参数(同前向算法示例)  
obs = [0, 1, 0]  # 观察序列  
states = [0, 1]  # 隐藏状态集合(这里用整数表示状态)  
start_p = [0.6, 0.4]  # 初始状态概率(虽然后向算法不使用它来计算概率)  
trans_p = [[0.7, 0.3], [0.4, 0.6]]  # 状态转移概率  
emit_p = [[0.1, 0.9], [0.9, 0.1]]  # 发射概率  
  
# 调用后向算法函数并打印结果  
P, beta = backward_algorithm(obs, states, start_p, trans_p, emit_p)  
print(f"观察序列的概率(近似): {P}")

4. 计算

利用前向概率和后向概率,可以得到关于单个状态和两个状态概率的计算公式。

给定模型λ和观测O,在时刻t处于状态q1的概率。记

可以通过前向后向概率计算。事实上,

由前向概率和后向概率定义可知:

于是得到:

给定模型λ和观测O,在时刻t处于状态qt且在时刻t+1处于状态qj的概率。记

可以通过前向后向概率计算:

所以:

对各个时刻t求和,可以得到一些有用的期望值:

在观测O下状态i出现的期望值,在观测O下由状态i转移的期望值

在观测O下由状态i转移到状态j的期望值

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】多态语法概念

目录 一、概念及定义二、虚函数重写的特例三、final和override四、抽象类 一、概念及定义 概念:在继承关系下的不同类,调用同一个函数,产生不同的行为,叫作多态。 图示: 定义:必须通过基类的指针或者引…

代码随想录算法训练营第四十八天(动态规划篇之01背包)| 1049. 最后一块石头的重量Ⅱ,494. 目标和

1049. 最后一块石头的重量Ⅱ 题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode) 思路 尽量将石头分为重量相同的两堆,这样两堆中的石头相撞之后剩下的石头就会最小。根据之前的01背包理论: 代码随想录算法训…

C语言easyx 贪吃蛇大作战,没有模仿,只有超越

作品名称:贪吃蛇大作战 版本历史和日期:V1.0 - 2024年2月11日 简介: 贪吃蛇大作战是一个基于EasyX图形库的经典贪吃蛇游戏。玩家通过键盘控制贪吃蛇的移动方向,目标是吃掉屏幕上随机生成的食物点,每吃掉一个食物点,蛇身就会增长一节。游戏提供三种模式:无屏障模式、有…

2024牛客寒假算法基础集训营2

C Tokitsukaze and Min-Max XOR 题目大意 给定一个数组从任取数构成序列序列满足,(可以只取一个数)问能构造出多少个 解题思路 定找双枚举时间复杂度到,考虑利用加速统计的方案,即将数字按二进制位拆分挂在树上对于…

vtk三维场景基本要素 灯光、相机、颜色、纹理映射 简介

整理一下VTK 三维场景基本要素,后面会一一进行整理; 1. 灯光 vtkLight 剧场里有各式各样的灯光,三维渲染场景中也一样,可以有多个灯光存在。灯光和相机 是三维渲染场景必备的要素,vtkRenderer会自动创建默认的灯光和…

第76讲安全退出实现

安全退出实现 VueX 是一个专门为 Vue.js 应用设计的状态管理构架,统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data )。 Vuex有五个核心概念: state, getters, mutations, actions, modules。 state:vuex的基本数…

Blazor 子组件交互例子

源码 子组件 SwitchBar.razor &#xfeff;using Microsoft.Extensions.Logging inject ILogger<Index> Logger<div style"ClassString" onclick"OnClick">ChildContent </div>code {[Parameter]public RenderFragment? ChildContent…

element ui表格手写拖动排序

效果图&#xff1a; 思路&#xff1a; 重点在于&#xff1a;拖动行到某一位置&#xff0c;拿到这一位置的标识&#xff0c;数据插入进这个位置 vueuse的拖拽hooks useDraggable 可以用&#xff1b;html5 drag能拖动行元素&#xff1b;mounsedown、mounsemove时间实现拖拽 页…

嵌入式电子产品开发感悟!

​ 2023特别深有感触的有以下几个事件&#xff1a; 1. 早在2月底就提交报告&#xff1a;抓紧开一款便携式的空气波压力按摩仪外壳&#xff0c;包括模具费和100台试产物料费用总计不超过22W&#xff0c;保证最迟在4月中旬全部生产好&#xff0c;以供业务参加5月份开始的大健康展…

C++对象继承

继承概念&#xff1a; 首先引入一个生活例子&#xff0c;普通人是一个类对象&#xff0c;学生是一个类对象&#xff0c;普通人拥有的属性学生一定会有&#xff0c;学生拥有的属性普通人不一定有。类比一下&#xff0c;把普通人抽象为A对象&#xff0c;学生抽象为B对象&#xf…

【知识整理】接手新技术团队、管理团队

引言 针对目前公司三大技术中心的不断升级&#xff0c;技术管理岗位要求越来越高&#xff0c;且团队人员特别是管理岗位的选择任命更是重中之重&#xff0c;下面针对接手新的技术团队做简要整理&#xff1b; 一、实践操作 1、前期准备 1、熟悉情况&#xff1a; 熟悉人员&am…

【开源】JAVA+Vue.js实现计算机机房作业管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登录注册模块2.2 课程管理模块2.3 课时管理模块2.4 学生作业模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程表3.2.2 课时表3.2.3 学生作业表 四、系统展示五、核心代码5.1 查询课程数据5.2 新增课时5.3 提交作…

基于JSP的网上购书系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88825694?spm1001.2014.3001.5503 Java项目-15 源码论文数据库配置文件 基于JSP的网上购书系统 摘要 在当今的社会中&#xff0c; 随着社会经济的快速发展以及计算机网络技术和通讯技术…

C语言-----自定义类型-----结构体枚举联合

结构体和数组一样&#xff0c;都是一群数据的集合&#xff0c;不同的是数组当中的数据是相同的类型&#xff0c;但是结构体中的数据类型可以不相同&#xff0c;结构体里的成员叫做成员变量 结构体类型是C语言里面的一种自定义类型&#xff0c;我们前面已经了解到过int,char,fl…

【matalab】基于Octave的信号处理与滤波分析案例

一、基于Octave的信号处理与滤波分析案例 GNU Octave是一款开源软件&#xff0c;类似于MATLAB&#xff0c;广泛用于数值计算和信号处理。 一个简单的信号处理与滤波分析案例&#xff0c;说明如何在Octave中生成一个有噪声的信号&#xff0c;并设计一个滤波器来去除噪声。 首…

华为问界M9:领跑未来智能交通的自动驾驶黑科技

华为问界M9是一款高端电动汽车&#xff0c;其自动驾驶技术是该车型的重要卖点之一。华为在问界M9上采用了多种传感器和高级算法&#xff0c;实现了在不同场景下的自动驾驶功能&#xff0c;包括自动泊车、自适应巡航、车道保持、自动变道等。 华为问界M9的自动驾驶技术惊艳之处…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(11)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;10&#xff09; 4.2 PCIe体系结构的组成部件 PCIe总线作为处理器系统的局部总线&#xff0c;其作用与PCI总线类似&#xff0c;主要目的是为了连接处理器系统中的外部设备…

k8s-深入理解Service(为Pod提供负载均衡和发现)

一、Service存在的意义 二、Service的定义和创建 Pod与Service的关系 Service的定义和创建 三、Service使用NodePort对外暴露应用 四种类型&#xff0c;常用的三种&#xff1a; 指定Service的NodePort端口 在实际生产中&#xff0c;k8s的集群不会直接暴露在公网中&#xff0c…

数据结构第十二天(队列)

目录 前言 概述 源码&#xff1a; 主函数&#xff1a; 运行结果&#xff1a; 前言 今天和大家共享一句箴言&#xff1a;我本可以忍受黑暗&#xff0c;如果我不曾见过太阳。 概述 队列&#xff08;Queue&#xff09;是一种常见的数据结构&#xff0c;遵循先进先出&#…

[word] word分割线在哪里设置 #其他#经验分享

word分割线在哪里设置 在工作中有些技巧&#xff0c;可以快速提高工作效率&#xff0c;解决大部分工作&#xff0c;今天给大家分享word分割线在哪里设置的小技能&#xff0c;希望可以帮助到你。 1、快速输入分割线 输入三个【_】按下回车就是一条长直线&#xff0c;同样分别…