统计学习方法第十章:隐马尔科夫模型

为什么要学习隐马尔科夫

第一层:HMM 的“肉身”虽然老了,但“灵魂”活在 Transformer 里

现在纯 HMM 直接端上台面的场景少了。但 Transformer 之所以能成功,恰恰是因为它解决了一些 HMM 解决不了的问题。理解了 HMM,你才能真的听懂 Transformer 论文里的潜台词。

1. 从“有限记忆”到“无限记忆”
HMM 最被人诟病的就是“马尔可夫假设”:未来只取决于现在,和过去无关。它记性很差。
Transformer 里的 Self-Attention(自注意力机制),干的其实是同一件事,但做到了极致:它让每个词都和前面所有词直接产生联系。它的“记忆”是整个输入序列。
你只有先知道了“记性差”的 HMM 是怎么回事,才能体会到 Self-Attention 这个“记性好”的方案有多颠覆,它到底厉害在哪。

2. 从“隐式学习”到“显式关注”
学习问题(鲍姆-韦尔奇)它算出一个“谁转移到谁”的概率矩阵,但你不知道模型到底把什么当成了隐藏的“状态”。那些状态(比如分词里的 B/M/E/S)是人强行赋予的。
而 Transformer 学出来的 Attention 矩阵,是 “肉眼可见的”。你可以直接把它画成一张热力图,看到一个词在“关注”哪些其他词。这种可解释性,某种程度上超越了那个“隐藏”的 HMM。


第二层:HMM 在特定战场上依然是“最优轻骑兵”

Transformer 是航空母舰,威力巨大,但耗油(算力、数据)也惊人。在很多“小场面”,你开航母反而不如骑摩托车。

  • 场景:低功耗设备上的实时语音命令
    比如你对着智能手表说“下一首”。设备算力极其有限,电池要撑一天。这时,一个只有几百 KB 的 HMM 模型,做简单的关键词识别,反应极快、耗电极低。上 Transformer?硬件和功耗根本不允许。

  • 场景:金融时序异常检测
    在监管严格的金融领域(比如反洗钱),模型做出一个判断,必须能向人解释:“我为什么标记这笔交易是异常?” HMM 推断出的最优状态序列,可以清晰地告诉你:“这笔交易触发了从‘正常’状态到‘异常’状态的罕见转移。” 这在深度学习“黑盒”里是很难做到的。可解释性,是 HMM 在强监管行业的免死金牌。

  • 场景:小样本下的序列建模
    如果你只有几百条数据,训练一个深度学习模型是灾难。但 HMM 的参数很少,可以用很少的数据就学到一个相对靠谱的模型。


第三层:它在教科书里,是一把打开更多锁的钥匙

你为什么学它?你一开始就说了:“想拓宽学习地图与思路”。HMM 的价值,更多是在思想和概念地图里。

  • 它是“生成式模型”的鼻祖代表:你把它搞懂,就理解了“先有因,后有果”的生成观。再去学 VAE(变分自编码器)、扩散模型(比如生成图片的 Stable Diffusion),你会发现它们的思想内核都是“有隐藏变量在驱动”。你已经在 HMM 上练习过“猜隐藏变量”了。

  • 它是“动态规划”思想的最佳教学案例:维特比算法那个“每一步只留最优路径”的思想,是算法里的明珠。这种“最优子结构”的动态规划思想,在处理任意序列问题(如序列标注、路径规划)时,都是无价之宝。

第一课:一个“躲猫猫”的故事

我们一开始只讲一件事:隐马尔可夫模型到底是什么?

先忘记所有术语。我们来玩一个猜天气的游戏。

假设你有一个朋友住在另一个城市。他每天只告诉你一件事:他今天是去“游泳”了,还是去“跑步”了。他很规律,每天只做这两件事之一。

现在,你的任务是:根据他连续几天的活动记录(比如:跑步,跑步,游泳),来猜这几天他所在城市的天气是“晴天”还是“雨天”。

在这个故事里,就藏着隐马尔可夫模型的全部要素:

  1. 你真的想知道的东西:天气(晴天/雨天)
    这东西你看不见,是“隐藏”的。你的朋友不会直接告诉你“今天是晴天”。你只能猜。这就是 “隐” ,我们把它叫做 “状态” 。

  2. 你能直接看到的东西:他的活动(跑步/游泳)
    这是你每天都能得到的、确切的记录。这是 “观测值” 。你能看到的活动,是由你看不到的天气“决定”的(晴天可能更喜欢去游泳,雨天可能更喜欢跑步)。

  3. 天气之间会“传染”:
    今天如果是晴天,明天更大概率还是晴天;今天是雨天,明天也更可能继续下雨。天气不是每天随机乱来的,它有惯性。这种“今天决定明天”,明天不取决今天的任何天气的依赖关系,就是 “马尔可夫链”。天气这个隐藏状态,就是按照这条链在变化。

  4. 天气会“表现”成活动:
    晴天的时候,朋友有80%的概率去游泳,20%的概率去跑步(他可能也会想练练长跑)。雨天的时候,则正好相反。这就像天气这个“隐藏原因”,发射出了一个你能看见的“结果”。

