ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

细粒度图像分类实战:CUB-200鸟类识别中的Transformer与对比学习

细粒度图像分类实战:CUB-200鸟类识别中的Transformer与对比学习 简介细粒度图像分类旨在区分视觉差异极小的子类别如鸟类品种识别是计算机视觉中的高阶挑战。其核心难点在于局部特征定位与类间微小差异的建模传统CNN受限于局部感受野难以整合跨区域判别信息。视觉Transformer通过全局自注意力机制可捕捉长距离特征关联结合对比学习与针对性数据增强能显著提升模型对细粒度特征的感知能力。该技术在生态监测、物种保护、农业植保等领域具有广泛应用价值而CUB-200鸟类数据集作为权威基准是验证算法有效性的理想平台。从CNN到视觉Transformer从损失函数优化到预训练微调完整的技术路径有助于构建鲁棒且可解释的细粒度分类模型。 近几年做细粒度图像分类的人应该都遇到过这种情况拿到一个像是《深度学习_人工神经网络_卷积神经网络_视觉Transformer_对比学习_数据增强_损失函数优化_预训练微调_细粒度分类_CUB200数据集_鸟类识别_模型鲁棒性_可解释性分析_.zip》这种名字的项目包先别急着解压跑代码。文件名越长往往意味着里面涉及的技术栈越杂模型的复现、调参、迭代链路也就越容易踩坑。我前前后后做过几个细粒度分类的工程CUB-200鸟类数据集算是最常用来练手和出论文效果的benchmark。今天这篇不打算复述某个代码仓库的README而是把我在这个任务上从CNN换到视觉Transformer、从纯交叉熵换到对比学习、从裸训换到预训练微调再到最后做鲁棒性分析和可解释性分析的完整思路整理出来。里面包含了大量的实验细节和踩坑记录希望能给正在做CUB-200或者其他细粒度分类方向的朋友一些参考。1. CUB-200鸟类识别为什么细粒度分类比普通分类难这么多细粒度分类Fine-grained Visual Categorization跟普通图像分类最大的区别在于类别之间共享大量的视觉特征。你让一个分类器区分猫和狗靠轮廓、体型、耳朵朝向基本就能出个八九不离十。但让模型区分一只黄腹地莺和一只橙尾鸲莺关键差异可能只在翅膀条纹的走向、喙的根部是否有色斑、或者尾部羽缘的细微色差。CUB-200数据集正是这类任务的经典代表。1.1 CUB-200数据集的“坑”与机遇CUB-200Caltech-UCSD Birds-200总共包含200种鸟类图像数量大约11788张。这里有个非常关键的数字训练集和测试集的划分大约为5994张训练、5794张测试平均下来每个类别训练样本只有30张左右。30张是什么概念对于深度学习模型来说这张图对应的特征空间几乎没有冗余度稍微过拟合一下训练集上就能达到99%以上的准确率但测试集可能一动就崩。而且CUB-200还有一个经常被忽略的特征——数据分布极不均衡。很多鸟的图片是在自然栖息地拍摄的背景非常复杂包含树枝、水面、天空、山地等等部分图像中鸟类只占很小一块区域甚至有些图像里鸟的姿态是遮挡的。这就给模型提出了两个要求既要关注前景对象的细微特征又要抵抗背景干扰。刚接触这个数据集的新手常常会直接套用ImageNet上的训练逻辑——ResNet-50预训练、224x224输入、常规随机裁剪加水平翻转然后跑50个epoch。结果往往是测试精度卡在70%-75%左右就上不去了。这不是模型不行而是数据本身的信息量支撑不了这种稀疏的训练方式。细粒度分类任务从本质上来说是在逼迫模型学习“区分性特征”而这种特征的提取需要模型对局部区域有极强的感知能力。1.2 细粒度任务的三个核心难点我在实践下来把CUB-200这类任务的难点归为三个层面第一局部特征定位困难。不同于普通分类中全局特征占主导细粒度分类要求模型能找到“判别性部位”——比如鸟的头部、翅膀、尾巴。模型必须学会关注这些区域而不是被大面积的颜色相近的羽毛“带偏”。第二类间差异极其微小。很多鸟类的差异点甚至需要专家级别的知识才能辨认人眼都不一定看得出。这种标签噪声和数据歧义会对模型训练的收敛产生很不稳定的影响。第三训练样本极其稀薄。30张/类的训练数据就意味着模型可以轻易地“记住”训练样本而不是学到泛化特征。这也直接决定了不做数据增强、不用预训练模型、不想办法引入额外的特征监督这个任务的模型很难有好的表现。2. 主干网络选型CNN与视觉Transformer在细粒度场景下的取舍做细粒度分类第一个要定的事情就是backbone。我在CUB-200上分别用ResNet-50、ResNet-101、EfficientNet、ViT-B/16和Swin-T做了对比实验。必须说不同选择会直接影响后面的所有工作这个环节非常值得花点时间分析。2.1 为什么纯CNN在CUB-200上表现没那么差CNN的核心优势在于局部感受野和权值共享这使其天然具有平移等变性和较强的空间局部建模能力。在CUB-200任务初期ResNet-50经过ImageNet预训练再微调在448x448输入下大约可以做到81%-83%的top-1准确率ResNet-101能再提升1-2个百分点。但CNN在这个任务上的瓶颈也很明显——它倾向于关注最具区分性的局部区域但无法建立区域间的长距离关系。比如模型可能学会了看鸟的头部但如果某个鸟类的判别性特征同时在头部和翅膀上CNN就难以有效地把两处信息联合起来做决策。这一点在细粒度场景中是致命的因为很多鸟的类间差异恰恰是多个部位特征的组合。另外传统的CNN如果不做特殊处理在细粒度任务中容易“只顾一点不及其余”。可视化特征图时你会发现大多数时候模型只盯着鸟头看身体和翅膀的特征完全被忽略。这就是领域迁移时典型的“捷径学习”现象。2.2 视觉Transformer带来的改变与代价我第一次把ViT-B/16用在CUB-200上时效果其实比预期的要“别扭”。直接用ImageNet-21k预训练的ViT-B/16在224x224输入下微调CUB-200top-1大约在78%-80%居然还略低于ResNet-50。原因很简单ViT的自注意力机制需要大量数据来学习合理的归纳偏置而CUB-200的30张/类数据量根本喂不饱它。但是当我换上了在iNaturalist-2021上预训练的ViT-B/16之后情况完全反转。iNaturalist是一个包含成千上万种自然物种的超大规模数据集预训练得到的模型已经内化了大量“细粒度”的视觉模式迁移效果直接起飞。加上随机裁剪到448x448输入并微调30个epochtop-1可以摸到88%-89%。这个幅度比ResNet-50的提升多了近6个百分点可见预训练数据分布对最终效果的影响之大。从原理上分析Transformer的全局自注意力机制能够建模任意两个patch之间的关系这让模型在判别局部特征的同时可以跨区域整合信息。在CUB-200这种细粒度任务上这种能力是极其宝贵的。代价则是ViT的参数量更大、推理速度更慢、对数据增强和训练超参数更敏感。我在微调ViT时如果一个不小心把学习率设得太高很容易出现Loss震荡甚至直接发散。2.3 Swin Transformer的折中方案如果既想要Transformer的全局建模能力又希望保留一些CNN的局部先验Swin Transformer是一个相当好的折中。Swin-T在CUB-200上配合iNat预训练448输入微调也能有87%左右的表现而且训练稳定性比ViT好得多。Swin-T的层级化设计和窗口注意力机制让它在图像分辨率变化、平移变化等场景下比ViT更有优势尤其是在CUB-200这种样本量较少的数据集上不容易过拟合。我在最终方案里选择了Swin-T作为主backbone倒不是因为它的精度一定最高而是因为它更好地平衡了鲁棒性和计算效率。当然如果你的算力资源充足用ViT-B/16加上精心调参的iNat预训练权重效果可以再高一截。3. 数据增强策略哪些手段真的提升了你的分类精度数据增强在细粒度分类里的重要性怎么强调都不为过。但这里有个容易让人误入歧途的地方——很多人把ImageNet上那套增强组合直接搬过来用结果反而掉点。原因在于细粒度分类任务对增强策略的要求是“既要有足够的扰动来防止过拟合又不能破坏细粒度特征的完整性”。3.1 基础增强组合的边界控制我自己的基线增强配置是这样随机裁剪Random Resized Cropscale范围0.2-1.0、随机水平翻转、颜色抖动ColorJitter亮度0.4对比度0.4饱和度0.4色相0.1外加一个常规的标准化。这套组合跑下来ResNet-50大概能到80%、Swin-T能到85%左右。注意这里的随机裁剪scale范围是我反复调过的。如果scale下界设置太低比如0.08会切出大量只有背景没有鸟的局部块模型反而学到了错误关联如果下界太高比如0.5则会减少有效的样本多样性最终精度和鲁棒性都会小幅度下降。0.2-1.0是我在多组试验中折中出来的范围适合CUB-200中目标占比不确定的场景。3.2 高阶增强CutOut、MixUp、CutMix的实际表现当然基础组合只是开胃菜。为了进一步压制过拟合我又分别试了CutOut、MixUp和CutMix三种主流正则化增强。CutOut是在训练图上随机挖掉一个方形区域强制模型不能只依赖某一个局部区域做判断。在CUB-200上CutOut带来了大约0.8-1.2个百分点的提升尤其是对容易过拟合的类别效果更显著。MixUp是一种在图像层面做线性插值的方法能够平滑决策边界提高模型的泛化性。实测下来MixUp对CUB-200的精度提升大概是0.5个百分点左右但它的副作用是会让模型注意力分散尤其是细粒度特征本来就微弱的情况下线性混合可能会让判别性区域的信号进一步减弱。让我比较意外的是CutMix它把某个图像的一块区域剪切下来粘贴到另一张图上标签也按比例混合。在CUB-200上CutMix直接带来了1.5-2个百分点的提升效果非常明显。原因我分析有两个其一CutMix保留了原图的大部分局部结构让模型可以在保持上下文信息的同时学习到更多的位置不变性其二CutMix生成的新训练样本比MixUp更“自然”背景和目标的组合依旧符合视觉直觉模型不容易偏离真实分布。不过使用CutMix的时候有个重要细节——不能从头到尾一直用。我一般会把CutMix的启用时机放在训练中期比如全程的40%之后前期还是用标准增强让模型先收敛出基本的特征提取能力中期再开始掺入CutMix强化泛化性能。否则模型从一开始就面对很多“拼接图”收敛速度会变得非常慢甚至在部分sees上出现过拟合和欠拟合并存的情况。3.3 专家级增强RandAugment 与 AutoAugment 的使用心得RandAugment和AutoAugment是两类基于自动搜索或随机策略的增强组合方法。在CUB-200上AutoAugment的ImageNet版本其实效果不太稳定有时候甚至比基础增强还差。原因是AutoAugment搜索出的策略针对ImageNet的自然图像分布而CUB-200的鸟类图像在语义主体和背景复杂度上差异较大直接迁移会产生一定的分布不匹配。RandAugment则相对更可控一些它由两个参数控制——增强强度magnitude和增强数量num_ops。我把magnitude设为9、num_ops设为2时在Swin-T上大概有0.5%-1%的提升。但也发现一个问题如果把增强数量提高到3模型的收敛速度明显变慢最终精度反而下降。这说明细粒度任务的增强策略存在一个“临界点”超过这个点后增强提供的多样性已经弥补不了细节信息被破坏造成的损失。所以最终的增强策略我定为基础增强 CutMix中后期开启 RandAugment低强度num_ops2 标签平滑0.1。这个组合在Swin-T和ViT上都表现稳定最终在CUB-200上比纯基础增强高出大约3个百分点。4. 对比学习与损失函数优化让模型学会“看细节”的关键细粒度分类的任务本质是做高精度的特征学习。传统交叉熵损失函数虽然简单直接但在训练样本极度稀缺时很容易导致特征空间分布不均匀类别边界模糊不清。对比学习Contrastive Learning就是来解决这个问题的它能让模型学到“同一类内聚拢、不同类推开”的特征表示这种表示学习方式天然适合细粒度场景。4.1 从交叉熵到Supervised Contrastive LossSupCon纯粹的自监督对比学习如SimCLR、MoCo在CUB-200上其实不太适用因为那个训练范式需要巨量的无标注数据来构建正负样本对而CUB-200总共就1万多张图撑不起这种吃资源的学习方式。所以我选用的是带监督信号的SupCon Loss它利用已有的类别标签来构造正负样本对。SupCon的原理用一句话描述就是同类的样本在特征空间中被拉近不同类的样本被推开。这个逻辑在细粒度分类中特别合适因为同类鸟的个体差异不同姿态、不同场景、光照不同远大于类间差异传统交叉熵模型有时会把这种个体差异当成类别区分信号导致过拟合而SupCon则强制模型忽略个体噪声只关注类别的本质特征。我的做法是把SupCon和交叉熵联合起来用总loss 交叉熵loss α * SupCon loss。其中α是一个权重参数我在实验里设置为0.5。这种组合方案的关键在于特征提取器在训练早期能利用SupCon构建出更具判别力的特征空间而交叉熵则负责把特征向量对齐到具体的类别输出层两者互补最终精度比单用交叉熵提升1.5-2个百分点。4.2 损失函数优化标签平滑、Focal Loss与动态温度系数在损失函数这一块我还做过几个尝试。标签平滑Label Smoothing是最简单也最有效的优化项。它的原理是把one-hot标签中的1替换成1-ε剩下的ε均匀分配给其他类别。在细粒度分类中类别间的视觉相似度很高模型如果太“自信”很容易在少数难样本上过拟合。把ε设为0.1之后CUB-200上的准确率通常能提升0.3-0.5个百分点而且训练过程更稳定。Focal Loss是处理类别不平衡的利器。虽然CUB-200每一类的训练样本量基本一致但训练过程中“难分样本”和“易分样本”的比例极度不均衡。Focal Loss通过调制因子降低易分样本的loss贡献让模型更专注于难分的类别。我在CUB-200上的实验表明Focal Loss在交叉熵基础上的提升约0.5-1个百分点尤其是对底层的长尾鸟种效果更明显。另一个值得借鉴的小技巧是温度系数的设置。SupCon中温度τ决定了模型对负样本的敏感程度。τ越小模型对难负样本的惩罚越强。在我做的对比实验中τ从默认的0.1降到0.07时细粒度特征的可分性略有提高但低于0.05以后会出现训练不稳定甚至NaN。这里我建议大家在实现时把温度系数设成一个可调超参而不是默认值一抄到底。4.3 对比学习在细粒度场景下的易踩坑点对比学习不是说加就能加的有几点容易出问题的坑我在项目里都遇到过第一Batch Size不能太小。SupCon需要在一个batch内构造足够的负样本对batch size如果只有16或者32对比学习的信号极其微弱基本等于无效。我的实验中batch size至少要到64理想情况是128或者更大。这就对显存要求很高如果显存不够可以考虑使用梯度累积来模拟大batch size。第二正样本的选择要克制。SupCon中一个batch内所有同类的样本都是正样本但如果一个batch里同一类有太多图片模型可能只学会“把这一批图片的特征拉近”而不去挖掘更本质的细粒度特征。我在实现时会对同类样本设置一个最大数量上限比如每个类别最多8张防止对比信号被冗余的正样本稀释。第三对比学习的加入时机。我在实验中发现训练刚开始的10个epoch内不宜让SupCon的权重过大因为此时特征提取器还没学到足够鲁棒的表征过早强制对比学习会导致特征空间过于坍缩。我的做法是把α从零开始线性warmup到目标值大概在5-10个epoch内完成。5. 预训练微调的全流程从权重初始化到收敛调参细粒度分类绕不开预训练。CUB-200只有1万多张图从头训练一个深度神经网络几乎没有可能。但预训练怎么选、微调怎么做门道很多。5.1 选ImageNet预训练还是iNaturalist预训练这是我在CUB-200上做过的第一个关键对比实验同样的Swin-T分别用ImageNet-1k预训练权重和iNaturalist-2021预训练权重进行微调后者比前者top-1准确率高出了近5个百分点84.3% vs 89.1%。原因非常直白ImageNet-1k虽然类别多但图像的主体是日常物品、人物和部分动物iNaturalist则包含海量的生物物种图像与鸟类识别有极高的语义相关性。预训练数据分布离目标任务越近迁移后收敛越快、上限也越高。所以如果你在做CUB-200这只类型的野生动物细粒度分类优先去找对应生态域的预训练权重例如iNaturalist、BioScan而不是默认在TorchVision里拉一个ImageNet权重。很多时候“模型效果差”不是任务的问题而是起点就跑错了。5.2 微调时的学习率策略与分层微分学习率拿到预训练权重后直接统一用一个小学习率微调是最省事的方式但并不是最好的方式。我推荐使用分层微分学习率Layer-wise Learning Rate Decaybackbone底层的特征更通用、更接近预训练分布应该用较小学习率微调分类头等高层模块则用更大学习率从头训练或快速适应。具体实现上我在Swin-T中按stage分层设置学习率层级越低学习率越小比如可以设置从小到大依次是1x、2x、4x、8x的比例关系基准学习率base_lr通常设为2e-5到5e-5之间。分类头用5e-4到1e-3直接训练。优化器我选择AdamW这比SGD在Transformer类模型上表现更稳定。weight decay我设置为0.05因为ViT/Swin这类结构对weight decay的敏感度比CNN高得多。这里有一个很有意思的细节weight decay过大时模型精度会下降但泛化能力上升过小时训练集精度高但验证集上容易波动。0.05算是一个平衡点。5.3 全量微调 vs 特征提取 vs 渐进式解冻很多初学者会问是不是应该先把backbone冻结只训练分类头然后再解冻所有层微调这个方法在部分数据集上有效但在CUB-200上我做了对比实验后发现全量微调 小心学习率的效果接近甚至略优于“冻结后解冻”的两阶段策略。原因是CUB-200的类别和ImageNet/iNaturalist的类别差异较大如果完全冻结backbone模型只能使用预训练特征的一小部分表达缺乏针对性。不过如果你使用的模型非常大比如ViT-L或者设备算力紧张渐进解冻仍是节省显存、防止灾难性遗忘的好方法。如果真的要做渐进解冻建议顺序是先解冻分类头 → 再微调最后1-2个stage → 然后逐步向前推进到全量微调。每一步都固定在前一阶段收敛的基础上减少特征分布的剧烈变化。5.4 数据加载与训练流程的工程细节工程上还有几个直接影响实验效果的因素图像分辨率CUB-200的鸟类细节非常依赖输入分辨率。我在Swin-T上对比了224x224和448x448两种输入分辨率后者准确率高出约3个百分点。但显存占用和训练时间显著增加如果有预算可以尝试多尺度训练随机在256和448之间切换。EMA指数移动平均对模型参数做EMA可以进一步稳定验证集的精度。我在训练后期启用EMA通常能带来0.2-0.3个百分点的提升且几乎不需要额外调参。验证时机不要只在每个epoch结束做验证建议在训练轮次的25%、50%、75%等节点做中间检查。CUB-200的训练曲线往往在接近收敛时会有小幅波动记录中间状态有助于选择最佳checkpoint。6. 鲁棒性与可解释性把准确率之外的功课补上模型在测试集上的准确率只是第一步。在鸟类识别这类需要实际部署的场景中模型对遮挡、模糊、背景干扰、光照变化的鲁棒性同样重要而在学术报告或工程文档中向别人解释模型为什么这么判断更是逃不掉的一环。6.1 鲁棒性测试从数据扰动到OOD评估我在CUB-200上做鲁棒性评估时通常构造了以下几类扰动扰动类型具体做法模型表现遮挡对测试图像加随机的黑色矩形遮挡遮挡面积从10%到50%Swin-T在20%以下遮挡时精度下降小于2%50%遮挡时下降约10%高斯模糊对测试图像用不同半径的高斯核模糊轻度模糊影响很小重度模糊时ViT-L下降明显CNN相对略好亮度变化调整图像亮度系数0.7-1.3两种模型都表现出较强的亮度不变性背景切割用语义分割把背景替换成纯色或随机噪声背景敏感度较高精度下降5%左右说明模型仍在依赖背景特征这里暴露出的一个核心问题是模型“侥幸”通过的鲁棒性测试不一定来自真实的鲁棒特征。比如当我把背景替换成随机噪声时CUB-200精度大幅下降说明模型对图像中的背景语义存在依赖这是细粒度分类常见但很容易被忽视的泛化隐患。如果要做实际部署建议在训练时引入随机背景增强即把背景区域替换成其他自然图像可以有效缓解这个问题。6.2 可解释性分析从Grad-CAM到注意力可视化可解释性分析我推荐两种方式一种是适用于CNN的传统Grad-CAM另一种是适用于Transformer的注意力图可视化。Grad-CAM的结果往往比注意力图更“锐利”主要集中在鸟的头部和躯干这符合细粒度分类的需要。注意力图则更能体现全局建模能力比如Swin-T在解码时会把翅膀、头部、尾部关联起来而ResNet往往只看头部。这个差异印证了Transformer在细粒度特征整合上的优势。在实际项目中我把Grad-CAM的输出叠加到原图上做了一个子图拼接的可视化页面发现几个很有意思的现象第一训练良好的模型在“正确分类”时关注区域通常是分散的——头部、翅膀、尾羽都有不同程度的高亮而“错误分类”时模型往往只盯着一个区域且这个区域很可能不是判别性部位。第二数据增强可以改变模型的注意力分布。模型启用CutMix训练后注意力图的高亮区域会更分散不再那么“迷信”单一的头部区域。这是那些精度提升背后看不见的收益。第三可解释性分析不是模型训练之后才做的“事后工作”它应该是特征学习与模型诊断的闭环一环。我在调参会里经常把注意力图和loss曲线放在一起看如果某个类别的loss一直降不下去我会去看它的注意力图发现模型在学错误的颜色、背景然后回过头去调整增强策略或者采样策略。6.3 模型集成与测试时增强最后提两个在竞赛和工程部署中常用的实用技巧。模型集成Ensemble在CUB-200上可以再提升1.5-2个百分点关键是集成多个差异化的模型我通常集成一个Swin-T和一个ViT-B/16再加一个ResNet-101作为“多样性成员”。测试时增强TTA则是把同一张测试图做多次随机裁剪和水平翻转对预测概率取平均。TTA在CUB-200上的收益大约是0.5-1个百分点成本是推理时间翻倍可以根据实际的吞吐量需求取舍。写在最后从CNN到Transformer从交叉熵到对比学习从裸训练到预训练微调CUB-200鸟类识别这个小任务几乎把现代视觉深度学习的整套方法论串了一遍。我在实践中最深的体感是精度只是表象真正决定模型质量的是特征空间的构建方式而特征空间的构建又是数据、网络结构、损失函数和优化策略四方博弈的结果。很多时候你换一个更强的backbone精度不涨不是模型不够好而是数据增强或者损失函数没有跟上这种结构的变化。最后再分享一个调参的小技巧把每一次实验的配置文件、日志和可视化结果都整理成固定的实验记录表格。我在做CUB-200时前后跑了上百组实验如果没有一套清晰的记录体系根本无从判断是哪一个改动带来了那0.3个百分点的提升。把这套流程建立起来比纠结某一个特定的trick要重要得多。本文还有配套的精品资源点击获取
返回列表