隐马尔科夫模型(Hidden Markov Model,以下简称HMM)是比较经典的机器学习模型了,它在语言识别,自然语言处理,模式识别等领域得到广泛的应用。
当然,随着目前深度学习的崛起,尤其是RNN,LSTM等神经网络序列模型的火热,HMM的地位有所下降。
使用HMM模型时我们的问题一般有这两个特征:
1)我们的问题是基于序列的,比如时间序列,或者状态序列。
2)我们的问题中有两类数据,一类序列数据是可以观测到的,即观测序列;而另一类数据是不能观察到的,即隐藏状态序列,简称状态序列。
states = ('Healthy', 'Fever')
observations = ('normal', 'cold', 'dizzy')
start_probability = {'Healthy': 0.6, 'Fever': 0.4}
transition_probability = {
'Healthy': {'Healthy': 0.7, 'Fever': 0.3},
'Fever': {'Healthy': 0.4, 'Fever': 0.6},
}
emission_probability = {
'Healthy': {'normal': 0.5, 'cold': 0.4, 'dizzy': 0.1},
'Fever': {'normal': 0.1, 'cold': 0.3, 'dizzy': 0.6},
}
class HMM:
def __init__(self, A, B, pi):
self.A = A
self.B = B
self.pi = pi
def generate_index_map(lables):
index_label = {}
label_index = {}
i = 0
for l in lables:
index_label[i] = l
label_index[l] = i
i += 1
return label_index, index_label
states_label_index, states_index_label = generate_index_map(states)
observations_label_index, observations_index_label = generate_index_map(observations)
def convert_observations_to_index(observations, label_index):
list = []
for o in observations:
list.append(label_index[o])
return list
def convert_map_to_vector(map, label_index):
v = np.empty(len(map), dtype=float)
for e in map:
v[label_index[e]] = map[e]
return v
def convert_map_to_matrix(map, label_index1, label_index2):
m = np.empty((len(label_index1), len(label_index2)), dtype=float)
for line in map:
for col in map[line]:
m[label_index1[line]][label_index2[col]] = map[line][col]
return m
A = convert_map_to_matrix(transition_probability, states_label_index, states_label_index)
B = convert_map_to_matrix(emission_probability, states_label_index, observations_label_index)
observations_index = convert_observations_to_index(observations, observations_label_index)
pi = convert_map_to_vector(start_probability, states_label_index)
HMM的三个问题
现在有几个问题:
1,知道HMM的参数 λ = (A, B, π) 和观测序列O = {o1,o2, ..., oT} ,如何计算模型 λ 下观测序列O出现的概率P(O | λ)。
2,HMM的参数如何确定?
比如:对于刚才的中文分词的小例子。
初始概率分布π好确定:是不是终结词的概率各是0.5。
观测矩阵B也好确定:1/65535嘛
但状态转移矩阵怎么确定?我怎么知道下个词是终结词的概率是多少?
3,知道HMM的参数 λ = (A, B, π) 和观测序列O = {o1,o2, ..., oT},如何计算给定观测序列条件概率P(I|O, λ )最大的状态序列I,即:
对于中文分词,我想到底如何分的词。
上面三个问题:
第一个问题被称为:概率计算问题。
解决办法:前向-后向算法(一种动态规划算法)。
第二个问题被称为:学习问题。
解决办法:如果状态序列已知,那用最大似然估计就好了,但HMM的状态序列未知,即含有隐变量,所以要使用Baum-welch算法(其实其本质就是EM算法)。
第三个问题被称为:预测问题/解码问题。
解决办法:Viterbi算法(一种动态规划算法)。
概率计算问题
该问题有两种解决办法:
1,直接/暴力算法。2,前向算法/后向算法。
前向算法:
def _forward(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
F = np.zeros((N,T))
F[:,0] = self.pi * self.B[:, obs_seq[0]]
for t in range(1, T):
for n in range(N):
F[n,t] = np.dot(F[:,t-1], (self.A[:,n])) * self.B[n, obs_seq[t]]
return F
参考博客:https://blog.csdn.net/xueyingxue001/article/details/52396494?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.pc_relevant_is_cache&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.pc_relevant_is_cache
http://www.hankcs.com/ml/hidden-markov-model.html