隐马尔可夫模型详解

目录

  1. 引言
  2. 马尔可夫模型基础
    1. 马尔可夫性质
    2. 马尔可夫链的联合分布
  3. 隐马尔可夫模型(HMM)简介
    1. 模型参数的表示
    2. HMM的联合分布
  4. HMM的三大元素与基本公式
  5. HMM的三大基本问题
    1. 评估问题:前向-后向算法(Forward-Backward)
      1. 前向算法(Forward)
      2. 后向算法(Backward)
      3. 前向-后向的更多推导
    2. 解码问题:维特比算法(Viterbi)
    3. 学习问题:Baum-Welch算法(EM算法)
  6. 隐马尔可夫模型的具体种类
    1. 离散观测隐马尔可夫模型(Discrete HMM)
    2. 连续观测隐马尔可夫模型(Continuous HMM)
    3. 半隐马尔可夫模型(Semi-HMM)
    4. 其他扩展
  7. 代码示例
  8. 代码简要解读

引言

隐马尔可夫模型(Hidden Markov Model, HMM)是一种能够对隐藏状态序列观测序列进行联合建模的统计模型。它在语音识别、自然语言处理、生物信息(基因序列分析)及很多时序预测领域都有广泛的应用。本教程将以通俗易懂的方式详细介绍从马尔可夫链到隐马尔可夫模型,并给出核心算法和典型的数学公式推导,力求让读者更好地理解其原理。


马尔可夫模型基础

马尔可夫性质

一个随机过程 { X t } \{X_t\} {Xt}(这里 t t t 可以是离散时刻)满足马尔可夫性质,表示当前状态未来状态的影响只与当前状态本身有关,而与过去的历史状态无关。用数学语言描述:

P ( X t + 1 = x   ∣   X 1 = x 1 , X 2 = x 2 , … , X t = x t ) = P ( X t + 1 = x   ∣   X t = x t ) . P\bigl(X_{t+1} = x \,\big\vert\, X_1 = x_1, X_2 = x_2, \dots, X_t = x_t\bigr) = P\bigl(X_{t+1} = x \,\big\vert\, X_t = x_t\bigr). P(Xt+1=x X1=x1,X2=x2,,Xt=xt)=P(Xt+1=x Xt=xt).

对于“一阶马尔可夫链”,此性质足够描述。若需要考虑记忆性更长的过程,可扩展为高阶马尔可夫链。

马尔可夫链的联合分布

马尔可夫链状态空间设为 S = { s 1 , s 2 , … , s N } S = \{s_1, s_2, \dots, s_N\} S={s1,s2,,sN}。定义状态转移概率

a i j = P ( X t + 1 = s j ∣ X t = s i ) , ∑ j = 1 N a i j = 1. a_{ij} = P(X_{t+1} = s_j \mid X_t = s_i), \quad \sum_{j=1}^N a_{ij} = 1. aij=P(Xt+1=sjXt=si),j=1Naij=1.

如果我们有初始分布 π = ( π 1 , π 2 , … , π N ) \pi = (\pi_1, \pi_2, \dots, \pi_N) π=(π1,π2,,πN),其中

π i = P ( X 1 = s i ) , ∑ i = 1 N π i = 1 , \pi_i = P(X_1 = s_i), \quad \sum_{i=1}^N \pi_i = 1, πi=P(X1=si),i=1Nπi=1,

那么,对于时刻 1 1 1 T T T 的状态序列 ( X 1 , X 2 , … , X T ) (X_1, X_2, \dots, X_T) (X1,X2,,XT),它的联合概率可写为:

P ( X 1 = s i 1 , X 2 = s i 2 , … , X T = s i T ) = π i 1   a i 1 i 2   a i 2 i 3   ⋯   a i T − 1 i T . P(X_1 = s_{i_1}, X_2 = s_{i_2}, \dots, X_T = s_{i_T}) = \pi_{i_1}\,a_{i_1 i_2}\,a_{i_2 i_3}\,\cdots\,a_{i_{T-1} i_T}. P(X1=si1,X2=si2,,XT=siT)=πi1ai1i2ai2i3aiT1iT.


