论文解读:CTC,端到端序列识别的开山之作

论文:Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks(Graves et al., ICML 2006)· PDF:cs.toronto.edu/~graves/icml_2006.pdf

一句话导读:这篇发明了 blank token 和"路径积分求和"两个核心动作,第一次让 RNN 不依赖 HMM、也不需要人工帧级对齐,就能直接从"帧数远大于标签数"的语音/手写数据端到端训出一个序列识别器。之后 20 年所有端到端 ASR 系统里,只要出现"CTC 头 / CTC loss"这两个字,血脉都能追到这一篇。

一、先被这个问题卡住

想象一段 10 秒的语音,采样成 1000 帧(每 10ms 一帧,直觉例子、非 TIMIT 实配)。你要输出的目标是 "the sound of" 这三个词------TIMIT 音素级标注下大约是 dh ax s aw n dcl d ix v 这一串 phone(跟稍后 Figure 1 展示的一致)。

现在训一个 RNN ------每一帧吐一个音素类别的概率分布。也就是 输入、 帧级概率表,但目标只有 9 个 phone。

问题一眼看出 :标准交叉熵需要帧级标签,但原始标注只给整段音频的 9 个音素,从来没告诉你第 137 帧对应哪个音素。要怎么算 loss?

2006 年之前的两条主流路:

  • 纯 HMM 派:HMM 自身可以用 forward-backward / Baum-Welch 处理未对齐序列,训练目标是所有对齐路径概率的和;生成式训练目标跟判别式识别任务不完全对齐。
  • RNN-HMM hybrid :RNN 只做局部帧分类,靠 HMM 提供的 Viterbi forced alignment 或状态后验作为帧级伪标签训练。伪对齐不可直接检验,pipeline 依赖这个中间假设。

问题的根每一帧的答案是个假问题------真实标注只声明输入和输出的对应关系,从来没规定"137 帧对应哪个音素"。CTC 的破题:承认它是假问题,把未知对齐从监督目标里挤出去。

二、CTC 的三个脑洞

脑洞 1:给模型一个"闭嘴"按钮

在原本的 个真实 label 之外,多加一个特殊符号 -(blank)。RNN 输出层从 维扩到 维,多出的那个维度就是"这一帧我什么也不想说"的概率。blank 有明确的结构作用(下一节展开)。

脑洞 2:Collapse 规则------路径压缩回 label 序列

一段长度 路径(每帧一个 label,可含 blank 和重复)通过两步压缩,得到最终 label 序列:

  1. 先合并连续相同的符号(下表按"合并非 blank"展示,便于看清重复 label 的差异;连续 blank 合不合都行,反正下一步都删)
  2. 再删掉所有 blank

举几个具体例子看清楚(都以 、label 表 为例):

路径(长度 5) 步骤 1(合并连续相同) 步骤 2(删 blank) 最终 label
- A A - B - A - B A B AB
A A - - B A - - B A B AB
- - A B B - - A B A B AB
A - A - - A - A - - A A AA
A A A - - A - - A A

关键洞察 :blank 的深层作用是让模型能区分 AA(两个 A)和 A(一个 A 出现在多帧)

如果没有 blank,AA 这条路径合并连续相同后变成 A------两个 A 无法区分。加了 blank 就能:想输出 AA 的路径,两组 A 之间必须至少隔一个 blank ------A-AA--AAA-AA 都合法;想输出 A 的路径可以是 AAA--AAAA 等。blank 同时承担两个作用:分隔相邻重复 label,并允许模型在无明确输出的帧保持沉默。

脑洞 3:不选一条对齐,把所有对齐加起来

同一个目标 label 序列 AB 对应很多种 长度 的路径------上面表格里前三行都能 collapse 成 AB。实际上 、target AB 的合法路径还有 A-B---AB--AAAB-A--BB

CTC 思路:不选一条对齐 。把所有能 collapse 成 AB 的路径 的概率加起来 当训练目标------训练最大化这个总和的 log likelihood,本质是把未知对齐当隐变量边缘化掉。问题被重构:未知对齐从训练目标里挤出去,变成一个不需要被回答的隐变量。

图 1 是上述三个脑洞训出来的模型在真实语音上的实际输出 。上半的 Framewise :每一帧都要给音素并贴合人工切分边界(竖线)。下半的 CTC:多数帧 blank 概率很高(横轴基线附近的空白区域),只在某几帧局部形成非 blank 的窄峰。读 CTC 输出的方式就是"顺着窄峰读一遍音素,跳过 blank",不需要任何 forced alignment 后处理。

三、三条主线公式

三个脑洞对应到公式只有三行。

路径概率------给定整段输入和 RNN 输出后,把一条路径的概率按时间步做乘积分解(帧间依赖由 RNN hidden state 隐式承载,CTC 头本身不显式建模 label 历史):

其中 是一条长度 的路径, 是 RNN 在第 帧对 label 的输出概率。