到这里,我们先停一下。请你用这个“猜天气”的例子,试着回答我两个小问题,看看刚才的故事你理解了多少:

  1. 在这个故事里,什么是 “状态序列”?什么是 “观测序列”?(不用背定义,用这个故事的词语告诉我)

  2. 如果朋友连续三天活动是 【跑步,游泳,跑步】,你觉得最可能对应的三天天气是下面哪一个,为什么?

    • A. 晴天,雨天,晴天

    • B. 雨天,晴天,雨天

    • C. 雨天,雨天,雨天

第一题:

  • 状态序列:就是那几天真实但看不见的天气(比如:晴天,雨天,晴天)。

  • 观测序列:就是你朋友每天的动作(跑步,游泳,跑步)。

第二题:

晴天的时候,朋友大部分时候去游泳,但偶尔也会想跑步。雨天的时候,朋友大部分时候去跑步,但偶尔也会想游泳。这就意味着,看到“跑步”,我们不能100%确定就是雨天,只能说“雨天的可能性更大”。

而更关键的是,天气之间是会相互影响的。我们不仅要看他某一天干了什么,还要看天气本身的“惯性”。

如果第一天和第三天都是晴天,第二天是雨天,也就是说天气序列是【晴天,雨天,晴天】,这意味着天气要这样变化:晴 -> 雨 -> 晴。这种天气变化是可能发生的,比如突然下了场阵雨,然后很快放晴了。

但是,有没有另一种可能呢?比如【晴天,晴天,晴天】?如果朋友在连续三天晴天里,决定第一天去跑步(可能是想活动一下),第二天去游泳,第三天又去跑步。这种也是完全可能的。

所以,这道题的答案其实是不一定。我们需要综合考虑两方面:

  1. 天气变化的可能性有多大? 比如,连续晴天的概率比晴-雨-晴这种跳跃式变化的概率要大。

  2. 某种天气下,做某件事的可能性有多大? 比如,晴天时,去跑步的概率虽然小,但也存在。

你看,这就引出了HMM要解决的核心问题:如何根据一串观测序列,找出最有可能产生这串观测的隐藏状态序列。 你的选择,在“今天干什么就一定是这种天气”的假设下是对的。而HMM更聪明的地方在于,它会算一个总账,把天气变化的规律和天气导致行为的规律都考虑进去。

如果我们查一下这个城市的天气历史,发现:

  • 如果今天是雨天,明天还是雨天的概率高达70%。

  • 如果今天是晴天,明天还是晴天的概率也高达80%。

这就是状态序列自己的规律,和观测无关

现在,我们再来看“哪个更可能”这个问题,就不只要考虑“动作猜天气”,还要考虑“天气的惯性”了。

我们对比两个场景:

场景A:【晴天,雨天,晴天】
这个场景意味着:第一天晴,突然要变成第二天雨,又突然要变回第三天晴。天气在两天内剧烈变了两次。如果天气有很强的惯性,这件事发生的概率会非常低,因为变化太频繁了。

场景C:【雨天,雨天,雨天】
这个场景意味着:雨天下了一天,第二天因为惯性,大概率还是雨;第三天同理,大概率还是雨。这件事非常顺畅,符合“惯性”的逻辑。那么,全是雨天,能产生【跑步,游泳,跑步】这个动作序列吗?完全可能。因为雨天的时候,朋友虽然更可能跑步,但也有一定概率会去游泳。

所以,综合考虑“动作由天气决定”和“天气有惯性”这两股力量,场景C的可能性其实大于场景A

这正是HMM的核心思想:最佳的状态序列,是那个既能把观测值解释通,自身又最“平滑”、最符合惯性规律的序列。

小结:构成HMM的两块核心积木

到这里,故事里的HMM就拼出两块最重要的积木了:

  1. 转移概率:就是“惯性”。状态(天气)之间怎么变?由 状态A → 状态B 的概率。

  2. 观测概率:就是“表现”。一个状态(天气)会产生什么观测(动作)?由 状态 → 观测值 的概率。

一个HMM,就是由这两个概率表定义出来的一个“故事生成器”。

