数学之美:维特比和维特比算法

维特比算法,现代数字通信中使用最频繁的算法,也是很多自然语言处理中的解码算法。由维特比大牛创建,今天的CDMA 3G通信标准就是由维特比创建的高通公司制定的。厉害的不行。维特比算法是一种特殊的但应用最广的动态规划算法。利用动态规划可以解决任何一个图中的最短路径问题,而维特比算法则是针对一种特殊的图——篱笆网络的有向图的最短路径问题提出的。之所以重要,是因为凡是使用隐马尔可夫模型描述的问题都可以用它来解码。

以拼音转汉字为例:

上图是一个很简单的隐马尔科夫模型,没有状态跳跃,也没有状态自环的问题。这个地方要说明一下,如果x认为是拼音的话,那么y就是对应的x的汉字,但是y并不是确定的。因为同一拼音可以有多种可能性的汉字,因此我们可以认为y输出的是一个关于拼音可能汉字字典的分布。这样我们可以假设xij为状态xi的第j个可能性取值,也就是y的取值。从而我们可以把上图转成如下篱笆图:

也就是每一列代表xi的可能性取值,x1与x2之间的连接,代表两个汉字之间存在的关系。从开始状态到最终状态可以产生很多条路径,每一条路径都代表一个可能的汉字序列。我们需要做的就是找出可能性最大的汉字序列。我们可以使用前面的公式计算出所有路径概率,选取最大的。但显然这些组合数非常多,使得序列状态数呈指数增长模式。因此需要一个最好能跟状态数成正比的算法。而维特比算法就于1967年提出。维特比算法具有如下特点:

学过图最短路径算法的很容易理解该算法。篱笆图有个特点,那就是不管最短路径是哪条,它必须通过篱笆图的每一列,也就是当i确定时,最短路径肯定要通过xij中的某一个j。这就有一个优点,就是我们只需要把每个xi中对应的所有j取值的当前最短路径记录下来,就可以在xi+1状态时很容易计算出xi+1状态所对应的j取值的最短路径计算出来。流程如下:

这种算法还有个优点就是解码过程是实时的。每打入一个拼音,算法就是解析出在该拼音xi下当前所有可能的最短路径。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是维算法的C语言实现: ``` #include <stdio.h> #include <stdlib.h> #define N 3 // 状态数 #define M 4 // 观测符号数 int main() { int i, j, t; int obs_seq[] = {0, 1, 2, 0}; // 观测序列 double a[N][N] = {{0.5, 0.2, 0.3}, {0.3, 0.5, 0.2}, {0.2, 0.3, 0.5}}; // 转移概率矩阵 double b[N][M] = {{0.5, 0.5, 0.0, 0.0}, {0.0, 0.5, 0.5, 0.0}, {0.0, 0.0, 0.5, 0.5}}; // 发射概率矩阵 double pi[N] = {0.2, 0.4, 0.4}; // 初始状态概率 double delta[M][N]; // delta矩阵 int psi[M][N]; // psi矩阵 int q[M]; // 最优状态序列 // 初始化 for (i = 0; i < N; i++) { delta[0][i] = pi[i] * b[i][obs_seq[0]]; psi[0][i] = 0; } // 递推 for (t = 1; t < M; t++) { for (j = 0; j < N; j++) { double max_delta = 0.0; int max_i = 0; for (i = 0; i < N; i++) { double tmp_delta = delta[t - 1][i] * a[i][j] * b[j][obs_seq[t]]; if (tmp_delta > max_delta) { max_delta = tmp_delta; max_i = i; } } delta[t][j] = max_delta; psi[t][j] = max_i; } } // 终止 double max_delta = 0.0; int max_i = 0; for (i = 0; i < N; i++) { if (delta[M - 1][i] > max_delta) { max_delta = delta[M - 1][i]; max_i = i; } } // 回溯 q[M - 1] = max_i; for (t = M - 2; t >= 0; t--) { q[t] = psi[t + 1][q[t + 1]]; } // 输出结果 printf("最优状态序列为:"); for (t = 0; t < M; t++) { printf("%d ", q[t]); } printf("\n"); return 0; } ``` 其中,`a`数组为转移概率矩阵,`b`数组为发射概率矩阵,`pi`数组为初始状态概率,`obs_seq`数组为观测序列。程序中使用了`delta`和`psi`两个矩阵来辅助计算。最终,程序输出最优状态序列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值