从经典模型走向端到端 · 课前实验 01

一句「开灯」,
如何变成文字?

先让 GMM 听懂一小帧,再让 HMM 把声音连成一条路。
放慢过程,亲手看见一次语音识别。

预设实验语音
词表:开灯 / 关灯 / 开门
仅使用预设语音,不采集麦克风或外部音频
01 / 声学前端

声音很长,模型一次只看一小帧。

25 ms 的窗口,每次向前移动 10 ms。
相邻帧重叠,保留发音变化。

你能听到的波形16 kHz · 单声道
橙色窗口 = 当前帧点击波形,或者拖动上方滑杆
预加重→分帧 + 加窗→FFT→24 个 Mel 滤波器→取对数 + DCT→12 维 MFCC
当前帧的 Mel 频带能量对数刻度

把密密麻麻的频谱,汇总成更接近听觉频带的能量。

模型实际看到的 12 个数标准化 MFCC · C₁—C₁₂

这 12 个数描述一帧的谱形状。它们既不是文字,也不是音素标签。

↳
为什么不能直接认一个字?

“灯”的发音持续许多帧。每帧只包含一点局部证据,要把证据沿时间连起来。

换个条件,再试一次

把“理解”变成一次小实验。

越大越倾向停留;期望时长 1 / (1 − p)
拖动参数,上面所有分数与路径会立即重新计算。
课堂里的三个问题

带着问题,进入端到端。

  1. GMM 的分量,是几个音素吗?

    不是。一个状态内有多个高斯分量;它们描述该状态的声学分布。

  2. 为什么“隐藏”?为什么要自循环?

    观测是声学特征,状态需要推断。自循环允许同一发音阶段占据不同数量的帧。

  3. Viterbi 和前向算法一样吗?

    Viterbi 取最佳路径;前向算法累加所有路径。本演示用最佳路径近似候选语音似然。

这份演示如何计算?模型简化与参考资料

本页从预设语音波形提取 MFCC,实际执行对角协方差 GMM 密度计算和对数域 Viterbi 解码。模型用 4 种系统普通话音色、3 种语速、3 个指令,共 36 条合成语音训练;内置演示语音使用另一个语速。只支持预设示例,没有录音或上传入口;不是通用语音识别器。

每个双字指令使用 6 个从左到右的声学状态,三个状态对应一个字的声学阶段,采用 Viterbi 分段对齐及状态内 GMM EM 估计参数。阶段边界由模型学习,并非人工音素边界;大型传统系统通常采用音素或上下文相关音素状态、更多特征与大量真实训练语音。

GMM 显示的是条件概率密度 p(x | s),不是 P(s | x),密度也不必小于 1。图中二维椭圆只是投影;打分使用 12 维 MFCC(C₁—C₁₂,不含 C₀),使用训练集全局均值与标准差归一化。噪声加入实际波形后重新提取特征,播放的是同一段加噪语音。打乱实验只改变特征顺序,波形与播放保持原顺序;所有推断在浏览器本地运行。

参考:Rabiner:HMM 与语音识别教程;CMU:从时间对齐到 HMM。