zoukankan      html  css  js  c++  java
  • 维特比算法Python实现

    前言

    维特比算法是隐马尔科夫问题的一个基本问题算法。维特比算法解决的问题是已知观察序列,求最可能的标注序列。

    什么是维特比算法?

    维特比算法尽管是基于严格的数学模型的算法,但是维特比算法毕竟是算法,因此可以感性地去理解。关于感性的认识,知乎上有维特比算法的感性认识讲解,讲的非常好,也非常仔细。在这里,我阐述一下自己的理解,如果有没有讲明白的地方,可以参考知乎上的讲解。
    比如说我们知道一个人有三个精神状态,比如说正常、冷、头晕。并且我们知道身体状态转换概率

    状态 健康 发烧
    健康 0.7 0.3
    发烧 0.4 0.6

    以及精神状态和身体状态的概率分布

    状态 正常 头晕
    健康 0.5 0.4 0.1
    发烧 0.1 0.3 0.6

    我们已经知道一个人的精神状态是正常、冷、头晕。我们想要知道这个人三天的身体状态。利用维特比算法就可以很好的预测。

    看起来很神奇?

    维特比算法完全基于普通的概率论知识,下面结合Python实现来阐述一下维特比算法究竟是什么。
    首先可以将概率矩阵借助Numpy输入程序

    tran = np.array([[0.7, 0.3],
                     [0.4, 0.6]])
    laun = np.array([[0.5, 0.4, 0.1],
                     [0.1, 0.3, 0.6]])
    init = np.array([0.6,0.4 ])
    look = np.array([0, 1,2])  # 观测序列
    kind = ['健康', '发烧']
    

    上面的init矩阵是健康状态的初始概率,0.6代表初始状态有0.6的概率为健康,0.4代表初始状态有0.4的概率为发烧。
    我们已经知道第一天的精神状态是正常,那么健康的概率就是P(正常|健康)*P(健康|初始状态)。发烧的概率也是同理。
    因此我们可以利用下面的代码实现初始健康状态的计算

    dp = np.array([a * b for a, b in zip(init, laun[:, look[0]])])
    print(max(dp))
    print('第1次' + kind[np.where(dp==max(dp))[0][0]])
    

    上面算出来的概率并不是代表初始状态下健康的概率,初始状态下健康的概率我们在问题初始时就已经知道,不需要计算。这里计算的是,在初始状态下,究竟是健康更可能推出来正常,还是发烧更能推出来健康。从这个角度来思考问题,可以发现这样也可以决定这个人的第一天的健康状态究竟是什么。
    后面的问题也是采用相同的办法来处理,比如对于第二天来说,精神状态是冷,也就是状态1。这里我们可以计算概率为P(冷|健康)P(健康|上一天健康)P(上一天健康)
    相应的python代码如下:

    for i in range(1,3):
        temp = np.copy(dp)
        for j in range(2):
            dp[j] = max([a * b for a, b in zip(temp, tran[:,j])])*laun[j,look[i]]
        print('第{}次'.format(i+1) + kind[np.where(dp==max(dp))[0][0]])
    

    根据上述代码,我们就可以计算出每天最有可能的健康状态。

    总结

    维特比算法利用概率知识,通过已知的观察序列情况,通过推算在某种标注序列的情况下发生观察序列的概率,然后求出最有可能的标注序列情况,从而解决标注序列推测的问题。

  • 相关阅读:
    Lucene
    SQL优化以及索引
    Mysql优化
    RocketMQ
    RocketMQ
    Session共享
    Linux安装Nginx
    初识nginx
    跨域,防止表单重复提交
    HttpClient案例
  • 原文地址:https://www.cnblogs.com/zhenlingcn/p/8409576.html
Copyright © 2011-2022 走看看