隐马尔可夫模型(HMM)简介

在普通马尔可夫链中,状态 X t X_t Xt 是可直接观察的。而隐马尔可夫模型提出:每个时刻 t t t 的状态 X t X_t Xt不可见(隐藏的),但我们可以观测到一个与之相关的随机变量(或向量) O t O_t Ot。因此,实际观测到的是序列 ( O 1 , O 2 , … , O T ) (O_1,O_2,\dots,O_T) (O1,O2,,OT),而状态序列 ( X 1 , X 2 , … , X T ) (X_1,X_2,\dots,X_T) (X1,X2,,XT) 就是 “隐”的马尔可夫链

模型参数的表示

一个HMM由如下参数刻画:

  1. 状态集合 S = { s 1 , s 2 , … , s N } S = \{s_1, s_2, \ldots, s_N\} S={s1,s2,,sN},隐藏状态数为 N N N
  2. 观测集合 V = { v 1 , v 2 , … , v M } V = \{v_1, v_2, \ldots, v_M\} V={v1,v2,,vM}(若为离散情况),或者是一个连续空间(若为连续情况)。
  3. 初始状态分布 π = ( π 1 , π 2 , … , π N ) \pi = (\pi_1, \pi_2, \dots, \pi_N) π=(π1,π2,,πN)
  4. 状态转移概率矩阵 A = [ a i j ] A = [a_{ij}] A=[aij],其中
    a i j = P ( X t + 1 = s j ∣ X t = s i ) , 1 ≤ i , j ≤ N . a_{ij} = P(X_{t+1} = s_j \mid X_t = s_i), \quad 1 \le i,j \le N. aij=P(Xt+1=sjXt=si),1i,jN.
  5. 观测概率分布 B B B
    • 若为离散情况: B = [ b j ( k ) ] B = [b_j(k)] B=[bj(k)],其中
      b j ( k ) = P ( O t = v k ∣ X t = s j ) . b_j(k) = P(O_t = v_k \mid X_t = s_j). bj(k)=P(Ot=vkXt=sj).
    • 若为连续情况:可以用高斯分布或其混合分布来表示
      b j ( o ) = p ( O t = o ∣ X t = s j ) . b_j(o) = p(O_t = o \mid X_t = s_j). bj(o)=p(Ot=oXt=sj).

常将这些参数记为 λ = ( A , B , π ) \lambda = (A, B, \pi) λ=(A,B,π)

HMM的联合分布

在HMM中,如果我们同时考虑状态序列 X X X 和观测序列 O O O,它们的联合概率可写为:

P ( X , O ∣ λ ) = P ( X 1 )   ∏ t = 2 T P ( X t ∣ X t − 1 )   ∏ t = 1 T P ( O t ∣ X t ) . P(X, O \mid \lambda) = P(X_1)\,\prod_{t=2}^T P(X_t \mid X_{t-1}) \,\prod_{t=1}^T P(O_t \mid X_t). P(X,Oλ)=P(X1)t=2TP(XtXt1)t=1TP(OtXt).

展开后,我们有:

P ( X , O ∣ λ ) = π x 1   ∏ t = 1 T − 1 a x t , x t + 1   ∏ t = 1 T b x t ( o t ) . P(X, O \mid \lambda) = \pi_{x_1}\,\prod_{t=1}^{T-1} a_{x_t, x_{t+1}} \,\prod_{t=1}^{T} b_{x_t}(o_t). P(X,Oλ)=πx1t=1T1axt,xt+1t=1Tbxt(ot).

这里 x t x_t xt 表示时刻 t t t 的隐藏状态在 { 1 , … , N } \{1,\dots,N\} {1,,N}中的具体取值; o t o_t ot 表示时刻 t t t 的观测值在观测集合中的索引(或具体向量)。


