ARTICLE DETAIL

资讯详情

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

细粒度图像检索技术全解析:从部件定位到Transformer与对比学习

细粒度图像检索技术全解析:从部件定位到Transformer与对比学习 细粒度图像检索这个方向我前前后后读了不下五十篇论文从最早的部件定位模型到后来的Transformer、扩散模型一路跟下来踩了不少坑也积累了一些自己的判断。今天这篇笔记算是我对自己阅读过程的一次系统梳理重点讲清楚细粒度图像检索到底在解决什么问题、论文之间的演进逻辑是怎样的、复现实验时那些文档里不会写的坑以及我自己记论文笔记的方法。如果你是刚进这个方向的研究生或者工作中遇到了长得几乎一样的商品图怎么检索这类需求想系统了解这个领域的技术脉络和落地要点那么这篇笔记可以帮你省下不少自己摸索的时间。我会尽量用直白的话讲清楚每篇论文的核心贡献也会把实验环节容易翻车的地方一并说出来。1. 弄懂细粒度图像检索在做什么1.1 什么是细粒度图像检索它和普通检索差在哪图像检索这个任务大家应该不陌生你给一张查询图系统从数据库里把相似的图片找出来。传统检索关注的是粗粒度的相似比如搜鸟就返回所有鸟的图片搜车就返回所有车的图片类间差异非常大哪怕用全局颜色直方图这类手工特征也能做得不错。细粒度图像检索Fine-Grained Image Retrieval则完全不同它要区分的是同一个大类下面的子类。举个例子都是鸟要区分美洲红尾鸲和东方蓝鸲都是车要区分宝马3系和宝马5系都是飞机要区分波音737-800和空客A320。这些类别之间的差异往往只体现在翅膀颜色、尾灯形状、机翼弧度这类非常细微的局部区域。我第一次接触这个任务时觉得这不就是分类吗后来才发现检索和分类的差异很大。分类只需要判断图片属于哪个类别而检索需要学习一个特征空间让同一子类的图片在空间里彼此靠近不同子类的图片彼此远离同时还要保证这个特征空间具备足够的泛化能力能够处理训练阶段从未见过的新类别。这种细带来的难度我举个例子你就明白了。如果你用普通的ImageNet预训练模型直接提取特征做检索top-1准确率可能只有六到七成很多错误结果看起来就是同一只鸟只是亚种不同。用户根本没法接受这样的结果。所以细粒度检索的核心任务就是想办法让模型关注那些真正有区分度的局部细节而不是被背景、姿态、光照这些干扰因素带偏。1.2 为什么细这么难类间差异小、类内差异大理解细粒度检索的难点关键在于体会两个差异之间的不平衡。第一个是类间差异小。不同子类之间可能只有某个部位的细微区别比如某种蝴蝶只在前翅后缘有一排小黑点另一种没有。这种差异对深度学习模型来说属于非常难以捕捉的高频细节。普通卷积神经网络默认关注的是全局纹理和形状很容易忽略这种小区域区别。第二个是类内差异大。同一种鸟不同姿态、不同光线、不同背景下的外观差异可能比不同种类鸟之间的差异还要大。这就导致模型很容易学到背景这个捷径——比如某种鸟经常出现在水边另一种经常出现在树林里模型学到有水就是A类有树就是B类这在训练集上准确率很高但一到真实场景就原形毕露。我读过的早期论文里很多工作其实就是在跟这两个难点做对抗。有些用部件定位先找到鸟的头部、翅膀、尾部再分别提取特征有些用注意力机制让模型自己找出最有区分度的区域还有些在损失函数上下功夫让特征空间的类间距离拉得更大。这些思路本质上都是在回答同一个问题如何让模型关注对的地方同时抵抗环境的干扰。1.3 细粒度检索的核心应用场景聊完技术难点说说实际场景。细粒度检索的价值在业界其实非常大最典型的就是电商场景。以服装为例用户拍一张照片要在数十万商品里找到同款或相似款颜色、领型、袖口这些细节差一点结果就完全不同。再比如汽车配件识别给定一张零配件照片要在大库里找到对应的型号这对维修保养行业来说是刚需。生物多样性监测也是一个重要方向。生态学家布设大量红外相机一天能拍几千张动物照片人工标注几乎不可能这时候细粒度检索就能派上大用场——给定某物种的参考图自动把相机数据里同一个物种的照片全部找出来。植物识别App、昆虫识别工具背后的核心算法本质上也是细粒度识别。还有医疗影像中的皮肤病变检索、工业质检中的缺陷分类检索场景很多。这些应用有一个共同特点类别非常多、样本不均衡、需要模型对细节高度敏感。这也是为什么细粒度检索一直是计算机视觉的热门方向每年的CVPR、ICCV、ECCV上都有大量相关工作。2. 细粒度图像检索的技术演进与论文脉络2.1 早期方法手工特征与基于部件定位的思路在我读到的早期工作大致2013到2016年里主流思路是先定位部件再提取特征。代表性的方法比如Part-based R-CNN它先训练一个物体检测器找到鸟的头部、躯干、尾部这些部件然后把每个部件的CNN特征拼接起来做分类或检索。这个思路直观但有两个很致命的问题。第一部件标注非常昂贵需要人工标注每张训练图的头部、翅膀、尾巴位置数据集的规模很难做大。第二检测本身的错误会直接传导到后续的特征提取一步错步步错。我记得自己第一次复现这类方法时单是部件检测器的训练就花了两三天最后的效果却不尽如人意检测框稍微偏一点特征就乱套了。不过这类工作给我最大的启发是细粒度识别的关键信息确实是局部区域这个结论后来被大量实验反复验证。哪怕到今天所有性能靠前的方法本质上都在做找到关键局部区域这件事只是实现方式从显式的关键点检测变成了隐式的注意力学习。2.2 深度特征与双线性特征的突破2015年的Bilinear CNN双线性CNN是一个标志性工作。它的想法很巧妙用两个CNN分别提取特征然后把两个特征向量的外积作为图像的表示。外积运算能捕捉特征通道之间的二阶统计信息相当于建模了特征A出现的同时特征B也出现的共生关系这种表示比单峰特征要丰富得多。我当时看这篇论文时觉得最精彩的部分不是外积这个数学操作而是作者对细粒度本质的洞察——局部区域之间的交互比局部区域本身更重要。比如鸟类的识别不仅要知道有红色羽毛和有黑色条纹还要知道红色羽毛和黑色条纹出现在同一位置这个组合信息它的判别力比单独任何一个特征都强。双线性特征的问题也很明显特征维度极高。如果两个网络都输出D维特征外积之后就是D的平方维。原始论文用VGG-16特征维度是512外积后就是262144维存储和计算开销都非常大。后续有一堆工作在做双线性特征的降维和近似但老实说在深度学习快速迭代的背景下这类方法很快被更新的框架超越了。2.3 注意力机制与弱监督定位从2016年开始注意力机制逐渐成了细粒度识别的主流工具。这类方法的优势在于不需要部件级别的标注只需要图像级别的类别标签模型自动学习关注哪里。代表性工作包括RA-CNN递归注意力卷积神经网络、MA-CNN多注意力卷积神经网络、NTS-Net导航-教师-学生网络等。RA-CNN的思路我记得很清楚它用三个尺度的网络结构第一个尺度看整张图找到最值得关注的区域第二个尺度把该区域放大再看再找更细节的区域第三个尺度继续放大。这种由粗到细的注意力递进非常契合人类观察细粒度物体的方式——先看整体再看局部最后看局部的局部。NTS-Net则提出了一个很形象的隐喻让两个学生互相监督学习。其中一个学生负责找出信息量最大的区域另一个学生通过对比确认哪些区域真的重要两者互相博弈最终让注意力定位越来越准。这个方法在CUB-200-2011数据集上的分类精度提升非常显著我的实际复现中也确实感受到了这种博弈机制带来的收益。注意力机制最大的优点是把找部件这个环节彻底自动化了让细粒度识别从依赖强标注走向弱监督。但它的通病在于训练不稳定注意力图很容易收敛到某些固定的背景区域需要设计额外的约束或正则化手段。这个问题直到现在也依然存在只是表现形式不同。2.4 度量学习、对比学习与检索的深度结合细粒度图像检索与分类有一个关键区别检索的目标不是输出类别标签而是学习一个距离度量使得同类别样本距离近、不同类别样本距离远。这就自然引出了度量学习Metric Learning这个方向。经典的度量学习损失包括Contrastive Loss对比损失、Triplet Loss三元组损失、Proxy-based Loss代理损失等。Triplet Loss的思路是构造三元组锚点正样本负样本让锚点与正样本的距离小于锚点与负样本的距离。实际训练中三元组的选择策略极其关键随机选择会导致绝大多数三元组太简单梯度消失全部选择最难的负样本又容易让训练不稳定甚至崩溃。后续的Hard Mining策略、Margin调整技巧以及Circle Loss、Multi-Similarity Loss等改进都是围绕这个问题展开的。对比学习在细粒度检索中的应用是近几年的事。SimCLR、MoCo等自监督框架让模型在不依赖标签的情况下学习特征而细粒度任务天然适合对比学习因为同类实例的不同视图本质上就是同一个子类的不同图像。我在实际实验中发现对比学习预训练后再用细粒度数据finetune得到的特征质量往往优于直接监督训练。一个比较典型的数据是在CUB-200-2011数据集上直接用ImageNet预训练模型提取特征做检索Recall1大概在60%左右用对比学习预训练再finetune能到75%以上。这个提升幅度在检索任务上是相当可观的。2.5 扩散模型与生成式方法在细粒度检索中的尝试最近两年扩散模型在生成任务上大放异彩有些工作开始尝试把扩散模型引入细粒度识别与检索。比如利用扩散模型去噪的过程来提取特征或者用扩散模型生成更多细粒度样本做数据增强。说实话这个方向目前还在探索阶段效果并不比专门的细粒度方法好太多。但我认为它的潜力在于扩散模型对细节的建模能力非常强因为去噪过程需要在像素级别上精确恢复图像结构这种能力如果能够有效迁移到特征提取中对细粒度问题可能有帮助。我读过一篇将扩散模型作为数据增强手段的工作通过生成不同姿态、不同背景但保持同一子类关键特征不变的图像有效缓解了类内差异大的问题。这个思路我很看好也打算在后续实验中深入验证。3. 三篇代表性论文的精读笔记3.1 论文一Bilinear CNN 的方法与启发论文《Bilinear CNN Models for Fine-grained Visual Recognition》发表于ICCV 2015是细粒度识别领域绕不开的经典。方法的核心用一个公式可以概括。给定图像I两个特征提取网络f_A和f_B分别输出特征图对同一位置的特征向量做外积然后将所有位置的外积求和池化得到双线性特征。作者用了两个分析第一外积建模了特征通道之间的二阶相关性第二位置求和池化让特征具备了一定的平移不变性。我在复现时有一个体会双线性特征真正厉害的地方在于它隐式地建模了parts共现信息。假设一个通道响应红色另一个通道响应三角形区域它们的外积就响应红色的三角形区域这种组合特征对细粒度判别极有价值。这也是为什么双线性池化在当时的细粒度任务上能把精度一下子拉高好几个点。但它的缺点也很现实特征维度爆炸带来的存储开销问题、训练时需要冻结预训练模型导致收敛慢的问题都让人头疼。后续的紧凑双线性池化Compact Bilinear Pooling通过随机投影降低维度算是解决了存储问题但性能有一定损失。3.2 论文二RA-CNN 的多尺度注意力递进《Look Closer to See Better: Recurrent Attention Convolutional Neural Network for Fine-grained Image Recognition》发表于CVPR 2017。RA-CNN的设计非常优雅三个尺度网络每个尺度包含一个注意力建议网络和一个特征提取网络。注意力建议网络从当前尺度的特征图生成一个注意力图然后用注意力图对原图做裁剪放大输入到下一个尺度。整个过程用SGD联合训练。我实际复现时发现它有两个关键细节值得注意。第一注意力图的生成方式不是简单用softmax而是用一个全连接层回归出注意力框的参数框的位置和大小是连续可微的这就保证了梯度可以回传到注意力生成模块。第二三个尺度之间是递进关系后一个尺度的输入依赖于前一个尺度的输出所以训练时要把整个网络当作一个端到端的整体来调优不能分开训练各部分。实验结果表明RA-CNN在CUB-200-2011上取得了当时的最优结果。我自己的复现虽然没有完全复现论文的数字但相比单尺度基线确实有稳定的提升大约涨了2到3个百分点。这个方法的理念影响了很多后续工作包括后来基于Transformer的多尺度特征交互某种程度上也是RA-CNN思路的延伸。3.3 论文三TransFG 与 Transformer 在细粒度识别中的迁移《TransFG: A Transformer Architecture for Fine-grained Recognition》发表于AAAI 2022是Vision Transformer应用到细粒度任务的代表工作之一。TransFG的核心是基于ViT的结构利用Transformer的自注意力机制自动定位具有区分度的局部区域。它提出的具体做法是在ViT的最后一层之前选取若干注意力头对每个注意力头的注意力图进行加权融合得到一组局部区域标记Patch Tokens再用这些局部标记做分类或检索。我觉得TransFG最有启发的部分在于它把注意力头的多样性利用起来了。不同注意力头关注的区域差异很大有的关注鸟的翅膀尖有的关注鸟的嘴部把这些多样的注意力信息整合起来就隐式地覆盖了多个判别性局部区域。这个思路本质上是把之前多尺度注意力的概念换了一种实现方式。从实验结果看TransFG在CUB-200-2011上的分类准确率接近90%比之前最好的CNN方法高了不少。但我也注意到TransFG的推理速度比CNN方法慢很多这在真实检索场景中是个不小的问题。所以在落地时需要根据场景权衡精度和效率。3.4 读论文时画的三张图问题图、方法图、实验图读论文这么多年我形成了一个习惯每篇论文至少画三张图不画清楚不算读懂。第一张是问题图。这篇论文瞄准的问题是什么是类间差异小还是类内差异大是局部特征提取不准确还是特征空间度量不合理把问题画清楚你才能判断这篇论文的贡献点到底在哪里。第二张是方法图。输入是什么经过哪些模块每个模块的输入输出是什么模块之间如何连接训练时哪些模块是端到端的哪些是分开训练的。这张图画完你基本上就可以复现这篇论文了因为方法的每个环节都清清楚楚。第三张是实验图。论文用了哪些数据集对比了哪些方法评价指标是什么涨了多少点。这张图看起来简单但信息密度很高它能帮你快速定位这个方向当前的技术水平以及哪些研究组在这个方向上有持续产出。这三张图画完之后我会在笔记里写一段如果我来做的感想思考如果让我改进这个方法我会从哪个环节入手。这个习惯让我在写论文、想idea时受益很多相当于每次读完都在脑子里做了一次头脑风暴。4. 实验评估数据集、指标与直接能用的训练配置4.1 常用数据集与划分方式细粒度图像检索和识别常用的数据集就那么几个我把它们的基本情况整理一下方便你快速做选型。CUB-200-2011是整个领域最经典的数据集包含200种鸟类、约12000张图像。官方划分是测试集和训练集各占约一半按类别划分保证训练集和测试集没有重复类别。这个数据集也是评估大多数细粒度方法的默认基准。Stanford Cars包含196种车型、约16000张图像。相比CUB它的类内差异更大因为同一年款不同颜色的车外观差异甚至比不同年款还大这对特征提取提出了更高要求。车类数据的纹理特征比较明显模型容易学到整体形状信息难度比鸟类低一些。FGVC-Aircraft是飞机数据集包含100种飞机型号、约10000张图像。它的特点是类间差异极小波音737和空客A320在外观上的差别很细微主要集中在机翼、引擎、尾翼等部位是挑战性很高的数据集。此外还有Stanford Dogs、Oxford Flowers、iNaturalist等。iNaturalist是长尾分布的大规模物种数据集类别数能到几千甚至上万更贴近真实应用。做研究时我建议最初在CUB-200-2011上验证思路然后迅速在另外两个中等数据集上做交叉验证不要只盯着一个数据集调参容易过拟合到特定分布上。4.2 评估指标RecallK 与 mAP 的直观理解检索任务最常用的指标是RecallK。简单说你给一张查询图系统返回排序后的K张图如果K张图里至少有一张和查询图属于同一类别就认为这次查询命中。RecallK就是所有查询中命中的比例。我举一个具体例子。测试集有1000张查询图设定K1系统对每张查询图只给最相似的1张结果如果这1张结果的类别和查询图一致就算命中。假设1000次查询中命中了650次那么Recall1就是65%。mAP则更严格一些它考虑的是排序质量而不仅仅是第一个结果对不对。mAP的计算方式是对每个查询计算其检索结果序列中每个正确结果位置的精确率再对这些精确率取平均得到该查询的平均精确率AP最后对所有查询的AP求平均就是mAP。我自己的经验是如果任务更看重找到至少一个正确结果比如找相似款商品那RecallK够用如果任务需要评估整个排序的质量比如推荐系统里用户会翻看很多结果那mAP更合适。写论文时通常两个指标都会报审稿人也很在意这个。4.3 实验配置范例以 ResNet50 为骨干的训练方案这里给出一份可以直接拿来用的实验配置。骨干网络我用ResNet50预训练权重来自ImageNet的监督训练。数据集使用CUB-200-2011。首先图像预处理。训练阶段把图像缩放到256x256然后随机裁剪到224x224加上随机水平翻转、随机颜色抖动这些数据增强能明显提升模型的泛化能力。测试阶段把图像缩放到256x256再中心裁剪到224x224不做其他增强。其次训练设置。优化器选用SGD初始学习率0.001动量0.9权重衰减1e-4。批量大小32训练60个epoch。学习率在第30和第45个epoch分别乘以0.1。损失函数用标准的交叉熵损失用于分类如果做检索可以在分类头之后接一个特征提取分支配合Triplet Loss一起优化。多任务损失是细粒度检索里很常见的做法。我一般用加权和的思路总损失等于交叉熵损失加上系数为0.5的Triplet Loss这样模型既能学到判别性特征又能学到度量结构。你需要根据具体数据集调整这个系数没有标准答案多试几次就有了手感。训练完成后取倒数第二层全连接层输出作为图像特征向量对特征做L2归一化然后计算查询图特征和数据库图特征的余弦相似度按相似度排序输出检索结果。这里有个小坑特征归一化非常关键不归一化的话每个特征的模长差异会严重干扰相似度排序我在早期实验里因为这个细节吃了不少亏后来固定下来先归一化再检索。一套配置在单张RTX 3090上CUB-200-2011完整训练大约需要3到4小时。如果你用的是A100或4090训练时间会进一步缩短。5. 复现实验的常见问题与排查实录5.1 环境与显存问题研一的时候我复现一篇论文花了一整天配置环境最后在batch size上栽了跟头。16G显存按论文设置batch size64直接OOMOut of Memory。当时我的第一反应是买更大的显卡后来才意识到可以通过梯度累积Gradient Accumulation解决。梯度累积的思路很简单batch size设16每次反向传播后不更新参数累积4次后再更新效果近似于batch size64。损失函数要注意累积时损失除以累积步数或者直接用平均损失不然数值会偏大。这个技巧让我的12G显存也能跑起大部分论文的实验配置非常实用。另外混合精度训练也值得强烈推荐。PyTorch的torch.cuda.amp模块用起来很顺手只要在forward和backward外面包一个autocast上下文再加上GradScaler基本不需要改其他代码。开启混合精度后显存占用能减少三分之一到一半训练速度还有提升代价是loss在极少数情况下会异常抖动需要用GradScaler做梯度缩放来缓解。5.2 数据加载与标签噪声问题细粒度数据集的标签质量直接影响模型上限。CUB-200-2011这类专业数据集标签相对可靠但如果你自己构建数据集很容易出现同一张图片被标成两个类别标注框偏移这类问题。我踩过一个特别具体的坑从爬虫抓取商品图构建细粒度服装检索数据集时很多图片的标签是错的同款不同色的衣服被归到不同类不同款但颜色相近的反而归到同一类。模型训练出来的特征严重漂移。排查方法也很简单训练初期看混淆矩阵哪些类别之间错得最多就把这些类别的原始图像调出来人工看十有八九是标签本身出了问题。另外细粒度数据集普遍存在类别不平衡问题iNaturalist更是长尾分布。我建议在训练时用Class-balanced Sampling或者简单的加权抽样让每个类别在batch里出现的频率相对均衡。这个方法虽然简单但在长尾场景下的提升非常明显。5.3 模型不收敛或收敛到平凡解细粒度模型训练时最容易出现两个问题损失不下降或者损失下降但准确率停滞。损失不下降先检查学习率。Transformer类模型一般需要更小的学习率我习惯用1e-5到5e-5CNN可以用1e-3到1e-4。如果Loss很早就开始震荡八成是学习率太大。损失下降但准确率停滞问题可能在数据增强太强或太弱。太强会导致模型学不到细粒度信息太弱会导致过拟合。我常用的排查方法是在训练集的一个小批量上看模型的loss能不能降到非常低如果能说明模型容量够问题在泛化如果不能说明模型结构或数据预处理有问题。还有一个容易踩的坑是注意力塌缩模型注意力收敛到固定区域比如总是关注背景里的草地。这时你需要检查注意力可视化结果如果明显不合理可以尝试增加注意力正则化损失或者增大dropout来提高注意力头的多样性。5.4 检索结果可视化时的坑检索实验最后一步是可视化结果这一步虽然不涉及训练但坑也不少。最典型的坑是显示图片时颜色不对。因为很多细粒度数据集里的图像是BGR格式直接用matplotlib显示会变成红蓝色调错乱。我每次写可视化代码时都要提醒自己加一行img img[:, :, ::-1]把BGR转成RGB。另外在输出查询图-检索结果图的拼接图时建议把每张结果图下方的文字标注清楚类别标签和相似度分数这样你才能快速分析模型为什么检索错了。我通常会生成两个文件夹一个存正确检索的案例一个存错误检索的案例然后逐个分析错误案例这种方法能非常有效地定位模型的盲点。检索结果可视化还能帮你发现数据集的bias问题。比如模型经常把绿叶背景的鸟A错检成绿叶背景的鸟B那可能是模型学到了背景而非鸟本身这时就需要通过数据增强或者更多样化的训练数据来缓解。6. 我的论文笔记方法论6.1 笔记模板与五段式记录法笔记方法是我最想分享的内容之一。我刚开始读论文时每次都是读完就忘两个星期后想起来完全不记得那篇论文用了什么方法。后来我开始用一套固定的笔记模板坚持了一年多效果非常好。这套模板分五段。第一段是一句话总结用不超过三句话讲清楚论文做了什么、解决了什么问题。如果写不出来说明还没读懂。第二段是方法拆解把方法流程用流程图或者步骤列表的形式画出来。第三段是关键实验记录数据集、指标、主要对比结果。第四段是优缺点分析写下我的评价。第五段是与我工作的关系思考这篇论文对我当前的研究或项目有什么启发。五段式记录法最核心的一点是用自己的话重写。你不能只把论文摘要复制粘贴过来那样等于没读。你必须用自己的理解重新组织语言这个过程会强制你去思考论文每个环节的逻辑关系。6.2 后续可以扩展的方向细粒度图像检索这个方向我自己梳理出几个值得继续关注的研究点。第一个是把更细粒度的语义信息引入检索。大多数现有方法只看图像本身其实很多细粒度类别的区分还需要领域知识。比如鸟类识别时知道这种鸟主要分布在中国东部就能大大缩小检索范围。如何把这种外部知识融入模型是一个很有价值的方向。第二个是跨模态细粒度检索。用户输入一段文字描述比如一只黄腹蓝背的鸟嘴部细长系统返回对应的鸟类图片。这种以文搜图的细粒度检索在技术上更有挑战性也更贴合实际应用。CLIP这类多模态模型给这个方向提供了很好的基础但细粒度问题的特殊性意味着还需要专门设计。第三个是训练数据的效率问题。细粒度标注成本极高如何用更少的标注数据达到可用的检索效果这是一个实际痛点。半监督、自监督、主动学习这些策略在细粒度任务上还有很多可以挖掘的空间。第四个是高效推理。Transformer模型精度虽高但推理速度慢在移动端根本跑不起来。如何在保持细粒度精度的情况下做模型压缩和加速是落地时绕不开的问题。如果让我给刚入门的朋友一个建议我会说不要一上来就追最新的论文先把CUB-200-2011上的经典方法复现一遍感受一下数据的特点理解每个方法的设计动机再去做改进。有了这些基础后面读新论文会快得多你要做的只是理解新方法在哪个环节做了改动、为什么改。这个方向没有太多玄学核心就是找到关键局部区域和拉大特征空间中的类间距离这两件事。把这两件事想透了读任何细粒度论文都不会迷路。
返回列表