现在我们试着把这个故事变成一个你能操作的模型。请你凭感觉,为这个“猜天气”模型,编一组合理的概率。

请填空(填你觉得合理的数字,加起来到100%就行):

1. 天气的惯性(转移概率)

  • 今天晴天 → 明天晴天:___%

  • 今天晴天 → 明天雨天:___%

  • 今天雨天 → 明天雨天:___%

  • 今天雨天 → 明天晴天:___%

2. 天气的表现(观测概率)

  • 今天是晴天 → 朋友去游泳:___%

  • 今天是晴天 → 朋友去跑步:___%

  • 今天是雨天 → 朋友去游泳:___%

  • 今天是雨天 → 朋友去跑步:___%

你填完这八个数字,一个完整的、可以运行的HMM就在你脑子里建好了。

我给的假设是:

  • 惯性:晴转晴80%,雨转雨70%。。

  • 表现:晴天时,朋友80%跑步,20%游泳;雨天时,反而70%游泳,30%跑步

一个真实模型就是这么客观:它不在乎常理,它只忠实于你给它设定的概率。

现在,一个完整的HMM就在你手里诞生了。我们有了:

  • 两个隐藏状态:晴天、雨天

  • 两个观测值:跑步、游泳

  • 一组转移概率:描述了天气的惯性

  • 一组观测概率:描述了天气如何“表现”为动作

第二课:有了模型,能问它哪三个问题?

有了模型,就像有了一个训练有素的骰子,我们可以向它提出三类问题。这也是教材上重点讲的三个基本问题。别怕术语,我们用刚才的模型来翻译它们。

第一个问题:评估问题(算有多像)

  • 问法:你拿到一个动作序列,比如【跑步,跑步,游泳】。你问我:“我的这个模型,生成这个动作序列的概率有多大?”

  • 生活解释:这就像你手里有骰子,想知道投出“3,5,1”这个序列的可能有多大。如果概率大,就说明这个序列很“像”你的模型生成的;概率极小,就可能说明这个序列不正常,或者根本不是你这个模型能解释的。

  • 书上名字概率计算问题。用的方法是前向-后向算法

第二个问题:解码问题(猜最可能的真相)

  • 问法:你同样拿到这个动作序列【跑步,跑步,游泳】。你问我:“根据我的模型,最可能对应的是哪三天的天气?”

  • 生活解释:这就是我们刚才做的猜谜游戏。你只看到了行为,想反推背后最可能的真相。这正是HMM的核心应用,比如语音识别,就是从声音信号(观测)反推你说的词(状态)。

  • 书上名字预测问题。用的方法是维特比算法

第三个问题:学习问题(调模型参数)

  • 问法:你觉得朋友的行为很奇怪,于是你收集了他一年的动作日记,但你完全不知道真实的天气是怎样的。你问我:“怎么用这一年的动作数据,反推出我模型里那八个概率应该设成多少,让模型尽可能贴近现实?”

  • 生活解释:这就像你看到一个骰子被扔了很多次,你想通过结果来推断这个骰子是不是做了手脚,每面朝上的真实概率是多少。这是最难,但也最有魔法感的问题,能让模型从数据中自己“学”到规则。

  • 书上名字学习问题。用的方法是鲍姆-韦尔奇算法(也叫EM算法)。

怎么“算有多像”?(暴力拆解法)

我们还是用亲手建的模型,和编的动作序列 【跑步,跑步,游泳】

现在,我们要算这个动作序列的概率有多大。怎么算?一个最直观、最暴力的想法是:把所有可能的天气序列都列出来,算一算每种天气序列产生这串动作的概率,然后全加起来。

这三天的天气,一共有 2×2×2 = 8 种可能:

  1. 晴,晴,晴

  2. 晴,晴,雨

  3. 晴,雨,晴

  4. 晴,雨,雨

  5. 雨,晴,晴

  6. 雨,晴,雨

  7. 雨,雨,晴

  8. 雨,雨,雨

我们要做的,就是把每一种天气序列的“总概率”算出来,然后全部加在一起。

我们先拿第1种天气序列 【晴,晴,晴】 来试试手。

你要算的是:“第一天是晴天、且跑步” 并且 “第二天是晴天、且跑步” 并且 “第三天是晴天、且游泳” 这件事,同时发生的总概率。

请你拿出你之前填好的 “转移概率” 和 “观测概率” 表,我们一起填空。

你填的表格是这样的:

  • 晴天初始概率我们假设是1(就从晴天开始算)

  • 晴→晴:80%

  • 晴→雨:20%

  • 雨天观测:游泳70%,跑步30%

  • 晴天观测:游泳20%,跑步80%

