CLIP-ReID阅读以及调试记录

论文
code
很详细的解说链接

论文主要工作

  • 首次将clip用于reid任务。
  • 提出了clip-reid,充分挖掘clip跨模型表达能力。在clip-reid中,每个id独立的token与模糊的文本描述集合,通过一个2stage的训练策略训练文本编码器。
  • 证明clip-reid在多个reid数据集(行人/汽车)到达sota结果。

训练流程

在这里插入图片描述
简要描述训练过程:

  • 将一个batch的图像以及对应的文本作为输入。 基于每个训练集中的id设置一系列可学习的文本tokens(x1, x2,…,xm)。
  • 设定一个图像编码器和文本编码器,以及线性层gv和gt。
  1. 下载预训练clip模型,初始化两个编码器、线性层,随机初始化可学习的文本token。
  2. 在第一stage训练时,计算文本与图像特征编码器的相似度。
  3. 通过eq5的损失函数前向传播优化,这一阶段只训练文本token,text encoder也是frozen的。
  4. 在第二stage训练,frozen文本token,只训练图像编码。

Clip-Reid算法框架

作者说明该算法的codebase为transReid、clip和CoOp。文章中将该算法与clip、CoOp进行了个对比,图画的蛮漂亮。
**加粗样式
**
主要说下clip-reid的不同之处:

  1. 借鉴了clip和coop的text 和image encoder,将完整语句替换为语义模糊的句子,每个句子长度是fixed,中间图像的描述词语是learnable tokens,这个作者做过实验,用四个token学习是效果最好的。
  2. stage1:text 和image encoder都是frozen的,只输入learnable的token送入text encoder学习,image encoder是采用imagenet预训练的模型,将数据送入encoder,只优化tokens。(A photo of x x x x person.)这个阶段与clip处理方法一致,用损失函数Loss(img2text)和Loss(text2img)。此外,在Loss(text2img),在同一batch的不同图像很可能属于同一个行人id,所以对loss进行了优化:
    同一batch中属于yi的所有正例索引
  3. stage2:该训练阶段只有image encoder中的参数进行优化。reid部分代码借鉴object reid,用triplet loss和加入label smooth 的id loss进行优化。为了充分利用clip,就用第一阶段的文本特征计算img2text的交叉熵。这一部分也粘贴下调试过程中的重点部分:
#processor/process_clipreid_stage2.py --line:55
#train
    batch = cfg.SOLVER.STAGE2.IMS_PER_BATCH
    i_ter = num_classes // batch
    left = num_classes-batch* (num_classes//batch)
    if left != 0 :
        i_ter = i_ter+1
    text_features = []
    # text feature extract
    with torch.no_grad():
        for i in range(i_ter):
            if i+1 != i_ter:
                l_list = torch.arange(i*batch, (i+1)* batch)
            else:
                l_list = torch.arange(i*batch, num_classes)
            with amp.autocast(enabled=True):
                text_feature = model(label = l_list, get_text = True)
            text_features.append(text_feature.cpu())
        text_features = torch.cat(text_features, 0).cuda()
    #image encoder optimize
    for epoch in range(1, epochs + 1):
        start_time = time.time()
        loss_meter.reset()
        acc_meter.reset()
        evaluator.reset()

        scheduler.step()

        model.train()
        for n_iter, (img, vid, target_cam, target_view) in enumerate(train_loader_stage2):
            optimizer.zero_grad()
            optimizer_center.zero_grad()
            img = img.to(device)
            target = vid.to(device)
            if cfg.MODEL.SIE_CAMERA:
                target_cam = target_cam.to(device)
            else: 
                target_cam = None
            if cfg.MODEL.SIE_VIEW:
                target_view = target_view.to(device)
            else: 
                target_view = None
            with amp.autocast(enabled=True):
                score, feat, image_features = model(x = img, label = target, cam_label=target_cam, view_label=target_view)
                #image-text match 
                logits = image_features @ text_features.t()
                loss = loss_fn(score, feat, target, target_cam, logits)

            scaler.scale(loss).backward()

            scaler.step(optimizer)
            scaler.update()

            if 'center' in cfg.MODEL.METRIC_LOSS_TYPE:
                for param in center_criterion.parameters():
                    param.grad.data *= (1. / cfg.SOLVER.CENTER_LOSS_WEIGHT)
                scaler.step(optimizer_center)
                scaler.update()

            acc = (logits.max(1)[1] == target).float().mean()

由于我训练的数据集较大,stage2常因为内存出问题,因此直接将stage1部分的模型保存。再次训练时,跳过1st的训练,load模型权重,直接进行2次训练,非常节省时间。

0516补充

网络部署

图像和文本的特征提取用的CLIP的visual encoder和text encoder,并且提供了两种方式:(1)transformer(vit-B16);(2)CNN以及global attention。训练细节包含学习率、warmingup策略设置、batch_size以及num_instance,推荐阅读原文和代码。

实验结果分析

  1. 两阶训练的必要性:CLIP可以融合文本和图像领域的嵌入特征。由于Reid数据集不会给不同的人id给特定的文本分析,因此该算法提供了被与训练过的一系列可学习的tokens。在第一阶段训练中,在训练image encoder的同时用对比损失训练text tokens。在第二阶段,将第一阶段训练的text tokens用来计算图像与文本匹配的交叉熵损失。消融实验的结果表明,可学习的text tokens虽然不能描述图像,但是会影响到image encoder的优化。
  2. 分析损失函数的权重:在stage2训练中,text encoder被冻,损失函数由id的交叉熵损失、triplet loss和image2text损失构成,在vit中,将各损失函数的权重设置为1、1、0.25;CNN设置为1、1和1。

代码调试

这个项目的代码并不难调,复现应该是比较简单的。但是分布式训练写的代码不太好,特别是load数据部分,百万数据集竟能load6个小时,后面根据fast reid的框架进行了修改,同时修改了num_workers,才稍好一点。就结果而言,在我配置的环境和自己的训练集,效果并没有fast reid好,但也有可能是没有加很多的数据增强,以及SIE信息没有加入。后续如果有很大的提升tricks会继续补充。或者后续将该训练策略移植到fast reid上做做对比实验,观察实验效果。
240605补充:
1 数据增强加了效果不好。分析原因:clip训练时只用了简单的数据增强,在finetune时使用一致的数据增强更容易收敛。
2将text_prompt部分移植到fast reid上,二阶段没用clip的visual部分,而是用了backbone+head与text prompt对齐,效果不如单纯backbone+head。

### CLIP ReID 实现方法 CLIP-ReID 的官方实现在论文 "CLIP-ReID: Exploiting Vision-Language Model for Image Re-identification without Concrete Text Labels" 中被详细介绍。此项目旨在利用预训练的视觉-语言模型(如CLIP),在无需具体文本标签的情况下执行图像再识别任务[^1]。 #### 数据集读取与处理 为了有效地准备和处理数据,`dataset` 文件夹中的代码使用了正则表达式来解析文件名并从中提取行人 ID 和摄像机 ID。例如: ```python import re pattern = re.compile(r'([-\d]+)_c(\d)') match = pattern.search('0008_c3') if match: pid, camid = map(int, match.groups()) ``` 这段代码定义了一个正则表达式模式 `r'([-\d]+)_c(\d)'` 来匹配特定格式的字符串,并能够从这些字符串中抽取出行人 ID (`pid`) 和摄像头编号 (`camid`)[^3]。 #### 模型构建与优化 在 `model` 文件夹下的 `make_model.py` 及 `clip.py` 文件里描述了如何加载预先训练好的 CLIP 模型以及对其进行调整以适应重新识别的任务需求。特别是对于 TorchScript 编译后的模型,可以采用如下方式加载: ```python import torch def load_clip_model(model_path): model = torch.jit.load(model_path).eval() return model ``` 这里展示了怎样通过调用 `torch.jit.load()` 函数加载由 PyTorch JIT 工具链编译过的模型文件,并立即将其置于评估模式下工作[^4]。 另外,在网络架构方面引入了一些改进措施,比如自定义的残差注意力模块 `ResidualAttentionBlock` 类,它通过对前向传播过程进行了特殊设计从而提高了效率和灵活性[^2]。 ### 应用案例 尽管具体的行业应用场景未在此处详述,但从技术角度来看,CLIP-ReID 能够应用于任何涉及大规模监控视频分析、智能安防系统或者基于图像的身份验证等领域。由于该算法能够在不依赖于精确标注的前提下完成跨模态检索任务,因此非常适合那些难以获得高质量人工标记样本的应用场景。
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值