DynaBERT: Dynamic BERT with Adaptive Width and Depth 解读
一、论文基本信息
论文题目:DynaBERT: Dynamic BERT with Adaptive Width and Depth
作者:Lu Hou、Zhiqi Huang、Lifeng Shang、Xin Jiang、Xiao Chen、Qun Liu
发表会议:NeurIPS 2020 Spotlight
方法简称:DynaBERT
官方代码:论文中给出了 Huawei Noah’s Ark Lab 的开源实现。论文摘要明确说明,DynaBERT 可以通过选择不同width和depth来灵活调整模型大小和推理延迟。(arXiv)
这篇论文的核心目标是:不要把 BERT 压缩成一个固定大小的小模型,而是训练一个可以按资源预算切换宽度和深度的动态 BERT。
也就是说,DynaBERT 训练完成后,可以直接抽取不同子网络,例如:
宽一些、深一些的子网络:精度更高,速度更慢。
窄一些、浅一些的子网络:速度更快,精度略低。
这样一个模型就能适配多种设备和多种资源条件。
二、论文要解决的问题
BERT、RoBERTa 这类预训练语言模型效果强,但计算和存储开销都很大。论文指出,边缘设备部署 BERT 面临两个现实问题:第一,不同设备硬件性能差异很大;第二,同一设备在不同运行状态下可用资源也会变化。
传统压缩方法通常会得到一个固定模型。例如蒸馏得到 6 层 BERT,或者剪枝得到某个固定宽度的模型。这样做的问题是:
一个固定模型只能对应一个固定计算预算。
如果设备资源充足,固定小模型无法利用更多计算换取更高精度。
如果设备资源紧张,固定模型又可能仍然太大。
所以 DynaBERT 要解决的问题是:
能不能训练一个 BERT,让它在推理时根据资源预算选择不同宽度和不同深度?
这个问题比单纯剪 head、剪 layer 更进一步。它不是只做一个方向的压缩,而是同时考虑:
宽度方向:attention heads 和 FFN 中间层神经元数量。
深度方向:Transformer layer 数量。
论文明确指出,DynaBERT 通过选择不同宽度和深度的子网络来调整模型大小和延迟,并且训练完成后,每个子网络不需要额外 fine-tuning。
三、核心思想
DynaBERT 的核心思想可以概括为:
先把 BERT 训练成宽度自适应模型,再进一步训练成宽度和深度都自适应的动态模型。
它的训练过程分成两个阶段。
第一阶段:训练DynaBERTW。
这个模型只支持adaptive width,也就是不同宽度子网络。宽度变化主要通过减少 attention heads 和 FFN 中间层神经元实现。
第二阶段:训练完整DynaBERT。
在 DynaBERTW 的基础上,再加入adaptive depth,也就是不同层数子网络。最终得到一个既能变窄、又能变浅的模型。
论文图 1 和方法部分明确说明,训练流程包括两个阶段:先训练 width-adaptive DynaBERTW,再训练 width-and-depth-adaptive DynaBERT,并通过知识蒸馏把大模型知识传给小子网络。
这里最重要的是:
DynaBERT 不是训练多个独立小模型,而是训练一个共享权重的动态 BERT。
同一个模型内部包含很多子网络,部署时只需要选一个满足资源约束的子网络运行。
四、DynaBERT 的“宽度”是什么?
在 CNN 中,宽度通常指通道数。但 BERT 是 Transformer 结构,不能简单把宽度理解为卷积通道。
论文把 BERT 的宽度拆成两个部分:
第一,Multi-Head Attention 中的 attention heads 数量。
第二,Feed-Forward Network 中间层神经元数量。
在一个 Transformer layer 中,MHA 的多个 heads 是并行计算的,FFN 中间层的神经元也可以看作并行计算单元。因此,DynaBERT 通过改变这两部分数量来控制宽度。论文明确说明,Transformer layer 的宽度可以通过改变 MHA 中 attention heads 数量和 FFN intermediate layer 中神经元数量来调整。
例如原始 BERT-base 每层有 12 个 heads,FFN 中间层维度为 3072。如果宽度倍率是 0.5,那么子网络可以只保留约一半 heads 和一半 FFN 中间神经元。
所以 DynaBERT 的 width-adaptive 本质上是:
剪 attention heads。
剪 FFN intermediate neurons。
这属于结构化压缩,因为它删除的是完整结构单元,而不是零散权重。
五、Network Rewiring:为什么要重新排列 heads 和 neurons
如果直接取前一半 heads、前一半 FFN neurons,可能会出现问题:前面的 heads 不一定比后面的 heads 重要。
所以 DynaBERT 在训练宽度自适应模型前,先做Network Rewiring。
它的做法是:
先估计每个 attention head 和 FFN neuron 的重要性。
然后把更重要的 heads 和 neurons 排到更靠前的位置。
这样,所有小宽度子网络都会优先使用最重要的结构单元。
论文明确说,Network Rewiring 的目的,是让更重要的 attention heads 和 neurons 被更多子网络共享;做法是在 fine-tuned BERT 中计算它们的重要性,并按重要性从高到低重新排列。
这一步非常关键。
因为 DynaBERT 的子网络通常是取“前若干 heads / 前若干 neurons”。如果不 rewiring,小子网络可能拿到的是随机顺序下的结构单元;如果做了 rewiring,小子网络优先拿到高重要性结构单元。
可以这样理解:
Network Rewiring 是为了让小模型先继承大模型中最有价值的部分。
六、重要性怎么计算?
DynaBERT 采用类似 Taylor pruning 的思想。
对于一个 attention head,论文估计的是:
如果移除这个 head,训练损失会变化多少。
如果移除后损失变化大,说明这个 head 重要。
如果移除后损失变化小,说明这个 head 冗余。
对于 FFN 中间层神经元,也采用类似思路:看与该神经元相关的权重被移除后,对训练损失的影响有多大。
论文说明,它使用一阶 Taylor 展开来估计 attention heads 和 neurons 的重要性,并且在开发集上计算这些重要性分数。
所以 DynaBERT 的 rewiring 不是随机重排,而是基于 loss sensitivity 的结构重要性排序。
这点和前面 head pruning 论文有明显联系:
Attention head 的重要性越高,它越应该被更多子网络共享。
七、第一阶段:训练宽度自适应 DynaBERTW
完成 rewiring 后,DynaBERT 开始训练DynaBERTW。
DynaBERTW 只支持宽度变化,不改变层数。它的训练方式是知识蒸馏。
具体来说:
Teacher:rewired 后的完整 BERT。
Student:不同宽度的 DynaBERTW 子网络。
蒸馏内容包括三部分:
输出 logits。
embedding 表示。
每一层 hidden states。
论文明确说明,在训练 DynaBERTW 时,会把 fixed teacher model 的 logits、embedding 和 hidden states 蒸馏给不同 width multiplier 的学生子网络。
这一步的作用是:
让不同宽度的子网络都模仿完整 BERT 的行为。
如果只用真实标签训练,小宽度子网络很容易性能不足;蒸馏能给小模型更丰富的监督信号。
八、为什么需要 DynaBERTW 作为中间老师?
论文没有直接从完整 BERT 一步训练到 width-depth adaptive DynaBERT,而是先训练 DynaBERTW。
原因是:完整 BERT 和很小的子网络之间能力差距太大。如果直接让小而浅的子网络模仿完整 BERT,训练难度会很高。
所以 DynaBERTW 扮演了一个teacher assistant。
它先学会宽度自适应,然后再作为第二阶段的老师,指导同时变窄和变浅的 DynaBERT。
论文明确指出,DynaBERTW 可以缩小 student 和 teacher 之间的模型规模差距;消融实验也显示,使用 DynaBERTW 作为 teacher assistant 在 SST-2、CoLA、MRPC 上都带来更好平均表现。
所以这个两阶段设计不是多余步骤,而是为了降低训练难度。
可以简单理解为:
先学会变窄,再学会又变窄又变浅。
九、第二阶段:训练宽度和深度都自适应的 DynaBERT
第二阶段开始训练完整 DynaBERT。
此时模型不仅支持不同宽度,还支持不同深度。
深度变化通过删除部分 Transformer layers 实现。论文采用类似 LayerDrop 中的Every Other策略,也就是均匀删层,让保留下来的层在整个网络深度上分布更平衡。论文明确说明,当 depth multiplier 小于 1 时,使用 Every Other 策略均匀丢层,并将学生保留层的 hidden states 与 teacher 对应层匹配。
第二阶段仍然使用知识蒸馏。
Teacher:最大深度的 DynaBERTW。
Student:不同宽度、不同深度的 DynaBERT 子网络。
蒸馏目标仍然包括:
logits。
embedding。
hidden states。
这样训练完成后,DynaBERT 就可以直接抽取很多子网络,例如:
1.0 width + 1.0 depth
0.75 width + 1.0 depth
0.5 width + 0.75 depth
0.25 width + 0.5 depth
不同子网络共享同一套权重,只是运行时选择不同结构规模。
十、DynaBERT 和 LayerDrop、US-Net、OFA 的关系
DynaBERT 和 LayerDrop 都可以调整深度,但 LayerDrop 主要解决depth adaptive,即删 layer。
DynaBERT 不只删 layer,还会同时改变 width,即删 attention heads 和 FFN neurons。
DynaBERT 和 US-Net 都支持宽度变化,但 US-Net 主要用于 CNN / MobileNet 这类视觉模型,DynaBERT 面向 BERT 的 Transformer 结构,因此宽度定义完全不同。
DynaBERT 和 OFA 都属于“一次训练,多种子网络部署”的思想。但 OFA 主要用于 CNN 架构搜索,支持 kernel size、depth、width、resolution 等;DynaBERT 则专门针对 BERT,把自适应维度设计成:
attention heads。
FFN neurons。
Transformer layers。
因此,DynaBERT 的价值在于:
把动态宽度和动态深度思想真正落到 BERT 结构上。
十一、实验设置
论文主要在GLUE benchmark和SQuAD v1.1上评估。
GLUE 包括多个自然语言理解任务,如 MNLI、QQP、QNLI、SST-2、CoLA、STS-B、MRPC、RTE 等。论文在 GLUE 开发集上报告结果:STS-B 使用 Spearman correlation,CoLA 使用 Matthews correlation,其他任务使用 accuracy;在 QQP 和 MRPC 的 test set 上报告 F1。
SQuAD v1.1 是抽取式问答任务,包含约 100k 个问答样本,评价指标是 EM 和 F1。
效率指标方面,论文不只看参数量,还比较:
#parameters。
FLOPs。
Nvidia K40 GPU latency。
Kirin 810 A76 ARM CPU latency。
论文明确说明,实验在不同效率约束下评估 DynaBERT 和 DynaRoBERTa,包括参数量、FLOPs、GPU 延迟和 ARM CPU 延迟。
这点很重要,因为 DynaBERT 不是只追求理论压缩率,而是考虑真实推理延迟。
十二、实验结果解读
12.1 GLUE:很多任务可以在变窄或变浅后保持精度
论文在 GLUE 开发集上展示了不同 width multiplier 和 depth multiplier 的结果。一个很明显的现象是,最大尺寸子网络不一定总是最好,某些任务在较小宽度或较小深度下也能达到相近甚至更好的结果。论文对此解释为:原始 BERT / RoBERTa 中存在冗余。
例如表 1 中,BERTBASE 在 CoLA 上是 58.1,而 DynaBERT 某些配置可以达到 60.8;BERTBASE 在 SST-2 上是 92.9,DynaBERT 多个配置都在 93 左右。
这个结果说明:
BERT 的宽度和深度都存在冗余,不是所有 heads、FFN neurons 和 layers 都必需。
尤其在某些分类任务上,适当缩小模型不一定会导致精度下降,甚至可能带来一定正则化效果。
12.2 宽度压缩比深度压缩更稳
论文有一个很重要的观察:
在相同压缩倍率下,压缩宽度通常比压缩深度更稳。
论文在 GLUE 结果分析中明确指出,使用某个 width multiplier 通常比使用相同的 depth multiplier 有更高准确率,这说明相比深度方向,宽度方向对压缩更鲁棒。
这很好理解。
减少宽度是减少 attention heads 和 FFN neurons,但仍然保留完整层级处理流程。
减少深度是直接删 Transformer layers,会缩短表示变换链路,对语义建模影响更大。
所以 DynaBERT 的结论是:
BERT 更容易变窄,变浅相对更敏感。
这对实际剪枝很有启发:如果要先压缩,优先考虑 heads 和 FFN neurons,可能比直接删层更安全。
12.3 SQuAD:小子网络仍然有竞争力
在 SQuAD v1.1 上,BERTBASE 的结果是81.5 EM / 88.7 F1。DynaBERT 最大子网络达到82.6 / 89.7。即使在较小配置下,例如 0.5 width + 1.0 depth,也能达到81.9 / 89.2;0.5 width + 0.75 depth 也有81.7 / 89.0。
这说明:
在问答任务中,DynaBERT 的较小子网络仍然可以保持接近 BERTBASE 的效果。
而当宽度和深度都压得很小,例如 0.25 width + 0.5 depth,性能下降到76.6 / 85.0,说明极限压缩下仍然会损失较明显精度。
这个结果比较合理:
DynaBERT 提供的是一条精度—效率曲线,而不是保证所有小模型都无损。
12.4 与 DistilBERT、TinyBERT、LayerDrop 对比
论文将 DynaBERT 与 DistilBERT、TinyBERT、LayerDrop 等方法比较。需要注意的是,DistilBERT 和 TinyBERT 的每个大小通常对应一个独立模型,而 DynaBERT 的不同点来自同一个模型中的不同子网络。论文也特别指出,TinyBERT 和 DistilBERT 的不同结果来自不同模型,而 DynaBERT / DynaRoBERTa 的不同结果来自一个模型内部的不同子网络。
这点是 DynaBERT 的核心优势:
不是为每个资源预算训练一个模型,而是一个模型覆盖多个预算。
论文在 SQuAD 上也指出,在相同参数量和 FLOPs 下,DynaBERT 子网络明显优于 TinyBERT 和 DistilBERT。
十三、消融实验说明了什么
论文做了比较完整的消融。
13.1 Network Rewiring 很重要
在训练 DynaBERTW 时,vanilla DynaBERTW 平均准确率为 79.0;加入 Network Rewiring 后提升到 81.4;再加入蒸馏和数据增强后提升到 82.9。
这说明:
把重要 heads 和 neurons 放在前面,让它们被更多子网络共享,是有效的。
这一步对小宽度子网络尤其重要。
13.2 知识蒸馏和数据增强很重要
同样在 DynaBERTW 消融中,加入 distillation 和 data augmentation 后,平均性能进一步提升 1.5 个点左右。
这说明:
小子网络需要从大模型中学习更丰富的中间表示,而不只是学习 hard label。
数据增强也能给蒸馏提供更多任务相关样本,使子网络学得更稳。
13.3 两阶段训练比直接训练更好
论文还比较了是否使用 DynaBERTW 作为 teacher assistant。结果显示,使用 DynaBERTW 的 DynaBERT 在 SST-2、CoLA、MRPC 上平均都更好。
这说明:
先训练宽度自适应模型,再训练宽度和深度都自适应的模型,比一步到位更稳定。
十四、方法优点
14.1 一个模型支持多种资源预算
DynaBERT 最大优点是:
只训练一个模型,就能得到很多不同大小、不同延迟的子网络。
这对部署非常有用。不同设备可以选择不同子网络,同一设备资源状态变化时也可以切换到更小或更大的子网络。
14.2 同时支持宽度和深度
很多方法只支持删层,或者只剪 heads。
DynaBERT 同时支持:
减少 attention heads。
减少 FFN neurons。
减少 Transformer layers。
因此它的结构选择空间比单一深度压缩更丰富。
14.3 Network Rewiring 让小子网络更强
通过重要性排序,DynaBERT 让高重要性 heads 和 neurons 被所有小子网络优先使用。
这比随机截取宽度更合理。
14.4 蒸馏目标比较完整
DynaBERT 不只蒸馏最终 logits,还蒸馏 embedding 和 hidden states。
这让小子网络不仅学最终预测,也学习中间表示。
14.5 考虑真实延迟
论文同时报告参数量、FLOPs、GPU latency 和 ARM CPU latency。
这使它比只看参数量或 FLOPs 的压缩方法更接近实际部署需求。
十五、方法局限
15.1 训练流程比较复杂
DynaBERT 不是简单剪枝。
它需要:
fine-tuned teacher。
importance estimation。
network rewiring。
DynaBERTW 训练。
DynaBERT 训练。
知识蒸馏。
数据增强。
可能还需要 final fine-tuning。
这使得复现和迁移到新任务的成本较高。
15.2 主要是任务级压缩,不是预训练阶段通用压缩
论文中强调,如果没有特别说明,文中的 BERT 指的是task-specific BERT,也就是已经针对下游任务 fine-tuned 的模型。
这意味着 DynaBERT 通常需要针对每个下游任务单独训练动态模型。
如果要得到一个通用的预训练动态 BERT,再适配所有任务,原论文并没有完全解决。
15.3 子网络选择不是输入自适应
DynaBERT 的“dynamic”主要指根据资源预算选择不同 width/depth 子网络。
它不是根据每个输入句子的难度动态选择子网络。
也就是说,它是:
resource-adaptive。
不是:
input-adaptive。
如果希望简单样本走小模型、困难样本走大模型,还需要额外的输入难度判断或早退机制。
15.4 子网络是前缀式结构
宽度压缩时,DynaBERT 保留前若干 heads 和前若干 FFN neurons。因此必须依赖 rewiring,把重要单元排到前面。
这种方式简单,但也有局限:
它不能为每个子网络自由选择任意 head 组合或 neuron 组合。
15.5 只压缩部分结构
DynaBERT 压缩 MHA heads、FFN intermediate neurons 和 Transformer layers,但 embedding hidden size 不变。论文也说明,embedding dimension 上的 neurons 因为通过 skip connections 跨层连接,不能灵活缩放。
所以它不是对 BERT 所有维度都完全弹性。
十六、整体评价
DynaBERT 的核心价值在于,它把 BERT 压缩从“一个预算训练一个小模型”推进到“一个模型支持多个宽度和深度”。
它不是单纯 head pruning,也不是单纯 layer pruning,而是把二者结合起来,同时考虑 FFN 中间层神经元压缩。
这篇论文真正重要的地方有三点:
第一,它定义了 BERT 的宽度弹性:attention heads + FFN intermediate neurons。
第二,它通过 Network Rewiring 让重要结构单元被更多小子网络共享。
第三,它用两阶段蒸馏训练,让一个模型能够支持多个 width-depth 子网络。
从实验结果看,DynaBERT 的很多子网络在 GLUE 和 SQuAD 上都能保持较强性能;在相同参数量、FLOPs 或延迟约束下,也常常优于固定大小的 BERT 压缩方法。
因此,DynaBERT 的定位可以概括为:
面向部署预算变化的动态 BERT。
它的目标不是一次性得到最小模型,而是提供一组可以按需选择的高效子网络。
十七、一句话总结
《DynaBERT: Dynamic BERT with Adaptive Width and Depth》提出一种可同时调节宽度和深度的动态 BERT:宽度通过减少 attention heads 和 FFN 中间层神经元实现,深度通过减少 Transformer layers 实现;方法先训练宽度自适应 DynaBERTW,再训练宽度和深度都自适应的 DynaBERT,并通过 Network Rewiring 与知识蒸馏让重要结构单元被更多子网络共享,从而实现一个模型覆盖多种参数量、FLOPs 和延迟预算。