HMM的三大元素与基本公式

  1. 隐藏状态(state) X t ∈ { s 1 , … , s N } X_t\in \{s_1,\dots,s_N\} Xt{s1,,sN}
  2. 观测变量(observation) O t ∈ { v 1 , … , v M } O_t\in \{v_1,\dots,v_M\} Ot{v1,,vM} 或连续空间。
  3. 初始分布 π \pi π、转移概率 A A A、观测概率 B B B

在时刻 t t t,“真实”状态为 X t X_t Xt,但我们只能观测到 O t O_t Ot。贯穿整个序列有长度为 T T T { O 1 , O 2 , … , O T } \{O_1,O_2,\dots,O_T\} {O1,O2,,OT} { X 1 , X 2 , … , X T } \{X_1,X_2,\dots,X_T\} {X1,X2,,XT}


HMM的三大基本问题

在实际应用中,我们常常会遇到以下三个核心问题:

  1. 评估(Evaluation):给定 λ \lambda λ 和观测序列 O O O,计算 P ( O ∣ λ ) P(O \mid \lambda) P(Oλ)
  2. 解码(Decoding):给定 λ \lambda λ 和观测序列 O O O,找到最优的隐藏状态序列 X ^ \hat{X} X^
  3. 学习(Learning):给定观测序列 O O O,估计最佳的 λ \lambda λ(或使 P ( O ∣ λ ) P(O \mid \lambda) P(Oλ) 最大)。

评估问题:前向-后向算法(Forward-Backward)

我们先考察:如何快速计算给定HMM( λ \lambda λ)生成观测序列 O O O 的概率 P ( O ∣ λ ) P(O \mid \lambda) P(Oλ)?这就是评估问题,可用前向-后向算法在多项式时间内完成。

前向算法(Forward)

定义“前向变量” α t ( i ) \alpha_t(i) αt(i)
α t ( i ) = P ( o 1 , o 2 , … , o t , X t = s i ∣ λ ) . \alpha_t(i) = P(o_1, o_2, \dots, o_t, X_t = s_i \mid \lambda). αt(i)=P(o1,o2,,ot,Xt=siλ).
即“从时刻1到时刻 t t t的所有观测值为 o 1 , … , o t o_1,\dots,o_t o1,,ot,并且时刻 t t t的隐藏状态为 s i s_i si”的联合概率。

  • 初始化
    α 1 ( i ) = π i   b i ( o 1 ) , 1 ≤ i ≤ N . \alpha_1(i) = \pi_i \, b_i(o_1), \quad 1 \le i \le N. α1(i)=πibi(o1),1iN.
    因为在时刻1,我们处于状态 s i s_i si的概率是 π i \pi_i πi,同时观测到 o 1 o_1 o1的概率是 b i ( o 1 ) b_i(o_1) bi(o1)

  • 递推
    α t + 1 ( j ) = [ ∑ i = 1 N α t ( i )   a i j ]   b j ( o t + 1 ) , 1 ≤ j ≤ N ,   1 ≤ t ≤ T − 1. \alpha_{t+1}(j) = \Bigl[\sum_{i=1}^N \alpha_t(i)\, a_{ij}\Bigr] \, b_j(o_{t+1}), \quad 1 \le j \le N,\ 1\le t \le T-1. αt+1(j)=[i=1Nαt(i)aij]bj(ot+1),1jN, 1tT1.
    这里 ∑ i = 1 N α t ( i )   a i j \sum_{i=1}^N \alpha_t(i)\, a_{ij} i=1Nαt(i)aij 表示从时刻 t t t的所有可能状态转移到时刻 t + 1 t+1 t+1状态 s j s_j sj的联合概率之和,然后再乘以在状态 s j s_j sj下产生观测 o t + 1 o_{t+1} ot+1的概率。

  • 终止
    P ( O ∣ λ ) = ∑ i = 1 N α T ( i ) . P(O \mid \lambda) = \sum_{i=1}^N \alpha_T(i). P(Oλ)=i=1NαT(i).
    即时刻 T T T可能处于任何状态下的联合概率之和。

从而可得观测序列的概率。该算法时间复杂度为 O ( N 2 T ) O(N^2 T) O(N2T)

后向算法(Backward)

“后向算法”同样能得到 P ( O ∣ λ ) P(O \mid \lambda) P(Oλ),定义“后向变量” β t ( i ) \beta_t(i) βt(i)
β t ( i ) = P ( o t + 1 , o t + 2 , … , o T ∣ X t = s i , λ ) . \beta_t(i) = P(o_{t+1}, o_{t+2}, \dots, o_T \mid X_t = s_i, \lambda). βt(i)=P(ot+1,ot+2,,oTXt=si,λ).
即“在时刻 t t t处于状态 s i s_i si时,后面时刻 t + 1 t+1 t+1 T T T的观测序列为 o t + 1 , … , o T o_{t+1},\dots,o_T ot+1,,oT的概率”。

  • 初始化
    β T ( i ) = 1 , 1 ≤ i ≤ N . \beta_T(i) = 1, \quad 1 \le i \le N. βT(i)=1,1iN.

  • 递推
    β t ( i ) = ∑ j = 1 N a i j   b j ( o t + 1 )   β t + 1 ( j ) , 1 ≤ i ≤ N ,   t = T − 1 , … , 1. \beta_t(i) = \sum_{j=1}^N a_{ij} \, b_j(o_{t+1}) \, \beta_{t+1}(j), \quad 1 \le i \le N, \ t = T-1,\dots,1. βt(i)=j=1Naijbj(ot+1)βt+1(j),1iN, t=T1,,1.

  • 终止
    P ( O ∣ λ ) = ∑ i = 1 N π i   b i ( o 1 )   β 1 ( i ) . P(O \mid \lambda) = \sum_{i=1}^N \pi_i \, b_i(o_1) \, \beta_1(i). P(Oλ)=i=1Nπibi(o1)β1(i).

和前向算法一样,后向算法也只需要 O ( N 2 T ) O(N^2 T) O(N2T) 的时间。

前向-后向的更多推导

在后面谈学习问题时,我们还会用到前向-后向算法来求各时刻处于某状态的后验概率等量。常见定义有:

  • γ t ( i ) \gamma_t(i) γt(i):时刻 t t t处于状态 s i s_i si的概率;
  • ξ t ( i , j ) \xi_t(i,j) ξt(i,j):时刻 t t t处于状态 s i s_i si且时刻 t + 1 t+1 t+1处于状态 s j s_j sj的概率。

这两个量可用 α t ( i ) \alpha_t(i) αt(i) β t ( i ) \beta_t(i) βt(i) 以及观测概率进行计算。例如,

γ t ( i ) = P ( X t = s i ∣ O , λ ) = α t ( i )   β t ( i ) P ( O ∣ λ ) . \gamma_t(i) = P(X_t = s_i \mid O, \lambda) = \frac{\alpha_t(i)\,\beta_t(i)}{P(O \mid \lambda)}. γt(i)=P(Xt=siO,λ)=P(Oλ)αt(i)βt(i).

ξ t ( i , j ) = P ( X t = s i , X t + 1 = s j ∣ O , λ ) = α t ( i )   a i j   b j ( o t + 1 )   β t + 1 ( j ) P ( O ∣ λ ) . \xi_t(i,j) = P(X_t = s_i, X_{t+1} = s_j \mid O, \lambda) = \frac{\alpha_t(i)\, a_{ij}\, b_j(o_{t+1})\, \beta_{t+1}(j)}{P(O \mid \lambda)}. ξt(i,j)=P(Xt=si,Xt+1=sjO,λ)=P(Oλ)αt(i)aijbj(ot+1)βt+1(j).

