通过动态规划思想, 拆分子问题, 结合有向图的联合概率写法, 用到D-separation性质来 优化F/B形式,即状态转移矩阵和发射概率矩阵
回顾
上篇通过EM算法思想来求解 HMM 的参数 θ=(π,A,B) 即 初始状态概率(向量), 状态转移概率(矩阵), 发射概率矩阵. 在上帝视角, 即已知隐变量 Z , 则通过简单的词频统计, 再归一化 就求解参数了.
而问题在于我们不是上帝, 只能通过观测值 X , 通过 F/B 算法 来求解出 Z, 即:
p(zk|x)=p(zk,x)p(x) 这是求解目标
这里的 x 表示所有的 n 个样本嘛, 因此为了和 F, B 产生联系, 可以将 x 进行划分 (展开).
Forward: p(zk|x1...k)
Backward: p(xk1...n|zk)
p(zk,x)=p(zk,x1...k,xk+1...n)
=p(zk,x1...k) p(xk+1...n|zk,x1..k)
条件概率: P(a, b) = P(a)P(b|a) = P(b) P(a|b)
可以省略掉 x1...k 考虑条件独立的情况下, 其对条件概率是没有影响的, 参考: D-separation性质
=p(zk,x1...k) p(xk+1...n|zk) 最核心公式
框架搭建起来了, 然而如何去求解这个公式, 还没有搞好, 于是这篇就来整一波计算 F/B 的细节.
Forward 算法求解
X:x1,x2,x3,...xn 每个观测是一个向量哦
Z:z1,z2,...zk..zn 每个隐变量是一个值
Z→X 发射概率矩阵
Z→Z 转移概率矩阵
**需求: ** p(zk,x1...k) 这个 概率值 (注: zk 是个标量, x1..k 是个向量)
要求解这个问题, 还是要用 动态规划 , 即把大的问题, 不断拆解为更小的问题来求解, 最直观的拆解, 即:
p(zk,x1...k) 拆解为: p(zk−1,x1..k−1)
在动态规划的框架下呢,
相当于 p(zk,x1...k)=某式子∗p(zk−1,x1...k−1)
因为, 这是它的子问题. 怎么做呢, 嗯首先, 观察一波右边, 看哪些变量是没有出现在左边的, 比如 x1...k−1 其实是包含在左边式子中的, 而 zk−1 是没有出现在左边式子的.
即我们要想办法, 将左边的式子, 称为有包含右边的 zk−1 项的, 方式就是求和, 如果是连续型, 就进行积分 呀.
p(zk,x1...k)=∑zk−1p(zk−1,zk,x1...k)
注意 ∑ 的下标是 zk−1 跟前面对 X 进行分段是有类似的思想
然后, 后面的工作就是要将这个式子, 如何转换为 某式子∗p(zk−1,x1...k−1) 的形式. 同上一样, 对 X 进行拆分:
=∑zk−1p(zk−1,zk, x1...k−1, xk)
=∑zk−1p(zk−1,x1...k−1) p(zk|zk−1,x1...k−1) p(xk|zk,zk−1,x1...k−1)
就是利用联合概率公式 P(a, b, c) = P(a) P(b|a) P(c|a, b) 注意是有向的哈, 根据之前的有向图是一样的.
这里来仔细分析一波这个求和里面的 公式:
-
p(zk−1),x1...k−1) 是咱要的 子问题
-
p(zk|zk−1,x1...k−1) 如果不考虑 x1...k−1 则变为 p(zk|zk−1) 就是咱熟悉的 状态转移矩阵
-
p(xk|zk,zk−1,x1...k−1) 如果不考虑 zk,x1...k−1 则变为 p(xk|zk) 就是咱熟悉的 发射概率矩阵
从上篇已经知道了, 在模型已经的情况下, 是很容易计算 发射概率和状态转移的, 因此, 我们现在又要来考虑, 上面 如果不考虑的变量, 是否对咱的条件概率产生影响. 判断是方式依然是 D-separation 规则:
-
对于 p(zk|zk−1,x1...k−1) 涉及的元素, x1...k−1,zk−1,zk 恰好是满足" tail to tail " 因此 x1...k−1 不影响结果
-
对于 p(xk|zk,zk−1,x1...k−1) 涉及, x1...k−1,zk−1,zk,xk 这恰好是"tail to head"因此 x1...k−1,zk−1不影响结果
p(zk,x1...k)=∑zk−1p(zk−1,x1...k−1) p(zk|zk−1)p(xk|zk)
后两项是状态转移矩阵 和 发射概率矩阵, 知道模型参数下, 是非常容易计算的, 现就关注:
类似EM算法的 E 步, 计算的时候, 也可手工初始化一个值来进项不断迭代计算的
p(zk−1,x1...k−1) 这个就是典型的 动态规划 了.
如果把上边 p(zk,x1...k) 看为是 αk(zk) , 则 p(zk−1,x1...k−1) 就是 αk−1(zk−1) .... 这样的一个动态过程, 其复杂度是 O(n∗m2)
动态规划的思想是, 将大的问题拆解为子问题, 即把之前的计算的过程保存下来, 再反复使用哦.
Backward 算法求解
前边的 Froward 算法是用来计算 p(zk|x1...k) 的概率值.
此处 Backward 算法则是来计算 p(xk+1...n|zk) 的概率值.
求解思路也是一样的, 不过要注意这里是 backward 即是从后面往前, 进行子问题拆分, 即:
p(xk+1...n|zk)=某个项∗p(xk+1...|zk+1)
=∑zk+1p(xk+2...n,xk+1,zk+1|zk)
**同上一样的拆分方法 即 **P(a, b, c) = P(a) P(b|a) P(c|a, b)
=∑zk+1p(zk+1|zk) p(xk+1|zk+1,zk)p(xk+2...n|zk+1,zk,xk+1)
同样用 D-separation 的性质来进行 判断看是否能无关变量
=∑zk+1p(xk+2...n|zk+1) p(xk+1|zk+1) p(zk+1|zk)
得到跟之前一样的形式, 即这3项分别为: 子问题, 发射概率, 转移矩阵
然后同样对子问题: p(xk+2..n|zk+1) 进行动态规划求解.
至此, 我们已经能知道, 在已知 X 的前提下, 对任意状态 Z_k 是可以求解的, 即 p(zk|x) , Forward * Backward 核心思想还是 EM算法呀. 这样对于 HMM 算法的参数求解, 针对已知 X, Z 直接统计即可; 在知道 X, 不知 Z 的情况下, 通过 EM 算法求解即可, 核心技巧是 F/B 算法, 而本篇对 F/B 算法的细节也做了推导, 其核心还是 发射概率, 状态转移还有动态规划求解, 至此, HMM 算是稍微明白了许多.
耐心和恒心, 总会获得回报的.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通