某天,你的女神告诉你说,她放假三天,将要去上海游玩,准备去欢乐谷、迪士尼和外滩(不必定三个都会去)。
她呢,会选择在这三个地方中的某几个逗留并决定是否购物,并且天天只待在一个地方。根据你对她的了解,知道她去哪一个地方,仅取决于她去的上一个地方,且是否购物的几率仅取决于她去的地方。已知她去的三个地方的转移几率表以下:算法
欢乐谷 | 迪士尼 | 外滩 | |
---|---|---|---|
欢乐谷 | 0.8 | 0.05 | 0.15 |
迪士尼 | 0.2 | 0.6 | 0.3 |
外滩 | 0.2 | 0.3 | 0.5 |
稍微对这个表格作些说明,好比第一行,前一天去了欢乐谷后,次日还待在欢乐谷的几率为0.8,去迪士尼的几率为0.05,去外滩的几率为0.15。
她在每一个地方的购物几率为:app
地点 | 购物几率 |
---|---|
欢乐谷 | 0.1 |
迪士尼 | 0.8 |
外滩 | 0.3 |
在出发的时候,她跟你说去每一个地方的可能性相同。后来,放假回来后,你看了她的朋友圈,发现她的购物状况以下:第一天不购物,第二三天都购物了。因而,你很好奇,她这三天都去了哪些地方。
怎么样,聪明的你能求解出来吗?atom
接下来,咱们将会介绍隐马尔可夫模型(HMM)。
隐马尔可夫模型是关于时序的几率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程。隐藏的马尔可夫链随机生成的状态的序列,称为状态序列;每一个状态生成一个观测,而由此产生的观测的随机序列,称为观测序列。序列的每个位置又能够看做是一个时刻。
隐马尔可夫模型由初始几率分布、状态转移几率分布以及观测几率分布肯定。隐马尔可夫模型的形式定义以下:
设Q是全部可能的状态的集合,V是全部可能的观测的集合,也就是说,Q是不可见的,而V是可见的,是咱们观测到的可能结果。spa
其中,N是可能的状态数,M是可能的观测数。
在刚才的例子中,Q是不可见的状态集合,应为Q={欢乐谷,迪士尼,外滩},而V是能够观测的集合,应为V={购物,不购物}。
I是长度为T的状态序列,O是对应的观测序列。code
在刚才的例子中,I这个序列是咱们须要求解的,即女生去了哪些地方,而O是你知道的序列,O={不购物,购物,购物}。
A是状态转移几率矩阵:xml
N是在时刻t处于状态qi的条件下在时刻t+1转移到状态qj的几率。在刚才的例子中,转移几率矩阵为:blog
B是观测几率矩阵:递归
N是在时刻t处于状态qj的条件下生成观测vk的几率。在刚才的例子中:utf-8
综上,咱们已经讲完HMM中的基本概念。同时,咱们能够知道,隐马尔可夫模型由初始状态几率向量π,状态转移几率矩阵A和观测几率矩阵B决定。π和A决定状态序列,B决定观测序列。所以,隐马尔可夫模型λλ可用三元符号表示,即it
A,B,π称为HMM的三要素。
固然,隐马尔可夫模型之因此被称为马尔可夫模型,是由于它使用了两个基本的假设,其中之一为马尔可夫假设。它们分别是:
齐次马尔科夫假设,即假设隐藏的马尔可夫链在任意时刻t的状态只依赖于其前一时刻的状态,与其余时刻的状态及观测无关,也与时刻t无关。
观测独立性假设,即假设任意时刻的观测只依赖于该时刻的马尔可夫链的状态,与其余观测及状态无关。
在刚才的假设中,咱们对应的两个假设分别为:她去哪一个地方,仅取决于她去的上一个地方;是否购物的几率仅取决于她去的地方。前一个条件为齐次马尔科夫假设,后一个条件为观测独立性假设。
以上,咱们就介绍了HMM的基本概念及假设。而HMM的三个基本问题以下:
上面的例子即为HMM的第三个基本问题,也就是,给定观测序列{不购物,购物,购物},结果最有可能的状态序列,即游玩的地方。
求解HMM的第三个基本问题,会用到大名鼎鼎的维特比算法(Viterbi Algorithm)。
维特比算法是一个特殊但应用最广的动态规划(dynamic programming)算法,利用动态规划,能够解决任何一个图中的最短路径问题,同时,它也是求解HMM描述的第三个基本问题的算法。
下面,对于刚才给出的例子,咱们将使用Python,来写代码实现Viterbi算法,同时求解刚才的问题。
# -*- coding: utf-8 -*-
# HMM.py
# Using Vertibi algorithm
import numpy as np
def Viterbi(A, B, PI, V, Q, obs):
N = len(Q)
T = len(obs)
delta = np.array([[0] * N] * T, dtype=np.float64)
phi = np.array([[0] * N] * T, dtype=np.int64)
# 初始化
for i in range(N):
delta[0, i] = PI[i]*B[i][V.index(obs[0])]
phi[0, i] = 0
# 递归计算
for i in range(1, T):
for j in range(N):
tmp = [delta[i-1, k]*A[k][j] for k in range(N)]
delta[i,j] = max(tmp) * B[j][V.index(obs[i])]
phi[i,j] = tmp.index(max(tmp))
# 最终的几率及节点
P = max(delta[T-1, :])
I = int(np.argmax(delta[T-1, :]))
# 最优路径path
path = [I]
for i in reversed(range(1, T)):
end = path[-1]
path.append(phi[i, end])
hidden_states = [Q[i] for i in reversed(path)]
return P, hidden_states
def main():
# 状态集合
Q = ('欢乐谷', '迪士尼', '外滩')
# 观测集合
V = ['购物', '不购物']
# 转移几率: Q -> Q
A = [[0.8, 0.05, 0.15],
[0.2, 0.6, 0.2],
[0.2, 0.3, 0.5]
]
# 发射几率, Q -> V
B = [[0.1, 0.9],
[0.8, 0.2],
[0.3, 0.7]
]
# 初始几率
PI = [1/3, 1/3, 1/3]
# 观测序列
obs = ['不购物', '购物', '购物']
P, hidden_states = Viterbi(A,B,PI,V,Q,obs)
print('最大的几率为: %.5f.'%P)
print('隐藏序列为:%s.'%hidden_states)
main()
输出结果以下:
最大的几率为: 0.02688.
隐藏序列为:['外滩', '迪士尼', '迪士尼'].
如今,你有很大的把握能够肯定,你的女神去了外滩和迪士尼。