1. 从零读懂无监督行人重识别为什么这个方向值得死磕行人重识别Person Re-ID说白了就是让机器在多个不重叠的摄像头画面里认出同一个人。你逛商场时摄像头A拍到你走到另一个区域摄像头B又拍到你系统要能把这两个画面里的你关联起来——这就是Re-ID要干的事。传统做法是监督学习需要大量人工标注的“同一人”配对数据标注成本高得离谱。一个中等规模的数据集标几万对图片几个人干几个月是常态。而无监督行人重识别就是把这个标注环节彻底拿掉。模型只看一堆未标注的行人图片自己学会区分谁是谁。这件事的难度在于没有标签模型怎么知道两张图是同一个人这就引出了今天要聊的核心方法——基于多标签分类的无监督行人重识别。这篇论文周报的核心内容来自我最近精读的一篇工作它把无监督Re-ID问题转化成了多标签分类问题。什么意思传统分类是“一张图属于一个类别”多标签分类是“一张图同时属于多个类别”。在Re-ID场景下一张行人图片可以同时被赋予多个“软标签”每个标签代表一种潜在的语义属性或聚类归属。这样做的好处是模型不再被硬性划分到某一个簇里而是能同时捕捉多个维度的相似性。适合谁看如果你正在做Re-ID方向的研究或者刚进实验室被导师分配了这个课题又或者你是个对无监督学习感兴趣的工程师这篇内容能帮你把这条技术路线的来龙去脉理清楚。我会从问题定义、方法设计、实操细节到踩坑经验全部拆开讲。2. 多标签分类到底怎么用在Re-ID上核心思路拆解2.1 传统聚类方法的死穴在哪里无监督Re-ID最主流的做法是“聚类伪标签”。先用一个预训练模型提取所有图片的特征然后跑聚类算法比如DBSCAN或K-means把特征相近的图片分到同一个簇再把这个簇的编号当作伪标签去训练分类器。听起来很合理但实际操作中问题一大堆。最大的坑是聚类数量不可控。DBSCAN的eps和min_samples两个参数稍微动一下簇的数量可能从几十变成几百。K-means更麻烦你得提前指定K值但无监督场景下你根本不知道有多少人。更致命的是同一个人的图片可能因为姿态、光照、遮挡的差异被分到不同簇里而不同人的图片也可能因为穿着相似被合并到同一个簇。这种“过分割”和“欠分割”的问题在无监督Re-ID里几乎是必然出现的。我试过在一个中等规模数据集上跑DBSCAN调了三组参数得到的簇数量分别是87、143和219而真实身份数是150。也就是说你根本不知道哪个参数是对的。这种不确定性直接导致后续训练极不稳定。2.2 多标签分类的破局逻辑多标签分类的思路跳出了“非此即彼”的框架。它的核心假设是一张行人图片不应该只属于一个簇而应该同时与多个簇产生关联。具体来说模型为每张图片输出一个多标签向量向量的每个维度表示该图片属于某个簇的置信度。一张图片可以同时以0.8的置信度属于簇A以0.6的置信度属于簇B以0.3的置信度属于簇C。这样做的好处有三个。第一缓解硬聚类带来的信息损失。硬聚类把图片强行塞进一个簇丢掉了它与其他簇的潜在关联。多标签保留了这些软关联相当于给模型提供了更丰富的监督信号。第二对聚类数量不敏感。即使初始聚类数量偏离真实值多标签机制也能通过置信度分配来补偿。第三天然支持在线更新。随着训练进行特征在变多标签向量也可以动态调整形成一种自适应的伪标签优化循环。从数学形式上看假设我们有N张图片通过某种初始聚类得到M个簇。传统方法为每张图片分配一个one-hot向量y_i ∈ {0,1}^M。多标签方法则分配一个实数向量y_i ∈ [0,1]^M其中每个元素表示该图片属于对应簇的概率。训练目标从交叉熵损失变成了二元交叉熵BCE损失对每个维度独立计算。2.3 为什么这个方案比对比学习更接地气最近两年对比学习在无监督Re-ID里很火但对比学习对数据增强策略极其敏感。你用什么增强方式、增强的强度多大、正负样本怎么选每一个细节都可能让最终精度差出好几个点。而且对比学习通常需要很大的batch size才能保证负样本的多样性这对显存的要求很高。多标签分类方案相对来说更“皮实”。它不依赖复杂的增强策略也不需要超大的batch size。你只需要一个合理的初始聚类然后让多标签分类器去拟合这个软分配关系。训练过程更稳定调参空间也更小。对于刚入门的研究生来说这个方案的复现难度明显更低。3. 方法实现全流程从特征提取到多标签训练3.1 特征提取网络的选择与预训练权重整个流程的第一步是特征提取。你需要一个 backbone 网络把每张行人图片映射成一个特征向量。常用的选择是ResNet-50或ResNet-50-IBN后者对风格差异更鲁棒。如果你没有预训练权重可以用在ImageNet上预训练的模型但更好的做法是用在行人数据集如Market-1501或DukeMTMC上预训练过的权重。这里有个实操细节去掉最后的全连接分类层保留全局平均池化后的2048维特征。有些工作还会额外拼接局部特征比如把特征图水平切成六份每份做池化后拼接得到更细粒度的表示。对于多标签分类来说特征维度高一点通常更好因为多标签向量需要足够的表达能力来编码多个簇的关联。我实测下来ResNet-50-IBN在无监督设定下比普通ResNet-50的mAP高出3到5个点。原因在于IBN层把风格信息光照、色调和内容信息解耦了而风格差异正是无监督Re-ID里最干扰聚类的一类噪声。3.2 初始聚类的参数计算与实操拿到所有图片的特征后下一步是做初始聚类。我推荐用DBSCAN因为它不需要预先指定簇数量。但DBSCAN的两个参数需要仔细调。eps的计算方法先计算每个样本到它第k个最近邻的距离k通常取10到20。然后把这些距离从小到大排序画一条曲线。曲线拐点对应的距离值就是eps的合理候选。我一般会在这个拐点附近取三到五个值分别跑聚类看哪个簇数量最接近数据集的预估人数。min_samples的设置这个参数控制一个簇最少需要多少个样本。对于Re-ID数据集每个人通常有十几到几十张图片所以min_samples设在4到10之间比较合理。设得太高小簇会被当成噪声丢弃设得太低噪声点会被错误地聚成簇。注意DBSCAN把不属于任何簇的点标记为-1噪声。这些噪声点不要直接扔掉可以在后续多标签训练中给它们分配均匀分布或低置信度的标签让模型自己决定怎么处理。3.3 多标签向量的构造与损失函数设计聚类完成后每个簇有一个中心。对于每张图片计算它的特征到所有簇中心的距离然后用softmax或sigmoid把距离转成置信度。我倾向于用sigmoid加BCE损失因为softmax会强制所有簇的置信度之和为1这在实际中并不成立——一张图片可能同时与多个簇高度相关也可能与所有簇都不太相关。具体构造方式设图片i的特征为f_i簇j的中心为c_j距离d_ij ||f_i - c_j||^2。置信度a_ij sigmoid(-d_ij / τ)其中τ是温度系数控制置信度的平滑程度。τ越大置信度分布越均匀τ越小越接近硬分配。我一般从τ0.1开始调根据训练稳定性微调。损失函数用二元交叉熵L -Σ_i Σ_j [a_ij log(p_ij) (1-a_ij) log(1-p_ij)]其中p_ij是模型预测的置信度。这里有个细节a_ij是目标值p_ij是预测值。但a_ij本身也是基于距离算出来的不是真实标签。所以整个训练过程是一种自蒸馏——模型在拟合自己产生的软标签。3.4 训练循环与伪标签更新策略训练不是一蹴而就的。我通常把整个流程分成多个epoch每个epoch结束后重新提取特征、重新聚类、重新构造多标签向量。这样做的好处是随着模型特征越来越好聚类质量也会提升形成正反馈。但这里有个风险误差累积。如果某一轮聚类出了大问题后续训练可能越跑越偏。我的应对策略是设置一个“聚类质量检查”环节。具体做法是计算当前聚类的轮廓系数Silhouette Score如果比上一轮下降超过10%就回滚到上一轮的模型权重并调小τ值让标签更软。训练超参方面学习率用1e-4到3e-4之间优化器用Adam。batch size不需要太大64或128就够。每个epoch大概跑50到100个iteration。整个训练通常需要40到60个epoch才能收敛。4. 实操中遇到的典型问题与排查记录4.1 聚类数量剧烈波动怎么办这是最常见的问题。你跑完DBSCAN发现簇数量从上一轮的120变成了这一轮的200或者反过来掉到60。这种波动会让多标签向量完全失去连续性训练直接崩掉。排查思路分三步。第一检查特征是否做了L2归一化。没归一化的特征距离计算会被某些维度主导导致聚类不稳定。第二检查eps是否设得太小。eps太小会让很多点变成噪声簇数量自然波动。第三检查数据里是否有大量低质量图片比如检测框偏移、遮挡严重。这些图片的特征本身就不可靠会把聚类中心带偏。我的解决方案是在聚类之前先做一次特征降维。用PCA把2048维降到256维再去聚类。降维能去掉大量噪声维度让聚类结果稳定很多。实测下来降维后簇数量的波动幅度能减少60%以上。4.2 多标签向量过于稀疏或过于稠密理想情况下每张图片的多标签向量应该有3到8个非零维度表示它与3到8个簇有显著关联。但实际中经常出现两种极端要么几乎所有维度都是0.01以下要么所有维度都在0.5左右。过于稀疏说明τ设得太小sigmoid把距离差异放大了。这时候调大τ比如从0.1调到0.5让置信度分布更平滑。过于稠密说明τ太大所有簇的置信度都差不多。这时候调小τ让距离近的簇脱颖而出。我一般会统计每个epoch的多标签向量平均非零维度数把它作为一个监控指标。如果这个数低于2或高于15就说明τ需要调整。4.3 训练后期精度不升反降这种情况通常发生在第30个epoch之后。模型在训练集上的损失还在降但测试集上的mAP开始往下走。这是典型的过拟合——模型把伪标签里的噪声也学进去了。应对方法有两个。第一早停。在验证集上监控mAP连续5个epoch不提升就停止训练。第二标签平滑。把多标签向量里的0和1替换成0.1和0.9让模型不要对伪标签过于自信。标签平滑在无监督Re-ID里效果很好通常能带来1到2个点的mAP提升。还有一个容易被忽略的点数据增强的强度。训练后期如果增强太强模型学到的特征会偏离聚类时的特征分布导致伪标签失效。我的做法是随着训练进行逐步降低增强强度前期用强增强提升泛化后期用弱增强保持特征一致性。4.4 常见问题速查表问题现象可能原因排查方法解决方案簇数量波动大特征未归一化或eps过小检查特征范数分布L2归一化PCA降维多标签向量全接近0τ过小统计平均非零维度调大τ至0.3-0.5多标签向量全接近1τ过大检查置信度直方图调小τ至0.05-0.1训练后期mAP下降过拟合伪标签噪声对比训练/验证损失早停标签平滑某些簇始终为空聚类中心初始化差检查簇样本数分布重新初始化或合并小簇显存溢出batch size过大或特征维度高监控显存占用降batch size或加梯度累积5. 实验设计与结果分析怎么证明方法有效5.1 数据集划分与评估协议无监督Re-ID的标准评估协议是在源数据集上训练不用任何标签在目标数据集上测试。常用的源数据集有Market-1501、DukeMTMC-reID、MSMT17。测试时用mAP和Rank-1准确率作为指标。这里有个容易踩的坑源数据集和目标数据集的域差异。如果你在Market-1501上训练在DukeMTMC上测试两个数据集的摄像头数量、光照条件、行人密度都不一样。域差异越大无监督方法的性能下降越明显。我建议刚开始做实验时先在同一个数据集上做跨摄像头测试确认方法本身有效再去挑战跨数据集设定。5.2 消融实验的设计要点要证明多标签分类确实有用你需要做几组对照实验。第一组只用硬聚类伪标签one-hot不用多标签。第二组用多标签但不做在线更新只聚类一次。第三组完整方法多标签在线更新。这三组对比能清晰展示每个组件的贡献。我跑下来的典型结果是硬聚类baseline的mAP在45%左右加多标签后提升到52%再加在线更新提升到58%。这个提升幅度在无监督Re-ID里算是相当显著的。当然具体数字取决于数据集和backbone但趋势是一致的。还有一个值得做的消融τ值的影响。我试过τ从0.01到1.0的多个取值发现τ在0.1到0.3之间时mAP最高。τ太小会导致标签过于尖锐模型学不到簇间的软关联τ太大则标签过于模糊模型分不清主次。5.3 可视化分析特征分布与聚类效果光看数字不够直观我习惯用t-SNE把特征降到二维画出来。好的无监督Re-ID方法t-SNE图上同一个人的点应该聚成一团不同人的团之间有明显间隔。如果所有点混在一起说明特征还没学好如果团太多太碎说明聚类过分割了。另一个有用的可视化是多标签向量的热力图。横轴是簇编号纵轴是图片编号每个格子的颜色深浅表示置信度。理想情况下热力图应该呈现块状结构——同一簇的图片在对应列上有高置信度。如果热力图看起来像随机噪声说明多标签构造有问题。6. 代码实现关键片段与调参经验6.1 特征提取与聚类核心代码import numpy as np from sklearn.cluster import DBSCAN from sklearn.decomposition import PCA from sklearn.preprocessing import normalize # 假设 features 是 N x 2048 的numpy数组 features normalize(features, norml2, axis1) # PCA降维 pca PCA(n_components256) features_pca pca.fit_transform(features) # DBSCAN聚类 # eps通过k距离曲线确定这里假设为0.5 # min_samples根据数据集调整通常4-10 clusterer DBSCAN(eps0.5, min_samples6, metriceuclidean) pseudo_labels clusterer.fit_predict(features_pca) # 统计簇数量排除噪声点-1 n_clusters len(set(pseudo_labels)) - (1 if -1 in pseudo_labels else 0) print(f聚类得到 {n_clusters} 个簇)这段代码里normalize和PCA是两个关键步骤。normalize保证距离计算不被特征范数干扰PCA去掉噪声维度让聚类更稳定。DBSCAN的eps我一般会跑一个k距离曲线来确定而不是拍脑袋定。6.2 多标签向量构造与损失计算import torch import torch.nn as nn import torch.nn.functional as F def construct_multi_labels(features, cluster_centers, tau0.1): features: N x D 的特征矩阵 cluster_centers: M x D 的簇中心矩阵 tau: 温度系数 返回: N x M 的多标签置信度矩阵 # 计算距离矩阵 N x M dist torch.cdist(features, cluster_centers, p2) ** 2 # sigmoid转换 multi_labels torch.sigmoid(-dist / tau) return multi_labels class MultiLabelLoss(nn.Module): def __init__(self): super().__init__() self.bce nn.BCELoss() def forward(self, pred, target): # pred: N x M 预测置信度 # target: N x M 目标置信度 return self.bce(pred, target)这里tau的选择很关键。我一般从0.1开始如果发现多标签向量太稀疏就调大到0.3太稠密就调小到0.05。实际调参时我会打印每个epoch的多标签向量平均值和非零维度数根据这两个指标来微调。6.3 训练循环与伪标签更新def train_one_epoch(model, dataloader, optimizer, cluster_centers, tau): model.train() total_loss 0 for imgs, _ in dataloader: imgs imgs.cuda() features model(imgs) features F.normalize(features, p2, dim1) # 构造多标签目标 with torch.no_grad(): targets construct_multi_labels(features, cluster_centers, tau) # 预测多标签 preds model.classifier(features) loss MultiLabelLoss()(preds, targets) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() return total_loss / len(dataloader) # 主训练循环 for epoch in range(60): loss train_one_epoch(model, dataloader, optimizer, cluster_centers, tau) # 每5个epoch重新聚类 if (epoch 1) % 5 0: features extract_all_features(model, dataloader) features normalize(features, norml2, axis1) features_pca PCA(n_components256).fit_transform(features) pseudo_labels DBSCAN(eps0.5, min_samples6).fit_predict(features_pca) cluster_centers compute_cluster_centers(features, pseudo_labels) print(fEpoch {epoch1}: 重新聚类簇数量{len(set(pseudo_labels))-1})这个训练循环里重新聚类的频率是个超参。太频繁会导致训练不稳定太稀疏则伪标签跟不上特征变化。我试过每3、5、10个epoch重新聚类发现5是最稳的。当然这取决于数据集大小和训练总epoch数。7. 这个方向还能怎么挖扩展思路与个人体会多标签分类做无监督Re-ID目前还有几个值得探索的方向。一个是标签相关性建模。现在的做法是每个簇独立计算置信度但实际上簇之间是有关系的——比如簇A和簇B可能对应同一个人在不同姿态下的图片它们应该被鼓励同时激活。可以用图神经网络或者注意力机制来建模簇间关系。另一个方向是跨域多标签迁移。在源域上学到的多标签分类器能不能迁移到目标域这里的挑战是源域和目标域的簇结构完全不同。一个可能的解法是用域对抗训练让特征提取器学到的特征在源域和目标域上分布对齐同时保持多标签分类能力。还有一个偏工程的方向多标签向量的压缩与加速。当簇数量达到几千时多标签向量的维度会非常高训练和推理都会变慢。可以用哈希或者量化技术把多标签向量压缩到低维空间同时保持分类性能。我个人在这个方向上的体会是无监督Re-ID的核心矛盾始终是“伪标签的质量”和“模型的学习能力”之间的博弈。多标签分类提供了一个更柔性的伪标签表示但它并没有从根本上解决聚类本身的局限性。未来如果有工作能把聚类和多标签分类联合优化而不是像现在这样交替进行可能会有更大的突破。另外对于刚入门的研究生我的建议是先把监督Re-ID的baseline跑通理解特征提取、损失函数、评估协议这些基础环节再去碰无监督。无监督方法的不确定性太多如果没有监督学习的底子很容易在调参的海洋里迷失方向。我见过不少同学一上来就冲无监督结果跑了两个月连baseline都没复现出来信心直接崩了。稳扎稳打先把基础打牢再挑战前沿这条路走起来会顺很多。