☰
DeepEMD详解:用最优传输与局部特征匹配突破小样本分类瓶颈
2026/10/14 1:42:11 网站建设 项目流程

1. 先搞清楚DeepEMD到底在解决什么问题

1.1 小样本分类里三个躲不开的老问题

做小样本分类(Few-Shot Image Classification)的人,基本都被三个问题反复折磨过。第一个是数据量太少,支持集里每个类别只有一两张图,模型稍微复杂一点就过拟合;第二个是类别集合不确定,训练时见过的类别和推理时遇到的类别完全不同,模型没法靠“记忆类别”来工作;第三个是分布漂移,支持集的图像和查询集的图像可能来自不同的拍摄条件、清晰度、背景环境,直接用全局特征做距离比较,结果经常飘得厉害。

早期方法(比如度量学习那一派)基本思路是:把图像编码成一个全局特征向量,然后在这个向量空间里用固定的距离函数(欧氏距离、余弦相似度)去比较查询图和支持图。这个思路简单,但有一个明显的天花板——全局向量把一整张图压成一个点,空间细节全丢了。一张图里猫在左边、狗在右边,和猫在右边、狗在左边,全局向量可能非常接近,但语义上完全不同。细粒度分类(比如区分不同种类的鸟、不同品种的狗)更是重灾区,两张图全局相似度都很高,差别只在鸟嘴或翅膀花纹的几个像素区域。

这就引出一个直觉:能不能别只比较一个全局特征,而是把两张图拆成若干个局部特征,让它们“按位置”或者“按语义”逐个匹配?DeepEMD正是沿着这条线往前走的一大步。它用Earth Mover’s Distance(EMD,即推土机距离)来做图像相似度度量,把本来要用在分布距离上的最优传输思想,搬到了小样本图像分类的特征匹配里。

1.2 为什么“局部特征加匹配”的思路比全局向量更合理

先说结论:局部特征匹配更接近人眼判断两张图是否相似的直觉。人看两张图是不是同一类,不会先把整张图信息压缩成一个数字再比较,而是会找对应的部位——看这个是不是同样是尖嘴、同样是白肚皮、同样是细长腿,然后综合一组部位证据下判断。

放到特征图上来说,图像经过卷积网络之后得到的是一个三维张量(通道、高度、宽度),每个空间位置对应一个局部特征向量。这个向量编码的是该位置附近一个小区域的语义信息。小样本场景下,支持集和查询集之间往往存在较大的外观差异(比如背景不同,或者拍摄角度不同),全局池化会把“属于该类物体的特征”和“属于背景的特征”混在一起算平均值,而背景又恰恰是变化最大、最不可靠的部分。如果让模型自己决定哪些局部特征应该被匹配、哪些应该被忽略,等于把“注意力”也纳入了距离度量本身。

于是DeepEMD的核心问题就变成了:给定支持图S和查询图Q的局部特征集合,如何定义一个可行的、可微的“匹配成本”,让模型在训练过程中能端到端地学习这个匹配过程本身。这才是全文真正要解决的技术难点。下一部分详细讲它怎么用最优传输来做这件事。

2. EMD距离凭什么能做图像相似度:最优传输的直觉与数学

2.1 搬土问题:从交通运输到图像匹配

EMD的历史典故很有意思——它原本是研究“如何以最低成本把一堆土从一个地方搬到另一个地方”的数学问题。假设你手上有几个土堆,每个土堆有不同的大小,你需要把它们的总量重新分配到另一批指定大小的坑里,而每个土堆到每个坑之间有一个运输成本(通常用距离表示),问:最优的搬运方案是什么,最小总成本是多少?

这个框架映射到图像匹配上非常自然。把支持图的局部特征集合看成“供应方”,每个位置的特征向量就是一个土堆,特征向量和查询图某个位置特征向量之间的距离(1减去余弦相似度)就是运输成本,查询图的局部特征集合就是“需求方”。最后EMD的值就是在这种最优搬运方案下的总花费。

