维特比算法的java实现_原创:维特比算法

article/2025/10/3 23:20:22

看了宗成庆博士的《统计自然语言处理(中文信息处理)》的第六章,对维特比算法有着非常精辟的讲解。把其中的讲解上传上来,个人感觉比较正统。

ebc77569fac4d43e657071d27d27c509.png

f45afdb063eb3a3cb841e5c454f2ba4c.png

ae1f02d54c868b8bfb2d6fe82732204f.png

今天用Java实现了这个算法,也可以转换为C代码:

package com.nlp.hmm.algorithm.viterbi;

/**

* 维特比算法

*

* @author XueQiang Tong

* @date 2017/04/25

*/

public class Viterbi {

/**

* @param obs

* 观察输出序列

* @param state

* 状态序列(隐式)

* @param start_p

* 初始概率

* @param trans_p

* 状态转换概率

* @param emit_p

* 发射概率

* @return 返回最优状态路径(这个路径具有最好的解释能力)

*/

public static int[] compute(int obs[], int state[], double[] start_p, double[][] trans_p, double[][] emit_p) {

double v[][] = new double[obs.length][state.length];// viterbi值矩阵

int path[][] = new int[state.length][obs.length];// 存储路径

// 1.初始化时间序列为0的节点( t=0)

for (int s : state) {

v[obs[0]][s] = start_p[s] * emit_p[s][obs[0]];

path[s][obs[0]] = s;

}

// 2.开始递归计算viterbi矩阵(从t=1开始)

for (int t = 1; t < obs.length; ++t) {

int newpath[][] = new int[state.length][obs.length];// 每次迭代时,定义一个新的存储path,因为每个时间序列的path都依赖于

// 上个序列的path

// 对该时间序列上的每个state节点进行迭代,每个节点都与上个序列的所有state交互

for (int s : state) {

double maxValue = -1.0;

int label = -1;

for (int s0 : state) {// 寻找出备选路径

double viterbiValue = v[t - 1][s0] * trans_p[s0][s] * emit_p[s][obs[t]];

if (viterbiValue > maxValue) {

maxValue = viterbiValue;

label = s0;

// 记录最大概率

v[t][s] = maxValue;

// 记录路径

System.arraycopy(path[label], 0, newpath[s], 0, t);

newpath[s][t] = s;

}

}

}

path = newpath;

}

// 找出最后一个时间序列上的viterbi值最大的state,从而找出最优路径

double maxValue = -1.0;

int label = -1;

for (int s : state) {

if (v[obs.length - 1][s] > maxValue) {

maxValue = v[obs.length - 1][s];

label = s;

}

}

return path[label];

}

}

测试文件:

1 packagecom.nlp.hmm.algorithm.viterbi;2

3

4 public classViterbiTest {5

6 public static voidmain(String[] args) {7 int[] obs = {0,1,2};//0--walk,1--shop,2--clean

8 int[] states = {0,1};//0--rainy,1--sunny

9 double[] start_p = {0.6,0.4};//0.6--rainy,0.4--sunny

10 double[][] trans_p = new double[states.length][states.length];//0--rainy,1--sunny

11 trans_p[0][0] = 0.7;12 trans_p[0][1] = 0.3;13 trans_p[1][0] = 0.4;14 trans_p[1][1] = 0.6;15 double[][] emit_p = new double[states.length][obs.length];//dimension1:rainy 0,sunny 1;dimension2:walk 0 shop 1 clean 2

16 emit_p[0][0] = 0.1;17 emit_p[0][1] = 0.4;18 emit_p[0][2] = 0.5;19 emit_p[1][0] = 0.6;20 emit_p[1][1] = 0.3;21 emit_p[1][2] = 0.1;22 int []path =Viterbi.compute(obs, states, start_p, trans_p, emit_p);23 for (intpa:path){24 System.out.print(pa+" ");25 }26 }27

28 }

输出结果为1,0,0,就是sunny,rainy,rainy。对比了一下,结果没问题,逻辑也没问题。维特比算法和前向搜索算法有着共同点,两者解决的hmm问题不一样。

下面是本人的python实现代码:

import numpy as np

def viterbi(obs,state,start_prob,transition_prob,emit_prob):

vit = np.array(np.zeros(shape = [len(obs),len(state)],dtype = np.float64))