Collapse 映射 :就是上面表格里的两步压缩规则。

目标 label 序列的概率(边缘化对齐):

训练目标:最大化 。后面的 forward-backward、梯度和解码,都是为高效计算这三个量服务。

四、求和爆炸怎么办:DP 在网格上跑

问题:暴力枚举所有长度 的扩展字母表路径是 ;即使只看能 collapse 到目标的合法路径,数量也组合爆炸,不可枚举。

解法:动态规划。跟 HMM 的 forward-backward 一样------把"所有路径概率之和"分解成"到达每个中间状态的部分和",从左往右递推。

具体做法:先把目标 扩成 ------在首尾和每对 label 之间插一个 blank。比如 扩成 (长度 )。然后在一个"时间 × 扩展序列位置 "的二维网格上跑递推。每格存 ------到第 帧、已经走到扩展序列 位的所有路径概率之和

允许的转移 :从 有三种候选:

  • 停留
  • 走一格
  • 跳两格)------仅当 是非 blank 且 时允许

第三条的约束是关键:如果两格前是同一个真实 label,跳过中间的 blank 就会让 collapse 时被合并成一个。blank 在这里就是保证 collapse 后长度不缩水的守门员

图 C 用 target = AAB 专门展示相邻重复 label 时的禁跳约束;原论文 Figure 3 的 CAT 例子里没有这种情形。

一句话概括 :DP 让"对所有路径求和"从 降到 ,从纯数学变成可以在 GPU 上跑起来的东西。

完整的 递推、rescaling 和梯度推导见原论文 §4.1-4.2;这里把 DP 理解成"精确路径求和的高效算法"就够。

五、解码:怎么把训好的模型的输出读成 label 序列

解码有两个思路。

Best path decoding (最简单):每一帧独立取 argmax,得到一条路径 ,然后 就是输出。

  • 优点:一次前向就搞定,几乎没额外开销。
  • 缺点:不保证得到最优 label 序列 ------最优 label 序列对应的可能是"多条路径概率的和"都很高,而不是任何单一路径概率最高。

为什么会不最优? 举个 3 帧、label 表 的玩具例子。假设某个 CTC 网络在这 3 帧的输出概率是:

P(-) P(A) P(B)
t=1 0.4 0.3 0.3
t=2 0.4 0.3 0.3
t=3 0.4 0.3 0.3

Best path 每帧都取 -(各 0.4),拼出 - - - → collapse 得到空串 (概率 0.064)。但 AB 的合法路径 AB-A-B-ABABBAAB 每条概率 ,加起来大于 0.064 ------所以 best path 给出的空串不一定是最优。这个例子只说明 best path 可能漏掉由多条低概率路径累加出的高概率 label;全局最优要靠 prefix search 找。

Prefix search decoding(更严谨):借用 forward-backward 递推,按 label 序列 prefix 的概率一步步扩展搜索树。

图 2 是一个玩具例子:label 表 ,根节点是空 prefix 不是 blank ------图里画成 -,这里 - 表示"空前缀"而非 blank token)。每个节点要么继续扩展一个 label(分支节点),要么终止(标 'e')。分支节点上方数字是 prefix 概率 ------以该 prefix 开头的所有 完整 label 序列的概率总和(因此是任一具体完成序列概率的上界);终止节点上方是终止概率 ------恰好停在此 prefix 的确切概率。停止条件:某完整答案的确切概率超过所有剩余 prefix 的上界。每次挑当前概率最高的活跃 prefix 扩展。

  • 优点:理论上给足时间能找到最优 label 序列。
  • 缺点:最坏复杂度指数------本文用了一个启发式(在 blank 概率 >99.99% 处切段、每段独立跑 prefix search)来控制搜索范围。

训好的 CTC 往往呈现 peaked 输出------多数帧概率质量集中在 blank,非 blank label 只在少数几帧形成尖锐窄峰。这意味着 best-path 和 prefix-search 在本文实验里差得不多(TIMIT 上 31.47 vs 30.51,不到 1 个点)。

图 4 展示了 peaked 输出是怎么涌现出来的: - (a) 初期:概率接近 baseline,误差信号铺满时间轴 - (b) 中期:label 概率向少数帧集中,误差信号也聚焦到对应位置 - (c) 收敛:真实 label 集中在窄峰、其余强 blank,误差信号趋近于零

spike 是 CTC 训练动力学涌现出来的,不是显式对齐监督------用于近似对齐可以,不能当严格 forced alignment。副产物用途:解码简单、边界隐式对齐;本文的 BLSTM 天然能看未来帧,不是流式,现代流式 CTC 部署要配合因果或 chunk encoder + 延迟控制。

六、实验与批判性观察

任务:TIMIT 音素识别。61 个音素类,训练集 4620 utt / 测试集 1680 utt,指标是 LER(编辑距离归一化)。