现在请你算,第一天是晴天并且跑步的概率是多少?
第二天在第一天是晴天的条件下,还是晴天并且跑步的概率是多少?
第三天在第二天是晴天的条件下,还是晴天并且游泳的概率是多少?

最后,把这三个数乘起来,就是这个天气序列产生这个动作序列的总概率。

第一天:
我们要的是“第一天是晴天”并且“跑步”。

  • 第一天是晴天概率:1

  • 晴天时跑步概率:0.8

  • 第一天概率 = 1 × 0.8 = 0.8

  • 你这一步算得完全正确。

第二天:
我们要的是“在第一天是晴天的条件下,第二天还是晴天”并且“跑步”。

  • 晴转晴的概率:0.8

  • 晴天时跑步的概率:0.8

  • 第二天概率 = 0.8 × 0.8 = 0.64

  • 注意,这里是两个数相乘,不是三个。因为“第一天是晴天”这个条件我们已经用过了,现在算的只是“从第一天晴到第二天晴”这一步转移,再配上第二天的观测。

第三天:
我们要的是“在第二天是晴天的条件下,第三天还是晴天”并且“游泳”。

  • 晴转晴的概率:0.8

  • 晴天时游泳的概率:0.2

  • 第三天概率 = 0.8 × 0.2 = 0.16


关键一步:把它们串起来

整个序列发生的总概率,是把这三步的概率乘在一起:
总概率 = 第一天概率 × 第二天概率 × 第三天概率
= 0.8 × 0.64 × 0.16

我们算一下:
0.8 × 0.64 = 0.512
0.512 × 0.16 = 0.08192

所以,天气序列【晴,晴,晴】产生动作序列【跑步,跑步,游泳】的概率是 0.08192

同理我们再算8次,即可得出最佳概率。

这就是“暴力枚举法”。 它的好处是直接、好懂,缺点也很明显:如果序列有100天,路径总数就是2的100次方,宇宙毁灭了都算不完。

所以,我们需要一个更聪明的“算总概率”的方法。

我们先不急着看公式,先看一个生活中算账的例子。

场景: 你想统计全校学生这三天吃饭的总花费。

  • 暴力法: 把每个学生每天的花费明细都打印出来,最后一张一张加。累死人。

  • 聪明法: 第一天结束时,直接统计“第一天花了多少钱”;第二天,只看“第二天当天花了多少”,加上前一天的汇总,得到“前两天的总花费”;第三天同理。你只需要记一个“累计值”,就可以扔掉明细了。

前向算法用的就是这个聪明思路。它只关心:到第 t 天为止,观测序列的前 t 个都发生,且第 t 天的天气是某个状态,这个累计概率是多少。

我们还是算【跑步,跑步,游泳】这个序列。我们约定一个符号:
α(第几天, 那天的天气) = 到那天为止的累计概率

第1天:跑步
我们算两个累计值:

  • α(1, 晴) = 第1天是晴,且跑步的概率 = 1(初始为晴)× 0.8(晴天跑步)= 0.8

  • α(1, 雨) = 第1天是雨,且跑步的概率 = 1(初始为雨)× 0.3(雨天跑步)= 0.3

这一步很简单,和暴力法没有区别。

第2天:跑步
现在进入关键一步。我们要算第2天是晴(且观测到跑步)的累计概率 α(2, 晴)。
它可以由第1天的两种天气转移过来:

  1. 从第1天是晴转来:第1天是晴的概率 α(1,晴)=0.8,然后从晴转晴的概率是0.8,接着在晴天下跑步的概率是0.8。
    这条分支的贡献是:0.8 × 0.8 × 0.8 = 0.512

  2. 从第1天是雨转来:第1天是雨的概率 α(1,雨)=0.3,然后从雨转晴的概率是0.3(表里雨转晴是30%),接着在晴天下跑步的概率是0.8。
    这条分支的贡献是:0.3 × 0.3 × 0.8 = 0.072

然后,把这两条路汇合在一起,就是 α(2, 晴):
α(2, 晴) = 0.512 + 0.072 = 0.584

同理,我们算 α(2, 雨),它也可以由第1天的两种天气转来:

  1. 从第1天是晴转来:0.8 × 0.2(晴转雨)× 0.3(雨天跑步) = 0.048

  2. 从第1天是雨转来:0.3 × 0.7(雨转雨)× 0.3(雨天跑步) = 0.063
    α(2, 雨) = 0.048 + 0.063 = 0.111

你看,到了第2天结束时,我们手里还是只有两个数:0.584 和 0.111。不管序列多长,每次都只算并保存“两个累计值”。

