viterbi 算法与python实现

article/2025/9/12 10:24:49

Viterbi算法

(部分内容转自知乎:《如何通俗地讲解 viterbi 算法?》)

1、问题描述

如下如所示,如何快速找到从 S 到 E 的最短路径?

一:遍历穷举法,可行,但速度太慢;

二:viterbi算法!

image-20200602113650382

注:viterbi 维特比算法解决的是篱笆型图的最短路径问题图的节点按列组织,每列的节点数量可以不一样,每一列的节点只能和相邻列的节点相连,不能跨列相连,节点之间有着不同的距离,距离的值就不在图上一一标注出来了,大家自行脑补。

2、算法分析

(1)S 到 A 列的最短路径

首先起点是S,从S到A列的路径有三种可能:S-A1、S-A2、S-A3,如下图:

image-20200602142701039

我们不能武断地说S-A1、S-A2、S-A3中的哪一段必定是全局最短路径中的一部分,目前为止任何一段都有可能是全局最短路径的备选项。继续往右看,到了B列,按B列的B1、B2、B3逐个分析。

(2)S 到 B 列的最短路径

先看 B1,经过B1的所有路径只有3条:S-A1-B1,S-A2-B1,S-A3-B1。

image-20200602142824359

这三条路径,各节点距离加起来对比一下,就可以知道其中哪一条是最短的。假设S-A3-B1是最短的,那么我们就知道了经过B1的所有路径当中S-A3-B1是最短的,其它两条路径路径S-A1-B1和S-A2-B1都比S-A3-B1长,绝对不是目标答案,可以大胆地删掉了。删掉了不可能是答案的路径,就是viterbi算法(维特比算法)的重点,因为后面我们再也不用考虑这些被删掉的路径了。现在经过B1的所有路径只剩一条路径了,如下图:

image-20200602143128523

接下来我们继续看B2,同理,经过B2的路径有3条:S-A1-B2,S-A2-B2,S-A3-B2。

image-20200602143229184

这三条路径中,各节点距离加起来对比一下,肯定也可以知道其中哪一条是最短的,其它两条路径路径S-A2-B2和S-A3-B1也可以删掉了。经过B2所有路径只剩一条,如下图:

image-20200602143259129

接下来我们继续看B3,同理,经过B3的路径也有3条:S-A1-B3,S-A2-B3,S-A3-B3。

image-20200602143406486

这三条路径中我们也肯定可以算出其中哪一条是最短的,假设S-A2-B3是最短的,那么我们就知道了经过B3的所有路径当中S-A2-B3是最短的,其它两条路径路径S-A1-B3和S-A3-B3也可以删掉了。经过B3的所有路径只剩一条,如下图:

image-20200602143434893

现在对于B列的所有节点我们都过了一遍,B列的每个节点我们都删除了一些不可能是答案的路径,删掉这些不可能是最短路径的情况之后,留下了三个有可能是最短的路径:S-A3-B1、S-A1-B2、S-A2-B3。现在我们将这三条备选的路径放在一起汇总到下图:

image-20200602143616069

(3)S 到 C 列的最短路径

类似上面说的B列,我们从C1、C2、C3一个个节点分析。

经过C1节点的路径有:S-A3-B1-C1、S-A1-B2-C1、S-A2-B3-C1。

image-20200602143803379

和B列的做法一样,从这三条路径中找到最短的那条(假定是S-A3-B1-C1),其它两条路径同样道理可以删掉了。那么经过C1的所有路径只剩一条,如下图:

image-20200602143858783

同理,我们可以找到经过C2和C3节点的最短路径,汇总一下:

image-20200602143916693

到达C列时最终也只剩3条备选的最短路径,我们仍然没有足够信息断定哪条才是全局最短。最后,我们继续看E节点,才能得出最后的结论。

(4)S 到 E 的最短路径

到E的路径也只有3种可能性:

image-20200602144011485

E点已经是终点了,我们稍微对比一下这三条路径的总长度就能知道哪条是最短路径了。

image-20200602144032080

