Zipformer 面试复习教程
为什么 Zipformer 要做多尺度?不同 Stack 到底改变了什么?Downsample / Upsample 为什么不会把信息直接“压没”?Block 为什么比 Conformer 更复杂?Attention 为什么可以复用?CTC / RNN-T / Pruned RNN-T 在哪里接入?Streaming 时真正缓存的是什么?
1. 核心概念
1.1 Zipformer 是什么
Zipformer 是一个面向语音识别的高效 Encoder 架构,最核心的变化可以概括成一句话:
不要让整个语音 Encoder 始终在同一个时间分辨率上计算。
Conformer 通常经过前端 subsampling 后,在整个 Encoder 中保持相对固定的时间分辨率;Zipformer 则采用类似 U-Net 的多尺度结构,让不同 Encoder Stack 在不同时间分辨率上建模。
原始 Zipformer 论文中的典型结构是:
输入声学特征 100 Hz │ │ Conv-Embed ↓ 50 Hz │ ├── Stack 1 : 50 Hz │ ↓ ├── Stack 2 : 25 Hz │ ↓ ├── Stack 3 : 12.5 Hz │ ↓ ├── Stack 4 : 6.25 Hz │ ↓ ├── Stack 5 : 12.5 Hz │ ↓ └── Stack 6 : 25 Hz │ ↓ Output 25 Hz原论文明确把这种结构称为 U-Net-like encoder,并指出中间 Stack 工作在更低的 frame rate;同时不同 Stack 可以使用不同 embedding dimension,中间 Stack 通常采用更大的维度。
因此 Zipformer 真正重要的不是某几个特殊模块,而是三个思想:
- Temporal Multi-Scale:不同 Stack 使用不同时间分辨率。
- Efficient Block:一次计算 Attention Weights,供多个模块复用。
- Residual / Bypass-based Information Preservation:多尺度压缩后仍通过上采样和可学习融合保留原始高分辨率信息。
1.2 先把 Tensor 维度彻底分清楚
ASR Encoder 中最重要的一个抽象通常是:
X∈RB×T×D X \in \mathbb{R}^{B \times T \times D}X∈RB×T×D
其中:
- BBB:batch size
- TTT:时间帧数量,也就是 sequence length
- DDD:每一帧的 feature / embedding dimension
例如:
X.shape = [B, T, D] = [16, 250, 384]意味着:
16 个 utterance 每个 utterance 有 250 个时间位置 每个时间位置对应 384 维表示这里一定要建立一个非常牢固的认识:
T 是“有多少帧”,D 是“每一帧有多少个特征通道”。
它们不是同一个概念。
例如:
t1 → [d1 d2 d3 ... d384] t2 → [d1 d2 d3 ... d384] t3 → [d1 d2 d3 ... d384]可以把它理解成:
时间轴 t1 t2 t3 ... tT 每个时间点 │ └── 一个 D 维向量因此 Zipformer 中:
Downsample主要改变的是:
T ↓而:
Feature Projection / convert_num_channels主要改变的是:
D这两个维度必须在脑子里分开。
2. 为什么需要 Zipformer
2.1 Conformer 的问题不是“效果不好”,而是计算预算没有被合理分配
Conformer 最大的优势是:
- Self-Attention 建模全局依赖
- Convolution 建模局部模式
因此非常适合 ASR。
但语音存在一个特殊事实:
不同层、不同阶段并不一定需要同样密集的时间采样。
例如:
50 Hz: | | | | | | | | | | | | | | | |这种高时间分辨率适合:
- 较细粒度的声学变化
- 音素边界
- 短时局部变化
但是到了 Encoder 的中间层,模型更关心:
- 更长时间范围的上下文
- 音节、词、短语级关系
- 更稳定的语义表示
那么继续对每一个细粒度时间位置做完整 Self-Attention,会产生大量重复计算。
2.2 Self-Attention 最大的问题是时间复杂度随 T 二次增长
Self-Attention 的核心是:
Q=XWQ,K=XWK,V=XWV Q=XW_Q,\quad K=XW_K,\quad V=XW_VQ=XWQ,K=XWK,V=XWV
然后:
A=Softmax(QK⊤dk) A=\operatorname{Softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)A=Softmax(dkQK⊤)
其中:
QK⊤∈RT×T QK^\top \in \mathbb{R}^{T \times T}QK⊤∈RT×T
所以 Attention Score Matrix 的规模直接与T2T^2T2相关。
可以粗略理解为:
Attention Cost∼O(T2D) \text{Attention Cost} \sim O(T^2D)Attention Cost∼O(T2D)
因此如果把时间长度降低一半:
T→T2 T \rightarrow \frac{T}{2}T→2T
那么 Attention 的主要二次项大约变成:
T2→T24 T^2 \rightarrow \frac{T^2}{4}T2→4T2
也就是说:
时间长度减半,不是只省一半计算,而是 Attention 的二次项大约省到四分之一。
这就是 Zipformer 为什么要 aggressively downsample 中间 Stack。
3. Zipformer 的整体结构
3.1 从输入一路追踪 Tensor
假设输入是 100 Hz 的声学特征:
X0∈RB×T×80 X_0 \in \mathbb{R}^{B \times T \times 80}X0∈RB×T×80
例如:
16 kHz audio ↓ 80-dim fbank ↓ [B, 1000, 80]经过前端 Conv-Embed 后,原论文典型设计把时间分辨率降低一半:
100 Hz ↓ 50 Hz也就是:
[B, 1000, 80] ↓ [B, 500, D1]原始论文明确说明 Conv-Embed 将 100Hz 降到 50Hz。
之后进入多个 Stack:
T ↓ Stack 1 50 Hz 500 Stack 2 25 Hz 250 Stack 3 12.5 Hz 125 Stack 4 6.25 Hz 63 Stack 5 12.5 Hz 125 Stack 6 25 Hz 250注意这里还有第二个变化:
T 在变化 D 也可以变化所以更准确地看是:
Stack 1: [B, 500, D1] Stack 2: [B, 250, D2] Stack 3: [B, 125, D3] Stack 4: [B, 63, D4] ...其中 Zipformer 的设计倾向于:
越到中间 T 越小 D 越大这并不是巧合。
3.2 为什么 T 越小,D 反而可以更大?
这是 Zipformer 非常值得面试时讲出来的设计思想。
假设两个 Stack:
Stack A: T = 500 D = 384 Stack B: T = 125 D = 768Stack B 的时间位置只有四分之一。
所以虽然每个位置的表示更宽,但是整个 Tensor 中元素数量:
Stack A:
500×384=192000 500 \times 384 = 192000500×384=192000
Stack B:
125×768=96000 125 \times 768 = 96000125×768=96000
实际上只有原来的一半。
更关键的是 Attention:
Stack A:
O(5002×384) O(500^2 \times 384)O(5002×384)
Stack B:
O(1252×768) O(125^2 \times 768)O(1252×768)
即使 D 增大,T 的平方下降仍然带来了巨大收益。
所以 Zipformer 的核心设计逻辑可以概括成:
把计算预算从“时间长度”重新分配到“特征表达能力”。
也就是:
高时间分辨率 ↓ 少一点 feature depth 低时间分辨率 ↓ 多一点 feature depth这也是为什么原论文指出不同 Stack 使用不同 embedding dimension,而中间 Stack 使用更大的维度。
4. Multi-Scale 到底是怎么工作的
4.1 Downsampling 不是简单x[:, ::2]
这是一个非常容易产生错误理解的地方。
最简单的下采样当然可以:
x=x[:,::2]但这样实际上只是:
丢掉一半帧例如:
x1 x2 x3 x4 x5 x6 ↓ ↓ ↓ x1 x3 x5信息损失会比较直接。
Zipformer 的设计不是简单丢帧,而是对多个时间位置做一个可学习聚合。
4.2 最基本的 Attention Downsample
以ds=2ds=2ds=2为例:
x1 x2 → y1 x3 x4 → y2 x5 x6 → y3最简单的思想是:
yi=a1x2i+a2x2i+1 y_i=a_1x_{2i}+a_2x_{2i+1}yi=a1x2i+a2x2i+1
并且:
a1+a2=1 a_1+a_2=1a1+a2=1
通常可以通过 softmax 让权重满足:
[a1,a2]=Softmax(q) [a_1,a_2]=\operatorname{Softmax}(q)[a1,a2]=Softmax(q)
这样模型就不是机械平均,而是在训练过程中学习:
前一个时间位置重要? 后一个时间位置重要?原始论文把它描述为:例如 downsample factor 为 2 时,通过两个可学习 scalar weight 对相邻两帧做加权聚合;之后在低时间分辨率上进行 Zipformer block 建模。
4.3 Downsample 的本质
假设输入:
X∈RT×Din X \in \mathbb{R}^{T \times D_{in}}X∈RT×Din
经过 factorsss的 Downsample 后:
Xd∈R⌈T/s⌉×Dout X_d \in \mathbb{R}^{\lceil T/s\rceil \times D_{out}}Xd∈R⌈T/s⌉×Dout
所以它完成两件事情:
时间维: T → T / s 特征维: Din → Dout因此 Downsample 可以同时改变:
Temporal Resolution + Feature Dimension这两个变化完全是独立的。
5. Upsampling 为什么存在
Downsample 后:
T = 500变成:
T = 250Encoder 在 250 个时间位置上进行了大量计算。
但是下一层或者最终输出可能仍然需要对应到:
T = 500因此必须把低分辨率结果重新对齐到高分辨率时间轴。
最简单的 Upsample 是:
y1 → y1 y1 y2 → y2 y2 y3 → y3 y3也就是:
Xu[2i]=Xd[i],Xu[2i+1]=Xd[i] X_u[2i]=X_d[i],\quad X_u[2i+1]=X_d[i]Xu[2i]=Xd[i],Xu[2i+1]=Xd[i]
这看起来很“粗糙”,但这里有一个关键认识:
Upsample 的目的不是恢复被 Downsample 丢掉的原始信息。
因为如果真的做了信息压缩:
x1 x2 ↓ y单凭一个yyy,理论上就不可能完全恢复x1,x2x_1,x_2x1,x2。
所以 Zipformer 的 Upsample 主要任务是:
把低时间分辨率表示重新扩展到高分辨率坐标系,然后和高分辨率信息做融合。
这也是 Bypass 存在的原因。
6. Bypass / Residual:Zipformer 为什么敢大胆下采样
假设 Stack 输入:
x_orig经过:
Downsample ↓ Zipformer Blocks ↓ Upsample ↓ x_low如果直接:
output = x_low那么原始高分辨率信息会被大量压缩。
Zipformer 采用 Bypass 把两者融合:
y=(1−c)⊙x+c⊙z y=(1-c)\odot x+c\odot zy=(1−c)⊙x+c⊙z
其中:
- xxx:Stack 输入
- zzz:经过 Downsample → Encoder → Upsample 的结果
- ccc:可学习的 channel-wise scalar
- ⊙\odot⊙:element-wise multiplication
原论文明确给出了这个形式,并指出 Bypass 会学习每个 channel 应该保留多少原始输入、注入多少新表示。
直观理解:
原始高分辨率信息 ──────┐ ├── Bypass → output 低分辨率深层信息 → Upsample ─┘于是一个 Stack 并不是:
“把高分辨率信息压缩掉,再恢复回来。”
而是:
“在低分辨率上做一套便宜而深的计算,同时保留原来的高分辨率路径。”
这个区别非常重要。
7. Cross-Scale Representation:不同尺度之间如何交流
Zipformer 的多尺度不是几个完全独立的 Encoder。
整体关系更接近:
High Resolution │ ↓ Stack 1 │ ↓ Downsample │ ↓ Stack 2 │ ↓ Downsample │ ↓ Stack 3 │ ↓ ... │ ↑ Upsample │ ↑ Stack 5 │ ↑ Stack 6所以一个 Stack 在低分辨率上学到的信息,会继续传入后续 Stack。
同时每一个 downsampled stack 又通过 Bypass 保留自己的高分辨率输入。
因此信息实际上有两条路径:
高分辨率路径 ─────────────────────────────────────→ 低分辨率路径 ↓ ↓ ↓ ↑ ↑ ↑这就是所谓的:
Multi-Scale Representation
而不是简单的:
多个不同采样率的模型并排运行。
8. Feature Dimension 的变化
这一部分和前面的 Temporal Resolution 必须分开理解。
8.1 D 代表什么
在:
X∈RB×T×D X \in \mathbb{R}^{B \times T \times D}X