现在请你用同样的思路,计算第3天(观测值是游泳)的两个累计值:

  • α(3, 晴):从第2天的晴和雨,转移到晴,且观测到游泳。

  • α(3, 雨):从第2天的晴和雨,转移到雨,且观测到游泳。

算完后,把 α(3, 晴) 和 α(3, 雨) 加起来,就是我们要的最终答案——观测序列【跑步,跑步,游泳】的总概率。

(提示:观测概率表里,晴天游泳是0.3,雨天游泳是0.7)

我们先想象一个画面:第三天早晨,你想知道今天天晴,并且正好去游泳的概率。

这个“第三天晴”可以由两辆车开过来:一辆从“第二天晴”出发,一辆从“第二天雨”出发。

第一辆车:从“第二天晴”开来的

我们要算:这辆车的“载货量”是多少?
公式是: (第二天晴的累计概率) × (从晴到晴的概率) × (在晴天下游泳的概率)

我们把数字从你的表格里拿出来,一个一个填进去:

  • 第二天晴的累计概率(我们上一步算好的):0.584

  • 从晴到晴的转移概率(你表格里晴→晴):0.8

  • 晴天下游泳的观测概率(你表格里晴天游泳):0.2

所以,第一辆车的载货量就是:
0.584 × 0.8 × 0.2 

第二辆车:从“第二天雨”开来的

公式是: (第二天雨的累计概率) × (从雨到晴的概率) × (在晴天下游泳的概率)

继续填数字:

  • 第二天雨的累计概率(上一步算好的):0.111

  • 从雨到晴的转移概率(你表格里雨→晴):0.3

  • 晴天下游泳的观测概率:0.2

所以,第二辆车的载货量是:
0.111 × 0.3 × 0.2 

最后,把这两辆车的“货”卸到同一个仓库里(加在一起),就是 α(3, 晴)。

怎么“猜真相”?(解码问题)

还是你手里的模型,还是这个动作序列 【跑步,跑步,游泳】。现在,我们要找出最可能产生这串动作的天气序列

和前向算法的关系:从“求和”变成“找最大值”

还记得前向算法吗?在算第二天是晴的累计概率时,我们把从“第一天晴”和“第一天雨”两条路来的概率加在了一起

现在,解码问题的思路是:我们不求和,我们只保留最有可能的那条路

为什么?因为我们要找的是单条最优路径,而不是所有路径的总和。哪条路概率最大,我们就选哪条。

这个算法有个专门的名字:维特比算法

我们用一个比喻。假设你是将军,有三天的行军路线要选。每天扎营的地方可以是“晴天高地”或“雨天山谷”。你不是要算所有路线总共要花多少粮草,而是要挑一条总代价最小的路。

维特比算法就是:每到一个新地点,只记住到达这个地点的所有路线中,目前最好(概率最大)的那条,把其他路线全部忘掉。

我们用同样的符号,但换个名字,叫 δ(第几天, 那天的天气) = 到那天为止的最大概率

第1天:跑步
和之前完全一样:

  • δ(1, 晴) = 1 × 0.8 = 0.8 (来自初始晴,跑步)

  • δ(1, 雨) = 1 × 0.3 = 0.3 (来自初始雨,跑步)

第2天:跑步
现在我们算到第2天是晴的最大概率 δ(2, 晴)。它可以从第1天晴或雨转来,但我们只选最大的那条路

  • 从第1天是晴转来:0.8 × 0.8 × 0.8 = 0.512

  • 从第1天是雨转来:0.3 × 0.3 × 0.8 = 0.072

比较一下,0.512 更大,所以我们选它,并且记住这条路的前一站是“晴”
δ(2, 晴) = 0.512,最佳前站:

同样的,算 δ(2, 雨):

  • 从第1天是晴转来:0.8 × 0.2 × 0.3 = 0.048

  • 从第1天是雨转来:0.3 × 0.7 × 0.3 = 0.063

0.063 更大,选它,并记住前站是“雨”。
δ(2, 雨) = 0.063,最佳前站:

现在请你用同样的思路,算第3天,观测值是“游泳”。

我们已经帮你算好了数值,你只负责比较和选择

到第3天是晴 δ(3, 晴) 的两条路:

  • 从第2天是晴转来:0.512 × 0.8 × 0.2 = 0.08192

  • 从第2天是雨转来:0.063 × 0.3 × 0.2 = 0.00378

(1)哪个更大?它对应的最佳前站是谁?

到第3天是雨 δ(3, 雨) 的两条路:

  • 从第2天是晴转来:0.512 × 0.2 × 0.7 = 0.07168

  • 从第2天是雨转来:0.063 × 0.7 × 0.7 = 0.03087