解码问题:维特比算法(Viterbi)

解码问题想要得到的是:给定观测序列 O O O 和模型 λ \lambda λ,哪一条隐藏状态序列 X = ( X 1 , … , X T ) X=(X_1,\dots,X_T) X=(X1,,XT) 最有可能出现?即

X ^ = arg ⁡ max ⁡ X P ( X ∣ O , λ ) . \hat{X} = \arg\max_X P(X \mid O,\lambda). X^=argXmaxP(XO,λ).

因为在HMM下等价于最大化 P ( X , O ∣ λ ) P(X, O \mid \lambda) P(X,Oλ),所以可用维特比算法进行动态规划求解。

定义“维特比变量” δ t ( i ) \delta_t(i) δt(i)

δ t ( i ) = max ⁡ X 1 , … , X t − 1 P ( X 1 , … , X t − 1 , X t = s i ,    o 1 , … , o t ∣ λ ) . \delta_t(i) = \max_{X_1,\dots,X_{t-1}} P(X_1,\dots,X_{t-1}, X_t=s_i,\; o_1,\dots,o_t \mid \lambda). δt(i)=X1,,Xt1maxP(X1,,Xt1,Xt=si,o1,,otλ).

  • 初始化
    δ 1 ( i ) = π i   b i ( o 1 ) . \delta_1(i) = \pi_i \, b_i(o_1). δ1(i)=πibi(o1).

  • 递推
    δ t + 1 ( j ) = [ max ⁡ 1 ≤ i ≤ N δ t ( i )   a i j ]   b j ( o t + 1 ) . \delta_{t+1}(j) = \Bigl[\max_{1\le i \le N} \delta_t(i)\,a_{ij}\Bigr] \, b_j(o_{t+1}). δt+1(j)=[1iNmaxδt(i)aij]bj(ot+1).
    并令
    ψ t + 1 ( j ) = arg ⁡ max ⁡ 1 ≤ i ≤ N δ t ( i )   a i j . \psi_{t+1}(j) = \arg\max_{1 \le i \le N} \delta_t(i)\,a_{ij}. ψt+1(j)=arg1iNmaxδt(i)aij.
    这里 ψ t + 1 ( j ) \psi_{t+1}(j) ψt+1(j) 是记录“最优路径”从上一时刻哪个状态转移而来。

  • 终止
    P ∗ = max ⁡ 1 ≤ i ≤ N δ T ( i ) , X T ∗ = arg ⁡ max ⁡ 1 ≤ i ≤ N δ T ( i ) . P^* = \max_{1\le i \le N} \delta_T(i), \quad X_T^* = \arg\max_{1 \le i \le N} \delta_T(i). P=1iNmaxδT(i),XT=arg1iNmaxδT(i).

  • 回溯:根据 ψ t ( ⋅ ) \psi_t(\cdot) ψt() 从后向前逐步找出最优状态序列。

学习问题:Baum-Welch算法(EM算法)

当HMM的参数 λ \lambda λ(即 A , B , π A, B, \pi A,B,π)未知时,我们可以通过观测序列 O O O 来“训练”或“学习”这些参数,使得该模型在一定意义下“最好地”解释观测数据。最常用的方法是Baum-Welch算法,可视为对HMM应用EM思想。

