
跨模态行人再识别这个话题我在做某跨平台系统的人形识别模块时啃了很久。项目标题里说的“基于双阶段度量学习”说白了就是一个非常务实的思路先让可见光RGB和红外IR各自的特征提取器把本模态的数据先学好再通过第二阶段把两个模态的特征拉进同一个度量空间解决“白天看得清、晚上靠红外”导致的人脸和行人ID对不上的问题。这个方案给我最大的感受是它不像某些端到端黑盒那么难调也不像纯手工特征那么落后而是把训练过程拆成了两个有明确目标的阶段每一步都能监控、能诊断。这篇文章把我从模型选型、损失函数设计、批次构造到踩过的坑和调参心得全部整理出来适合正在做ReID、跨模态检索或者安防视频分析的同行参考刚入门的朋友也能照着一套流程复现出可用结果。1. 项目到底在解决什么问题1.1 跨模态行人再识别难在哪行人再识别Person Re-ID本身的任务是给一张查询图在跨摄像头的图库中找出同一个人。常规的单模态ReID大家已经做得比较成熟了但一旦换成跨模态也就是用红外图去搜RGB图库、或者反过来指标会掉得非常厉害。原因也很直接RGB图像有丰富的颜色信息而红外图像是灰度热成像两者的像素分布差距极大。同一个人的蓝色外套在RGB里是蓝色调在红外里可能就是一个亮灰色的区域颜色通道根本没有可比性。这种“模态鸿沟”会让传统模型产生严重的分布偏移。在单一模态上训练好的特征提取器迁移到另一个模态上时提取到的特征分布完全不同算出来的距离就没有意义。我见过很多第一次接触跨模态ReID的朋友第一反应是把两个模态的图混在一起直接训练一个分类模型结果发现模型学会了按模态分类而不是按行人ID分类——因为这个信号太强了模型默认“看起来不同的东西就是不同的类别”。1.2 双阶段度量学习为什么是合理的解法所谓双阶段度量学习核心是把“模态内学习”和“跨模态对齐”分开处理。第一阶段让每个模态各自学习判别性特征第二阶段再通过度量学习把两个模态的特征空间对齐。这个思路和人类认知比较像你先认清楚RGB下这个人长什么样再认清楚红外下这个人长什么样最后才知道这两张图其实是同一个人。选这个方案而不选端到端硬train的原因有几个。第一跨模态数据通常量不大端到端强制对齐容易过拟合分阶段训练可以通过预训练用好单模态数据。第二度量学习的目标函数三元组损失、中心损失等需要相对稳定的特征作为基础第一阶段先把特征训得“像样”第二阶段做对齐时才不会梯度乱飞。我在实际项目里把第一阶段看作预热第二阶段看作精调整个训练过程的可控性比单阶段好太多。2. 双分支骨干与双阶段方案的整体设计2.1 网络整体结构两个分支一个共享度量空间整个网络采用双分支结构RGB分支和IR分支各自独立。主干网络我用的是ResNet-50两类输入尺寸统一为224x224。RGB分支输入三通道图像IR分支输入的是单通道热成像图我选择复制三份变成三通道这样可以复用ImageNet预训练权重实验对比下来比单通道输入效果好。这里有一个关键设计点两个分支不是完全独立的。ResNet-50前面的几个block可以各自初始化但从第三层开始采用部分权值共享让深层特征逐步对齐。这个设计在第一阶段帮助不大但在第二阶段非常关键——共享权值等于给跨模态对齐提供了一个天然的桥优化器只需要在有限的方向上做调整。特征提取之后两个分支的特征都接一个全局平均池化再经过一个embedding模块映射到512维的共享度量空间做L2归一化后再计算各种距离和损失。2.2 第一阶段让每个模态先学会分辨行人第一阶段的目标很简单分别用RGB数据和IR数据训练各自的分支让每个分支都具备足够的行人判别能力。损失函数就是标准的cross-entropy分类损失配合softmax分类器。数据集里每个行人是一个ID类训练时用行人的ID做分类标签。这个阶段我加了两个细节。第一个是label smoothing设置为0.1。跨模态数据集通常存在同一个人在不同模态下的外观差异很大的样本如果标签做太硬的one-hot模型很容易过拟合到个别样本的噪声上。第二个是随机擦除只对RGB分支用因为红外图做随机擦除会破坏本来就稀缺的热成像轮廓信息。这个阶段训练大约30个epoch学习率从1e-3开始用cosine退火降到1e-4。第一阶段训完后我会单独跑一次单模态的re-ranking验证在RGB图库中检索RGB查询图以及在IR图库中检索IR查询图。如果两个模态各自的Rank-1准确率都能到比较合理的水平说明第一阶段过关了。这里我踩过一个坑只关注总准确率不看分模态准确率结果第二阶段怎么调都差一口气最后发现是红外分支在IR图库上自身就检索不准基础没打好。2.3 第二阶段跨模态度量对齐与联合优化第二阶段是项目核心。此时冻结主干网络前两层的权值只微调深层和embedding模块同时引入三部分损失联合优化。第一部分是跨模态三元组损失。在每个训练迭代中以某一模态的样本为锚点在其相同模态中取正样本在另一个模态中取负样本构造跨模态三元组。这样模型被迫学会忽略模态差异、关注行人身份差异。这个三元组的margin我设置为0.3太大导致难样本过多训练不稳定太小又拉不开类别距离。第二部分是跨模态中心损失。传统中心损失是为每个类别维护一个特征中心我这里每个类别维护两个中心——RGB中心与IR中心然后用一个回归项把两个中心的距离拉近。这个思路本质上是给模态对齐加了一个类和类之间的强约束比单纯靠三元组更稳定。第三部分是身份分类损失仍然保留确保对齐过程中不丢失判别性。整个第二阶段的总损失是这三个损失的加权和三元组损失权重1.0中心损失权重0.1分类损失权重0.5。我用这个配置训60个epoch左右特征空间的跨模态分布就明显收敛了。3. 核心实现与实操细节3.1 数据准备、预处理与校验数据上我使用的两个主流公开benchmark一类是校园监控场景的大型RGB-IR数据集另一类是相对较小的双摄像头配对数据集。它们共同的问题是红外图像数量明显少于RGB图像且同一行人的RGB和IR拍摄时间、姿态差异很大。预处理流程是这样的所有图像按短边缩放并中心裁剪到224x224。RGB图做随机水平翻转、随机擦除和轻微色彩抖动IR图只做随机翻转和轻微的高斯噪声添加。这里要特别强调IR图的标准化参数不能复用RGB的均值和方差需要单独统计IR数据集的像素均值和方差。我一开始直接沿用ImageNet的标准均值方差红外分支收敛明显变慢换回IR数据自己统计的均值方差后收敛速度提升明显。训练批次构造是另一个决定性细节。我采用P个行人、每个行人K张RGB、K张IR的组织方式一批里包含P×K×2张图。P设为4K设为8是一个稳妥起步点显存不够可以降到P4、K4。这种构造方式保证了一批内既有同模态的正负样本又有跨模态的正负样本让每一个梯度更新都能同时作用于判别性学习和模态对齐。3.2 关键组件模态专属BatchNorm的重要性这个组件是我认为本项目性价比最高的一处设计。标准的BatchNorm在混合了两个模态数据的批次里会被“平均化”因为RGB和IR的batch统计量差异很大同一个BN层被迫去适配两种分布最后往往两头不讨好。我改成模态专属BNRGB分支用一套BN统计量IR分支用另一套BN统计量即使权值共享也互不干扰。实操时我是在ResNet的每个残差block里把BN层替换成两个并行的BN实例前向时根据输入来自哪个模态选择对应的BN。这个改动带来的提升非常可观在我的配置下Rank-1直接涨了将近4个百分点而且模型收敛更稳定。原理上也好理解BN本身就是对数据分布做归一化模态不同归一化参数就该不同强行共用反而引入额外偏置。embedding模块我也单独处理共享度量空间那一层不做模态区分但是前面接的两个模态各自的Projector是独立的这样可以保证最终输出的512维向量才能被真正对齐。3.3 训练全流程与关键超参记录我把完整的训练流程跑了一遍这里给出可以直接复用的参数配置配置项第一阶段第二阶段主干ResNet-50ImageNet预训练冻结前两层微调深层优化器Adamlr1e-3Adamlr3e-4BatchP×K4×8单模态P×K4×8双模态三元组margin无0.3中心损失权重无0.1分类损失权重1.00.5训练epoch3060学习率策略cosine decaywarmup 5个epoch cosine第二阶段用warmup是必须的直接从第一阶段切到第二阶段损失函数增加了中心损失和跨模态三元组梯度方向突变很容易震碎第一阶段的成果。我给第二阶段加了5个epoch的线性warmup让embedding模块先适应新损失再进入正式训练。训练时每5个epoch存一次checkpoint用验证集测跨模态Rank-1和mAP。我记得最有意思的一次是epoch 35左右Rank-1曲线突然出现一个短暂的下降训练损失仍在下降。排查后发现是lr衰减速率设置过慢模型在局部震荡。我调整了cosine周期后曲线恢复稳定。所以训练日志里同时记录分模态准确率非常关键能帮你判断到底是谁在拖后腿。4. 训练过程中的典型问题与排查实录4.1 梯度震荡与模态不平衡跨模态训练最容易遇到的问题就是“模态不平衡”。IR样本数量少IR分支收到的梯度少导致共享权值不断被RGB分支主导最终IR分支的特征被“带偏”。外在表现是总损失下降但IR单模态检索准确率不升反降。我用了两个手段解决。第一个是梯度比例控制对IR分支的梯度乘一个1.2的补偿系数让两个分支的更新量基本均衡。第二个是两阶段训练本身就缓解了这个问题——在第一阶段IR分支已经具备独立判别能力第二阶段即使梯度信号少一些也不会彻底摧毁原有特征。如果你不想手调梯度系数另一个思路是在sampler上做文章每个epoch把IR样本重复采样使每个batch里RGB和IR数量完全相等。这是最简单有效的均衡方式我在最后版本里就是采样均衡与梯度系数并存。4.2 红外分支怎么调都比较差IR分支是跨模态ReID的天然短板因为红外图像本身分辨率低、纹理信息少。我排查了很多次后发现问题往往不在网络结构而在数据的组织形式上。IR图像直接三通道复制这种输入方案处理简单但要注意复制通道会放大像素噪声。我测试过把IR图的输入通道在R、G、B上做一个小幅差异化扰动相当于给三个通道分别加不同的scale偏移效果比纯复制要好一点。具体做法是单通道IR图归一化后分别乘以1.0、0.95、1.05再拼接成三通道。这个做法让网络有机会感知到一点“伪深度”信息实测有1个点左右的提升。另外IR分支的dropout要开得比RGB分支稍大我设了0.5RGB分支保持0.3。原因还是IR数据少过拟合风险高。4.3 评测指标和协议不统一导致的假象跨模态ReID评测有一个非常坑的细节评测协议不统一导致不同论文和开源代码之间数据不可比。常见的搜索模式分为all-search和indoor-search单样本和多模态还有直接使用全图库还是去掉查询图本身。这些微小的差异可能在Rank-1上产生2到5个百分点的波动。我的经验是跑通模型后一定要在报告里写清楚自己用的是哪种协议对比别人的结果前先确认协议一致。我自己就在这个坑上浪费过一周——我跑的mAP看起来比某篇已发表工作高很多后来发现对方用的是更严格的全图库协议而我只在indoor子集上检索。后面的评估我一律统一采用全图库、单样本、去掉查询图自身的协议结果才真正可比。如果你要发论文或对比开源库一定要先把这个协议锁死否则后面所有分析都是空中楼阁。4.4 特征分布可视化诊断技巧训练阶段出现问题时光看损失曲线是不够的。我习惯每10个epoch用t-SNE把验证集的RGB和IR特征投影到二维平面观察两类特征的分布状态。如果看到RGB和IR形成两个分明的大簇说明模态对齐做得还不到位如果看到同一行人的点在不同模态下大致聚集在一起但类别间又有重叠说明判别力与对齐存在矛盾。可视化可以直观导向下一步分布分明但类别重叠就提高分类损失权重分布混杂找不到簇结构就先检查骨干是否冻结过多。这个技巧在调中心损失权重时尤其好用。我最终把中心损失从0.1调到0.2时t-SNE图上跨模态的同行人特征明显更紧凑了但RGB单模态准确率微降。这种权衡在损失函数设计里很常见可视化能帮你做出不盲目的决策。5. 实测效果与个人经验总结5.1 实验结果与哪些模块真正起作用在我自己的评测配置下这套双阶段方案最终拿到了主流数据集上Rank-1约65%到70%、mAP约58%到62%的成绩。如果拿掉第一阶段直接用单阶段硬trainRank-1会掉6到7个百分点。如果拿掉模态专属BN会掉3到4个百分点。如果拿掉中心损失跨模态对齐的效果会变差mAP掉的比Rank-1更明显。这说明在跨模态ReID任务中真正起作用的是训练策略和损失结构而不是某个花哨的网络模块。很多人一上来就换更强的backbone但在我看来先把两阶段框架和模态专属BN做好收益比直接换EffNet大得多。5.2 从项目里沉淀出来的几点体会第一跨模态ReID的本质问题是分布对齐不是特征提取。任何增强特征提取的手段如果没有配合对齐约束效果都会大打折扣。第二双阶段训练的可解释性让调试变得高效每个阶段都有明确的评判标准出了毛病可以快速定位是阶段一的问题还是阶段二的问题。第三模态专属BN这种小改动性价比远超想象可以说是跨模态任务的“免费午餐”。这个项目后续可以扩展的方向也不少比如加入可见光与红外的语义级对齐模块或者把第二阶段改造为端到端微调等等。我自己接下来最想尝试的是把双阶段架构迁移到任意模态组合上——比如可见光与深度图、RGB与事件相机这类跨模态检索任务的痛点完全一致。如果你也在做类似方向强烈建议先按这篇文章的流程从双分支加双阶段损失搭起再逐步优化你会发现绝大多数问题都能在框架层面提前规避掉。