有意思的地方在于,这不是让每个土堆一对一地搬到对应的坑里去,而是允许“一个土堆拆开给多个坑,一个坑接受多个土堆”,只要总量守恒就行。这正好对应图像匹配里一个非常普遍的情况:支持图里某个关键部位的特征,可能在查询图里被多个局部区域共享语义(比如“羽毛纹理”这种区域特征)。如果是硬性的逐一匹配,这种情况就处理不了。

2.2 cost矩阵与可学习的距离

具体到DeepEMD的计算流程:支持集图像S和查询集图像Q分别经过同一个特征提取网络,得到两个特征张量,维度都是(d,H,W)。把空间位置展平,支持图有M个局部特征,记为 u_1, ..., u_M,查询图有N个局部特征,记为 v_1, ..., v_N。于是可以构造一个M×N的成本矩阵C,其中每个元素:

c_ij = 1 - (u_i · v_j) / (||u_i|| · ||v_j||)

这就是把余弦相似度取反,变成“距离越大成本越高”的形式。为什么用余弦相似度而不是欧氏距离?因为局部特征向量经过卷积网络之后,其模长不一定有稳定的语义含义,而方向(也就是归一化之后的向量)通常包含更丰富的类别判别信息,余弦相似度恰好只比较方向,对模长变化不敏感,在小样本这种小数据场景下更稳。

2.3 Sinkhorn迭代:让最优传输可微的关键

直接求解EMD(线性规划问题)在计算上是可解的,但有个致命问题:线性规划求解器的梯度很难回传,没法直接嵌入到神经网络里端到端训练。DeepEMD的工程贡献就在这里——它使用了熵正则化的最优传输,也就是通过Sinkhorn迭代来近似求解EMD,而Sinkhorn的每一步都是可微的,可以放到网络里作为一层普通的可微模块。

熵正则化的思路是给原始的运输问题加一个熵惩罚项,使得解变得平滑、唯一、容易迭代求解。加上正则项之后,可以用交替归一化来逼近最优解。如果用伪代码表示,大概是这样的:

def sinkhorn(cost, p, q, epsilon, iterations=50): # cost: (M, N) 运输成本矩阵 # p: (M,) 供应方权重,满足 sum(p) = 1 # q: (N,) 需求方权重,满足 sum(q) = 1 K = torch.exp(-cost / epsilon) u = torch.ones_like(p) for _ in range(iterations): v = q / (K.T @ u) u = p / (K @ v) transport_plan = u[:, None] * K * v[None, :] distance = (transport_plan * cost).sum() return distance

这个迭代过程通常在几十步内就能收敛。epsilon是熵正则化强度,它越大,解越“软”,传播越均匀;它越小,越接近真正的线性规划解,但数值上容易不稳定。我在复现时发现这个参数相当敏感,实际工程上要在稳定性和准确性之间找平衡。更重要的是,这个sinkhorn过程可以分解成矩阵乘法、逐元素乘除法、指数函数,这些全部可微,所以整个EMD模块可以作为一层放进网络里用反向传播训练。

带权重EMD的约束条件比基本版更复杂一些。基本版要求 sum_i sum_j f_ij = 1;加了局部重要度权重之后,约束变成 sum_j f_ij <= p_i, sum_i f_ij <= q_j,其中p_i和q_j分别是支持图和查询图局部特征的重要性权重,这也引出了后面要讲的第3个模块。

3. 三个关键模块:结构相似度、重要度权重与特征适配

DeepEMD不是只把EMD往网络里一插就完事。直接在原始特征图上计算EMD会有个问题:背景区域、非判别性区域也会参与匹配,这些区域既不稳定又浪费时间。论文为此设计了三个组件,它们各有分工,配合起来才有最终的效果。

3.1 结构相似度:先过滤掉“根本不是同一个东西”的匹配

第一个组件叫结构相似度度量,目的是在计算cost矩阵之前,先判断支持图和查询图的某些局部位置是否具备“可匹配性”。如果支持图的某个位置和查询图的某个位置,它们在各自特征图里的局部上下文差异极大,那就说明这两个位置很可能不是在描述同一类语义区域,强行匹配只会引入噪声。

具体做法是:对每个局部位置,取它周围邻域内的特征向量集合,计算它们的方差(variance),得到一个标量。方差的大小可以当成这个位置特征是否“尖锐”的度量,尖锐的特征通常对应明确的语义边界或关键部位,平坦的特征通常对应背景或平滑区域。如果支持图某个位置方差很低(是个平坦背景)而查询图对应位置方差很高(是个关键部位),说明两边语义不匹配,那就把cost矩阵中这个位置对的值设为一个很大的常数,让最优传输求解器“知难而退”,不去搬运这两堆土。

我个人的理解是,它是在模仿人的一种预判机制:人在对比两张图时,会先快速排除掉那些明显不是同一个东西的区域,再集中精力比较可疑区域。结构相似度就是这个“预筛过程”。它不参与可学习参数的优化,是一个固定的预处理操作,但实验证明它的存在让整体准确率提高了不少。

3.2 重要度权重:让网络自己决定哪些位置值得匹配

结构相似度是硬过滤,重要度权重就是软过滤。论文用一个可学习的模块给每个局部特征生成一个权重值,代表“这个位置在度量类别相似度时有多重要”。权重会参与EMD的约束条件:供应方(支持图)的权重分布 p 和需求方(查询图)的权重分布 q 不再均匀,而是由网络学习出来的。

怎么学习这个权重?论文的做法是把局部特征(连同它的上下文信息)送入一个小型的网络,输出一个标量,然后在这个标量上做softmax归一化。注意softmax放在哪个维度上是有讲究的:它是把同一张图内的所有局部位置的权重归一化到和为1,这样每个图作为一个整体的“土量”是固定的。

这个设计对应一个很重要的直觉:EMD原本是假设每个土堆和每个坑的“总量”是固定的,但图像特征里的每个局部位置,它们的重要性天然就不一样。比如鸟类的头部区域可能比脚部区域更能区分不同品种,那么模型应该把更多权重分配给头部的局部特征。重要度权重的引入让距离度量本身不再是一个固定的成本函数,而是变成了一个随输入变化的、数据依赖的度量。这一步非常关键——它实际上是在学“怎么比较两张图”而不是只学“怎么编码一张图”。

3.3 特征适配:把查询特征拉到支持集的坐标系里来比较

第三个组件是特征适配(feature adaptation)。小样本场景中支持集和查询集之间的特征分布往往有偏移,比如支持集图片拍摄于晴天、查询集图片拍摄于阴天,即便同一类物体,其特征分布也会有系统性的差异。直接比较原始特征会有偏差。

特征适配的思路是:利用支持集的局部特征作为“基底”,把查询集的局部特征重新表示成这些基底的加权组合,从而把查询特征“拉”到支持集所在的分布空间里。这是个类似注意力的机制:查询图的每个局部特征都去和支持图的局部特征算相似度,得到一组权重,然后用这个权重对支持图的特征做加权求和,得到适配后的查询特征。

这样做的好处是,它让每张查询图都基于当前任务的支持集内容进行了特定调整,分类器不再是被动地在一个固定的特征空间里做距离判断,而是主动适应每个任务。这个组件和重要度权重是互补的——重要度权重决定“哪些土堆值得搬运”,特征适配决定“搬运之后土堆放在哪个坐标系里看”。两者可以同时使用,消融实验表明同时使用的效果要优于单独使用任何一个。

4. 训练与推理:密集对比损失和三种评估方式

4.1 密集对比损失:比整图分类更严格的监督

有了EMD距离模块之后,最自然的训练方式就是“用EMD距离做softmax分类,算一个交叉熵损失”。但这个做法有一个隐患:它只约束了图级别的匹配结果,没有约束局部特征级别的匹配质量。