λ ( m ) \lambda^{(m)} λ(m) 表示第 m m m次迭代得到的模型参数。
在一次迭代中,“E步”计算基于 λ ( m ) \lambda^{(m)} λ(m) 时的后验概率 γ t ( i ) \gamma_t(i) γt(i) ξ t ( i , j ) \xi_t(i,j) ξt(i,j);“M步”则更新下式:

  1. 初始状态分布
    π i ( m + 1 ) = γ 1 ( i ) . \pi_i^{(m+1)} = \gamma_1(i). πi(m+1)=γ1(i).

  2. 状态转移概率
    a i j ( m + 1 ) = ∑ t = 1 T − 1 ξ t ( i , j ) ∑ t = 1 T − 1 γ t ( i ) . a_{ij}^{(m+1)} = \frac{\sum_{t=1}^{T-1} \xi_t(i,j)}{\sum_{t=1}^{T-1} \gamma_t(i)}. aij(m+1)=t=1T1γt(i)t=1T1ξt(i,j).

  3. 观测概率(离散情况)
    b j ( m + 1 ) ( k ) = ∑ t = 1 T 1 ( o t = v k )   γ t ( j ) ∑ t = 1 T γ t ( j ) , b_j^{(m+1)}(k) = \frac{\sum_{t=1}^T \mathbf{1}(o_t = v_k)\,\gamma_t(j)}{\sum_{t=1}^T \gamma_t(j)}, bj(m+1)(k)=t=1Tγt(j)t=1T1(ot=vk)γt(j),
    其中 1 ( ⋅ ) \mathbf{1}(\cdot) 1() 为指示函数,若 o t = v k o_t = v_k ot=vk 则为1,否则为0。
    对于连续情况,会对 γ t ( j ) \gamma_t(j) γt(j) 做加权似然估计,具体地估计高斯均值、方差等混合参数。

通过多次迭代(E步 + M步),参数会收敛到某个局部极值,从而得到可以解释训练序列的HMM参数。


隐马尔可夫模型的具体种类

离散观测隐马尔可夫模型(Discrete HMM)

  • 观测值:离散有限集合 { v 1 , … , v M } \{v_1,\dots,v_M\} {v1,,vM}
  • 观测概率 b j ( k ) = P ( O t = v k ∣ X t = s j ) b_j(k) = P(O_t = v_k \mid X_t=s_j) bj(k)=P(Ot=vkXt=sj)
  • 应用:词性标注、离散符号序列分析等。

连续观测隐马尔可夫模型(Continuous HMM)

  • 观测值:连续向量(如语音的声学特征)。
  • 常用建模:用混合高斯分布(GMM)刻画状态的观测概率:
    b j ( o ) = ∑ m = 1 M j c j m   N ( o ;   μ j m ,   Σ j m ) , b_j(o) = \sum_{m=1}^{M_j} c_{jm}\,\mathcal{N}(o;\,\mu_{jm},\,\Sigma_{jm}), bj(o)=m=1MjcjmN(o;μjm,Σjm),
    其中 c j m c_{jm} cjm 是混合系数, μ j m \mu_{jm} μjm Σ j m \Sigma_{jm} Σjm 分别为均值向量和协方差矩阵。

半隐马尔可夫模型(Semi-HMM)

  • 区别:在普通HMM中,状态持续时间服从几何分布;而实际中有时需更灵活的时长分布。
  • 特性:Semi-HMM可显式建模状态持续时间,从而更准确描述某些过程(如语音识别中的音素持续)。

其他扩展

  • 层级HMM(Hierarchical HMM)
  • 耦合HMM(Coupled HMM)
  • 部分可观测马尔可夫决策过程(POMDP)
  • 结合深度学习的HMM变体

代码示例

以下为一个简化的离散观测HMM示例(Python),演示核心:前向、后向和维特比算法。实际应用中通常还需数值稳定处理(例如取对数规避下溢),以及Baum-Welch学习等部分。

import numpy as np