(2)哪个更大?它对应的最佳前站是谁?

现在到了第3天,我们有两个“终点”:

  • δ(3, 晴) = 0.08192,前站是

  • δ(3, 雨) = 0.07168,前站是

比较这两个终点的概率,0.08192 更大。所以最终终点是

现在我们从终点往回走:

  • 第3天是,它的最佳前站是 → 第2天是

  • 第2天是,它的最佳前站是 → 第1天是

所以,维特比算法给出的最优天气序列是:【晴,晴,晴】

到这里,我们把两个算法放在一起,帮你彻底分清:

前向算法维特比算法
解决什么问题评估问题(算有多像)解码问题(猜真相)
怎么合并路径求和(所有路都留着)取最大值(只留一条最优)
结果一个概率值(观测序列的总概率)一条最优状态序列
符号αδ

学习问题到底难在哪?

我们先重新站到那个场景里。

你朋友给你看了他一整年的活动日记(比如:【跑步, 游泳, 跑步, 跑步, 游泳...】),但他打死也不告诉你每天的真实天气

现在的局面是:

  • 你知道的:他每天是跑步还是游泳(观测序列)。

  • 你不知道的:每一天到底是晴天还是雨天(状态序列)。

  • 你想反推的:天气变化的规律(转移概率)和天气如何影响他的活动(观测概率)。

这件事的难度在于,它是一个“鸡生蛋,蛋生鸡”的死循环:

  • 想知道每天是什么天气(状态),你得先知道天气变化的规律和活动规律(参数)。

  • 想知道天气变化的规律和活动规律(参数),你得先知道每天是什么天气(状态)。

两边都不知道,这就是死局。怎么破?

死局的唯一解法,就是先随便打破一个缺口

既然状态和参数我们都不知道,那我们能不能先瞎蒙一组参数,用这组很可能是错的参数,去反推一个“如果这组参数是对的,那么每天最可能是什么天气”。

然后,根据这个“猜出来的天气”,我们再去修正参数,让参数更靠谱一点。再用新参数去重新猜天气,再修正参数…… 就这样一轮一轮地转下去,直到参数和猜的天气都不怎么变了,一个合理的模型就自己“长”出来了。

这就是鲍姆-韦尔奇算法(也叫EM算法)的全部智慧。它分两步,反复循环:

  1. E步(Expectation,求期望):基于当前参数,去猜状态

  2. M步(Maximization,最大化):基于猜出来的状态,去修正参数

光说概念还是容易空,我们拿你最熟悉的“猜天气”模型,做一个非常简单的数学游戏,让你亲手感受一下参数是怎么被修正的。

假设我们只有2天的数据,观测序列只有一句话: [ 跑步 , 游泳 ]

我们重复无数次这组2天的数据来学习。现在,我们正式开始瞎蒙和修正的循环。

第0轮:瞎猜一个初始模型

我们一开始什么都不懂,就随便设参数(假设初始概率各一半):

转移概率(今天→明天):

  • 晴→晴:0.5,晴→雨:0.5

  • 雨→雨:0.5,雨→晴:0.5
    (就是说,天气变化完全没规律,明天各一半概率)

观测概率(天气→动作):

  • 晴天→跑步:0.5,晴天→游泳:0.5

  • 雨天→跑步:0.5,雨天→游泳:0.5
    (就是说,天气对活动也没影响,干啥都各一半)

这个模型很“笨”,它认为一切都是随机的。


第1轮:E步(猜状态)

现在,我们用这个很笨的模型,来算一下,看到 [跑步, 游泳] 这个序列时,每一天的天气最可能是什么

第一天(观测到跑步):

  • P(第一天是晴) = 0.5,P(晴天时跑步) = 0.5 → P(晴且跑步) = 0.5 × 0.5 = 0.25

  • P(第一天是雨) = 0.5,P(雨天时跑步) = 0.5 → P(雨且跑步) = 0.5 × 0.5 = 0.25
    两者一样,所以我们暂时认为,第一天是晴和雨的概率各一半。

第二天(观测到游泳):
同理,第二天是晴和雨的概率也各一半。

这一轮E步,因为参数是“瞎”的,所以猜出来的结果也非常模糊,等于没猜出什么信息。

第1轮:M步(修正参数)

现在是最关键的一步。我们虽然没得到确定的答案,但我们可以用这些“概率”来重新计算参数

我们先算观测概率。问题:“晴天”这个状态下,朋友有多大可能去“跑步”?

根据我们上一轮E步模糊的猜测,我们算一个“期望次数”:

  • 第一天,是晴天的概率是 0.5,而这天观测到的是跑步。所以“晴天”和“跑步”的关联计数,我们计 0.5 分。

  • 第二天,是晴天的概率也是 0.5,但这天观测到的是游泳。所以“晴天”和“游泳”的关联计数,我们计 0.5 分。

那么,晴天的总出现次数是 0.5 + 0.5 = 1 次。
其中,发生跑步的次数是 0.5 次。

所以,新的晴天→跑步的概率 = 0.5 / 1 = 0.5

你发现了吗?因为第一步猜的结果是模糊的,所以修正后的参数还是 0.5,没变!

这很正常。如果观测序列更长,有几百个数据点,这些微小的差别就会累积,让参数一点点偏离 0.5,向着真实规律靠拢。

假设打破概率分布

  • 晴天→跑步:0.8

  • 雨天→游泳:0.7

如果我们用这个模型生成几千天的动作数据,再把这些数据喂给一个“0.5”的初始模型,让它用鲍姆-韦尔奇算法去学。它就会:

  1. 用“0.5”的参数去猜天气,发现在标注为“可能是晴天”的日子里,跑步多得离谱。

  2. 在M步修正时,它就会把晴天→跑步的概率从0.5调高,比如调到0.6。

  3. 下轮E步,新参数会让“晴天”的判定更准,从而发现更多跑步和晴天的关联。

  4. 再M步,继续调高,直到逼近你设定的0.8。

它就是这样,像一只蜗牛,一步一步从数据里把规律给“拱”出来的。

第三课:回归教材指南:从故事到符号

请你现在打开《统计学习方法》第十章。我们不需要从头到尾啃,只需要按一个逻辑顺序,把最重要的部分和你的直觉对接上。

第一步:先看目录和标题,建立“路标”

不要急着看公式。先快速扫一遍这一章有哪些小节。你会发现,它的结构就是我们学的“世界观 + 三个问题 + 应用”。你心里已经有这张地图了,现在只是去看看书上的“官方路标”叫什么。

第二步:认领“世界观”部分(10.1 节)

找到定义 10.1(隐马尔可夫模型)和那两个概率矩阵 A 和 B。

  • 转移概率矩阵 A:这就是你填的“天气惯性”表。书上用 a_{ij} 表示从状态 i 转到状态 j 的概率。你可以把它翻译成:a_{晴,雨} = 0.2。

  • 观测概率矩阵 B:这就是你填的“天气表现”表。书上用 b_j(k) 表示在状态 j 下,观测到 k 的概率。翻译过来就是:b_{晴}(跑步) = 0.8。

  • 初始状态概率向量 π:这就是第一天是晴或雨的概率。我们当时假设是 1,书里用 π_i 表示。

你的任务:把你亲手填的那8个概率值,在教材的矩阵 A 和 B 里“安家”,看着符号能念出数字。这一节就算过了。

第三步:认领“评估问题”和“前向算法”(10.2 节)

这是你之前花功夫最多的地方。找到书上的前向算法步骤(算法 10.2)。

  • 符号 α:书上叫“前向概率”,定义是 α_t(i) = P(o_1, o_2, ..., o_t, i_t = q_i | λ)。看着吓人,但翻译成故事就是:到第 t 天,观测序列是跑步游泳这些,且第 t 天天气是某个状态的概率。就是我们一起算的那个“累计概率”。

  • 关键递推公式:就是那个带  的公式。你会发现,它做的就是我们那两步:把上一轮两个 α 值,分别乘以转移概率 a_{ji},再乘以观测概率 b_i(o_{t+1}),最后求和

你的任务:对照我们算 α(2, 晴) 和 α(2, 雨) 的步骤,在公式里指认出哪部分是“转移”,哪部分是“观测”,哪部分是“求和”。看懂这一步,前向算法的公式关就算过了。

第四步:认领“解码问题”和“维特比算法”(10.3 节)

找到书上的维特比算法(算法 10.3)。

  • 符号 δ:书上叫“局部最优路径的概率”。它和前向算法的 α 长得像双胞胎,但计算规则完全不同。

  • 关键区别:在递推时,它用 max 替换了 。你看着公式,找到那个 max 符号。这就是我们之前从“求和”变成“只留赢家”的数学表达。

  • 回溯指针:书上用 Ψ_t(i) 来记录每一步的“最佳前站”。我们之前是口头上说“记下来”,这个符号就是用来做书面记录的。

你的任务:把我们走维特比算法时,为每一天的“晴”和“雨”选出的“最佳前站”,填入书里 Ψ 的表格中。这会让你彻底明白回溯是怎么形式化的。

第五步:眺望“学习问题”(10.4 节)