举个例子,某张查询图整体被判为类A正确,但可能它的很多局部区域匹配到了错误类别的支持图特征上。图级别的分类误差会让梯度变得很稀疏,模型不知道该优化哪些局部特征的匹配路径。于是论文引入了密集对比损失(Dense Comparison Loss):对查询图的每一个局部位置,单独计算它和支持集中每个类别“局部原型”的匹配程度,然后对该位置的分类结果也做交叉熵损失。

这里的“局部原型”是指把支持集中某个类别所有图像的局部特征在对应位置上取平均得到的特征。这样,查询图的一个局部特征如果匹配到了一个类别上,它就不仅影响整图预测,还直接参与该位置自己的监督信号。最终的总损失是稀疏损失和密集损失的加权组合。

这个损失和我之前看过的很多度量学习损失都不太一样。大多数方法是在图级别拉近类内距离、推开类间距离,而密集对比损失直接拉近了“每个局部位置”与“正确类别原型区域”的距离。它相当于把监督信号下放到了特征图的每一个空间位置上,让特征提取网络被迫学习到更有区分度的局部特征。训练的时候梯度信号密度高了很多,模型收敛也更稳定。

4.2 ST / MT / MP三种推理协议

论文在评估时区分了三种任务协议,这个细节容易被初学者忽略,但理解它有助于搞懂论文实验设计。

ST(Single-way one-shot)是每次只把查询图和单个类别的支持图进行匹配,看两张图是否属于同一类。这种设置比较“理想化”,类别少、匹配简单,论文用它来做一些组件分析和可视化实验。MT(Multi-way one-shot)是标准的5-way 1-shot设置,从5个类别里区分查询图属于哪一类,支持集每个类别只有一张图。MP(Multi-way multi-shot)则是更接近实际应用的5-way 5-shot,每个类别有多张支持图,需要把多个支持图像的局部特征在对应位置上取平均形成“类原型”,然后再和查询图计算EMD距离。

有意思的是,在MP场景下,多张支持图平均之后得到的“类原型局部特征”比单张支持图的局部特征更稳定、更少噪声,所以EMD匹配的收益会比ST和MT更明显。这也说明DeepEMD的匹配机制在数据稍微多一点的时候也能自然扩展,不会像很多基于单张图匹配的方法那样面临“不会用多张支持图”的尴尬。

推理时,预测标签直接取EMD距离最小的那个类别。整个过程不需要额外的可学习分类器头,解码逻辑极简。

5. 实验验证与复现踩坑

5.1 数据集与公开结果

DeepEMD在当年的标准小样本基准上做了全面评测,包括常用的小样本数据集。以miniImageNet上的5-way任务为例,论文报告的结果我记得在1-shot设置下能达到65.9左右的准确率,5-shot能到82.4附近。tieredImageNet上1-shot大约在71.7,5-shot大约在86.4。CIFAR-FS和CUB细粒度数据集上也都有明显提升。

横向对比当年主流方法:基于特征嵌入的度量学习方法(ProtoNet、RelationNet等)在miniImageNet 5-way 1-shot上普遍在60上下,DeepEMD的65.9可以说是一次比较大的跳升,把当时的SOTA往上推了不少。尤其是在细粒度分类CUB上,局部特征匹配带来的收益更突出,因为细粒度数据集的类别差异本来就集中在局部区域,全局特征基本不管用。

还有一个值得注意的点:论文在使用更强backbone(比如ResNet-18、WRN)后,性能还能继续往上走,说明EMD匹配不是某种只在小网络里有效的“巧合”,而是对更丰富特征表达能力也有需求的机制。

5.2 复现时的超参数敏感性

我实际复现的时候,最大的感受是:这个模型的性能对训练策略比较敏感,对模型本身的组件更敏感。先说组件:去掉结构相似度过滤,准确率掉一到两个点;去掉重要度权重,掉一到两个点;两个都去掉,直接回到普通余弦相似度水平。这说明每个组件都在真实起作用,不是论文的“包装”。