path = np.array(np.zeros(shape = [len(state),len(obs)],dtype = np.int32))

#初始化

for i in range(len(state)):

vit[0,i] = start_prob[i] * emit_prob[i][0]

path[i][0] = state[i]

for t in range(1,len(obs)):

newPath = np.zeros_like(path)

v = np.dot(np.reshape(vit[t-1],[len(state),1]),np.reshape(emit_prob[:,t],[1,len(state)])) * transition_prob

vi = np.max(v,axis = 0)

vit[t,:] = vi[:]

pa = np.argmax(v,axis = 0)

for i in range(len(pa)):

label = pa[i]

newPath[i,:] = path[label,:]

newPath[i][t] = state[i]

path = newPath

return path[np.argmax(vit[len(obs)-1,:]),:]


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

相关文章

隐马尔可夫(HMM)、前/后向算法、Viterbi算法 再次总结

本总结是是个人为防止遗忘而作&#xff0c;不得转载和商用。 说明&#xff1a;此篇是作者对“隐马尔可夫模型”的第二次总结&#xff0c;因此可以算作对上次总结的查漏补缺以及更进一步的理解&#xff0c;所以很多在第一次总结中已经整理过的内容在本篇中将不再重复&#xff0c…

维特比(Viterbi)算法

维特比算法 (Viterbi algorithm) 是机器学习中应用非常广泛的动态规划算法&#xff0c;在求解隐马尔科夫、条件随机场的预测以及seq2seq模型概率计算等问题中均用到了该算法。实际上&#xff0c;维特比算法不仅是很多自然语言处理的解码算法&#xff0c;也是现代数字通信中使用…

小白给小白详解维特比算法(一)

小白给小白详解维特比算法&#xff08;一&#xff09; 小白给小白详解维特比算法一 篱笆网络Lattice的最短路径问题 这个问题长什么样子这个问题难在哪里简化成这个模样你总能回答了吧下一步我们该干什么 别倒立了我们再从头想一下这个问题 我们是怎么走过来的来我们从A开始走这…

viterbi算法

维特比算法&#xff08;Viterbi Algorithm&#xff09; 标签&#xff08;空格分隔&#xff09;&#xff1a; 未分类 维特比算法&#xff08;Viterbi Algorithm&#xff09; viterbi算法用于寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states) 对于…

维特比算法

1. 概述 维特比算法是安德鲁.维特比(Andrew Viterbi)于1967年为解决通信领域中的解码问题而提出的&#xff0c;它同样广泛用于解决自然语言处理中的解码问题&#xff0c;隐马尔可夫模型的解码是其中典型的代表。无论是通信中的解码问题还是自然语言处理中的解码问题&#xff0c…

维特比算法(Viterbi algorithm)

一、维特比算法(Viterbi)原理以及简单实现 维特比算法&#xff08;Viterbi algorithm&#xff09;是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列&#xff0c;特别是在马尔可夫信息源上下文和隐马尔可夫模型中。 维特比算法实际是用动…

机器学习:维特比算法(Viterbi Algorithm)

一、维特比算法&#xff08;Viterbi Algorithm&#xff09;讲解方式01&#xff1a;篱笆网络&#xff08;Lattice&#xff09;的最短路径问题 已知下图的篱笆网络&#xff0c;每个节点之间的数字表示相邻节点之间的距离&#xff0c;举个例子来说&#xff0c;如果我走&#xff0…

字符串匹配原理及实现(C++版)

字符串匹配原理及实现&#xff08;C版&#xff09; 1. 字符串匹配概念2. BF2.1 原理2.2 代码实现 3. KMP3.1 原理3.2 代码实现 4. BM4.1 坏字符4.2 好后缀4.3 代码实现 1. 字符串匹配概念 在查找操作中&#xff0c;我们用到很重要的概念就是字符串匹配&#xff0c;所谓字符串匹…

C++之单字符串匹配问题

有很多算法可以解决单模式匹配问题。而根据在文本中搜索模式串方式的不同&#xff0c;我们可以将单模式匹配算法分为以下几种&#xff1a; 基于前缀搜索方法&#xff1a;在搜索窗口内从前向后&#xff08;沿着文本的正向&#xff09;逐个读入文本字符&#xff0c;搜索窗口中文…

字符串——字符串匹配