鲍姆-韦尔奇算法的公式是最复杂的,我们不求现在完全推导。你只需要找到这一节,看一眼那些公式,然后告诉自己:“哦,这就是那个E步猜,M步修正的数学写法。” 让你的直觉先占个座,以后需要时再来深挖。这一步不要求你现在看懂,认个门就行。


检查点

现在,请你合上书,用你自己的话,把下面这几个符号“翻译”成我们故事里的东西:

  1. A = [a_{ij}] 里的一个具体值 a_{晴,雨}

  2. α_t(i) 这个符号,它算的是个什么东西?

  3. 维特比算法里,那个 max 替换了前向算法里的什么?

应用一:中文分词 —— 怎么把一句话切开?

1. 背景与难点

中文不像英文,词和词之间没有空格。比如“去北京大学玩”这六个字,计算机看到的就是一串连续的“动作序列”。它不懂是人名“北京大学”,还是“北京”和“大学”两个词。切词是中文自然语言处理的第一步。

2. HMM建模:角色扮演游戏

我们可以把“分词”变成我们的“猜天气”游戏。

  • 隐藏状态(天气):我们不再猜“晴/雨”,而是猜每个字的词位。也就是这个字在一个词里扮演什么角色。最常用的是四个标签:

    • B(Begin):一个词的开始

    • M(Middle):一个词的中间

    • E(End):一个词的结尾

    • S(Single):单独成词
      (注:教材上可能用B、E、M、S这套标签,和你说明一下)

  • 观测值(动作):就是句子里的每一个具体的字,比如“去”、“北”、“京”、“大”、“学”、“玩”。

3. 模型参数的意思(不用记,感受一下)

一个训练好的分词HMM,它的概率表长这样:

  • 状态“惯性”(转移概率):描述了标签之间的连接规律。

    • B(词首)→ M(词中) 和 B(词首)→ E(词尾) 的概率很大。(因为一个词的开始后,肯定是这个词的中间或结尾)

    • E(词尾)→ B(词首) 或 E(词尾)→ S(单字词) 的概率很大。(因为一个词结束了,就该是新词的开始)

    • B(词首)→ B(词首) 的概率就是0。(一个词不能连续两个开头,这保证了我们的猜测符合词的构造逻辑)

  • 状态“表现”(观测概率):描述了某个标签,有多大概率“吐”出某个字。

    • “北”这个字,有很高的概率是从标签B(词首) 或 S(单字词) 里出来的。(因为它常做地名的开头或单用)

    • “的”这个虚词,有极高的概率是从标签S(单字词) 里出来的。

    • “京”这个字,有很高的概率是从标签M(词中) 或 E(词尾) 里出来的,紧跟“北”之后。

4. 用维特比算法“猜真相”

现在,拿到一个观测序列:“去北京大学玩”。
模型要做的就是:用维特比算法,找出一条最可能的标签序列(天气序列),来解释这串字。

可能的标签序列1:去/S 北/B 京/E 大/B 学/E 玩/S (分词结果:去 / 北京 / 大学 / 玩)
可能的标签序列2:去/S 北/B 京/M 大/M 学/E 玩/S (分词结果:去 / 北京大学 / 玩)

维特比算法会计算这两条路径的概率,路径2中“北京大学”作为一个整体(BMME)的概率,通常要远高于被切开的路径1。模型就这样“猜”出了最合理的分词方式。

应用二:词性标注 —— 判断每个词的词性

分词之后,我们就可以做词性标注了。这又是一个“猜天气”游戏。

  • 隐藏状态(天气):这次我们猜的是词性标签。比如 n.(名词)、v.(动词)、a.(形容词)、d.(副词)等等。

  • 观测值(动作):就是已经切好的一个个词,比如“我”、“喜欢”、“苹果”。

  • 状态“惯性”(转移概率):描述了词性之间的语法连接规律。

    • d.(副词)→ v.(动词) 的概率很大(如“非常/喜欢”)

    • v.(动词)→ n.(名词) 的概率很大(如“吃/苹果”)

    • n.(名词)→ v.(动词) 的概率就小一些

  • 状态“表现”(观测概率):描述了一个词性生成一个具体词的概率。

    • “苹果”,有很高的概率是从标签 n.(名词) 里出来的。

    • “喜欢”,有很高的概率是从标签 v.(动词) 里出来的。

拿到一个分词后的序列:“我/r 喜欢/v 吃/v 红/a 苹果/n”。对于“红”这个字,模型要判断它是动词(很少见)、形容词(很常见)还是名词(也可能)。维特比算法会综合考虑“红”本身常是什么词(观测概率),以及前后最可能搭配什么词性(转移概率),最终给出最优的词性序列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值