目录
- 第一部分:语音信号基础
- 第一章:绪论------语音识别的理论框架
- 第二章:语音信号的产生与感知
- 第三章:语音特征提取------从波形到特征向量
- 第二部分:声学建模
- 第四章:隐马尔可夫模型(HMM)理论
- 第五章:高斯混合模型与 HMM 训练
- 第六章:深度神经网络声学模型
- 第三部分:序列建模与解码
- 第七章:语言模型
- 第八章:解码与搜索
- 第九章:序列判别训练
- 第四部分:端到端模型
- 第十章:CTC(连接时序分类)
- 第十一章:注意力机制与编码器-解码器
- 第十二章:RNN-T(循环神经网络变换器)
- 第五部分:理论分析与前沿
- 第十三章:语音识别的信息论视角
- 第十四章:SSM 与语音识别
- 第十五章:多任务学习与自监督
- 第十六章:完整可运行代码实现
- 附录
第一部分:语音信号基础
第一章:绪论------语音识别的理论框架
1.1 语音识别问题的数学形式化
语音识别的核心问题是:
给定声学观测序列 O=(o1,o2,...,oT)O = (o_1, o_2, \dots, o_T)O=(o1,o2,...,oT),找到最可能的词序列 W∗=(w1,w2,...,wM)W^* = (w_1, w_2, \dots, w_M)W∗=(w1,w2,...,wM)。
用贝叶斯公式表示:
W∗=argmaxWP(W∣O)=argmaxWP(O∣W)P(W)P(O)W^* = \arg\max_W P(W|O) = \arg\max_W \frac{P(O|W) P(W)}{P(O)}W∗=argWmaxP(W∣O)=argWmaxP(O)P(O∣W)P(W)
由于 P(O)P(O)P(O) 与 WWW 无关,可以简化为:
W∗=argmaxWP(O∣W)⋅P(W)W^* = \arg\max_W P(O|W) \cdot P(W)W∗=argWmaxP(O∣W)⋅P(W)
这个公式将语音识别分解为三个独立的模块:
| 模块 | 数学表示 | 作用 |
|---|---|---|
| 声学模型 | $P(O | W)$ |
| 语言模型 | P(W)P(W)P(W) | 词序列的先验概率 |
| 解码器 | argmaxW\arg\max_WargmaxW | 搜索最可能的词序列 |
1.2 语音识别的层次结构
语音识别涉及多个层次的映射:
声波 → 帧特征 → 音素 → 子词 → 词 → 句子
(波形) (MFCC) (HMM) (BPE) (词典) (语言模型)
每个层次对应不同的理论工具:
| 层次 | 输入 | 输出 | 理论工具 |
|---|---|---|---|
| 信号处理 | 波形 | 特征向量 | 傅里叶变换、滤波器组 |
| 声学建模 | 特征序列 | 音素/子词 | HMM、DNN |
| 语言建模 | 历史词 | 下一个词 | N-gram、Transformer |
| 解码 | 所有信息 | 词序列 | 动态规划、束搜索 |
1.3 语音识别的历史脉络
| 年份 | 里程碑 | 贡献者 | 贡献 |
|---|---|---|---|
| 1952 | Audrey | Bell Labs | 第一个数字语音识别系统 |
| 1960s | 动态时间规整 | Vintsyuk | DTW 算法 |
| 1970s | 隐马尔可夫模型 | Baker, Jelinek | HMM 用于语音 |
| 1980s | 统计方法 | IBM, CMU | 大词汇量连续语音识别 |
| 1990s | 最大熵模型 | 多位学者 | 判别训练 |
| 2000s | 深度学习 | Hinton et al. | DNN-HMM 混合系统 |
| 2012 | 端到端 CTC | Graves et al. | CTC 损失函数 |
| 2015 | 注意力机制 | Chan et al. | Listen, Attend and Spell |
| 2018 | 自监督预训练 | Schneider et al. | Wav2Vec |
| 2020+ | 大规模预训练 | OpenAI, Meta | Whisper, Wav2Vec 2.0 |
1.4 本文的组织
本文从语音信号的物理特性出发,逐步构建出现代语音识别的完整理论体系。我们特别关注:
- HMM 的数学理论:为什么 HMM 适合语音识别?
- CTC 的理论基础:如何解决输入输出不对齐问题?
- 注意力机制:如何学习输入输出之间的对齐?
- SSM 与语音:状态空间模型如何用于语音?
第二章:语音信号的产生与感知
2.1 语音的产生机制
2.1.1 语音产生模型
人类语音的产生可以建模为源-滤波器模型:
s(t)=e(t)∗h(t)s(t) = e(t) * h(t)s(t)=e(t)∗h(t)
其中:
- s(t)s(t)s(t):语音信号
- e(t)e(t)e(t):激励源(声门脉冲或噪声)
- h(t)h(t)h(t):声道滤波器(传递函数)
- ∗*∗:卷积
浊音 (voiced):声带振动产生准周期脉冲,如 /a/, /i/, /u/
清音(unvoiced):气流通过狭窄通道产生噪声,如 /s/, /f/, /sh/
2.1.2 声道的共振特性
声道(咽腔、口腔、鼻腔)是一个非均匀的声学管道,具有多个共振峰(formants)。
共振峰频率 F1,F2,F3,...F_1, F_2, F_3, \dotsF1,F2,F3,... 决定了不同的元音:
| 元音 | F1F_1F1 (Hz) | F2F_2F2 (Hz) | 位置 |
|---|---|---|---|
| /i/ | 270 | 2290 | 前高 |
| /e/ | 530 | 1840 | 前中 |
| /a/ | 730 | 1090 | 中低 |
| /o/ | 570 | 840 | 后中 |
| /u/ | 300 | 870 | 后高 |
2.1.3 语音的时变特性
语音信号是非平稳的------声道形状随时间变化,导致频谱特性变化。
但在短时间内(10-30 ms),语音可以近似为平稳的------这是短时分析的基础。
2.2 语音的感知特性
2.2.1 人耳的频率感知
人耳对频率的感知是对数 的,而非线性的。这导致了梅尔尺度(Mel scale)的引入:
mel(f)=2595⋅log10(1+f700)\text{mel}(f) = 2595 \cdot \log_{10}\left(1 + \frac{f}{700}\right)mel(f)=2595⋅log10(1+700f)
在梅尔尺度上,等距的频率间隔在感知上是等距的。
2.2.2 掩蔽效应
同时掩蔽:一个强信号会掩蔽同一时间的弱信号(频率接近时更明显)。
时序掩蔽:一个强信号会掩蔽其前后的弱信号。
2.2.3 响度感知
响度与强度的关系近似为对数关系------这是分贝(dB)标度的基础:
L=10log10II0L = 10 \log_{10} \frac{I}{I_0}L=10log10I0I
2.3 语音的统计特性
2.3.1 短时平稳性
语音信号在短时间内(10-30 ms)可以近似为平稳随机过程。
2.3.2 非高斯性
语音信号的幅度分布通常是非高斯的------存在尖峰和重尾。
2.3.3 长时依赖
语音存在长时依赖------音素、音节、词之间有复杂的时序关系。这正是 SSM 和 Transformer 的优势所在。
第三章:语音特征提取------从波形到特征向量
3.1 预处理
3.1.1 预加重
高频部分通常能量较低,预加重滤波器提升高频:
yn=xn−αxn−1,α≈0.97yn = xn - \alpha xn-1, \quad \alpha \approx 0.97yn=xn−αxn−1,α≈0.97
这使得频谱更平坦,有利于后续分析。
3.1.2 分帧加窗
将连续信号分成短帧(通常 20-30 ms),每帧乘以窗函数:
xmn=xn+mH⋅wn,n=0,1,...,N−1x_mn = xn + mH \cdot wn, \quad n = 0, 1, \dots, N-1xmn=xn+mH⋅wn,n=0,1,...,N−1
其中 HHH 是帧移(hop size),wnwnwn 是窗函数(通常为 Hamming 窗)。
3.1.3 端点检测
检测语音的起始和结束点,去除静音段。
3.2 短时傅里叶变换(STFT)
3.2.1 定义
Xmk=∑n=0N−1xmne−j2πkn/NX_mk = \sum_{n=0}^{N-1} x_mn e^{-j2\pi kn/N}Xmk=n=0∑N−1xmne−j2πkn/N
STFT 给出了信号在时间和频率上的二维表示------语谱图(spectrogram)。
3.2.2 语谱图
语谱图是 ∣Xmk∣2|X_mk|^2∣Xmk∣2 的时频表示:
- 横轴:时间
- 纵轴:频率
- 亮度:能量
语谱图是语音识别中最重要的可视化工具。
3.3 梅尔频率倒谱系数(MFCC)
3.3.1 计算流程
MFCC 的计算流程:
波形 → 预加重 → 分帧加窗 → FFT → 梅尔滤波器组 → 对数 → DCT → MFCC
3.3.2 梅尔滤波器组
梅尔滤波器组是一组三角形带通滤波器,在梅尔尺度上均匀分布:
Hmk={0k<fm−1k−fm−1fm−fm−1fm−1≤k≤fmfm+1−kfm+1−fmfm≤k≤fm+10k>fm+1H_mk = \begin{cases} 0 & k < fm-1 \\ \frac{k - fm-1}{fm - fm-1} & fm-1 \leq k \leq fm \\ \frac{fm+1 - k}{fm+1 - fm} & fm \leq k \leq fm+1 \\ 0 & k > fm+1 \end{cases}Hmk=⎩ ⎨ ⎧0fm−fm−1k−fm−1fm+1−fmfm+1−k0k<fm−1fm−1≤k≤fmfm≤k≤fm+1k>fm+1
3.3.3 对数能量
对每个滤波器的输出取对数:
Sm=log(∑k∣Xk∣2Hmk)Sm = \log\left(\sum_k |Xk|^2 H_mk\right)Sm=log(k∑∣Xk∣2Hmk)
取对数的原因:
- 人耳对响度的感知是对数的
- 使特征分布更接近高斯
- 便于后续的倒谱分析
3.3.4 离散余弦变换(DCT)
对对数能量进行 DCT:
cn=∑m=0M−1Smcos(πn(m+0.5)M)cn = \sum_{m=0}^{M-1} Sm \cos\left(\frac{\pi n (m + 0.5)}{M}\right)cn=m=0∑M−1Smcos(Mπn(m+0.5))
DCT 的作用:
- 去相关:将相关的滤波器输出转换为近似独立的系数
- 压缩:大部分信息集中在前几个系数
- 降维:通常只保留前 13 个系数
3.3.5 MFCC 的物理意义
- c0c_0c0:对数能量(语音/非语音检测)
- KaTeX parse error: Expected '}', got 'EOF' at end of input: c_1 - c_{12:频谱包络的低频变化(共振峰信息)
- 高阶系数:频谱细节(通常被丢弃)
3.4 动态特征
3.4.1 一阶差分(Delta)
Δcn=∑k=1Kk(cn+k−cn−k)2∑k=1Kk2\Delta cn = \frac{\sum_{k=1}^{K} k(cn+k - cn-k)}{2\sum_{k=1}^{K} k^2}Δcn=2∑k=1Kk2∑k=1Kk(cn+k−cn−k)
一阶差分捕捉特征的变化率------近似于速度信息。
3.4.2 二阶差分(Delta-Delta)
ΔΔcn=∑k=1Kk(Δcn+k−Δcn−k)2∑k=1Kk2\Delta\Delta cn = \frac{\sum_{k=1}^{K} k(\Delta cn+k - \Delta cn-k)}{2\sum_{k=1}^{K} k^2}ΔΔcn=2∑k=1Kk2∑k=1Kk(Δcn+k−Δcn−k)
二阶差分捕捉特征的加速度信息。
3.4.3 完整特征向量
标准 MFCC 特征向量通常包含:
ot=c0,c1,...,c12,Δc0,...,Δc12,ΔΔc0,...,ΔΔc12T\mathbf{o}_t = c_0, c_1, \\dots, c_{12}, \\Delta c_0, \\dots, \\Delta c_{12}, \\Delta\\Delta c_0, \\dots, \\Delta\\Delta c_{12}^Tot=c0,c1,...,c12,Δc0,...,Δc12,ΔΔc0,...,ΔΔc12T
维度:39(13 静态 + 13 一阶差分 + 13 二阶差分)
3.5 滤波器组特征(Fbank)
3.5.1 与 MFCC 的区别
Fbank 特征跳过 DCT 步骤,直接使用对数梅尔滤波器组能量:
ot=S1,S2,...,SMT\mathbf{o}_t = S_1, S_2, \\dots, S_M^Tot=S1,S2,...,SMT
3.5.2 为什么深度学习偏爱 Fbank
- DCT 是线性变换,深度网络可以自己学习
- Fbank 保留了更多信息
- DCT 假设特征独立,但深度网络可以处理相关特征
3.6 特征归一化
3.6.1 倒谱均值减(CMS)
c^n=cn−1T∑t=1Tctn\hat{c}n = cn - \frac{1}{T}\sum_{t=1}^{T} c_tnc^n=cn−T1t=1∑Tctn
去除录音环境的影响(假设环境影响是加性的)。
3.6.2 方差归一化
c^n=cn−μnσn\hat{c}n = \frac{cn - \mu_n}{\sigma_n}c^n=σncn−μn
使不同维度的特征具有相同的尺度。
3.6.3 CMVN(倒谱均值方差归一化)
结合均值减和方差归一化,是最常用的特征归一化方法。
第二部分:声学建模
第四章:隐马尔可夫模型(HMM)理论
4.1 HMM 的定义
4.1.1 模型结构
隐马尔可夫模型(Hidden Markov Model, HMM) 由以下参数定义:
λ=(π,A,B)\lambda = (\pi, A, B)λ=(π,A,B)
其中:
- π={πi}\pi = \{\pi_i\}π={πi}:初始状态概率,πi=P(q1=si)\pi_i = P(q_1 = s_i)πi=P(q1=si)
- A={aij}A = \{a_{ij}\}A={aij}:状态转移概率,aij=P(qt+1=sj∣qt=si)a_{ij} = P(q_{t+1} = s_j | q_t = s_i)aij=P(qt+1=sj∣qt=si)
- B={bj(o)}B = \{b_j(o)\}B={bj(o)}:观测概率,bj(o)=P(ot∣qt=sj)b_j(o) = P(o_t | q_t = s_j)bj(o)=P(ot∣qt=sj)
4.1.2 两个基本假设
马尔可夫假设:当前状态只依赖于前一个状态:
P(qt∣qt−1,qt−2,...,q1)=P(qt∣qt−1)P(q_t | q_{t-1}, q_{t-2}, \dots, q_1) = P(q_t | q_{t-1})P(qt∣qt−1,qt−2,...,q1)=P(qt∣qt−1)
输出独立假设:当前观测只依赖于当前状态:
P(ot∣qt,qt−1,...,ot−1,... )=P(ot∣qt)P(o_t | q_t, q_{t-1}, \dots, o_{t-1}, \dots) = P(o_t | q_t)P(ot∣qt,qt−1,...,ot−1,...)=P(ot∣qt)
4.1.3 HMM 的三个基本问题
| 问题 | 数学描述 | 算法 |
|---|---|---|
| 评估 | $P(O | \lambda)$ |
| 解码 | $\arg\max_Q P(Q | O, \lambda)$ |
| 学习 | $\arg\max_\lambda P(O | \lambda)$ |
4.2 前向算法
4.2.1 前向变量定义
αt(i)=P(o1,o2,...,ot,qt=si∣λ)\alpha_t(i) = P(o_1, o_2, \dots, o_t, q_t = s_i | \lambda)αt(i)=P(o1,o2,...,ot,qt=si∣λ)
4.2.2 递推公式
初始化 :
α1(i)=πibi(o1)\alpha_1(i) = \pi_i b_i(o_1)α1(i)=πibi(o1)
递推 :
αt+1(j)=∑i=1Nαt(i)aijbj(ot+1)\alpha_{t+1}(j) = \left\\sum_{i=1}\^{N} \\alpha_t(i) a_{ij}\\right b_j(o_{t+1})αt+1(j)=i=1∑Nαt(i)aijbj(ot+1)
终止 :
P(O∣λ)=∑i=1NαT(i)P(O|\lambda) = \sum_{i=1}^{N} \alpha_T(i)P(O∣λ)=i=1∑NαT(i)
4.2.3 计算复杂度
前向算法的复杂度为 O(N2T)O(N^2 T)O(N2T),其中 NNN 是状态数,TTT 是序列长度。
直接计算 P(O∣λ)P(O|\lambda)P(O∣λ) 需要 O(NT)O(N^T)O(NT)------前向算法将指数复杂度降为多项式!
4.3 后向算法
4.3.1 后向变量定义
βt(i)=P(ot+1,ot+2,...,oT∣qt=si,λ)\beta_t(i) = P(o_{t+1}, o_{t+2}, \dots, o_T | q_t = s_i, \lambda)βt(i)=P(ot+1,ot+2,...,oT∣qt=si,λ)
4.3.2 递推公式
初始化 :
βT(i)=1\beta_T(i) = 1βT(i)=1
递推 :
βt(i)=∑j=1Naijbj(ot+1)βt+1(j)\beta_t(i) = \sum_{j=1}^{N} a_{ij} b_j(o_{t+1}) \beta_{t+1}(j)βt(i)=j=1∑Naijbj(ot+1)βt+1(j)
4.3.3 前向-后向关系
P(O∣λ)=∑i=1Nαt(i)βt(i),∀tP(O|\lambda) = \sum_{i=1}^{N} \alpha_t(i) \beta_t(i), \quad \forall tP(O∣λ)=i=1∑Nαt(i)βt(i),∀t
4.4 Viterbi 算法
4.4.1 问题定义
找到最可能的状态序列:
Q∗=argmaxQP(Q∣O,λ)Q^* = \arg\max_Q P(Q|O, \lambda)Q∗=argQmaxP(Q∣O,λ)
4.4.2 Viterbi 变量
δt(i)=maxq1,...,qt−1P(q1,...,qt−1,qt=si,o1,...,ot∣λ)\delta_t(i) = \max_{q_1, \dots, q_{t-1}} P(q_1, \dots, q_{t-1}, q_t = s_i, o_1, \dots, o_t | \lambda)δt(i)=q1,...,qt−1maxP(q1,...,qt−1,qt=si,o1,...,ot∣λ)
4.4.3 递推公式
初始化 :
δ1(i)=πibi(o1)\delta_1(i) = \pi_i b_i(o_1)δ1(i)=πibi(o1)
递推 :
δt+1(j)=maxiδt(i)⋅aij⋅bj(ot+1)\delta_{t+1}(j) = \max_i \\delta_t(i) \\cdot a_{ij} \cdot b_j(o_{t+1})δt+1(j)=imaxδt(i)⋅aij⋅bj(ot+1)
回溯 :
qt∗=ψt+1(qt+1∗)q_t^* = \psi_{t+1}(q_{t+1}^*)qt∗=ψt+1(qt+1∗)
其中 ψt(j)=argmaxiδt−1(i)⋅aij\psi_t(j) = \arg\max_i \\delta_{t-1}(i) \\cdot a_{ij}ψt(j)=argmaxiδt−1(i)⋅aij。
4.4.4 Viterbi 与前向的关系
Viterbi 算法将前向算法中的求和替换为取最大值------这是动态规划的经典应用。
4.5 Baum-Welch 算法
4.5.1 期望最大化(EM)框架
Baum-Welch 算法是 EM 算法在 HMM 上的特例。
E 步:计算期望的统计量
γt(i)=P(qt=si∣O,λ)=αt(i)βt(i)∑jαt(j)βt(j)\gamma_t(i) = P(q_t = s_i | O, \lambda) = \frac{\alpha_t(i) \beta_t(i)}{\sum_j \alpha_t(j) \beta_t(j)}γt(i)=P(qt=si∣O,λ)=∑jαt(j)βt(j)αt(i)βt(i)
ξt(i,j)=P(qt=si,qt+1=sj∣O,λ)=αt(i)aijbj(ot+1)βt+1(j)∑i,jαt(i)aijbj(ot+1)βt+1(j)\xi_t(i,j) = P(q_t = s_i, q_{t+1} = s_j | O, \lambda) = \frac{\alpha_t(i) a_{ij} b_j(o_{t+1}) \beta_{t+1}(j)}{\sum_{i,j} \alpha_t(i) a_{ij} b_j(o_{t+1}) \beta_{t+1}(j)}ξt(i,j)=P(qt=si,qt+1=sj∣O,λ)=∑i,jαt(i)aijbj(ot+1)βt+1(j)αt(i)aijbj(ot+1)βt+1(j)
M 步:更新参数
π^i=γ1(i)\hat{\pi}_i = \gamma_1(i)π^i=γ1(i)
a^ij=∑t=1T−1ξt(i,j)∑t=1T−1γt(i)\hat{a}{ij} = \frac{\sum{t=1}^{T-1} \xi_t(i,j)}{\sum_{t=1}^{T-1} \gamma_t(i)}a^ij=∑t=1T−1γt(i)∑t=1T−1ξt(i,j)
b^j(o)=∑t:ot=oγt(j)∑t=1Tγt(j)\hat{b}j(o) = \frac{\sum{t: o_t = o} \gamma_t(j)}{\sum_{t=1}^{T} \gamma_t(j)}b^j(o)=∑t=1Tγt(j)∑t:ot=oγt(j)
4.5.2 收敛性
定理 4.1:Baum-Welch 算法保证对数似然单调递增:
logP(O∣λk+1)≥logP(O∣λk)\log P(O|\lambda_{k+1}) \geq \log P(O|\lambda_k)logP(O∣λk+1)≥logP(O∣λk)
但只能保证收敛到局部最优。
第五章:高斯混合模型与 HMM 训练
5.1 高斯混合模型(GMM)
5.1.1 定义
高斯混合模型是多个高斯分布的加权和:
bj(o)=∑k=1KwjkN(o;μjk,Σjk)b_j(o) = \sum_{k=1}^{K} w_{jk} \mathcal{N}(o; \mu_{jk}, \Sigma_{jk})bj(o)=k=1∑KwjkN(o;μjk,Σjk)
其中:
- wjkw_{jk}wjk:第 kkk 个分量的权重
- μjk\mu_{jk}μjk:均值向量
- Σjk\Sigma_{jk}Σjk:协方差矩阵
- N(o;μ,Σ)\mathcal{N}(o; \mu, \Sigma)N(o;μ,Σ):多元高斯分布
5.1.2 GMM 的表达能力
定理 5.1(通用逼近):足够多分量的 GMM 可以以任意精度逼近任何连续概率密度函数。
这使得 GMM 成为 HMM 观测概率的强大参数化工具。
5.2 GMM-HMM 系统
5.2.1 模型结构
在 GMM-HMM 系统中:
- 每个 HMM 状态对应一个 GMM
- GMM 建模该状态的观测分布
bj(o)=∑k=1KjwjkN(o;μjk,Σjk)b_j(o) = \sum_{k=1}^{K_j} w_{jk} \mathcal{N}(o; \mu_{jk}, \Sigma_{jk})bj(o)=k=1∑KjwjkN(o;μjk,Σjk)
5.2.2 三音素建模
上下文相关的三音素(triphone)建模:
bl−c+r(o)=GMM for center phone c in context l-c-rb_{l-c+r}(o) = \text{GMM for center phone } c \text{ in context } l \text{-}c\text{-}rbl−c+r(o)=GMM for center phone c in context l-c-r
三音素的数量远大于单音素,需要状态绑定(tying)来减少参数。
5.2.3 决策树绑定
使用决策树对相似的三音素状态进行绑定:
根节点
/ \
元音? 辅音?
/ \ / \
F1>500? ... VOT>30? ...
5.3 GMM 参数估计
5.3.1 EM 算法
GMM 参数通过 EM 算法估计:
E 步:计算后验概率
γjk(t)=wjkN(ot;μjk,Σjk)∑lwjlN(ot;μjl,Σjl)\gamma_{jk}(t) = \frac{w_{jk} \mathcal{N}(o_t; \mu_{jk}, \Sigma_{jk})}{\sum_{l} w_{jl} \mathcal{N}(o_t; \mu_{jl}, \Sigma_{jl})}γjk(t)=∑lwjlN(ot;μjl,Σjl)wjkN(ot;μjk,Σjk)
M 步:更新参数
w^jk=∑tγjk(t)∑t∑lγjl(t)\hat{w}{jk} = \frac{\sum_t \gamma{jk}(t)}{\sum_t \sum_l \gamma_{jl}(t)}w^jk=∑t∑lγjl(t)∑tγjk(t)
μ^jk=∑tγjk(t)ot∑tγjk(t)\hat{\mu}{jk} = \frac{\sum_t \gamma{jk}(t) o_t}{\sum_t \gamma_{jk}(t)}μ^jk=∑tγjk(t)∑tγjk(t)ot
Σ^jk=∑tγjk(t)(ot−μ^jk)(ot−μ^jk)T∑tγjk(t)\hat{\Sigma}{jk} = \frac{\sum_t \gamma{jk}(t) (o_t - \hat{\mu}{jk})(o_t - \hat{\mu}{jk})^T}{\sum_t \gamma_{jk}(t)}Σ^jk=∑tγjk(t)∑tγjk(t)(ot−μ^jk)(ot−μ^jk)T
5.3.2 分量分裂
训练 GMM 的常用策略:
- 先训练少量分量的 GMM
- 将每个分量分裂为两个
- 继续训练
- 重复直到达到目标分量数
第六章:深度神经网络声学模型
6.1 DNN-HMM 混合系统
6.1.1 基本思想
用深度神经网络(DNN)替代 GMM 来估计 HMM 的观测概率:
bj(ot)=P(sj∣ot)=softmax(DNN(ot))jb_j(o_t) = P(s_j | o_t) = \text{softmax}(\text{DNN}(o_t))_jbj(ot)=P(sj∣ot)=softmax(DNN(ot))j
注意:DNN 直接估计后验概率 P(state∣observation)P(\text{state}|\text{observation})P(state∣observation),而不是似然 P(observation∣state)P(\text{observation}|\text{state})P(observation∣state)。
通过贝叶斯规则转换:
P(ot∣sj)=P(sj∣ot)P(ot)P(sj)P(o_t | s_j) = \frac{P(s_j | o_t) P(o_t)}{P(s_j)}P(ot∣sj)=P(sj)P(sj∣ot)P(ot)
6.1.2 上下文窗口
DNN 的输入不是单帧,而是上下文窗口:
xt=ot−L,...,ot,...,ot+L\mathbf{x}_t = o_{t-L}, \\dots, o_t, \\dots, o_{t+L}xt=ot−L,...,ot,...,ot+L
典型窗口大小:L=5L = 5L=5(共 11 帧)。
6.1.3 DNN 架构
标准 DNN 声学模型:
- 输入:d×(2L+1)d \times (2L+1)d×(2L+1)(特征维度 × 窗口大小)
- 隐藏层:3-7 层,每层 1024-2048 个神经元
- 激活函数:ReLU, sigmoid
- 输出层:softmax(状态数)
6.2 卷积神经网络(CNN)
6.2.1 时频卷积
在语谱图上应用 2D 卷积:
ht,f=σ(∑m∑nwm,nxt+m,f+n+b)h_{t,f} = \sigma\left(\sum_{m}\sum_{n} w_{m,n} x_{t+m, f+n} + b\right)ht,f=σ(m∑n∑wm,nxt+m,f+n+b)
- 时间轴卷积:捕捉时序模式
- 频率轴卷积:捕捉频率模式
6.2.2 TDNN(时延神经网络)
TDNN 在时间轴上使用卷积:
ht=σ(∑τ=−TTwτxt+τ+b)h_t = \sigma\left(\sum_{\tau=-T}^{T} w_\tau x_{t+\tau} + b\right)ht=σ(τ=−T∑Twτxt+τ+b)
TDNN 可以看作 1D CNN 的特例。
6.3 循环神经网络(RNN)
6.3.1 基本 RNN
ht=σ(Whht−1+Wxxt+b)h_t = \sigma(W_h h_{t-1} + W_x x_t + b)ht=σ(Whht−1+Wxxt+b)
问题:梯度消失/爆炸,难以捕捉长时依赖。
6.3.2 LSTM
ft=σ(Wfht−1,xt+bf)(遗忘门)f_t = \sigma(W_f h_{t-1}, x_t + b_f) \quad \text{(遗忘门)}ft=σ(Wfht−1,xt+bf)(遗忘门)
it=σ(Wiht−1,xt+bi)(输入门)i_t = \sigma(W_i h_{t-1}, x_t + b_i) \quad \text{(输入门)}it=σ(Wiht−1,xt+bi)(输入门)
c~t=tanh(Wcht−1,xt+bc)(候选)\tilde{c}_t = \tanh(W_c h_{t-1}, x_t + b_c) \quad \text{(候选)}c~t=tanh(Wcht−1,xt+bc)(候选)
ct=ft⊙ct−1+it⊙c~t(细胞状态)c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t \quad \text{(细胞状态)}ct=ft⊙ct−1+it⊙c~t(细胞状态)
ot=σ(Woht−1,xt+bo)(输出门)o_t = \sigma(W_o h_{t-1}, x_t + b_o) \quad \text{(输出门)}ot=σ(Woht−1,xt+bo)(输出门)
ht=ot⊙tanh(ct)h_t = o_t \odot \tanh(c_t)ht=ot⊙tanh(ct)
LSTM 通过门控机制和线性记忆通路,有效缓解了梯度消失问题。
6.3.3 双向 RNN
h→t=f(h→t−1,xt)\overrightarrow{h}t = f(\overrightarrow{h}{t-1}, x_t)h t=f(h t−1,xt)
h←t=f(h←t+1,xt)\overleftarrow{h}t = f(\overleftarrow{h}{t+1}, x_t)h t=f(h t+1,xt)
ht=h→t;h←th_t = \\overrightarrow{h}_t; \\overleftarrow{h}_tht=h t;h t
双向 RNN 可以利用未来信息(非流式场景)。
6.4 注意力机制
6.4.1 自注意力
Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dk QKT)V
6.4.2 多头注意力
MultiHead(Q,K,V)=Concat(head1,...,headh)WO\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W^OMultiHead(Q,K,V)=Concat(head1,...,headh)WO
其中 headi=Attention(QWiQ,KWiK,VWiV)\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)headi=Attention(QWiQ,KWiK,VWiV)。
6.4.3 位置编码
由于自注意力是位置无关的,需要添加位置信息:
PE(pos,2i)=sin(pos/100002i/d)PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d})PE(pos,2i)=sin(pos/100002i/d)
PE(pos,2i+1)=cos(pos/100002i/d)PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d})PE(pos,2i+1)=cos(pos/100002i/d)
第三部分:序列建模与解码
第七章:语言模型
7.1 N-gram 语言模型
7.1.1 定义
N-gram 语言模型假设当前词只依赖于前 N−1N-1N−1 个词:
P(w1,w2,...,wM)=∏i=1MP(wi∣wi−N+1,...,wi−1)P(w_1, w_2, \dots, w_M) = \prod_{i=1}^{M} P(w_i | w_{i-N+1}, \dots, w_{i-1})P(w1,w2,...,wM)=i=1∏MP(wi∣wi−N+1,...,wi−1)
7.1.2 参数估计
最大似然估计:
P(wi∣wi−N+1,...,wi−1)=C(wi−N+1,...,wi)C(wi−N+1,...,wi−1)P(w_i | w_{i-N+1}, \dots, w_{i-1}) = \frac{C(w_{i-N+1}, \dots, w_i)}{C(w_{i-N+1}, \dots, w_{i-1})}P(wi∣wi−N+1,...,wi−1)=C(wi−N+1,...,wi−1)C(wi−N+1,...,wi)
其中 C(⋅)C(\cdot)C(⋅) 是计数函数。
7.1.3 平滑技术
问题:许多 N-gram 从未在训练数据中出现(零概率问题)。
解决方法:
- 加一平滑(Laplace):所有计数加一
- Good-Turing 平滑 :用出现 r+1r+1r+1 次的 N-gram 来估计出现 rrr 次的概率
- Kneser-Ney 平滑:考虑词的上下文多样性
7.2 神经语言模型
7.2.1 前馈神经网络
P(wi∣wi−N+1,...,wi−1)=softmax(Wh+b)P(w_i | w_{i-N+1}, \dots, w_{i-1}) = \text{softmax}(Wh + b)P(wi∣wi−N+1,...,wi−1)=softmax(Wh+b)
其中 h=ReLU(Weewi−N+1;... ;ewi−1+b1)h = \text{ReLU}(W_e e_{w_{i-N+1}}; \\dots; e_{w_{i-1}} + b_1)h=ReLU(Weewi−N+1;...;ewi−1+b1),ewe_wew 是词嵌入。
7.2.2 RNN 语言模型
ht=f(ht−1,ewt)h_t = f(h_{t-1}, e_{w_t})ht=f(ht−1,ewt)
P(wt+1∣w1,...,wt)=softmax(Wht+b)P(w_{t+1} | w_1, \dots, w_t) = \text{softmax}(W h_t + b)P(wt+1∣w1,...,wt)=softmax(Wht+b)
RNN 可以利用任意长度的历史(理论上)。
7.2.3 Transformer 语言模型
使用因果注意力(causal attention):
P(wt+1∣w1,...,wt)=Transformer(w1,...,wt)P(w_{t+1} | w_1, \dots, w_t) = \text{Transformer}(w_1, \dots, w_t)P(wt+1∣w1,...,wt)=Transformer(w1,...,wt)
现代大语言模型(GPT, LLaMA 等)都是 Transformer 语言模型。
7.3 困惑度(Perplexity)
7.3.1 定义
语言模型的困惑度定义为:
PPL=exp(−1M∑i=1MlogP(wi∣w1,...,wi−1))\text{PPL} = \exp\left(-\frac{1}{M}\sum_{i=1}^{M} \log P(w_i | w_1, \dots, w_{i-1})\right)PPL=exp(−M1i=1∑MlogP(wi∣w1,...,wi−1))
7.3.2 解释
- PPL 越小,模型越好
- PPL = VVV(词汇表大小)对应均匀分布
- PPL = 1 对应完美预测
第八章:解码与搜索
8.1 解码问题
8.1.1 数学形式
W∗=argmaxWP(O∣W)⋅P(W)α⋅∣W∣βW^* = \arg\max_W P(O|W) \cdot P(W)^\alpha \cdot |W|^\betaW∗=argWmaxP(O∣W)⋅P(W)α⋅∣W∣β
其中:
- α\alphaα:语言模型权重
- β\betaβ:长度奖励
8.1.2 搜索空间
搜索空间是指数级 的------词汇表大小 VVV,序列长度 MMM,组合数为 VMV^MVM。
8.2 Viterbi 解码
8.2.1 词级 Viterbi
在词级网络上运行 Viterbi 算法:
δt(w)=maxw′δt−1(w′)⋅aw′w⋅bw(ot)\delta_t(w) = \max_{w'} \\delta_{t-1}(w') \\cdot a_{w'w} \\cdot b_w(o_t)δt(w)=w′maxδt−1(w′)⋅aw′w⋅bw(ot)
8.2.2 帧同步解码
在每个时间步,扩展所有活跃的假设。
8.3 束搜索(Beam Search)
8.3.1 算法
维护一个大小为 BBB 的束 (beam),每步只保留得分最高的 BBB 个假设:
对于每个时间步 t:
对于束中的每个假设 h:
对于词汇表中的每个词 w:
计算新假设的得分
保留得分最高的 B 个假设
8.3.2 束搜索的近似性
束搜索不保证找到全局最优解------它是一种贪心搜索策略。
束大小 BBB 的权衡:
- BBB 大:更接近最优,但计算量大
- BBB 小:计算快,但可能丢失正确答案
8.4 格(Lattice)解码
8.4.1 格的定义
格是一个有向无环图(DAG),节点表示时间-状态对,边表示词假设。
8.4.2 格的优势
- 紧凑地表示多个假设
- 支持后验概率计算
- 便于多遍搜索和重打分
第九章:序列判别训练
9.1 最大似然训练的局限
9.1.1 最大似然目标
LML=∑rlogP(Or∣Wr)\mathcal{L}_{ML} = \sum_r \log P(O_r | W_r)LML=r∑logP(Or∣Wr)
最大似然训练最大化正确词序列的似然,但不直接最小化识别错误率。
9.1.2 判别训练的动机
判别训练直接优化与错误率相关的目标:
Ldisc=∑rlogP(Or∣Wr)∑W′P(Or∣W′)γ\mathcal{L}{disc} = \sum_r \log \frac{P(O_r | W_r)}{\sum{W'} P(O_r | W')^{\gamma}}Ldisc=r∑log∑W′P(Or∣W′)γP(Or∣Wr)
9.2 最大互信息(MMI)
9.2.1 目标函数
LMMI=∑rlogP(Wr∣Or)P(Wr)=∑rlogP(Or∣Wr)∑W′P(Or∣W′)\mathcal{L}{MMI} = \sum_r \log \frac{P(W_r | O_r)}{P(W_r)} = \sum_r \log \frac{P(O_r | W_r)}{\sum{W'} P(O_r | W')}LMMI=r∑logP(Wr)P(Wr∣Or)=r∑log∑W′P(Or∣W′)P(Or∣Wr)
9.2.2 梯度计算
MMI 的梯度涉及对所有词序列的求和------这需要前向-后向算法在词格上运行。
9.3 最小贝叶斯风险(MBR)
9.3.1 目标函数
W∗=argminW∑W′R(W,W′)P(W′∣O)W^* = \arg\min_W \sum_{W'} R(W, W') P(W' | O)W∗=argWminW′∑R(W,W′)P(W′∣O)
其中 R(W,W′)R(W, W')R(W,W′) 是风险函数(如词错误率)。
9.3.2 近似
由于 P(W∣O)P(W|O)P(W∣O) 的计算困难,通常在格上近似。
第四部分:端到端模型
第十章:CTC(连接时序分类)
10.1 对齐问题
10.1.1 传统方法的对齐
传统 HMM 系统需要强制对齐(forced alignment)来建立帧和标签之间的对应关系。
10.1.2 CTC 的动机
问题:能否在不需要显式对齐的情况下训练序列模型?
CTC 的答案 :引入一个特殊的空白符 (blank)ϵ\epsilonϵ,将输入和输出序列长度对齐。
10.2 CTC 的数学理论
10.2.1 CTC 变换
给定输入序列 X=(x1,...,xT)X = (x_1, \dots, x_T)X=(x1,...,xT) 和输出序列 Y=(y1,...,yU)Y = (y_1, \dots, y_U)Y=(y1,...,yU)(T≥UT \geq UT≥U),CTC 定义了一个多对一 的映射 B\mathcal{B}B:
B:(a1,...,aT)→(y1,...,yU)\mathcal{B}: (a_1, \dots, a_T) \to (y_1, \dots, y_U)B:(a1,...,aT)→(y1,...,yU)
映射规则:
- 合并相邻的重复字符
- 删除空白符 ϵ\epsilonϵ
例子:
- (a,a,ϵ,b,b)→(a,b)(a, a, \epsilon, b, b) \to (a, b)(a,a,ϵ,b,b)→(a,b)
- (ϵ,a,a,b,ϵ)→(a,b)(\epsilon, a, a, b, \epsilon) \to (a, b)(ϵ,a,a,b,ϵ)→(a,b)
- (a,a,a,b,b)→(a,b)(a, a, a, b, b) \to (a, b)(a,a,a,b,b)→(a,b)
10.2.2 CTC 条件概率
CTC 将输出概率定义为所有可能对齐的概率之和:
P(Y∣X)=∑π∈B−1(Y)P(π∣X)P(Y|X) = \sum_{\pi \in \mathcal{B}^{-1}(Y)} P(\pi|X)P(Y∣X)=π∈B−1(Y)∑P(π∣X)
其中 B−1(Y)\mathcal{B}^{-1}(Y)B−1(Y) 是所有映射到 YYY 的对齐序列。
由于 CTC 的条件独立假设:
P(π∣X)=∏t=1TP(πt∣X)=∏t=1TP(πt∣xt)P(\pi|X) = \prod_{t=1}^{T} P(\pi_t | X) = \prod_{t=1}^{T} P(\pi_t | x_t)P(π∣X)=t=1∏TP(πt∣X)=t=1∏TP(πt∣xt)
10.2.3 前向-后向算法
前向变量:
αt(s)=P(y1,...,ys/t,x1,...,xt)\alpha_t(s) = P(y_1, \dots, y_{s/t}, x_1, \dots, x_t)αt(s)=P(y1,...,ys/t,x1,...,xt)
其中 ys/ty_{s/t}ys/t 表示输出序列的前 sss 个字符在时间 ttt 处。
递推:
αt(s)={αt−1(s)⋅yϵtif ys=ϵαt−1(s−1)⋅yyst+αt−1(s)⋅yϵtif ys≠ϵ,ys=ys−1αt−1(s−1)⋅yyst+αt−1(s−2)⋅yϵtif ys≠ϵ,ys≠ys−1\alpha_t(s) = \begin{cases} \alpha_{t-1}(s) \cdot y_{\epsilon}^t & \text{if } y_s = \epsilon \\ \alpha_{t-1}(s-1) \cdot y_{y_s}^t + \alpha_{t-1}(s) \cdot y_{\epsilon}^t & \text{if } y_s \neq \epsilon, y_s = y_{s-1} \\ \alpha_{t-1}(s-1) \cdot y_{y_s}^t + \alpha_{t-1}(s-2) \cdot y_{\epsilon}^t & \text{if } y_s \neq \epsilon, y_s \neq y_{s-1} \end{cases}αt(s)=⎩ ⎨ ⎧αt−1(s)⋅yϵtαt−1(s−1)⋅yyst+αt−1(s)⋅yϵtαt−1(s−1)⋅yyst+αt−1(s−2)⋅yϵtif ys=ϵif ys=ϵ,ys=ys−1if ys=ϵ,ys=ys−1
其中 ykt=P(πt=k∣xt)y_k^t = P(\pi_t = k | x_t)ykt=P(πt=k∣xt) 是模型在时间 ttt 输出字符 kkk 的概率。
10.2.4 CTC 损失
LCTC=−logP(Y∣X)=−log∑π∈B−1(Y)∏t=1TP(πt∣xt)\mathcal{L}{CTC} = -\log P(Y|X) = -\log \sum{\pi \in \mathcal{B}^{-1}(Y)} \prod_{t=1}^{T} P(\pi_t | x_t)LCTC=−logP(Y∣X)=−logπ∈B−1(Y)∑t=1∏TP(πt∣xt)
10.3 CTC 的理论性质
10.3.1 条件独立假设
CTC 假设不同时间步的输出是条件独立的:
P(πt∣X)=P(πt∣xt)P(\pi_t | X) = P(\pi_t | x_t)P(πt∣X)=P(πt∣xt)
这意味着 CTC 无法建模输出之间的依赖关系。
10.3.2 单调对齐
CTC 只考虑单调对齐------输入和输出的时间顺序相同。
这适合语音识别(发音顺序与文字顺序一致),但不适合机器翻译(词序可能不同)。
10.3.3 CTC 的峰值现象
CTC 的输出概率通常在某些时间步出现尖锐的峰值------这对应于"决定"输出一个字符的时刻。
10.4 CTC 的解码
10.4.1 贪心解码
π^t=argmaxkP(πt=k∣xt)\hat{\pi}_t = \arg\max_k P(\pi_t = k | x_t)π^t=argkmaxP(πt=k∣xt)
然后应用 B\mathcal{B}B 变换得到输出序列。
10.4.2 前缀束搜索
维护一个前缀的束,每步扩展并剪枝。
10.4.3 基于语言模型的解码
Y^=argmaxYlogPCTC(Y∣X)+αlogPLM(Y)+β∣Y∣\hat{Y} = \arg\max_Y \log P_{CTC}(Y|X) + \alpha \log P_{LM}(Y) + \beta |Y|Y^=argYmaxlogPCTC(Y∣X)+αlogPLM(Y)+β∣Y∣
第十一章:注意力机制与编码器-解码器
11.1 编码器-解码器框架
11.1.1 基本结构
编码器:将输入序列编码为隐状态序列
h1,h2,...,hT=Encoder(x1,x2,...,xT)h_1, h_2, \dots, h_T = \text{Encoder}(x_1, x_2, \dots, x_T)h1,h2,...,hT=Encoder(x1,x2,...,xT)
解码器:基于隐状态序列生成输出序列
P(yt∣y<t,X)=Decoder(y<t,h1,...,hT)P(y_t | y_{<t}, X) = \text{Decoder}(y_{<t}, h_1, \dots, h_T)P(yt∣y<t,X)=Decoder(y<t,h1,...,hT)
11.1.2 注意力机制
注意力机制计算解码器当前状态与编码器各位置的"相关性":
et,i=score(st−1,hi)e_{t,i} = \text{score}(s_{t-1}, h_i)et,i=score(st−1,hi)
αt,i=exp(et,i)∑jexp(et,j)\alpha_{t,i} = \frac{\exp(e_{t,i})}{\sum_j \exp(e_{t,j})}αt,i=∑jexp(et,j)exp(et,i)
ct=∑iαt,ihic_t = \sum_i \alpha_{t,i} h_ict=i∑αt,ihi
其中 st−1s_{t-1}st−1 是解码器前一时刻的状态,ctc_tct 是上下文向量。
11.1.3 评分函数
| 评分函数 | 公式 | 名称 |
|---|---|---|
| 内积 | sThs^T hsTh | Dot |
| 双线性 | sTWhs^T W hsTWh | General |
| 拼接 | vTtanh(W1s+W2h)v^T \tanh(W_1 s + W_2 h)vTtanh(W1s+W2h) | Concat |
11.2 LAS(Listen, Attend and Spell)
11.2.1 模型结构
LAS 是第一个端到端的注意力语音识别模型:
Listener(编码器):多层 RNN 或 Transformer
Speller(解码器):基于注意力的 RNN
11.2.2 训练目标
LLAS=−∑tlogP(yt∣y<t,X)\mathcal{L}{LAS} = -\sum_t \log P(y_t | y{<t}, X)LLAS=−t∑logP(yt∣y<t,X)
这是标准的交叉熵损失。
11.2.3 注意力对齐
注意力权重 αt,i\alpha_{t,i}αt,i 自动学习输入和输出之间的对齐关系------不需要强制对齐。
11.3 Transformer 语音识别
11.3.1 编码器
输入特征 → 线性变换 → 位置编码 → N × (自注意力 → FFN)
11.3.2 解码器
输出嵌入 → 位置编码 → N × (掩码自注意力 → 交叉注意力 → FFN)
11.3.3 优势
- 并行计算(训练快)
- 长距离依赖建模能力强
- 注意力对齐可解释
第十二章:RNN-T(循环神经网络变换器)
12.1 RNN-T 的动机
12.1.1 CTC 的局限
- 条件独立假设
- 无法建模输出依赖
12.1.2 注意力模型的局限
- 需要整个输入序列(非流式)
- 注意力对齐可能不稳定
12.1.3 RNN-T 的设计目标
- 建模输出依赖
- 支持流式处理
- 稳定的对齐
12.2 RNN-T 的数学理论
12.2.1 模型结构
RNN-T 包含三个组件:
编码器(Encoder) :
h1enc,...,hTenc=Encoder(x1,...,xT)h_1^{\text{enc}}, \dots, h_T^{\text{enc}} = \text{Encoder}(x_1, \dots, x_T)h1enc,...,hTenc=Encoder(x1,...,xT)
预测网络(Prediction Network) :
hupred=PredNet(y1,...,yu−1)h_u^{\text{pred}} = \text{PredNet}(y_1, \dots, y_{u-1})hupred=PredNet(y1,...,yu−1)
联合网络(Joint Network) :
P(k∣t,u)=softmax(Joint(htenc,hupred))kP(k | t, u) = \text{softmax}(\text{Joint}(h_t^{\text{enc}}, h_u^{\text{pred}}))_kP(k∣t,u)=softmax(Joint(htenc,hupred))k
12.2.2 RNN-T 概率
RNN-T 将所有可能的对齐路径求和:
P(Y∣X)=∑π∈B−1(Y)∏t=1TP(πt∣t,ut)P(Y|X) = \sum_{\pi \in \mathcal{B}^{-1}(Y)} \prod_{t=1}^{T} P(\pi_t | t, u_t)P(Y∣X)=π∈B−1(Y)∑t=1∏TP(πt∣t,ut)
其中 utu_tut 是在时间 ttt 处对应的输出位置。
12.2.3 前向-后向算法
RNN-T 的前向变量:
α(t,u)=∑all paths to (t,u)∏P(πt′∣t′,ut′)\alpha(t, u) = \sum_{\text{all paths to } (t,u)} \prod P(\pi_{t'} | t', u_{t'})α(t,u)=all paths to (t,u)∑∏P(πt′∣t′,ut′)
递推关系:
α(t,u)=α(t−1,u)⋅P(ϵ∣t−1,u)+α(t,u−1)⋅P(yu∣t,u−1)\alpha(t, u) = \alpha(t-1, u) \cdot P(\epsilon | t-1, u) + \alpha(t, u-1) \cdot P(y_u | t, u-1)α(t,u)=α(t−1,u)⋅P(ϵ∣t−1,u)+α(t,u−1)⋅P(yu∣t,u−1)
12.2.4 RNN-T 损失
LRNN−T=−logP(Y∣X)=−logα(T,U)\mathcal{L}_{RNN-T} = -\log P(Y|X) = -\log \alpha(T, U)LRNN−T=−logP(Y∣X)=−logα(T,U)
12.3 RNN-T 与 CTC 的比较
| 性质 | CTC | RNN-T |
|---|---|---|
| 输出依赖 | 无(条件独立) | 有(通过预测网络) |
| 对齐 | 单调 | 单调 |
| 流式 | 支持 | 支持 |
| 计算复杂度 | O(TU)O(TU)O(TU) | O(TU)O(TU)O(TU) |
| 解码 | 前缀束搜索 | 前缀束搜索 |
12.4 Conformer 编码器
12.4.1 Conformer 块
Conformer 结合了卷积和注意力:
输入 → FFN/2 → 多头自注意力 → 卷积模块 → FFN/2 → 输出
12.4.2 卷积模块
输入 → 1D 点卷积 → GLU → 深度可分离卷积 → BatchNorm → Swish → 1D 点卷积
卷积模块捕捉局部模式,注意力模块捕捉全局依赖。
第五部分:理论分析与前沿
第十三章:语音识别的信息论视角
13.1 信息熵与语音
13.1.1 语音的熵
语音信号的信息熵:
H(X)=−∑xP(x)logP(x)H(X) = -\sum_x P(x) \log P(x)H(X)=−x∑P(x)logP(x)
英语的熵估计约为 1.0-1.5 bits/字符(考虑上下文后)。
13.1.2 互信息
输入特征 XXX 和输出标签 YYY 之间的互信息:
I(X;Y)=H(Y)−H(Y∣X)I(X; Y) = H(Y) - H(Y|X)I(X;Y)=H(Y)−H(Y∣X)
好的声学模型应该最大化 I(X;Y)I(X; Y)I(X;Y)。
13.2 贝叶斯决策理论
13.2.1 最大后验决策
W∗=argmaxWP(W∣O)W^* = \arg\max_W P(W|O)W∗=argWmaxP(W∣O)
13.2.2 最小贝叶斯风险
W∗=argminW∑W′R(W,W′)P(W′∣O)W^* = \arg\min_W \sum_{W'} R(W, W') P(W'|O)W∗=argWminW′∑R(W,W′)P(W′∣O)
13.2.3 0-1 损失
当 R(W,W′)=1W≠W′R(W, W') = \mathbb{1}W \\neq W'R(W,W′)=1W=W′ 时,最小贝叶斯风险等价于最大后验。
13.3 信道模型
13.3.1 语音识别作为信道解码
语音识别可以看作一个噪声信道问题:
W→信道→OW \to \text{信道} \to OW→信道→O
- 发送端:词序列 WWW
- 信道:语音产生过程(含噪声)
- 接收端:声学观测 OOO
解码就是从接收信号恢复发送信号。
第十四章:SSM 与语音识别
14.1 SSM 用于语音的动机
14.1.1 语音信号的特性
- 长序列:1 分钟音频 = 60,000 帧(10ms 帧移)
- 长时依赖:音素、音节、词之间的依赖
- 时变性:语音信号是非平稳的
14.1.2 SSM 的优势
- 线性复杂度:处理长序列高效
- 长程记忆:HiPPO 理论保证
- 选择性机制:适应语音的时变特性
14.2 S4 用于语音
14.2.1 S4 的特性
S4(Structured State Space for Sequences)具有:
- 卷积和递推的对偶性
- 高效的长程依赖建模
- 稳定的梯度传播
14.2.2 语音识别中的 S4
将 S4 用作声学模型的骨干网络:
ht=S4(x1,...,xt)h_t = \text{S4}(x_1, \dots, x_t)ht=S4(x1,...,xt)
14.3 Mamba 用于语音
14.3.1 选择性机制的优势
Mamba 的选择性机制特别适合语音:
- 重要的语音帧(如音素边界)获得更大的 Δ\DeltaΔ
- 静音或噪声帧被快速遗忘
- 模型可以自适应地调整"记忆策略"
14.3.2 流式处理
Mamba 的递推模式天然支持流式处理------这对实时语音识别至关重要。
14.4 SSM 与注意力的混合
14.4.1 混合架构
结合 SSM 和注意力的优势:
- SSM 层:捕捉长程依赖
- 注意力层:精确的对齐和建模
14.4.2 理论分析
SSM 和注意力可以互补:
- SSM:高效但固定的衰减模式
- 注意力:灵活但 O(n2)O(n^2)O(n2) 复杂度
混合架构可以在效率和表达能力之间取得平衡。
第十五章:多任务学习与自监督
15.1 多任务学习
15.1.1 联合 CTC-Attention
同时使用 CTC 和注意力损失:
L=λLCTC+(1−λ)LAtt\mathcal{L} = \lambda \mathcal{L}{CTC} + (1-\lambda) \mathcal{L}{Att}L=λLCTC+(1−λ)LAtt
CTC 提供单调对齐约束,注意力提供灵活的上下文建模。
15.1.2 多任务目标
除了转录任务,还可以加入:
- 说话人识别
- 语言识别
- 情感识别
- 语音分离
15.2 自监督预训练
15.2.1 Wav2Vec 2.0
预训练任务:预测被遮盖的语音片段
Lw2v=−logexp(sim(qt,ct)/τ)∑kexp(sim(qt,ck)/τ)\mathcal{L}{w2v} = -\log \frac{\exp(\text{sim}(q_t, c_t)/\tau)}{\sum{k} \exp(\text{sim}(q_t, c_k)/\tau)}Lw2v=−log∑kexp(sim(qt,ck)/τ)exp(sim(qt,ct)/τ)
其中 qtq_tqt 是量化的目标,ctc_tct 是对比样本。
15.2.2 HuBERT
预训练任务:预测伪标签(通过聚类得到)
Lhubert=−∑t∈MlogP(zt∣x\M)\mathcal{L}{hubert} = -\sum{t \in M} \log P(z_t | x_{\backslash M})Lhubert=−t∈M∑logP(zt∣x\M)
其中 MMM 是被遮盖的位置,ztz_tzt 是伪标签。
15.2.3 Whisper
预训练任务:多任务序列到序列
- 语音识别
- 语音翻译
- 语言识别
- 时间戳预测
15.3 预训练的理论分析
15.3.1 表示学习
预训练学习到的表示应该:
- 不变性:对不相关的变化(如说话人)不变
- 等变性:对相关的变化(如音素)等变
15.3.2 信息最大化
预训练可以理解为最大化输入和表示之间的互信息:
maxI(X;Z)\max I(X; Z)maxI(X;Z)
第十六章:完整可运行代码实现
16.1 MFCC 特征提取
python
"""
MFCC 特征提取的完整实现。
包含: 预加重、分帧、FFT、梅尔滤波器组、DCT。
"""
import numpy as np
def pre_emphasis(signal, coeff=0.97):
"""预加重滤波器。"""
return np.append(signal[0], signal[1:] - coeff * signal[:-1])
def framing(signal, frame_size, frame_shift, fs):
"""分帧。
Args:
signal: 输入信号
frame_size: 帧长 (秒)
frame_shift: 帧移 (秒)
fs: 采样率
Returns:
frames: (num_frames, frame_length) 帧矩阵
"""
frame_length = int(frame_size * fs)
shift_length = int(frame_shift * fs)
num_frames = (len(signal) - frame_length) // shift_length + 1
indices = np.arange(0, num_frames)[:, None] * shift_length + np.arange(frame_length)
frames = signal[indices]
return frames
def hamming_window(N):
"""Hamming 窗。"""
return 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(N) / (N - 1))
def mel_filterbank(num_filters, fft_size, fs, low_freq=0, high_freq=None):
"""梅尔滤波器组。
Args:
num_filters: 滤波器数量
fft_size: FFT 大小
fs: 采样率
low_freq: 最低频率
high_freq: 最高频率
Returns:
filterbank: (num_filters, fft_size//2+1) 滤波器组
"""
if high_freq is None:
high_freq = fs / 2
# 梅尔尺度转换
def hz2mel(f):
return 2595 * np.log10(1 + f / 700)
def mel2hz(m):
return 700 * (10**(m / 2595) - 1)
# 滤波器中心频率 (梅尔尺度均匀分布)
mel_low = hz2mel(low_freq)
mel_high = hz2mel(high_freq)
mel_points = np.linspace(mel_low, mel_high, num_filters + 2)
hz_points = mel2hz(mel_points)
# FFT 频率 bin
bin_points = np.floor(hz_points / (fs / fft_size)).astype(int)
# 构造滤波器组
filterbank = np.zeros((num_filters, fft_size // 2 + 1))
for m in range(num_filters):
left = bin_points[m]
center = bin_points[m + 1]
right = bin_points[m + 2]
for k in range(left, center):
filterbank[m, k] = (k - left) / (center - left)
for k in range(center, right):
filterbank[m, k] = (right - k) / (right - center)
return filterbank
def mfcc(signal, fs, num_coeffs=13, num_filters=26, frame_size=0.025,
frame_shift=0.01, pre_emph=0.97):
"""计算 MFCC 特征。
Args:
signal: 输入信号
fs: 采样率
num_coeffs: MFCC 系数数量
num_filters: 梅尔滤波器数量
frame_size: 帧长 (秒)
frame_shift: 帧移 (秒)
pre_emph: 预加重系数
Returns:
mfcc_features: (num_frames, num_coeffs) MFCC 特征
"""
# 预加重
signal = pre_emphasis(signal, pre_emph)
# 分帧
frames = framing(signal, frame_size, frame_shift, fs)
num_frames, frame_length = frames.shape
# 加窗
window = hamming_window(frame_length)
frames = frames * window
# FFT
fft_size = 1
while fft_size < frame_length:
fft_size *= 2
X = np.fft.rfft(frames, n=fft_size)
power = np.abs(X)**2 / fft_size
# 梅尔滤波器组
fb = mel_filterbank(num_filters, fft_size, fs)
# 滤波器组能量
filterbank_energy = power @ fb.T
# 对数能量
log_energy = np.log(filterbank_energy + 1e-10)
# DCT
num_frames, num_filters = log_energy.shape
dct_matrix = np.zeros((num_coeffs, num_filters))
for n in range(num_coeffs):
for m in range(num_filters):
dct_matrix[n, m] = np.cos(np.pi * n * (m + 0.5) / num_filters)
mfcc_features = dct_matrix @ log_energy.T
return mfcc_features.T
def demonstrate_mfcc():
"""演示 MFCC 特征提取。"""
print("=" * 60)
print("MFCC 特征提取演示")
print("=" * 60)
np.random.seed(42)
# 生成模拟语音信号
fs = 16000
duration = 1.0
t = np.arange(0, duration, 1/fs)
# 模拟语音: 基频 + 共振峰
f0 = 100 # 基频
signal = (0.5 * np.sin(2*np.pi*f0*t) +
0.3 * np.sin(2*np.pi*500*t) + # F1
0.2 * np.sin(2*np.pi*1500*t) + # F2
0.1 * np.random.randn(len(t))) # 噪声
print(f"\n信号参数:")
print(f" 采样率: {fs} Hz")
print(f" 时长: {duration} s")
print(f" 样本数: {len(signal)}")
# 提取 MFCC
mfcc_features = mfcc(signal, fs, num_coeffs=13)
print(f"\nMFCC 特征:")
print(f" 帧数: {mfcc_features.shape[0]}")
print(f" 特征维度: {mfcc_features.shape[1]}")
print(f" 特征均值: {np.mean(mfcc_features, axis=0)[:5]}")
print(f" 特征标准差: {np.std(mfcc_features, axis=0)[:5]}")
return mfcc_features
if __name__ == "__main__":
demonstrate_mfcc()
16.2 HMM 前向-后向算法
python
"""
HMM 前向-后向算法的完整实现。
包含: 前向算法、后向算法、Viterbi 算法、Baum-Welch 算法。
"""
import numpy as np
class HMM:
"""离散 HMM 模型。"""
def __init__(self, num_states, num_obs):
"""
Args:
num_states: 状态数
num_obs: 观测符号数
"""
self.N = num_states
self.M = num_obs
# 随机初始化参数
self.pi = np.random.dirichlet(np.ones(num_states))
self.A = np.random.dirichlet(np.ones(num_states), size=num_states)
self.B = np.random.dirichlet(np.ones(num_obs), size=num_states)
def forward(self, O):
"""前向算法。
Args:
O: (T,) 观测序列
Returns:
alpha: (T, N) 前向变量
log_prob: 对数似然
"""
T = len(O)
alpha = np.zeros((T, self.N))
# 初始化
alpha[0] = self.pi * self.B[:, O[0]]
# 递推
for t in range(1, T):
alpha[t] = (alpha[t-1] @ self.A) * self.B[:, O[t]]
# 终止
log_prob = np.log(np.sum(alpha[-1]) + 1e-10)
return alpha, log_prob
def backward(self, O):
"""后向算法。
Args:
O: (T,) 观测序列
Returns:
beta: (T, N) 后向变量
"""
T = len(O)
beta = np.zeros((T, self.N))
# 初始化
beta[-1] = 1.0
# 递推
for t in range(T-2, -1, -1):
beta[t] = self.A @ (self.B[:, O[t+1]] * beta[t+1])
return beta
def viterbi(self, O):
"""Viterbi 算法。
Args:
O: (T,) 观测序列
Returns:
path: (T,) 最优状态序列
log_prob: 对数概率
"""
T = len(O)
delta = np.zeros((T, self.N))
psi = np.zeros((T, self.N), dtype=int)
# 初始化
delta[0] = np.log(self.pi + 1e-10) + np.log(self.B[:, O[0]] + 1e-10)
# 递推
for t in range(1, T):
for j in range(self.N):
scores = delta[t-1] + np.log(self.A[:, j] + 1e-10)
psi[t, j] = np.argmax(scores)
delta[t, j] = scores[psi[t, j]] + np.log(self.B[j, O[t]] + 1e-10)
# 回溯
path = np.zeros(T, dtype=int)
path[-1] = np.argmax(delta[-1])
for t in range(T-2, -1, -1):
path[t] = psi[t+1, path[t+1]]
log_prob = delta[-1, path[-1]]
return path, log_prob
def baum_welch(self, O_list, max_iter=100):
"""Baum-Welch 算法。
Args:
O_list: 观测序列列表
max_iter: 最大迭代次数
"""
for iteration in range(max_iter):
# 初始化统计量
pi_acc = np.zeros(self.N)
A_acc = np.zeros((self.N, self.N))
B_acc = np.zeros((self.N, self.M))
total_log_prob = 0
for O in O_list:
T = len(O)
# 前向-后向
alpha, log_prob = self.forward(O)
beta = self.backward(O)
total_log_prob += log_prob
# gamma 和 xi
gamma = alpha * beta
gamma = gamma / (gamma.sum(axis=1, keepdims=True) + 1e-10)
xi = np.zeros((T-1, self.N, self.N))
for t in range(T-1):
xi[t] = alpha[t][:, None] * self.A * self.B[:, O[t+1]] * beta[t+1]
xi[t] = xi[t] / (xi[t].sum() + 1e-10)
# 累积统计量
pi_acc += gamma[0]
A_acc += xi.sum(axis=0)
for t in range(T):
B_acc[:, O[t]] += gamma[t]
# 更新参数
self.pi = pi_acc / len(O_list)
self.A = A_acc / (A_acc.sum(axis=1, keepdims=True) + 1e-10)
self.B = B_acc / (B_acc.sum(axis=1, keepdims=True) + 1e-10)
print(f" Iteration {iteration+1}: log_prob = {total_log_prob:.4f}")
def demonstrate_hmm():
"""演示 HMM 算法。"""
print("=" * 60)
print("HMM 算法演示")
print("=" * 60)
np.random.seed(42)
# 创建 HMM
hmm = HMM(num_states=3, num_obs=5)
print(f"\nHMM 参数:")
print(f" 状态数: {hmm.N}")
print(f" 观测数: {hmm.M}")
# 生成观测序列
T = 20
O = np.random.randint(0, hmm.M, T)
print(f" 观测序列: {O}")
# 前向算法
alpha, log_prob = hmm.forward(O)
print(f"\n前向算法:")
print(f" 对数似然: {log_prob:.4f}")
# Viterbi 算法
path, viterbi_prob = hmm.viterbi(O)
print(f"\nViterbi 算法:")
print(f" 最优路径: {path}")
print(f" 对数概率: {viterbi_prob:.4f}")
# Baum-Welch 训练
print(f"\nBaum-Welch 训练:")
O_list = [np.random.randint(0, hmm.M, T) for _ in range(10)]
hmm.baum_welch(O_list, max_iter=10)
return hmm
if __name__ == "__main__":
demonstrate_hmm()
16.3 CTC 前向-后向算法
python
"""
CTC 前向-后向算法的完整实现。
"""
import numpy as np
def ctc_forward(log_probs, targets, blank=0):
"""CTC 前向算法。
Args:
log_probs: (T, V) 对数概率矩阵
targets: (U,) 目标序列 (已扩展,包含 blank)
blank: blank 符号的索引
Returns:
log_alpha: (T, S) 对数前向变量
log_prob: 对数概率
"""
T, V = log_probs.shape
U = len(targets)
S = 2 * U + 1 # 扩展后的序列长度
# 构建扩展序列 (插入 blank)
extended = [blank]
for t in targets:
extended.append(t)
extended.append(blank)
# 初始化对数前向变量
log_alpha = np.full((T, S), -np.inf)
# 初始条件
log_alpha[0, 0] = log_probs[0, blank]
if S > 1:
log_alpha[0, 1] = log_probs[0, targets[0]]
# 递推
for t in range(1, T):
for s in range(S):
# 从 blank 转移
if s >= 0:
log_alpha[t, s] = np.logaddexp(log_alpha[t, s],
log_alpha[t-1, s] + log_probs[t, extended[s]])
# 从同一字符转移
if s >= 1 and extended[s] != blank:
log_alpha[t, s] = np.logaddexp(log_alpha[t, s],
log_alpha[t-1, s-1] + log_probs[t, extended[s]])
# 从不同字符转移
if s >= 2 and extended[s] != extended[s-2]:
log_alpha[t, s] = np.logaddexp(log_alpha[t, s],
log_alpha[t-1, s-2] + log_probs[t, extended[s]])
# 终止
log_prob = np.logaddexp(log_alpha[T-1, S-1], log_alpha[T-1, S-2])
return log_alpha, log_prob
def ctc_backward(log_probs, targets, blank=0):
"""CTC 后向算法。"""
T, V = log_probs.shape
U = len(targets)
S = 2 * U + 1
extended = [blank]
for t in targets:
extended.append(t)
extended.append(blank)
log_beta = np.full((T, S), -np.inf)
# 初始条件
log_beta[T-1, S-1] = 0
if S > 1:
log_beta[T-1, S-2] = 0
# 递推
for t in range(T-2, -1, -1):
for s in range(S):
if s < S:
log_beta[t, s] = np.logaddexp(log_beta[t, s],
log_beta[t+1, s] + log_probs[t+1, extended[s]])
if s+1 < S and extended[s+1] != blank:
log_beta[t, s] = np.logaddexp(log_beta[t, s],
log_beta[t+1, s+1] + log_probs[t+1, extended[s+1]])
if s+2 < S and extended[s+2] != extended[s]:
log_beta[t, s] = np.logaddexp(log_beta[t, s],
log_beta[t+1, s+2] + log_probs[t+1, extended[s+2]])
return log_beta
def demonstrate_ctc():
"""演示 CTC 算法。"""
print("=" * 60)
print("CTC 前向-后向算法演示")
print("=" * 60)
np.random.seed(42)
# 参数
T = 10 # 输入序列长度
V = 5 # 词汇表大小 (包含 blank)
blank = 0
# 生成随机对数概率
log_probs = np.random.randn(T, V)
log_probs = log_probs - np.log(np.sum(np.exp(log_probs), axis=1, keepdims=True))
# 目标序列
targets = [1, 2, 3] # 不包含 blank
print(f"\n参数:")
print(f" 输入长度: {T}")
print(f" 词汇表大小: {V}")
print(f" 目标序列: {targets}")
# 前向算法
log_alpha, log_prob = ctc_forward(log_probs, targets, blank)
print(f"\n前向算法:")
print(f" 对数概率: {log_prob:.4f}")
print(f" 前向变量形状: {log_alpha.shape}")
return log_alpha, log_prob
if __name__ == "__main__":
demonstrate_ctc()
16.4 注意力机制
python
"""
注意力机制的完整实现。
包含: 缩放点积注意力、多头注意力。
"""
import numpy as np
def scaled_dot_product_attention(Q, K, V, mask=None):
"""缩放点积注意力。
Args:
Q: (N_q, d_k) 查询矩阵
K: (N_k, d_k) 键矩阵
V: (N_k, d_v) 值矩阵
mask: (N_q, N_k) 掩码矩阵
Returns:
output: (N_q, d_v) 注意力输出
weights: (N_q, N_k) 注意力权重
"""
d_k = Q.shape[-1]
# 计算注意力分数
scores = Q @ K.T / np.sqrt(d_k)
# 应用掩码
if mask is not None:
scores = scores + mask * (-1e9)
# Softmax
exp_scores = np.exp(scores - np.max(scores, axis=-1, keepdims=True))
weights = exp_scores / np.sum(exp_scores, axis=-1, keepdims=True)
# 加权求和
output = weights @ V
return output, weights
def multi_head_attention(Q, K, V, num_heads, d_model, mask=None):
"""多头注意力。
Args:
Q: (N_q, d_model) 查询矩阵
K: (N_k, d_model) 键矩阵
V: (N_k, d_model) 值矩阵
num_heads: 注意力头数
d_model: 模型维度
mask: 掩码矩阵
Returns:
output: (N_q, d_model) 注意力输出
"""
d_k = d_model // num_heads
# 线性变换
W_Q = np.random.randn(d_model, d_model) * 0.01
W_K = np.random.randn(d_model, d_model) * 0.01
W_V = np.random.randn(d_model, d_model) * 0.01
W_O = np.random.randn(d_model, d_model) * 0.01
Q_proj = Q @ W_Q
K_proj = K @ W_K
V_proj = V @ W_V
# 分头
N_q = Q.shape[0]
N_k = K.shape[0]
Q_heads = Q_proj.reshape(N_q, num_heads, d_k).transpose(1, 0, 2)
K_heads = K_proj.reshape(N_k, num_heads, d_k).transpose(1, 0, 2)
V_heads = V_proj.reshape(N_k, num_heads, d_k).transpose(1, 0, 2)
# 每个头独立计算注意力
outputs = []
for h in range(num_heads):
out, _ = scaled_dot_product_attention(Q_heads[h], K_heads[h], V_heads[h], mask)
outputs.append(out)
# 拼接
concat = np.concatenate(outputs, axis=-1)
# 输出投影
output = concat @ W_O
return output
def demonstrate_attention():
"""演示注意力机制。"""
print("=" * 60)
print("注意力机制演示")
print("=" * 60)
np.random.seed(42)
# 参数
N_q = 5
N_k = 10
d_model = 64
num_heads = 8
# 随机输入
Q = np.random.randn(N_q, d_model)
K = np.random.randn(N_k, d_model)
V = np.random.randn(N_k, d_model)
print(f"\n参数:")
print(f" 查询长度: {N_q}")
print(f" 键/值长度: {N_k}")
print(f" 模型维度: {d_model}")
print(f" 注意力头数: {num_heads}")
# 缩放点积注意力
output, weights = scaled_dot_product_attention(Q, K, V)
print(f"\n缩放点积注意力:")
print(f" 输出形状: {output.shape}")
print(f" 注意力权重形状: {weights.shape}")
print(f" 权重行和: {np.sum(weights, axis=-1)[:3]}")
# 多头注意力
output_mha = multi_head_attention(Q, K, V, num_heads, d_model)
print(f"\n多头注意力:")
print(f" 输出形状: {output_mha.shape}")
return output, weights
if __name__ == "__main__":
demonstrate_attention()
附录
A. 数学符号表
| 符号 | 含义 | 维度 |
|---|---|---|
| O=(o1,...,oT)O = (o_1, \dots, o_T)O=(o1,...,oT) | 声学观测序列 | RT×d\mathbb{R}^{T \times d}RT×d |
| W=(w1,...,wM)W = (w_1, \dots, w_M)W=(w1,...,wM) | 词序列 | 词表 |
| Q=(q1,...,qT)Q = (q_1, \dots, q_T)Q=(q1,...,qT) | 状态序列 | 状态集 |
| π\piπ | 初始状态概率 | RN\mathbb{R}^NRN |
| AAA | 状态转移矩阵 | RN×N\mathbb{R}^{N \times N}RN×N |
| BBB | 观测概率 | 状态 × 观测 |
| αt(i)\alpha_t(i)αt(i) | 前向变量 | R\mathbb{R}R |
| βt(i)\beta_t(i)βt(i) | 后向变量 | R\mathbb{R}R |
| γt(i)\gamma_t(i)γt(i) | 状态后验 | R\mathbb{R}R |
| ξt(i,j)\xi_t(i,j)ξt(i,j) | 转移后验 | R\mathbb{R}R |
| B\mathcal{B}B | CTC 映射 | 序列 → 序列 |
| α(t,s)\alpha(t,s)α(t,s) | CTC 前向变量 | R\mathbb{R}R |
B. 关键公式速查
贝叶斯公式 :
P(W∣O)=P(O∣W)P(W)P(O)P(W|O) = \frac{P(O|W)P(W)}{P(O)}P(W∣O)=P(O)P(O∣W)P(W)
HMM 前向递推 :
αt+1(j)=∑iαt(i)aijbj(ot+1)\alpha_{t+1}(j) = \left\\sum_i \\alpha_t(i) a_{ij}\\right b_j(o_{t+1})αt+1(j)=i∑αt(i)aijbj(ot+1)
Viterbi 递推 :
δt+1(j)=maxiδt(i)aijbj(ot+1)\delta_{t+1}(j) = \max_i \\delta_t(i) a_{ij} b_j(o_{t+1})δt+1(j)=imaxδt(i)aijbj(ot+1)
Baum-Welch 更新 :
a^ij=∑tξt(i,j)∑tγt(i)\hat{a}_{ij} = \frac{\sum_t \xi_t(i,j)}{\sum_t \gamma_t(i)}a^ij=∑tγt(i)∑tξt(i,j)
CTC 概率 :
P(Y∣X)=∑π∈B−1(Y)∏tP(πt∣xt)P(Y|X) = \sum_{\pi \in \mathcal{B}^{-1}(Y)} \prod_t P(\pi_t | x_t)P(Y∣X)=π∈B−1(Y)∑t∏P(πt∣xt)
注意力 :
Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dk QKT)V
MFCC :
cn=∑mSmcos(πn(m+0.5)M)cn = \sum_m Sm \cos\left(\frac{\pi n(m+0.5)}{M}\right)cn=m∑Smcos(Mπn(m+0.5))
Mel 尺度 :
mel(f)=2595log10(1+f/700)\text{mel}(f) = 2595 \log_{10}(1 + f/700)mel(f)=2595log10(1+f/700)
C. 参考文献
-
Rabiner, L. R. (1989). A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition. Proceedings of the IEEE.
-
Graves, A., Fernández, S., Gomez, F., & Schmidhuber, J. (2006). Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks. ICML 2006.
-
Chan, W., Jaitly, N., Le, Q., & Vinyals, O. (2016). Listen, Attend and Spell. ICASSP 2016.
-
Graves, A. (2012). Sequence Transduction with Recurrent Neural Networks. ICML Workshop.
-
Gulati, A., et al. (2020). Conformer: Convolution-augmented Transformer for Speech Recognition. Interspeech 2020.
-
Baevski, A., et al. (2020). Wav2Vec 2.0: A Framework for Self-Supervised Learning of Speech Representations. NeurIPS 2020.
-
Radford, A., et al. (2023). Robust Speech Recognition via Large-Scale Weak Supervision. ICML 2023. (Whisper)
-
Gu, A., Goel, K., & Ré, C. (2022). Efficiently Modeling Long Sequences with Structured State Spaces. ICLR 2022. (S4)
-
Gu, A., & Dao, T. (2023). Mamba: Linear-Time Sequence Modeling with Selective State Spaces. arXiv:2312.00752.
-
Jelinek, F. (1997). Statistical Methods for Speech Recognition. MIT Press.
本文涵盖了语音识别从声学建模到端到端模型的完整理论体系,特别强调了 HMM、CTC、注意力机制和 SSM 的数学理论。