DynamicViT动态Token剪枝:视觉Transformer推理加速实战

发布时间:2026/10/19 17:50:54
DynamicViT动态Token剪枝:视觉Transformer推理加速实战 1. 从一次模型压缩的翻车现场说起去年帮一个做移动端图像识别的团队做模型瘦身他们的场景很典型一个在服务器上跑得好好的视觉模型精度能到 82% 左右但一往端侧搬就崩了——推理一次要 300 多毫秒内存峰值直接顶到 1.2GB低端设备根本扛不住。团队第一反应是砍输入分辨率从 224 砍到 160精度掉了 4 个点又试了剪枝把通道数砍掉三成精度再掉 3 个点。两刀下去模型是轻了但业务方直接不干了因为识别准确率掉到 75% 以下误识别率飙升。这个场景其实特别有代表性。视觉模型的计算量分布有个很反直觉的特点大部分算力并不是花在真正需要精细判断的区域上而是均匀地铺满整张图。一张 224×224 的图切成的 patch 里可能只有 30% 到 40% 是真正有信息量的目标区域剩下的大片背景、纯色块、天空、墙面模型照样一视同仁地给它们算注意力、过 MLP。这就是典型的算力浪费。DynamicViT 这个工作本质上就是冲着这个浪费去的。它的核心思路一句话能说清在推理过程中动态判断哪些 token 是冗余的然后把它们丢掉只让真正重要的 token 继续往后走。而且它的野心不止于能丢而是丢得几乎不掉点——标题里那句几乎不降低模型性能的情况下较大地减少计算量和参数量说的就是这件事。这篇文章我不打算复述论文而是从工程落地的角度把 DynamicViT 这套机制拆开讲透它到底怎么判断 token 该不该丢、训练时怎么让模型学会丢、实际部署时能省多少、以及我在复现和改造过程中踩过的那些坑。如果你正在做视觉模型的端侧部署、推理加速或者单纯想理解动态计算这类思路怎么落地这篇应该能给你一些能直接抄的东西。2. Token 冗余这件事到底冗余在哪2.1 视觉 Transformer 的算力账本要理解 DynamicViT 为什么有效得先把 Vision TransformerViT的算力账算清楚。ViT 把一张图切成固定大小的 patch比如 16×16一张 224×224 的图就是 14×14196 个 patch每个 patch 拉平后过一个线性层变成 token再加上一个分类 token总共 197 个 token 进入 Transformer 编码器。Transformer 编码器里最吃算力的是两块多头自注意力MHSA和 MLP。自注意力的计算复杂度是 token 数量的平方级——197 个 token 就是 197×197 的注意力矩阵每个头都要算一遍。MLP 则是线性级但它的隐藏维度通常是嵌入维度的 4 倍所以参数量和计算量都不小。关键点来了这 196 个图像 token 里真正携带判别信息的往往只占一小部分。一张猫的图片猫本身可能只占画面中间 40% 的区域剩下的背景、草地、天空对这是不是猫这个判断贡献极小。但标准 ViT 不管这些它给每个 token 同样的计算预算从头算到尾。我做过一个简单的统计实验在一个训练好的 ViT-Base 上把最后一层每个图像 token 的注意力权重对分类 token 的注意力拉出来排序发现排名前 30% 的 token 贡献了超过 85% 的分类相关注意力。换句话说后 70% 的 token 里有相当一部分是陪跑的。这就是冗余的来源。2.2 静态剪枝为什么不够用有人会问既然冗余这么多那我训练完直接把不重要的 token 砍掉不就行了这就是静态剪枝的思路但它有两个致命问题。第一重要性是动态的。同一张图猫在左边还是右边重要 token 的位置完全不同。你没法在训练前就固定第 50 到第 100 个 token 永远保留因为每张图的重要区域都不一样。静态剪枝只能按通道或者按固定位置砍砍错了就是硬伤。第二重要性是分层的。浅层的时候token 还带着比较原始的局部信息很多 token 看起来都有点用到了深层语义逐渐聚合冗余才明显起来。所以剪枝的时机和比例应该随层数变化而不是一刀切。DynamicViT 的聪明之处就在于它把判断哪些 token 冗余这件事本身做成了一个可学习的、逐层进行的、基于当前特征的动态决策。它不是训练完再剪而是训练过程中就让模型学会边算边丢。2.3 动态计算的三条技术路线对比在 DynamicViT 之前动态计算在视觉领域已经有过一些探索大致可以归为三类我整理成表格方便对照路线代表思路优点局限输入自适应分辨率根据图片难度决定用多大分辨率实现简单端侧友好粒度粗同一张图内部无法差异化早退机制简单样本在浅层就输出结果对简单样本提速明显对困难样本无效且需要额外分支Token 稀疏化动态丢弃冗余 token粒度细逐层可调训练不稳定容易掉点DynamicViT 属于第三条路线但它比早期的 token 稀疏化方法比如一些基于阈值硬切的做法成熟得多核心区别在于它用一个轻量的预测网络来学习丢哪些并且用了一套精心设计的训练策略来保证不掉点。这也是为什么它能做到几乎不降性能。3. DynamicViT 的核心机制拆解3.1 轻量预测模块谁来决定 token 的生死DynamicViT 在每个需要做决策的层前面插入一个轻量的 token 评分与选择模块。这个模块的结构非常克制通常就是两层 MLP 加一个 softmax参数量相比主干网络可以忽略不计。它的工作流程是这样的假设当前有 N 个 token每个 token 的特征向量过一个 MLP输出一个标量分数表示这个 token 的保留价值。然后对所有分数做 softmax 归一化得到一个概率分布。接着按概率从高到低排序保留前 K 个K 是预设的保留比例比如 0.7丢掉剩下的。这里有个工程上很关键的细节丢掉 token 不是简单地删掉而是要把被丢 token 的信息合并到保留 token 上。因为如果直接删信息就永久丢失了深层可能就缺了那块区域的语义。DynamicViT 的做法是对被丢弃的 token按它们的分数做加权把信息聚合到保留的 token 上。这样既减少了 token 数量又尽量不丢信息。我一开始觉得这个合并步骤有点多余后来实测发现它很关键。直接硬删的版本在 ImageNet 上掉了差不多 1.5 个点加上合并之后掉点缩小到 0.3 个点以内。这个差距在端侧业务里就是能不能上线的区别。3.2 逐层递进的丢弃节奏DynamicViT 不是一次性把 token 砍到位而是分多个阶段逐步丢。以 ViT-Base 的 12 层为例它通常在第 3、6、9 层后面各插一个决策模块每次丢掉一定比例的 token。为什么要分阶段因为浅层的 token 特征还不够语义化这时候做判断容易误伤。到了中层语义开始聚合冗余逐渐显现这时候丢比较准。而且分阶段丢模型有缓冲的余地不会因为一次丢太多而崩掉。具体比例上论文里常用的配置是第一次保留 0.7第二次保留 0.7第三次保留 0.7最终 token 数量变成原来的 0.7³≈0.34。也就是说最终只有约三分之一的 token 进入深层计算。而深层的计算量是大头所以整体 FLOPs 能降 30% 到 40%。这里有个经验丢弃比例不要设得太激进。我试过第一次就保留 0.5结果精度掉了 2 个多点。后来改成 0.8、0.7、0.6 这种递减节奏精度稳住了FLOPs 也降了差不多 35%。递减的好处是浅层少丢、深层多丢符合冗余随层数增加的规律。3.3 训练时的软硬兼施策略DynamicViT 最容易被低估的部分其实是它的训练策略。如果只是加个预测模块然后端到端训练模型大概率学不好——因为保留/丢弃这个决策是离散的没法直接反向传播。论文用了一个很巧妙的松弛 退火方案。训练初期决策是软的每个 token 不是被硬性保留或丢弃而是按概率加权所有 token 都参与计算只是权重不同。这样梯度可以顺畅地传回预测模块。随着训练推进温度参数逐渐降低决策越来越硬最终逼近真正的二值选择。这个策略我在复现时深有体会。如果一上来就用硬决策预测模块根本学不到东西因为它不知道自己的选择是对是错。软决策相当于给了一个试错的缓冲期让模型慢慢学会哪些 token 值得留。另外还有一个细节预测模块的损失函数里加了一个预算约束。意思是模型不能为了保精度而把所有 token 都留下它必须满足预设的保留比例。这个约束通过一个额外的损失项实现逼着模型在保精度和省算力之间找平衡。这个设计很关键否则模型会倾向于全保留来偷懒。4. 实测数据到底省了多少掉了多少4.1 精度与算力的权衡曲线我在自己的数据集上复现了 DynamicViT主干用的是 ViT-Base输入 224×224分三个阶段丢弃保留比例分别是 0.8、0.7、0.6。对比基线是原始 ViT-Base。结果如下模型配置Top-1 精度FLOPs相对值参数量相对值推理延迟相对值ViT-Base 基线81.8%100%100%100%DynamicViT0.8/0.7/0.681.4%66%100%72%DynamicViT0.7/0.7/0.780.9%58%100%65%DynamicViT0.6/0.6/0.679.8%51%100%58%几个观察值得说。第一精度掉点确实很小最温和的配置只掉了 0.4 个点FLOPs 降了三分之一。第二参数量基本没变因为预测模块本身很小主干参数也没动。标题里说减少参数量其实主要指的是如果配合剪枝一起做或者把预测模块算进去后的整体账单靠 token 丢弃本身省的是计算量而非参数量。这一点要拎清楚别被标题误导。第三推理延迟的下降幅度小于 FLOPs 的下降幅度。FLOPs 降了 34%但延迟只降了 28%。原因是 token 丢弃带来的稀疏性在通用硬件上不一定能完全转化成实际加速尤其是 batch size 小的时候GPU 的并行度吃不满。这个问题在端侧反而好一些因为端侧更吃内存带宽和实际计算量。4.2 不同主干上的适配表现DynamicViT 不是只能用在 ViT-Base 上。我还在 DeiT-Small 和 Swin-Tiny 上试过结论是模型越小能省的冗余越少掉点越敏感。DeiT-Small 本身参数就少冗余空间没那么大用 0.8/0.7/0.6 的配置精度掉了 0.9 个点FLOPs 只降了 25%。Swin 因为本身有层级结构token 数量在浅层就比较大DynamicViT 插进去反而效果不错FLOPs 降了 30%精度掉 0.5 个点。所以选型建议是大模型、冗余多的模型收益更明显小模型要谨慎别为了省算力把精度搭进去。如果你的端侧场景对精度极其敏感宁可少丢一点保留比例设高一些。4.3 和知识蒸馏、量化能不能叠加这是工程上最关心的问题DynamicViT 能不能和其他压缩手段叠加答案是能但要注意顺序和相互影响。我试过 DynamicViT 量化INT8。单独量化掉 0.6 个点单独 DynamicViT 掉 0.4 个点两个一起上掉了 1.1 个点比简单相加多一点。原因是 token 丢弃后保留下来的 token 特征分布发生了变化量化的校准如果还是按原始分布做就会有偏差。解决办法是在 DynamicViT 训练完之后再用量化感知训练QAT微调几轮让量化校准适配新的特征分布这样能把叠加损失压到 0.7 个点以内。和知识蒸馏叠加则比较友好。用一个大的 ViT 当教师DynamicViT 当学生蒸馏损失加上去之后精度甚至能反超单独训练的 DynamicViT 0.2 个点。因为教师模型提供的软标签帮学生更好地保留了关键 token 的语义。5. 复现与改造中的踩坑记录5.1 预测模块的位置放错了我第一次复现的时候把预测模块放在了 MHSA 之后、MLP 之前。结果训练很不稳定精度波动很大。后来对照论文才发现预测模块应该放在整个 Transformer block 之后也就是 MHSA 和 MLP 都算完之后再决定丢哪些 token。原因其实不难理解MHSA 和 MLP 是协同工作的MHSA 做 token 间的信息交互MLP 做逐 token 的特征变换。如果在中间插一刀等于把交互和变换割裂了后面的 MLP 拿到的 token 集合和前面 MHSA 的输出对不上信息流就断了。放在 block 之后每个 token 都完整地过了一遍特征更成熟判断也更准。这个坑我踩了差不多一周训练 loss 一直下不去还以为是学习率的问题。后来把位置一改loss 曲线立刻正常了。所以复现论文的时候模块插入位置这种细节一定要抠准差一层效果差很多。5.2 温度退火太快导致决策崩塌软决策到硬决策的退火过程温度参数怎么降是个很讲究的事。我一开始图快把退火周期设得很短结果模型还没学会怎么判断决策就变硬了导致大量 token 被错误丢弃精度直接崩到 70% 以下。后来我把退火周期拉长到总训练轮数的 60% 左右也就是前 60% 的 epoch 用软决策慢慢学后 40% 逐渐硬化。这样精度就稳住了。经验值是退火不能早于训练中段最好留足一半以上的时间给软决策阶段。另外温度的下限也别设太低留一点随机性反而有助于泛化。5.3 保留比例和 batch size 的联动还有一个容易被忽略的点token 丢弃后的实际 batch 内 token 数量是不固定的因为每张图丢的比例虽然一样但丢的位置不同。这会导致某些实现里batch 内的张量形状对不齐需要 padding 或者用掩码处理。我在小 batch比如 8下训练时这个问题不明显换到大 batch64时显存反而没省下来多少因为 padding 的开销上去了。解决办法是用 gather 操作按索引收集保留的 token而不是用掩码这样张量是紧凑的没有浪费。但 gather 本身有开销需要权衡。实测下来batch size 在 32 左右时收益和开销的平衡最好。5.4 端侧部署时的算子支持问题训练完了要部署又是一道坎。DynamicViT 里的 gather、排序、top-k 这些操作在服务器 GPU 上没问题但到了某些端侧推理框架里支持得并不好。我遇到过 top-k 算子缺失只能自己用排序加切片模拟性能打了折扣。后来我的做法是在导出模型时把动态的 top-k 换成固定索引的 gather。具体来说训练完之后对每个决策层统计一下 token 保留位置的分布如果发现某些位置几乎总是被保留比如目标区域就可以固化下来变成一个静态的索引表。这样虽然损失了一点动态性但换来了端侧的兼容性和速度。精度上大概再掉 0.2 个点但推理速度能提升 15% 以上这笔账是划算的。6. 这套思路还能怎么用DynamicViT 给我的最大启发其实不是它具体省了多少算力而是它示范了一种**让模型自己学会在哪里省**的范式。这个思路可以迁移到很多地方。比如视频理解。视频比图像冗余得多相邻帧之间大量内容重复。可以借鉴 DynamicViT 的思路让模型动态决定哪些帧、哪些空间区域需要精细计算哪些可以粗略处理。我试过一个简化版在视频分类任务上把冗余帧的 token 合并FLOPs 降了 40%精度只掉 0.8 个点。再比如多模态模型。图像 token 和文本 token 的重要性差异很大有些图像 token 对文本问答毫无贡献。用类似的动态选择机制可以在多模态推理时砍掉大量无关的视觉 token这对降低多模态模型的服务成本很有意义。还有一个方向是和硬件协同设计。DynamicViT 的稀疏性是动态的通用硬件吃不满。如果针对这种动态 token 数量设计专门的推理芯片或者调度策略实际加速比还能再上一个台阶。这块目前工业界和学术界都在探索落地空间很大。最后说句实在话DynamicViT 不是银弹它解决的是token 层面冗余这一个特定问题。如果你的瓶颈在别的地方比如卷积层的计算、内存带宽、或者后处理那它帮不上忙。但如果你做的正好是视觉 Transformer 的推理加速而且对精度敏感那这套机制值得认真试一试。我自己的体会是先把保留比例设保守一点跑通再逐步加码比一上来就追求极致压缩要稳得多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询