在效率方面相对于粗暴地遍历所有路径,viterbi 维特比算法到达每一列的时候都会删除不符合最短路径要求的路径,大大降低时间复杂度。

(以上所有内容转自知乎《如何通俗地讲解 viterbi 算法?》,如有侵权请联系我删除!)

3、python实现

上述问题只涉及节点之间的距离,这里我们假设每个节点本身有一个状态,节点与节点之间的距离用权重表示。为了简化描述和编程方便,将 S 到 A 列的权重全部置为1,C 列到 E 的权重也全部置为1,只考虑A、B、C三列。

image-20200602151132415

用矩阵 state 表示节点的状态,(d, n)=state.shape,d 就表示每一层节点的数量,n 表示总层数。

用矩阵 weight 表示相邻层之间的路径距离,n 层就有 n-1 个权重矩阵,weight[k][i][j] 表示第 k-1 层的节点 i 到第 k 层的节点 j 之间的距离。

import numpy as npstate = [[0.9, 0.1, 0.3],[0.1, 0.8, 0.4],[0.0, 0.1, 0.3]]
weight = [[[0.1, 0.4, 0.5], [0.2, 0.7, 0.1], [0.9, 0.0, 0.1]],[[0.8, 0.1, 0.1], [0.4, 0.3, 0.3], [0.1, 0.2, 0.7]]]def viterbi(state, weight):''':param state: 状态矩阵:param weight: 权重矩阵:return:'''state = np.array(state)weight = np.array(weight)d, n = state.shapeassert weight.shape == (n - 1, d, d), 'state not match path!'# 路径矩阵,元素值表示当前节点从前一层的那一个节点过来是最优的path = np.zeros(shape=(d, n))for i in range(n):print(f'进入第 {i} 层')if i == 0:path[:, i] = np.array(range(d)) + 1print('')continuefor j in range(d):print(f'更新节点 ({j}, {i}) 的状态')temp = state[:, i - 1] * weight[i - 1, :, j]temp_max = max(temp)temp_index = np.where(temp == temp_max)path[j, i] = temp_index[0] + 1state[j, i] = max(temp) * state[j, i]print('')print(state)print(path)if __name__ == '__main__':viterbi(state, weight)

http://chatgpt.dhexx.cn/article/Vp18fUWY.shtml

相关文章

维特比算法(viterbi)原理以及简单实现

维特比算法 看一下维基百科的解释,维特比算法(Viterbi algorithm)是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔可夫模型中。 通俗易懂的解释知乎…

flask中jsonify遇到的坑

1.jsonify可以将字典转换成json对象传入前端 data {"movie": movie_list,"page": page,"dic_list": dic,"total_page": total_page}>>坑1 字典的值不能为range(x,x),上图dic就是像range(x,x),会报错 …

flask中的jsonify返回的是乱码

用flask返回json时遇到了返回字符串支持中文显示的问题,在web端显示的是utf-8的编码如图; 虽然不影响接口的读取,但是可读性太差,于是研究了一下怎么直接显示成中文。最后找到了解决方案如下,在配置中加入下面一行代码就OK了。 …

request jsonify

python的flask框架为用户提供了直接返回包含json格式数据响应的方法,即jsonify,在开发中会经常用到。如下一段简单的flask后端代码,服务端视图函数根据请求参数返回json格式的数据到客户端。 转载于:https://www.cnblogs.com/daqingzi/p/9018…

Flask使用json或jsonify返回响应的数据

前言 在做网站前后端数据交互的时候,我们经常需要使用Ajax等方法向后端发送请求来获取响应的数据,而我们经常需要的就是json格式的响应数据,它实际上就是一个字符串。要知道Flask如何返回json响应数据,首先就需要知道如何将字典di…

Flask 学习-8. jsonify返回中文没正常显示问题

前言 Flask 接口返回的json 格式数据有中文的时候,默认是以ASCII码 返回的,没正常显示中文。 jsonify 返回 json 数据 函数直接返回dict 数据 或返回jsonfy() 函数处理的数据,都是以json格式返回的 from flask import Flask, jsonify fro…