再说训练。resize分辨率、数据增强策略对结果影响很大,小样本训练本身就很吃数据增强。我在复现时把随机裁剪和颜色抖动调强之后,1-shot分数提升了差不多一个多点。这本质上是因为小样本任务中特征提取网络的泛化能力比匹配模块本身更影响上限,增强是给特征提取网络“喂更多视角”的有效手段。

Sinkhorn迭代的超参数里,最敏感的是熵正则化系数epsilon。epsilon取太大,传输矩阵变得过于均匀,匹配失去特异性;取太小,迭代过程数值容易发散,偶尔会出NaN。我自己的做法是在训练初期用一个稍大的epsilon保证稳定,训练中后期逐步调小,让匹配更“锐利”。此外迭代次数一般50步足够,再增加精度改善也可以忽略,但计算量线性增长,不划算。

5.3 和其他小样本方法的对比

Revisiting一下当时和DeepEMD竞争的方法,会发现一个有趣的差异:当时主流路线分两派,一派是优化特征提取网络(比如用更强的元学习策略、更强的backbone),另一派是优化分类策略(比如用更复杂的分类器、加transductive learning)。DeepEMD选的是一条中间路线——特征提取网络可以沿用经典结构,但它把“比较距离”这件事重新定义成了可学习的EMD。这带来的好处是它和很多其他改进可以正交叠加:你可以在它上面换更强的backbone,也可以叠加transductive处理,还能进一步优化特征适配模块的结构。

这个观察后来对我自己设计小样本方法也有启发:与其在一个维度上死磕,不如想想“比较方式本身”还有没有更好的建模空间。距离函数不一定是固定的,也不一定非要学习一个超球面映射,直接学习“怎么把两张图的局部特征搬到一起匹配”也可以是有效思路。

6. 我的整体评价与后续启发

6.1 DeepEMD的边界和适用场景

深读之后,我也梳理了一下它注定存在的限制。首先,EMD的计算复杂度是O(M·N),其中M和N分别是支持图和查询图的局部特征数量,特征图分辨率高的时候这个矩阵乘法和迭代会相当吃显存和算力。我当时用单卡训练,batch size不敢开太大,训练速度跟同年代的ProtoNet比慢了不止一倍。所以它在计算资源充足、离线训练场景下没问题,边缘端或实时场景基本不用考虑。

其次,EMD对特征图空间尺寸比较敏感。如果backbone最后输出的特征图空间分辨率太低(比如只有1x1),EMD退化成全局向量比较,效果自然就没优势了。这就决定了它不太适合直接用在那些特别深、特别窄的网络结构上。需要保证特征图有足够的空间信息承载“局部匹配”这件事。

还有一个边界是:它本质上是在做“图像与图像”或“图像与原型”的距离建模,如果支持集图像本身质量很差(比如严重遮挡、模糊),局部特征的可靠性会受影响,EMD的匹配质量也随之下降。这一点上和所有局部特征方法一致——局部特征再强,也得先有信息可以提取。

6.2 它的思想在后续工作里留下来了什么

这篇论文最让我觉得有价值的地方,不是它拿了多少个SOTA,而是它把两个原本离深度学习图像分类比较远的概念成功落了地:一个是可微的最优传输模块,一个是“比较方式也可以学习”的思路。后来我做其他方向时发现,在点云匹配、跨模态检索、甚至图像生成的质量评估里,都能看到和DeepEMD同源的思想——用最优传输来度量两组特征之间的差异。

如果你准备读这篇论文,我的建议是:先动手复现最简单的版本——用ResNet-12提取特征,只保留EMD距离模块和交叉熵损失,在你熟悉的小样本数据集上跑通,确认cost矩阵和Sinkhorn迭代的实现没有bug。然后一个个把结构相似度、重要度权重、特征适配加回去,每加一个记录一次准确率变化,这样比直接读完全文再去复现完整版要高效得多。我当时就是这样一步步啃下来的,过程中对“距离度量本身也是参数”的理解,比看十遍公式都来得更深。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询