1、前向算法
前向算法是隐马尔可夫模型(HMM)中用于计算观测序列概率的一种算法。它是解决HMM的评估问题的有效方法,旨在确定给定模型参数时,某个特定观测序列出现的概率。前向算法通过动态规划逐步构建前向概率表,并最终得到整个观测序列的概率。
import numpy as np
def forward_algorithm(observations, state_transition_matrix, emission_matrix, initial_state_distribution):
num_observations = len(observations)
num_states = state_transition_matrix.shape[0]
# 初始化前向概率矩阵
alpha = np.zeros((num_observations, num_states))
# 初始化
alpha[0, :] = initial_state_distribution * emission_matrix[:, observations[0]]
# 递归
for t in range(1, num_observations):
for i in range(num_states):
alpha[t, i] = np.dot(alpha[t-1, :], state_transition_matrix[:, i]) * emission_matrix[i, observations[t]]
# 终止
prob = np.sum(alpha[num_observations-1, :])
return prob, alpha
# 示例使用
# 定义HMM模型参数
state_transition_matrix = np.array([[0.7, 0.3], [0.4, 0.6]])
emission_matrix = np.array([[0.2, 0.4, 0.4], [0.5, 0.4, 0.1]])
initial_state_distribution = np.array([0.6, 0.4])
observations = [0, 1, 2] # 观测序列,这里假设观测值已转换为索引
# 计算
prob, alpha = forward_algorithm(observations, state_transition_matrix, emission_matrix, initial_state_distribution)
print("Probability of the observed sequence:", prob)
2、后向算法
后向算法(Backward Algorithm)是一种用于隐马尔可夫模型(HMM)的算法,主要用于计算给定模型参数情况下,观测序列的概率。与前向算法相似,后向算法也是一种动态规划算法,用于高效计算观测序列的概率,但是它是从序列的末尾开始向前计算概率值。
import numpy as np
def backward_algorithm(A, B, initial_dist, observations):
num_states = A.shape[0]
T = len(observations)
# 初始化后向概率矩阵
beta = np.zeros((num_states, T))
beta[:, T-1] = 1 # 在最后一个观测,所有状态的后向概率都设置为1
# 递归计算后向概率
for t in reversed(range(T-1)):
for i in range(num_states):
beta[i, t] = sum(A[i, j] * B[j, observations[t+1]] * beta[j, t+1] for j in range(num_states))
# 计算整个观测序列的概率
total_prob = sum(initial_dist[i] * B[i, observations[0]] * beta[i, 0] for i in range(num_states))
return beta, total_prob
# 示例使用的HMM参数和观测序列
A = np.array([[0.7, 0.3], [0.4, 0.6]])
B = np.array([[0.2, 0.4, 0.4], [0.5, 0.4, 0.1]])
initial_dist = np.array([0.6, 0.4])
observations = [0, 1, 2] # 整数索引代表观测
beta, total_prob = backward_algorithm(A, B, initial_dist, observations)
print("后向概率矩阵:\n", beta)
print("观测序列的总概率:", total_prob)
3、应用
前向后向算法通常用于计算给定模型参数下,整个观察序列出现的概率。这通过将最终时间点的所有前向概率相加来完成。确定最可能的隐藏状态序列。虽然解码通常使用Viterbi算法,但前向后向算法提供了必要的概率框架来进行解码。调整模型参数以最大化给定观察序列的概率。通过Baum-Welch算法(也称为前向后向算法的一个特例)进行。
import numpy as np
# 定义模型参数
A = np.array([[0.7, 0.3], [0.4, 0.6]]) # 状态转移概率矩阵
B = np.array([[0.1, 0.9], [0.8, 0.2]]) # 观察概率矩阵
pi = np.array([0.5, 0.5]) # 初始状态概率分布
# 观察序列(用数字表示,0:携带伞, 1:不携带伞)
observations = [0, 1, 0]
# 前向算法
def forward(A, B, pi, observations):
N = A.shape[0] # 状态数量
T = len(observations) # 观察序列长度
fwd = np.zeros((N, T))
fwd[:, 0] = pi * B[:, observations[0]]
for t in range(1, T):
for n in range(N):
fwd[n, t] = np.sum(fwd[:, t-1] * A[:, n]) * B[n, observations[t]]
return fwd
# 后向算法
def backward(A, B, observations):
N = A.shape[0] # 状态数量
T = len(observations) # 观察序列长度
bwd = np.zeros((N, T))
bwd[:, -1] = 1
for t in range(T-2, -1, -1):
for n in range(N):
bwd[n, t] = np.sum(bwd[:, t+1] * A[n, :] * B[:, observations[t+1]])
return bwd
# 计算前向概率
fwd = forward(A, B, pi, observations)
prob_fwd = np.sum(fwd[:, -1])
# 计算后向概率
bwd = backward(A, B, observations)
prob_bwd = np.sum(pi * B[:, observations[0]] * bwd[:, 0])
print(fwd, prob_fwd, bwd, prob_bwd)