特征:10ms 帧、5ms 滑窗;MFCC 12 维 + log-energy + 一阶差分,共 26 维。

关键 baseline 和结果

系统 LER
Context-independent HMM 38.85%
Context-dependent HMM 35.21%
BLSTM/HMM 33.84 ± 0.06%
Weighted-error BLSTM/HMM 31.57 ± 0.06%
CTC (best path) 31.47 ± 0.21%
CTC (prefix search) 30.51 ± 0.19%

观察

  • 网络容量对齐:CTC 和 BLSTM/HMM hybrid 用了几乎相同规模的 BLSTM(114,662 vs 114,461 参数)。容量对齐较克制,但不是严格消融------训练目标、对齐机制、学习率和噪声水平都不同。
  • HMM baseline 参数量大得多 (90 万+),但依然输给 11 万参数的 CTC------至少在这套 recipe 下,堆 HMM/GMM 参数并没有弥合训练目标和对齐机制带来的差距。
  • Prefix search 加成很小(31.47 → 30.51,<1 点)------是"CTC 输出天然 peaked"的实验证据。但 TIMIT 是音素级、无 LM、小任务,不能外推到词/子词级工业 ASR;是否用 beam search / LM 取决于任务和延迟预算。
  • 消融留白:几个我关心但论文没做的实验------(a) blank 单元的必要性(去掉 blank 后 collapse 会失效:无法区分相邻重复 label,且每帧被迫输出一个真实 label);(b) DP 求和 vs 蒙特卡洛路径采样的对比;(c) 只跑了 TIMIT,没在更大数据上验证 scale up 行为------最后这条被后续 10 年反复证明"CTC 确实能 scale",但 2006 年这篇没做。

七、局限与分析

Blank 是问题重构的胜利 ,不是数学工作------把"未知对齐"改写成 DP 可边缘化的隐变量。这套思路后来在 RNN-T / Transformer-Transducer 里被继续用。(注意别把 Whisper 的 timestamp token 也归到"blank 家族"------Whisper 是 encoder-decoder attention 架构、时间戳靠特殊 token 表达,机制不同源。)

帧间条件独立是明显的 tradeoff 假设 label 给定 encoder 表征后条件独立------CTC 头不建模 label-to-label 语言依赖,全靠 encoder hidden state 隐式带上下文。encoder 强的时代(LSTM/Conformer 之后)问题不明显;encoder 弱或强语言先验场景就露馅。**RNN-T(Graves 2012)**站在这条 tradeoff 的另一侧------加了 prediction network 显式建模 label 历史,代价是解码格子从一维变二维、beam search 更贵、训练/实现都更重。CTC 与 RNN-T 像同一问题的两侧:一个轻,一个显式建模 label 历史但更贵。

spike 是 emergent,不是显式监督。CTC loss 里没有"输出要 peaked"或"对齐真实音素起点"的约束项,但训练完输出就是那样。后续实证发现窄峰位置跟真实音素起始有系统性但小幅度偏移------被下游任务反复利用(关键词检测、近似对齐、流式端点检测),但做严格 forced alignment 有精度天花板。

当代 ASR 里 CTC 是哪一支。今天端到端 ASR 大致有三个训练目标 / 解码接口,都在解决同一个"输入帧长 ≠ 输出 token 长"的问题:

家族 代表工作 对齐是否单调 是否显式建模 label 历史 典型解码 代价
CTC 家 wav2vec 2.0 微调头、Conformer-CTC 单调(blank + collapse) 否(帧间条件独立) best-path / prefix beam 语言依赖弱、需外挂 LM
Attention encoder-decoder 家 Whisper、SpeechT5 非单调(软注意力) 是(decoder 自回归) beam search 全序列注意力代价大,流式难
Transducer 家 RNN-T、Transformer-Transducer 单调(blank + 显式两轴 DP) 是(prediction network) 2D beam search 训练/解码都比 CTC 重

(另有一批非自回归模型如 Paraformer 把 CTC 用作辅助 loss------不属于纯 CTC 主路线,是混合训练策略。)

三个家族不能简单归为一脉血脉------是三种不同的技术路线选择。CTC 是三条路线里最简单、耐用、不过时的一条:loss 三行公式说完、DP 网格一张图讲透、代码 30 行能跑通------这在深度学习史上很罕见。

相关推荐
讳疾忌医丶1 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
高亦真2 小时前
今天是学习嵌入式的第37天
linux·学习·算法
罗西的思考3 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 --- (2)--- 训练
人工智能·算法·机器学习
深圳市方中禾科技5 小时前
FZH1625 LCD 驱动芯片深度评测与实战指南
算法·led
我不会起名字3225 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
huang5791477 小时前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_7 小时前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法
Elsa️7468 小时前
算法一周刷题总结
c++·算法
小小程序猴18 小时前
深圳乘路资讯AI培训怎么样?课程靠谱吗?——一套课程可信度评估模型与实证分析
人工智能·算法