flask jsonify之序列化时的default函数、jsonify序列化自定义对象

目录 1.看源码 2、重写默认的default函数,实现自己的序列化机制 3、把对象转化成字典 3.1 __dict__的方式 3.2、定义keys和__getitem__的方式 4、最终的代码实现 5、关于default函数的其他知识 1.看源码 打开site-package,flask,json…

Flask | 解决jsonify返回中文乱码问题

在采用 return jsonify(data) 返回内容中含有中文时,前端接收数据出现中文乱码问题,乱码格式如下(仅中文为ASCII码): 故在此记录下该问题的解决方式,以作后期参考: 在定义Flask app时&#xff…

jsonify返回中文编码的问题

app.config[JSON_AS_ASCII]Flase 在它下面加上上面的代码就欧克了 没加之前或者为True: 加了之后:

flask学习二(jsonify)

示例一: 实现动态路由,代码如下 # coding:utf-8 from flask import Flask from flask import jsonify # 创建对象 app Flask(__name__)users_list {"1001":["123","张三",19],"1002":["234","…

flask中jsonify和json区别

一 JSON数据结构 要把json与字典区分开来 dumps(字典转换成Json) loads(Json转换成字典) Python 的字典是一种数据结构,JSON 是一种数据格式。 json 就是一个根据某种约定格式编写的纯字符串,不具备任何数据结构的特征。而 python 的字典…

关于flask入门教程-记录集转jsonify

Flask 框架里,可以用 jsonify 返回 json 数据,但是为什么不用 Python 自带的 json 模块返回 JSON 数据呢? 其实两者是差不多的,jsonify指明了Content-Type 是 application/json , 这样做是符合 HTTP 协议的规定的&…

Flask 的 jsonify 理解

文章目录 python 代码解决原因Content-Type的区别 python 代码 # -*- coding:utf-8 -*- from flask import Flask, jsonifyapp Flask(__name__)urls [{id: 1,title: python,description: https://www.python.org/},{id: 2,title: flask,description: https://flask.palletsp…

Flask中jsonify和json.dumps用法以及区别(简单案例)

环境:python3.6, Flask1.0.3 flask提供了jsonify函数供用户处理返回的序列化json数据, 而python自带的json库中也有dumps方法可以序列化json对象. 其二者的区别,写个简单的案例实测一下便见分晓。 from flask import Flask from flask im…

const常量函数详解

在类中,如果你不希望某些数据被修改,可以使用const关键字加以限定。const 可以用来修饰成员变量和成员函数。 const常量与指针 const int *p1与const int *p2的顺序不同,但是他们指向的值都不能改变,上述代码说明虽然指向的值不能…

C++const函数的运用:深度解析const函数的魅力

C 深度解析const函数的魅力 1. C const函数的基本概念(Basic Concepts of const Functions in C)1.1 const函数的定义与特性(Definition and Characteristics of const Functions)1.2 const函数的使用场景(Usage Scena…

const 用法

const 用法 const 修饰变量,这个变量被称为常变量,不能被修改,但本质上还是一个变量 #通过指针改变num的值 int main() {int num 10;int* p #*p 20;printf("%d ", num);return 0; }#这里num被 const修饰本来不能被修改…

const成员函数

const成员函数 const修饰成员函数的时候,const需要放在成员函数的后面,不能放在一开始,如果放在一开始的话,那么const其实是在修饰成员函数的返回值,而不是在修饰成员函数了 const成员函数中不能修改成员变量 普通成员…

const函数

const是衡量一个程序员是否老道的一个标准,除了修饰变量之外,还可以修饰函数,主要有以下几种形式 const int& fun(int& a); //修饰返回值 int& fun(const int& a); //修饰形参 int& fun(int& a) const{} //const成员…

梳理c++ const 修饰函数

const是衡量一个程序员是否老道的一个标准,除了修饰变量之外,还可以修饰函数,主要有以下几种形式 const int& fun(int& a); //修饰返回值 int& fun(const int& a); //修饰形参 int& fun(int& a) const{} //const成员…