文章目录 字符串匹配一、基本概念字符串匹配问题符号和术语后缀重叠引理 二、朴素字符串匹配算法三、Rabin-Karp算法(字符串Hash算法)进制Hash质数Hash 四、利用有限自动机进行字符串匹配有限自动机字符串匹配自动机计算状态转移函数代码 五、Knuth-Morris-Pratt算法模式的前缀…

朴素字符串匹配

描述 字符串匹配问题的形式定义&#xff1a; 文本(Text)是一个长度为 n 的字符串:T;模式(Pattern)是一个长度为 m 且 m≤n 的字符串:P; T 和 P 中的元素都属于有限的字母表 Σ 表; 有效位移 (Valid Shift): 如果 0≤ s ≤n-m&#xff0c;并且 T[s1…sm] P[1…m]&#xff0c…

算法之字符串匹配一

目录 前言&#xff1a; BF算法&#xff1a; RK算法 总结&#xff1a; 参考资料 前言&#xff1a; 字符串匹配指的是一个短点的字符串与一个长点的字符串进行匹配&#xff0c;并确认短的字符串是否在长的字符串中存在。匹配算法有很多&#xff0c;本文介绍两种简单、容易…

字符串匹配算法(C语言实现)

目录 文章目录 前言 一、BF算法 二、KMP算法 1.算法介绍 2.算法思路 3.整体代码实现 总结 前言 字符串匹配算法又称模式匹配算法&#xff0c;该算法的目的是为了子串从主串中寻找是否有与其匹配的部分&#xff0c; 其可分为BF暴力检索、RK哈希检索、KMP、BM等等&#xff0c;本…

shell字符串匹配

一、简介 Bash Shell提供了很多字符串和文件处理的命令。如awk、expr、grep、sed等命令&#xff0c;还有文件的排序、合并和分割等一系列的操作命令。grep、sed和awk内容比较多故单独列出&#xff0c;本文只涉及字符串的处理和部分文本处理命令。 二、字符串处理 1、expr命令…

golang字符串匹配算法

简介 字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串&#xff08;称为模式串&#xff09;。在 Golang 中&#xff0c;可以使用最常见的字符串匹配算法之一&#xff1a;Knuth-Morris-Pratt&#xff08;KMP&#xff09;算法&#xff0c;它的时间复杂度为 O(nm…

【数据结构】字符串匹配(暴力匹配)

原理解析&#xff1a; 字符串匹配方法&#xff0c;创建两个字符串结构&#xff0c;主 串和子串比较。 主串字符 a 和 子串字符 c 不匹配&#xff0c;主串的指针向下移动&#xff0c;移动到上一次开始比较的下一个位置。 子串指向开始的位置。 主串字符 b 和 子串字符 c 不匹配…

字符串匹配算法比较

字符串匹配&#xff08;string match)是在实际工程中经常会碰到的问题&#xff0c;通常其输入是原字符串(String)和子串&#xff08;又称模式&#xff0c;Pattern)组成&#xff0c;输出为子串在原字符串中的首次出现的位置。通常精确的字符串搜索算法包括暴力搜索(Brute force)…

子串查找(字符串匹配)

子串查询 首先&#xff0c;我们来定义两个概念&#xff0c;主串和模式串。我们在字符串 A 中查找字符串 B&#xff0c;则 A 就是主串&#xff0c;B 就是模式串。我们把主串的长度记为 n&#xff0c;模式串长度记为 m。由于是在主串中查找模式串&#xff0c;因此&#xff0c;主串…

字符串匹配算法综述

字符串匹配算法综述 字符串匹配算法综述&#xff1a;BF、RK、KMP、BM、Sunday 字符串匹配算法&#xff0c;是在实际工程中经常遇到的问题&#xff0c;也是各大公司笔试面试的常考题目。此算法通常输入为原字符串&#xff08;string&#xff09;和子串&#xff08;pattern&…

字符串匹配算法详解

希望看到文章的你们&#xff0c;能够在今年的研究生考试中超常发挥。 愿你们都能考上自己心仪的学校&#xff0c;为你们的备考生涯划上一个完美的句号。做为你们的师兄有几句话想对你们说&#xff0c;希望这些话能对你们有一些帮助。 马上就要考试了&#xff0c;不要再继续啃难…