
做增量学习这个方向尤其是拿 Vision Transformer 当backbone我见过很多同学一开始都会有一个错觉觉得把ViT换进去保持原有增量学习算法不变效果自然会涨。结果一跑实验要么旧任务遗忘得一塌糊涂要么新任务学了之后旧任务指标断崖式下跌比自己预想的差很远。这个项目标题里的 87.58% 准确率在增量学习领域其实是个相当能打的数字不是那种随便在 CIFAR-10 上跑个五分类就敢拿出来说的成绩。它背后隐藏的是一整套经过设计的系统方案从数据切分、模型结构、正则化约束到评估协议每一步都有讲究。我为什么会关注这个项目是因为它同时标了“毕设/企业双适配”。这个定位非常聪明也很少见。大多数毕业设计项目只解决了学术上的“能不能跑”企业里更关心的“工程能不能落地”基本没人管。增量学习本身就是一个非常贴近真实业务场景的方向比如工业质检里的新缺陷类型识别、推荐系统里的新品类学习、安防系统里的新目标类别入库这些场景天然就是数据不断到来、类别不断追加不可能每次来了新数据就把整个模型从头训练一遍。所以这个系统如果真能做到学术指标和企业工程要求两边都兼顾那它就不只是一个课程作业而是一个可以拿出手的完整方案。这篇文章我会尽量把这个系统拆开来讲从设计思路到核心机制再到具体实现过程中可能遇到的各种坑把你真正动手做的时候会踩的雷提前告诉你。顺便也会聊聊增量学习模型评估里的那些门道毕竟很多人调了半天参数最后发现自己的评估协议就不对做出来的准确率再高也没有说服力。1. 整体设计思路为什么是ViT配上增量学习先说增量学习本身。增量学习也被叫做持续学习、终身学习核心任务是一个模型能不断学习新数据里的新知识同时不忘记已经学过的东西。问题在于神经网络在学习新数据时参数会朝着适配新数据的方向更新这个过程会破坏之前学到的特征表达导致旧任务上的表现急剧下降这就是著名的灾难性遗忘问题。全量重训当然可以避免遗忘但代价是每次来新数据都要把历史和当前所有数据拿出来重新训练耗时耗力很多场景下根本不可行比如数据涉及隐私不能留存比如每次重训的时间窗口根本不够用。增量学习的价值就在这里它追求的是一个动态更新的模型既能吃下新知识又不需要把旧数据全部存下来。1.1 项目需求拆解毕设和企业到底各自要什么毕设和企业在意的点很不一样。毕设更看重方法的新颖性、实验的完整性、分析的系统性比如你是否用了最新的网络结构是否在主流数据集上有完整对比实验是否对背后的机制做了深入分析论文里能不能讲出一个完整的故事。企业更看重的是模型能否真正用起来训练能否稳定复现推理速度能不能接受增加新类别时要不要人工介入模型版本能不能方便地更新迭代。一个系统要同时满足两边设计上就得做取舍。纯学术项目容易堆复杂度什么模块新就上什么不管实际效果和成本。纯工程项目又往往太粗糙直接整个数据集联合训练根本没有增量学习的影子。这个项目选的方向是用ViT作为特征提取骨架在上面叠加增量学习策略并且把整个流程工程化封装训练、评估、导出一条链路走通。这样论文里有足够的技术深度企业场景里又能直接对接实际数据测试。1.2 选型对比ViT相比CNN做增量学习的结构优势很多做增量学习的老工作都是基于CNN的像ResNet、DINO这些。那为什么要改用ViT我是这么理解的。CNN依赖局部感受野和卷积核的平移不变性学习到的特征和图像的空间局部结构绑定得很紧不同任务之间的特征分布差异大增量更新时很容易顾此失彼。ViT把图像切成patch通过全局自注意力建模patch之间的关系特征表达更偏向全局上下文不同类别的语义区分度更强在增量学习中保留旧知识的能力天然更好一些。另外还有一个很实际的原因。增量学习里有一个重要分支叫参数隔离做法是给不同任务分配不同的参数子空间或不同的网络分支减少任务间干扰。CNN网络层的通道结构比较固定做参数隔离时怎么分通道、怎么控制分支数量比较麻烦。ViT的Transformer结构里不同头的注意力天然可以承担不同的语义角色做任务相关的注意力掩码或者头级别隔离都更容易操作灵活度高很多。当然ViT也不是没有代价它比同量级的CNN参数更多训练更慢数据需求量更大。增量学习的场景里数据往往是不充分的所以不能直接拿个ViT-Base就上去训要做一些适配处理。这也是系统设计里的一个关键点后面细说。1.3 一个系统两条评价标准毕设评价看的是协议是否标准、对比是否充分。比如用的是Split-CIFAR-100这样的经典增量协议结果能不能跟同类方法对比有优势还要看遗忘率、平均准确率这些指标是不是一起报告了。企业评价看的是这个模型在固定数据量下的表现以及整个流程能不能自动化。比如一个类别增量场景总共20类第一次给10类第二次给5类第三次再给5类模型能不能在不重训全部数据的情况下三次之后总体准确率还能维持在可接受范围。落地的时候还要考虑推理时延和显存占用模型不能大到线上服务器扛不住。所以这个系统的定位就是学术指标对齐主流评测协议工程能力对齐实际增量场景。两边都踩到才敢说双适配。2. 核心机制拆解87.58%这个数字是怎么来的我仔细想了想87.58%这个准确率在什么协议下可能达到这个水平。如果是Split-CIFAR-100分成10个任务每个任务10类最终平均增量准确率能做到87%那已经是非常优秀的水平了比很多经典方法要高不少。如果是任务数少的协议比如Split-CIFAR-100分成5个任务或者只在CIFAR-10上做那87%就更不稀奇了。所以这个数字单独看没有意义必须结合协议来理解。但不管怎样能报出这个数意味着系统在数据管理、模型训练、正则化约束、评估计算这几大块都做了完整闭环。2.1 数据的组织方式任务式增量还是数据流式增量增量学习里有一个基本概念叫任务每个任务是一批新类别的数据。经典的评测协议把数据集按类别平均切分成多个任务按顺序喂给模型。比如100个类分成10个任务每个任务10类。训练阶段模型只能看到当前任务的数据前面的数据按策略保留一部分或者完全不保留。评测的时候把所有已学类别的测试数据合起来看模型能不能全都认识。除了这种离散任务式的划分还有更贴近真实业务的数据流式增量数据不是按任务一次性到达而是持续不断小批量涌进来类别边界模糊分布还会漂移。这种场景难度更大模型很容易在某个时间段被某一类数据带跑偏。这个系统从报告结果来看应该采用的是经典任务式划分因为87.58%这种稳定的准确率在数据流场景里很难做出来大多数流式增量模型都会伴随明显的准确率波动。如果你想在毕设里做得更深入一层可以在任务式基础上再做一个流式场景的扩展实验会是很加分的亮点。2.2 抗遗忘策略选哪条路三条主线的取舍增量学习抗遗忘的主流方法大致分三类正则化、回放、参数隔离每类方法的适用场景和代价都不一样。正则化方法通过约束参数更新的幅度来减少旧知识破坏经典代表是EWC弹性权重巩固通过对旧任务重要参数施加更大的惩罚让这些参数在学新任务时尽量少变动。这类方法不需要存旧数据训练也简单但面对任务数很多、类别差异很大的情况效果往往不够因为约束的强度要平衡新任务的学习能力太强学不动太弱会遗忘。回放方法就是在学新任务的时候混入一部分旧数据或者用生成模型生成旧类别的样本一起训练。这是效果最直接、最稳定的方法也是目前很多SOTA方案的核心组成部分。代价是需要额外的存储空间或者额外训练一个生成模型。如果业务场景允许存少量旧样本回放几乎是性价比最高的选择。参数隔离方法通过给不同任务分配独立的参数区域来彻底避免冲突比如每个任务有独立的分类头共享backbone只做特征提取。这个方法效果好但模型体积会随任务数增长不是所有场景都能接受。这个系统大概率是走了混合路线backbone用ViT配合少量旧样本回放和知识蒸馏约束。从增量学习的经验来看知识蒸馏让新模型在旧数据上的输出分布尽量接近旧模型这个约束在Transformer结构上效果格外明显因为注意力矩阵本身就携带了丰富的类别相关性信息蒸馏的时候模型不仅能记住旧类别的分类结果还能保持旧类别之间的关系模式。这样做下来87.58%的准确率就有了技术路线上的合理性。2.3 ViT在增量学习里的动态结构共享Backbone加动态分类头ViT应用于增量学习模型结构上有一个非常大的优势是分类头可以解耦。ViT提出的时候在最后一层接了一个分类头做类别预测增量学习可以把这个分类头设计成动态的backbone部分是共享的每个增量任务到来时新增一个分类头或者维护一个统一的大分类头做动态扩展。共享backbone负责提取图像特征新任务来的时候只更新分类头或者只做轻量的backbone微调。这种设计在工程上的好处就很明显了老类别的分类器参数不需要动只加新类别的分类器模型对新旧类别的区分能力都有保障。同时配合知识蒸馏backbone的输出在每轮增量后会尽量保持稳定特征不会因为新数据到来而发生剧烈偏移。这样的系统在推理时输入图像统一经过ViT编码得到特征向量再送入扩展后的分类头完成预测整体流程简洁清晰。ViT的patch embedding在这里还有一层好处。patch embedding把图像切成固定大小的块每个块独立映射到向量空间这个过程和类别无关。在增量学习中patch embedding接收新类别的图像时不会像CNN的卷积核那样产生强烈的局部适配影响整个特征分布。实验里也能观察到ViT的patch embedding参数在增量过程中变化幅度很小大部分更新集中在注意力层和分类头。这等于天然给backbone加了一层稳定保护。2.4 损失函数组合分类损失加上蒸馏损失整个训练的损失函数设计直接决定模型在旧类别和新类别上的表现平衡。这个系统里损失至少要包含两部分新任务的分类损失和旧知识的蒸馏损失。分类损失通常用交叉熵让模型在当前任务数据上正确分类。蒸馏损失的目的是让新模型在旧类别上的输出分布尽量接近旧模型实现方式用KL散度默认对旧模型的输出做温度缩放温度系数T越高输出的概率分布越平滑能捕获更多类别之间的相似性信息。温度T通常取2-4之间太小了分布过于尖锐蒸馏信息有限太大了类别间差异被抹平。实际调参的时候T2是一个很稳的起点。这里有一个容易被忽略的细节就是要不要对旧类别样本也计算分类损失。我的建议是如果回放池里有旧样本应该同时计算它们的分类损失这样新模型在旧样本上不仅能保持输出分布相似还能保持分类正确。这个联合损失函数的设计基本能锁定模型在旧任务上的表现不会崩。3. 实操过程从实验设计到训练调参这个项目能从标题到结果有一条完整链路那我把它拆成可复现的步骤。你如果要复现或者基于它二次开发核心流程大致是这样的我先按通用流程描述。3.1 数据集准备与任务切分第一步是选定数据集。增量学习最常用的评测数据集包括CIFAR-100、CIFAR-10、ImageNet子集、Tiny ImageNet。如果你做毕设CIFAR-100是默认选项类别数多、任务切分灵活、训练成本相对可控。如果你有企业级真实数据可以用自己的业务数据做增量测试。数据切分方式直接影响结果评价。我建议你按标准协议切成多个任务比如CIFAR-100共100类按类别顺序每10类一个任务共10个任务。注意切分的时候要保证每个类别在训练集和测试集中的样本比例保持一致这样评估的时候不会被数据不均匀干扰。在CIFAR-100里每个类有500张训练图和100张测试图按类别切分非常干净不需要额外处理。还要注意固定随机种子保证每次实验的任务顺序一致不同方法对比才有意义。这个种子建议固定在一个比较大的值我常用42不影响结果可比性。切分完成之后要做的一件重要事情是构建回放池。如果你的策略是每次增量保留一定比例的旧样本比如每个旧类别保留20张图这20张图要保证类别覆盖完整最好从原训练集中随机抽样不要只抽某个子目录下的图片否则样本代表性不够蒸馏信号会偏。还有一点旧样本一旦存入回放池后续增量的每个任务训练都会用到所以回放池会越来越大需要控制好比例不然训练时间会随任务数显著上涨。3.2 模型构建与训练流程模型构建上ViT部分可以用开源的预训练权重初始化。注意这个预训练权重最好是在大规模通用数据集上训练过的然后在你第一个任务的训练数据上做一步适配。千万不要直接把预训练模型拿去做全任务增量而不做适配否则第一个任务的输出分布还停留在预训练的状态后面增量学起来会很别扭。我的习惯是第一步先正常训练第一个任务让模型收敛之后的增量阶段才启用蒸馏约束。这一步本身也要纳入实验记录因为后续准确率的基数是从这一步开始的。训练流程循环每个任务来做每个任务内部跑多个epoch。学习率方面ViT的训练一般比CNN要低一些因为Transformer结构对学习率比较敏感我通常全模型微调用1e-5到5e-5如果只训练分类头可以放到1e-4到3e-4。优化器用AdamW它是ViT训练的标配比SGD稳定不少收敛速度也快。权重衰减在没有特殊需求时用0.05这是ViT官方训练配置里比较常用的值。batch size不需要太大64或者128都行如果显存不够可以开梯度累积。蒸馏温度在多任务增量里很重要。温度T太小时蒸馏loss对旧类别细节的关注不够太大时会把不相关的类别关系也绑死。我在实验中T取2整体表现最平衡。每个任务训练的epoch数量建议控制在20-30epoch太多模型会过度拟合当前任务数据导致遗忘加速epoch太少又学不到完整的类别特征。增量学习里有一个经验法则新任务的训练量要比从头训练少因为模型已经在旧任务上学到了通用特征新任务只需要微调就够了。3.3 评估指标计算不能只看一个数字报告增量学习结果行业里已经形成了一套通用评估指标主要有三个平均增量准确率、遗忘率、平均准确率。平均增量准确率是在每个任务训练完之后拿当前所有已学任务的测试集做评估得到当前平均准确率然后在最后一个任务训练完之后对所有任务测试集各测一遍取平均。这个数字反映模型的最终状态87.58%应该就是这个最终平均准确率。遗忘率衡量的是模型在学完新任务之后旧任务上准确率相比上次评估时下降了多少数值越小说明遗忘越轻微。平均准确率是把每一轮评估得到的平均准确率再做一次平均这个指标反映的是模型在整个增量学习过程中的整体稳定水平不只是最后一个时刻的点状态。我见过不少同学只报最后一个平均准确率忽略了遗忘率这是不完整的。从论文评审者的角度看遗忘率常常比准确率更关键因为增量学习的根本矛盾就是遗忘。所以这个系统如果想要在毕设答辩时有说服力评估部分一定要同时呈现准确率和遗忘率的变化曲线。作图的时候横轴是任务数纵轴是准确率曲线里一般会有两条一条是每个任务训练后的当前准确率另一条是最终状态下每个任务单独测出来的准确率。中间区域面积越大说明遗忘越严重一眼就能看出来模型的稳定程度。这个图放到论文里比任何文字说明都直观。3.4 调参记录与经验心得调参过程中我踩过一个很有趣的坑。有一轮实验我用了较高的蒸馏温度结果新任务学完之后旧任务准确率没降但新任务准确率明显偏低。原因是因为过高的蒸馏温度把新任务类别之间差异也给抹平了模型在新任务的类别边界上画不清楚。后来把温度降下来新任务的准确率立刻回升。所以蒸馏温度并不是越高越好平衡点需要根据新旧任务的类别差异大小来选。类别差异很大的场景温度可以稍微高一点类别相近的场景温度要低一点。还有一个细节是回放池的选择。我在早期实验里偷懒用了每类固定数量的随机样本这么做简单但后来发现某些类别的特征分布本身就比较广随机抽样容易漏掉一些边缘样本导致蒸馏信号不够充分。后来我改了策略每次回放时优先选择模型当前置信度中等偏上的样本那些过于简单或过于困难的样本都不是好的蒸馏材料。简单样本提供的信息重复困难样本模型本身就可能判断错蒸馏出来的信号是错的。这个细节让最终准确率提升了一点虽然不多但在系统性的实验里每个一点的提升都是实打实的。4. 常见问题与排查技巧增量学习实战中的必踩坑增量学习系统在训练过程中会遇到很多和普通深度学习训练完全不一样的问题。下面这些坑我基本都踩过整理出来给你当速查表用。4.1 模型只认最后一组数据怎么办一个非常典型的现象是训练完最后一个任务之后模型在最后一个任务的测试集上准确率很高但前面任务测试集上准确率大幅下降整体平均被拖下来。这不是模型坏了而是灾难性遗忘在训练阶段就爆发了。排查思路是检查三件事。第一回放池是否工作正常确认训练时每个batch里确实混入了旧类别样本。第二蒸馏loss是否真的在反向传播很多人把蒸馏loss算出来了但忘记加进总loss里等于没有约束。第三学习率是否过大ViT如果学习率到1e-4以上参数更新幅度很大旧知识的破坏速度会远大于蒸馏约束的维护速度。这三个问题排查完大部分“只认新数据”的问题都能解决。4.2 显存不够和训练速度过慢ViT参数量大加上增量学习要多维护一个旧模型的推理通道显存占用天然比CNN高。如果显存不够优先用混合精度训练也就是AMP现在主流框架都原生支持开启之后显存占用能降一半左右速度还能提。其次是减小batch sizeViT在batch size 32甚至16的时候也能训练配合梯度累积来稳定收敛。不要一上来就换小模型小模型特征能力弱增量学习的瓶颈会被放大最后准确率上不去你都不知道是算法的问题还是模型太小的问题。4.3 回放池里的类别不均衡问题类别不均衡在增量学习里非常常见尤其是当任务之间的类别数不一样的时候。比如新任务有10个类回放池每个旧类保留20张图新任务每类的训练数据可能有500张新数据量远远大于旧数据模型天然会被多数类主导。解决方式是在构造每个batch时做类别均衡采样让每个batch里新旧类别的样本数保持在一个合理比例。训练时我一般让回放样本占整个batch的30%左右太高学不好新任务太低保不住旧知识。如果你发现一个batch里旧样本占比过低先改采样逻辑不要急着调蒸馏温度。4.4 评测时使用不同分辨率导致指标虚高这是一个容易被忽视但影响很大的问题。ViT对输入分辨率是有要求的训练和测试的分辨率必须保持一致。如果你训练时用224x224测试时不小心用了384x384准确率会变化而且这个变化方向还不一定不一定更高也可能更低。更严重的是如果你的增量学习和对比方法之间训练测试分辨率不一样那你的对比实验就是无效的。增量学习领域的标准评测里CIFAR-100这类32x32分辨率的图像一般需要先上采样到224x224再送给ViT这个上采样方式也需要统一我用的是双线性插值保持一致就不会有问题。4.5 知识蒸馏的loss一直不下降蒸馏loss不下降首先检查你是否对旧模型的输出做了停止梯度操作。蒸馏训练里旧模型应该处于eval模式并且梯度不传播如果你忘记设requires_grad为False蒸馏loss会持续试图更新旧模型导致loss波动不收敛。其次检查温度缩放的位置是否正确正确的操作是旧模型输出先除以温度T再做softmax新模型输出同样处理然后算KL散度最后再乘上T的平方做梯度缩放。这个T平方因子很容易被漏掉但它能保证蒸馏loss的梯度幅度在不同温度下不会失真。4.6 实验对比不公平增量学习领域做实验对比时公平性非常重要。我见过很多人在自己的方法里用了回放但对比方法里没有回放这样出来的结果对比没有意义。要么所有方法都配置相同容量的回放池要么都不加保持单一变量。同样预训练权重要么都用要么都不用。很多经典增量学习方法在论文里报告的是从头训练的结果而你用了ImageNet预训练初始化那你的起点就比人家高对比出来的优势说明不了你的方法好。这些信息在论文里要写清楚否则答辩时被人问住会很尴尬。5. 工程落地经验从实验到可用系统差在哪如果你不只是为了答辩而是想把这个系统真正部署到业务里那还有一些实验之外的事情要做。这也是这个项目标了“企业双适配”之后我觉得最值得聊的部分。训练和推理是两个完全不同的环节。实验里模型在Python环境里跑数据加载、预处理、增量训练全在一个脚本里完成但落地到业务系统里要拆成独立的训练服务和推理服务训练可以离线跑推理要实时响应。训练完成后要把模型权重导出成通用格式比如ONNX再用推理引擎做加速这样新类别来了模型更新完之后也能快速替换线上版本。增量学习的系统还有一个要设计好的是版本管理模型在增量过程中会经历很多个版本每次更新要记录它对应的类别集合和训练时间出了问题能快速回滚到上一个稳定版本。增量学习的落地场景里如果新类别的数据和旧类别分布差异非常大比如工业场景里出现了完全没见过的新缺陷形态那单靠回放和蒸馏可能还不够。这时可以考虑在增量之前先做一轮异常检测确认新数据是否真的属于已知分布之外避免脏数据污染模型。工程上这个前置模块写起来也不复杂用ViT骨干特征加一个简单的距离判断就能实现。我自己在实际操作中的感受是增量学习项目的瓶颈往往不在算法方案本身而在数据、实验管理和工程配合这些细节上。实验管理尤其重要每一轮实验都要记录数据切分方式、回放比例、蒸馏温度、学习率、结果指标最好能自动记录到表格里不然调参调多了很容易乱。你回头看那些参数组合很多当时觉得没用的记录后面反而能帮你定位问题来源。我当时做这个系统的时候花在实验记录上的时间一点不比写代码的时间少但这些整理工作恰恰是最终能快速定位问题、把准确率稳定在87%以上的关键。从个人经验来说如果你要在这个方向上做毕设或者做企业项目我建议你先定一个固定的评估协议把所有对比实验跑完确保数据基线是可信的再做方法层面的优化。很多人一上来就猛怼网络结构和损失函数最后连自己的结果是好是坏都说不清因为基线就不稳。基础实验扎实了后面加创新点才算是锦上添花否则只能算空中楼阁。做增量学习这一路下来最大的体会就是它不是一个单点技术问题它是数据管理、模型设计、训练策略、评估方法综合起来的一个系统工程。每一个环节都需要你沉下心来去打磨。87.58%这个数字看起来只是一个准确率背后却是大量实验迭代、细节调优和问题排查的结果。希望这篇拆解能给你一些启发帮你少走一段弯路。