class DiscreteHMM:
    def __init__(self, A, B, pi):
        """
        A: 状态转移矩阵 (N x N)
        B: 观测概率矩阵 (N x M),B[j,k] 表示在状态 j 时观测到 k 的概率
        pi: 初始状态概率向量 (N,)
        """
        self.A = np.array(A)  # (N, N)
        self.B = np.array(B)  # (N, M)
        self.pi = np.array(pi)  # (N,)
        self.N = self.A.shape[0]  # 状态数 N
        self.M = self.B.shape[1]  # 观测种类数 M
    
    def forward(self, O):
        """
        前向算法计算 P(O | 模型)
        O: 观测序列 (长度 T 的离散索引列表),如 [0, 2, 1, ...]
        返回: P(O | 模型)
        """
        T = len(O)
        alpha = np.zeros((T, self.N))
        
        # 初始化
        alpha[0, :] = self.pi * self.B[:, O[0]]
        
        # 递推
        for t in range(1, T):
            for j in range(self.N):
                # alpha[t, j] = sum_{i=1 to N}(alpha[t-1,i] * A[i,j]) * B[j,O[t]]
                alpha[t, j] = np.dot(alpha[t-1, :], self.A[:, j]) * self.B[j, O[t]]
        
        # 终止:把时刻 T 所有状态下的概率加总
        return np.sum(alpha[T-1, :])
    
    def backward(self, O):
        """
        后向算法计算 P(O | 模型)
        O: 观测序列
        返回: P(O | 模型)
        """
        T = len(O)
        beta = np.zeros((T, self.N))
        
        # 初始化
        beta[T-1, :] = 1.0
        
        # 递推
        for t in range(T-2, -1, -1):
            for i in range(self.N):
                # beta[t,i] = sum_{j=1 to N}(A[i,j] * B[j,O[t+1]] * beta[t+1,j])
                beta[t, i] = np.sum(self.A[i, :] * self.B[:, O[t+1]] * beta[t+1, :])
        
        # 终止:使用初始状态概率 pi 和 B[:,O[0]] 以及 beta[0,:]
        return np.sum(self.pi * self.B[:, O[0]] * beta[0, :])
    
    def viterbi(self, O):
        """
        维特比算法求最优状态序列
        O: 观测序列
        返回: (最佳路径概率, 最优状态序列)
        """
        T = len(O)
        delta = np.zeros((T, self.N))
        psi = np.zeros((T, self.N), dtype=int)
        
        # 初始化
        delta[0, :] = self.pi * self.B[:, O[0]]
        
        # 递推
        for t in range(1, T):
            for j in range(self.N):
                # 对各 i, 取 argmax (delta[t-1,i] * A[i,j])
                temp_vals = delta[t-1, :] * self.A[:, j]
                psi[t, j] = np.argmax(temp_vals)
                delta[t, j] = np.max(temp_vals) * self.B[j, O[t]]
        
        # 终止:找到时刻 T 最可能的最后状态
        p_star = np.max(delta[T-1, :])
        best_last_state = np.argmax(delta[T-1, :])
        
        # 回溯:依靠 psi[] 把最优路径检索出来
        best_path = [best_last_state]
        for t in range(T-1, 0, -1):
            best_path.insert(0, psi[t, best_last_state])
            best_last_state = psi[t, best_last_state]
        
        return p_star, best_path

if __name__ == "__main__":
    # 示例模型参数
    A = [
        [0.7, 0.3],
        [0.4, 0.6]
    ]
    B = [
        [0.5, 0.5],  # 状态0时,观测0和1的概率
        [0.1, 0.9]   # 状态1时,观测0和1的概率
    ]
    pi = [0.6, 0.4]
    
    hmm = DiscreteHMM(A, B, pi)
    
    # 示例观测序列 O (长度 T=4),假设观测字典是 {0,1}
    O = [0, 1, 1, 0]
    
    # 1) 前向算法
    prob_forward = hmm.forward(O)
    print(f"Forward算法计算得到的序列概率: {prob_forward}")
    
    # 2) 后向算法
    prob_backward = hmm.backward(O)
    print(f"Backward算法计算得到的序列概率: {prob_backward}")
    
    # 3) 维特比算法
    p_star, best_path = hmm.viterbi(O)
    print(f"Viterbi算法的最优路径概率: {p_star}")
    print(f"Viterbi算法的最优状态序列: {best_path}")

你可能感兴趣的:(算法,人工智能,机器学习,信号处理,信息与通信,概率论)