资讯详情

资讯详情

X Modality详解:红外与可见光跨模态行人重识别的辅助特征空间

红外和可见光跨模态行人重识别Infrared-Visible Cross-Modal Person Re-Identification圈里一般简写成RGB-IR ReID是个特别容易让人绕晕的方向。白天监控拍到的是彩色全身照到了晚上只能靠红外相机拍出来是灰蒙蒙的单通道图同一个行人在两种镜头下可能连衣服颜色都完全对不上。AAAI 2020那篇提出“X Modality”的论文解决的就是这个场景训练时让网络自己生成一个额外的辅助模态把它当中间人将红外特征和可见光特征拉近。我第一次读这篇论文时最不理解的恰恰是这个X到底是什么后来动手拆了一遍网络结构才发现它的设计比想象中朴素——只是一个共享backbone上的独立全连接分支。这篇文章把论文的动机、结构、损失和复现细节整体过一遍适合刚入门ReID、正在找跨模态方向论文读的同学也适合想快速在公开数据集上搭一个baseline的实验党。1. 红外与可见光之间的鸿沟这个任务到底难在哪1.1 从普通ReID到跨模态ReID多出来的不只是“换个摄像头”先说说常规的行人重识别。给定一张query行人图要求从海量gallery图库里找出同一个人的其他图像这就是ReID。普通ReID能跑起来很大程度上依赖一个隐藏前提训练和测试图像都来自可见光RGB摄像头虽然光照、姿态、遮挡、相机视角都会变化但底层信号是一致的颜色、边缘、纹理这些low-level特征在不同图像之间仍然有可比性。跨模态ReID就是故意把这个前提打破。红外图像没有可见光颜色亮度分布完全来自热辐射与反射光成像差了一整个物理过程。于是最直接的问题是普通ReID里最常用的颜色特征在红外模态下直接失效。你不能说“那个人穿红衣服”因为在红外图里红色和蓝色可能都是同一档灰度。更麻烦的是分布层面的错位。在实际数据里同一个行人跨模态图像之间的差异往往大于不同行人同一模态下的差异。换句话讲网络很容易先学会判断“这张是红外图、那张是可见光图”而不是努力判断“这是哪个人”。刚开始做这个方向的人训练loss掉得很快但跨模态Rank-1怎么都上不去多半就是陷入了这种模态判别优先于身份判别的状态。1.2 为什么“子空间对齐”这套老思路在这里会失灵面对这种大gap前几年比较主流的做法是把红外和可见光映射到同一个共享特征空间再拿对比损失、三元组损失甚至对抗损失压着两个分布尽量重合。思路听着很顺实际做起来却有个绕不开的问题你并不知道那个所谓的“公共空间”应该长什么样。如果只是强行让两个模态在某个特征空间里分布重合那网络大概率会选择偷懒——丢掉那些跨模态不一致但对身份判别很有用的信息只保留两个模态都认可的那部分普通特征。结果就是对齐是齐了但每个模态自身的判别性也被削弱了。这有点像让两个语言完全不同的人必须用一种代码说话结果两人都放弃了自己最擅长的表达只剩下一套最贫乏的通用词汇。X Modality这篇论文想换一个角度既然直接定义公共空间很难那干脆不要定义具体含义而是让网络自己学习一个辅助的中间表示。这个表示既不像红外也不像可见光作者管它叫“X模态”。训练时拿它当中转站让两个真实模态绕着它对齐。2. X Modality不神秘网络自己生成一个辅助特征空间2.1 作者没有去“定义”X而是让网络自己长出来单看“X Modality”这个名字很容易误以为作者发明了一种新的传感器或者图像变换。其实不是。论文里的X更像一个待定变量它不来自任何真实物理成像过程也不需要被翻译成“伪红外”或“伪可见光”。做法是在特征层面额外加一个分支。输入仍然是那批红外图像和可见光图像但这个分支输出的特征既不要求保留红外特征的形式也不要求保留可见光特征的形式。它就是一个新的、由网络自己塑造出来的辅助特征空间。这个空间里到底该存放什么信息取决于任务在训练过程中需要什么。我自己的理解是X之所以叫X就是因为它刻意保持“未知”状态。作者并不关注它物理上是什么只需要它在优化过程中变成一个对红外和可见光都足够友好的邻居。你可以把它看成一道桥只不过这道桥不是事先画好图纸而是网络一边走一边铺出来的。2.2 核心结构共享backbone加三个独立全连接分支具体落到网络结构上这套设计相当简洁。主干是ResNet50去掉最后的分类层和全局池化再接一个全局平均池化得到一个2048维的特征向量。重点在池化之后。这里不是直接接一个分类器而是分出三条独立的特征支路红外支路一个独立的全连接层把2048维压到512维左右可见光支路另一个独立的全连接层同样把维度压下来X支路第三个独立的全连接层共享backbone提出来的特征但映射到X特征空间。每个支路后面可以再接自己的BN层和身份分类器。三个支路的参数互不共享相当于在同一个卷积骨干上训练了三个不同的embedding函数。结构图摊开来看就是这样输入红外图像 / 可见光图像 → 共享ResNet50卷积层 → 全局平均池化2048维 → 三个独立全连接层 FC_ir → 红外特征 FC_vis → 可见光特征 FC_x → X模态特征 → 三个身份分类器 跨模态验证损失这里有个容易误解的点需要注意X分支的输入并不是把红外特征和可见光特征拼起来而是复用共享backbone的输出特征。也就是说对每一张输入图像网络同时算出红外视角、可见光视角、X辅助视角三份特征。第二个容易踩的坑是部分实现会在三个支路后面加各自的BN这三个BN同样不能共享参数否则等于又偷偷把两个模态的统计量混在一起了。2.3 为什么训练时把X当成一个“模态”会产生帮助关键是训练时的监督方式。X分支输出的特征被当作一个真实的模态来参与身份分类它和红外、可见光共享同一套行人ID标签。这意味着如果一张红外图和一张可见光图属于同一个人网络在更新时会让它们的X特征也往同一个身份中心靠近。这样反复迭代之后X分支学到的就不再是“某类图像长什么样”而是“这个人的语义身份该落到特征空间的哪个位置”。当网络再拿它去约束两个真实模态时相当于提供了一个具体可达的锚点两个模态在像素层面差异再大至少在这个辅助空间里能坐下来对齐。X的另一层价值是它天然充当了“经验共享介质”。红外和可见光各自保留了自己的判别性特征但它们在X空间里共享身份语义这就避免了传统子空间对齐那种“两边都被迫放弃专属特征”的问题。可以理解为每个模态保留自己最擅长的表达方式同时通过X这个中间方言来完成信息交换。2.4 和GAN式中间域方法相比优势在训练稳定性当时还有一个热门方向是用GAN做跨模态图像生成比如从红外图生成可见光图或者把两个模态都转到一个中间图像域再做ReID。这个思路很直观效果也有但代价是GAN训练天生不稳定生成质量直接决定后续模型上限。X Modality这种特征层面的辅助模态完全绕开了对抗训练。它不需要重建图像不会出现“生成的脸是糊的”“颜色偏了”这类问题。付出的代价是解释性弱一些你很难说清楚X特征里到底编码了什么。但从工程角度看这是一个很划算的取舍换来的是训练过程稳定、收敛速度快、复现门槛低。3. 网络怎么搭共享骨干、非共享全连接层与三条特征支路3.1 前向流程拆解一张图进来三份特征出去把前向流程一步步拆开看整个过程并不复杂。第一步输入一张图像可能是红外也可能是可见光。由于是跨模态训练batch里会同时包含两种模态的数据。图像进入共享的ResNet50卷积骨干经过一系列卷积和残差模块后得到feature map再做全局平均池化得到2048维的语义向量。第二步这个2048维向量被复制成三份分别通过FC_ir、FC_vis、FC_x三个全连接层。需要特别强调的是三个全连接层虽然输入相同但参数完全不同所以输出的特征分布在训练过程中会逐渐分化FC_ir擅长从共享特征里挑出红外模态关心信息FC_vis挑起可见光模态的担子而FC_x去编码一个更中立的语义表达。第三步三份特征分别作身份分类。分类层的目标标签完全一样都是那张图对应行人的ID所以本质上网络在学三件不同的事但最终指向同一个身份语义。3.2 训练时三分支同步更新反向传播怎么回到共享backbone很多人第一次看这种结构会问三个分支各自有损失那共享backbone会不会收到互相矛盾的三份梯度答案是会但这不是坏事。红外分支的ID损失要求backbone的特征能反映红外模态下的身份差异可见光分支的ID损失要求它同时能反映可见光模态下的身份差异而X分支加上验证损失又在暗中推动backbone把两种模态往公共方向引导。三份梯度如果方向基本一致那backbone会学到更鲁棒的中层特征如果个别方向冲突优化器也会自动协调通常体现在损失权重上。实际训练时一个常见做法是把红外图和可见光图放在同一个batch里前向共用backbone权重计算特征然后分别过三个FC。这样反向传播时共享backbone的梯度来自全部三个分支FC层更新自己的参数整体看起来像一个多任务学习框架。3.3 推理时丢弃X分支为什么性能反而更好这篇论文一个非常有意思的设计是X模态只存在于训练阶段推理时直接丢掉。推理过程只用两条真实支路红外图像走FC_ir得到红外特征可见光图像走FC_vis得到可见光特征然后通过欧氏距离或者余弦距离做检索。X分支完全不参与。为什么不保留它因为X特征本质上是一个虚拟的辅助表征没有对应的真实图像采集过程。你可以把它理解成训练时的脚手架盖完楼之后就没必要留着了。更关键的是丢掉X不影响任何计算量模型部署时仍是标准双支路结构。这也意味着X分支的目的不是增加推理特征而是完全为了训练时拉近两个真实模态的embedding空间。3.4 复现时最容易搞错的一个细节X分支的输入源我在看别人复现这段代码时发现最容易搞错的地方就是X分支的输入到底是谁的特征。有人以为X应该输入红外特征和可见光特征融合后的结果于是在代码里写了cat(feat_ir, feat_vis)。实际操作中X分支通常直接吃共享backbone的输出。也就是说同样一张输入图经过backbone后产生一个共享特征这个特征分别过三个FC。不需要额外的融合操作也不需要把红外图和可见光图的特征先对齐再送给X。这个细节直接影响参数和训练逻辑一旦搞错X分支就不再是“第三种视角”而变成了红外和可见光的混合物效果会明显变差。4. 损失函数组合身份损失加验证损失怎么配比4.1 身份损失三条支路各接一个分类器身份损失在ReID里是最基础的监督信号这篇论文也没有例外。每条支路后面接一个全连接分类器把特征映射到训练集行人ID数量维度再用softmax交叉熵计算损失。三条支路的分类器可以共用也可以独立。如果用独立分类器那每个支路都学习各自的特征到身份映射关系如果共用那等于强制三条支路的特征在分类边界上一致反而会削弱X分支的灵活性。我读论文时的理解是各支路接独立分类器更符合设计初衷。损失形式上可以写成L_id CE(clf_ir(feat_ir), y) CE(clf_vis(feat_vis), y) CE(clf_x(feat_x), y)三个分类目标都是同一个y也就是行人ID。这意味着X特征被赋予了和真实模态同级别的身份语义压力这是X空间“有用”的根本来源。4.2 验证损失让不同模态的同一个人靠近光有身份损失还不够。身份损失解决的是“这张图是谁”但没法直接告诉网络“红外里的张三和可见光里的张三应该在特征空间里挨着”。所以论文还引入验证损失成对地约束跨模态特征距离。验证损失的对象不是随便选的pair而是有具体结构的红外-可见光这一对自然是最核心的因为推理时就是拿这两种模态做匹配除此之外红外-X、可见光-X也各算一对目的是让两个真实模态都往X空间这个锚点上靠。对于同一个人ID的pair验证损失要求它们距离近不同ID的pair要求距离远。可以理解成在身份损失之外加了一层更直接的度量学习只不过它约束的不只是两个真实模态还把X也拉了进来。4.3 总损失组合与权重参数的关系总损失大体是身份损失和验证损失的加权和L L_id λ * L_veriλ这个权重很关键。如果λ太小验证损失形同虚设红外和可见光特征照样各玩各的如果λ太大网络为了满足距离约束会把所有特征都压到一个很小的球壳上身份分类精度反而下降。读论文的时候建议特别留意原文是怎么设置λ的通常在同一数量级范围附近复现时从1开始调整比较稳。另外验证损失内部也涉及一个平衡问题红外-可见光、红外-X、可见光-X这三类pair是不是要设置不同权重论文里各版本实现并不完全一致。我自己复现的简化版是三类pair同等对待效果已经可以接受所以如果只是想快速验证X思路不必一开始就在权重上做文章。4.4 我在配比损失时的一个直观理解把整组损失放在一起看结构其实很清晰。身份损失负责“判别性”保证每个特征分支都携带足够区分不同身份的信息验证损失负责“模态不变性”把不同模态拉到相近区域X分支则是那个额外的缓冲垫。从优化的角度看X分支等于给两个真实模态加了一个共享中间点。没有X时网络只能直接逼着feat_ir≈feat_vis冲突比较硬有了X网络可以先让feat_ir≈feat_x、feat_vis≈feat_x真实模态不需要直接折中而是各自向同一个辅助点靠近优化更平滑。5. 实验效果与复现要点在SYSU-MM01和RegDB上到底提升了什么5.1 两个主流数据集与常见评测协议跨模态ReID公开评测主要集中在两个数据集上。一个是SYSU-MM01包含大概几百个行人ID图像来自校园内的可见光和红外摄像头。评测协议通常分成all-search和indoor-search两种模式query是红外图gallery是可见光图指标以Rank-1、Rank-10、Rank-20和mAP为主。另一个是RegDB由红外与可见光相机成对采集行人ID数量大约在400左右。常见做法是随机划分一半身份用于训练、一半用于测试有些论文会报10折交叉验证也有些只在单次划分上跑结果差异会比较大。读论文看到具体数字时一定要先确认它用的是哪种划分和协议否则跨论文比较很容易被误导。5.2 论文自报结果怎么看别只看Rank-1不同论文之间的绝对数值很难直接对比因为backbone、输入尺寸、是否使用re-ranking、训练集划分都可能不同。这篇论文里作者更想展示的是X分支带来的相对提升在同一套baseline、同一套数据协议下加入X模态辅助训练后Rank-1和mAP能往上走多少。具体数字以论文原文为准印象里在SYSU-MM01的all-search设置下论文把原来的双支路baseline提升了好几个点RegDB上也有类似幅度的增益。更重要的是消融实验把X分支拿掉之后性能会明显回落。也就是说提升确实来自X这个辅助特征空间而不是来自额外的全连接层参数或更长的训练时间。5.3 复现环境里几个容易被忽略的细节如果你打算动手复现有几个细节我会建议特别留意。第一红外图像的输入处理。红外相机输出通常是单通道而预训练ResNet50的输入是三通道。常见的做法是把单通道图复制成三通道但这种“伪彩色”输入和真实的RGB分布差很多最好在训练时对全模型做微调而不是只训分类头。第二batch构造方式。验证损失要求同一个ID在同一个batch里同时有红外图和可见光图。如果用普通的随机采样器一个batch里很可能是清一色红外或清一色可见光验证损失根本算不了。需要自己实现PairSampler之类的逻辑先抽P个ID再对每个ID取K张红外和K张可见光。第三BN统计量问题。共享backbone里的BN会把两种模态的统计量混在一起。有些工作会把红外和可见光分开跑BN能获得更稳定的收敛。X分支后如果接BN同样面临这个问题必要时可以试验一下分开BN的效果。5.4 简化版训练伪代码下面是一段思路层面的PyTorch风格伪代码不是为了直接能跑而是帮大家把结构关系理清for ir_imgs, vis_imgs, labels in loader: # 红外和可见光都进同一个backbone feat_ir backbone(ir_imgs) feat_vis backbone(vis_imgs) # 三条支路各算各的embedding emb_ir fc_ir(feat_ir) emb_vis fc_vis(feat_vis) emb_x_ir fc_x(feat_ir) # 红外图对应的X特征 emb_x_vis fc_x(feat_vis) # 可见光图对应的X特征 # 身份损失三条支路都分类到同一个ID loss_id ce(clf_ir(emb_ir), labels) \ ce(clf_vis(emb_vis), labels) \ ce(clf_x(emb_x_ir), labels) \ ce(clf_x(emb_x_vis), labels) # 验证损失示意同ID拉近不同ID推远 loss_veri veri(emb_ir, emb_vis, labels) \ veri(emb_ir, emb_x_ir, labels) \ veri(emb_vis, emb_x_vis, labels) loss loss_id lambda_veri * loss_veri loss.backward() optimizer.step()5.5 跨测试集上的一个常见翻车原因不少人在自己的数据上复现时发现效果不如论文第一个想到的是调参但很多时候问题出在评价协议上。SYSU-MM01如果用single-shot gallery和multi-shot galleryRank-1差距可能有十来个点RegDB如果没做10折交叉验证单次划分的运气成分也不小。所以复现第一步不是调参而是确认评价方式与论文一致。6. 阅读笔记与思考这个思路还能怎么用6.1 从X Modality想到的横向延伸X模态本质上是我在前面反复提到的“辅助中间表示”。这个思想并不局限于红外和可见光之间的匹配对任何两个分布差异较大的模态都有借鉴意义。比如文本-图像检索文本特征和图像特征天然不在一个语义粒度上同样可以引入一个辅助特征空间当过渡草图-照片识别草图极度稀疏照片极度丰富更需要一个中间表示来弥合差距跨分辨率ReID也类似低分辨率和高分辨率的特征分布差异不亚于跨模态。沿着这个思路去读论文你会觉得X Modality不只是一个网络结构更像是一种设计范式与其强行约束两个主模态不如在旁边放一个“脚手架”让主模态通过脚手架完成间接对齐。6.2 局限性与适用边界X模态也不是万能的。它依赖一个前提训练数据里同一个ID必须有足够多的红外-可见光配对X分支才有机会把身份语义作为锚点。如果你手上是红外数据多、可见光数据严重不均衡X空间的塑造过程就会偏科。另外X特征缺少可解释性它到底编码了什么很难用现有工具去可视化。这在学术上可能还好但如果要做高可靠性的安防系统这种黑盒辅助特征会让业务方很难信任。还有一点X分支的辅助作用是在特定训练域上塑成的换到域差异极大的新场景是否需要重新拟合X空间论文没有展开讨论。这是后续研究可以继续做的工作。6.3 我实际用到的快速验证方法如果你想快速判断X Modality对自己任务有没有帮助不一定要完整复现整篇论文。可以先跑一个标准双流baseline记录Rank-1然后在FC层后面只加一个X分支损失加上X相关的验证约束其他所有超参数不变。这一步改动不大代码量增加很小却能在两三次实验之内看出趋势。我实际测试下来X分支对baseline偏低的情况提升最明显。如果baseline本身已经很强比如Rank-1已经到80%以上X带来的增益会变小毕竟空间里能挤出来的对齐余地不多了。所以这个trick更适合中小规模数据集和表现一般的上手模型。6.4 读这类跨模态论文我习惯先看损失再翻结构最后分享一个我读论文的习惯拿到一篇跨模态方法论文先画损失函数的结构图再看网络结构图。因为损失决定了哪些特征会被拉到一起哪些特征要保持独立这比看几个方框连成的模型图更能反映出方法本质。X Modality这篇论文核心其实就一句话在双分支对称结构上加一个不需要定义具体含义的辅助特征空间用身份损失和验证损失双重监督把它训练出来。如果你能把这句话真正吃透再去看它的实验和后续工作应该会轻松很多。复现条件有限的同学可以按我前面说的简化版先试。不用一上来就追求完整复现所有trick先看X分支在自己的数据上能不能带来正向变化再决定要不要投入更多调参精力。跨模态这摊子事很多时候几行代码的改动效果差异就是几个rank点的距离。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →