【reID学习记录】Person_reID_baseline_pytorch学习

  可以将Person re-ID视为图像检索问题。给定摄像机A中的一个查询图像(query),我们需要查找其他摄像机(gallery)中同一个人的图像。Person re-ID的关键是找到该人员的区别性表示形式。
 
本文参考链接:https://github.com/layumi/Person_reID_baseline_pytorch/tree/master/tutorial

  • 首先在linux命令行中新建一个目录mkdir reID(名字可以按你项目名定义),之后敲git命令,确认git工具已经安装好了,没有的话就 sudo apt install git
  • 在github查看你所需要使用下载源码项目的URL地址
    代码链接:https://github.com/layumi/Person_reID_baseline_pytorch
    git
  • 进入需下载代码的目录中cd /home/jychen/work/ReID,在linux命令行中使用 git clone https://github.com/layumi/Person_reID_baseline_pytorch.git ,对该项目源码clone到本地,等待clone完成
  • 进入需下载Market-1501数据集的目录中cd /home/jychen/work/ReID/data,输入wget -c http://188.138.127.15:81/Datasets/Market-1501-v15.09.15.zip下载数据集
    数据集链接:http://188.138.127.15:81/Datasets/Market-1501-v15.09.15.zip

  Market-1501 数据集在清华大学校园中采集,夏天拍摄,在 2015 年构建并公开。它包括由6个摄像头(其中5个高清摄像头和1个低清摄像头)拍摄到的 1501 个行人、32668 个检测到的行人矩形框。每个行人至少由2个摄像头捕获到,并且在一个摄像头中可能具有多张图像。训练集有 751 人,包含 12,936 张图像,平均每个人有 17.2 张训练数据;测试集有 750 人,包含 19,732 张图像,平均每个人有 26.3 张测试数据。3368 张查询图像的行人检测矩形框是人工绘制的,而 gallery 中的行人检测矩形框则是使用DPM检测器检测得到的。该数据集提供的固定数量的训练集和测试集均可以在single-shot或multi-shot测试设置下使用。
 
目录结构
Market-1501
  ├── bounding_box_test
       ├── 0000_c1s1_000151_01.jpg
       ├── 0000_c1s1_000376_03.jpg
       ├── 0000_c1s1_001051_02.jpg
  ├── bounding_box_train
       ├── 0002_c1s1_000451_03.jpg
       ├── 0002_c1s1_000551_01.jpg
       ├── 0002_c1s1_000801_01.jpg
  ├── gt_bbox
       ├── 0001_c1s1_001051_00.jpg
       ├── 0001_c1s1_009376_00.jpg
       ├── 0001_c2s1_001976_00.jpg
  ├── gt_query
       ├── 0001_c1s1_001051_00_good.mat
       ├── 0001_c1s1_001051_00_junk.mat
  ├── query
       ├── 0001_c1s1_001051_00.jpg
       ├── 0001_c2s1_000301_00.jpg
       ├── 0001_c3s1_000551_00.jpg
  └── readme.txt
 
目录介绍
1) “bounding_box_test”——用于测试集的 750 人,包含 19,732 张图像,前缀为 0000 表示在提取这 750 人的过程中DPM检测错的图(可能与query是同一个人),-1 表示检测出来其他人的图(不在这 750 人中)
2) “bounding_box_train”——用于训练集的 751 人,包含 12,936 张图像
3) “query”——为 750 人在每个摄像头中随机选择一张图像作为query,因此一个人的query最多有 6 个,共有 3,368 张图像
4) “gt_query”——matlab格式,用于判断一个query的哪些图片是好的匹配(同一个人不同摄像头的图像)和不好的匹配(同一个人同一个摄像头的图像或非同一个人的图像)
5) “gt_bbox”——手工标注的bounding box,用于判断DPM检测的bounding box是不是一个好的box
 
命名规则
以 0001_c1s1_000151_01.jpg 为例
1) 0001 表示每个人的标签编号,从0001到1501;
2) c1 表示第一个摄像头(camera1),共有6个摄像头;
3) s1 表示第一个录像片段(sequece1),每个摄像机都有数个录像段;
4) 000151 表示 c1s1 的第000151帧图片,视频帧率25fps;
5) 01 表示 c1s1_001051 这一帧上的第1个检测框,由于采用DPM检测器,对于每一帧上的行人可能会框出好几个bbox。00 表示手工标注框

  • conda activate pytorch进入先前配好的pytorch环境,conda list查看环境里都有什么东西和它们的版本,bash pip install torchvision下载torchvision,我的pytorch环境里有python 3.6.2(后来发现要3.6.6以上版本,后文更新了),pytorch 1.7.1,torchvision 0.8.2
  • 打开Person_reID_baseline_pytorch里的prepare.py,替换download_path路径为刚下载的数据路径,然后保存,进入Person_reID_baseline_pytorch路径,python prepare.py
    prepare

prepare.py的目的是将具有相同ID的图像放在一个文件夹中。
 
os.walk函数
os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]])

  • top – 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。
    • root 所指的是当前正在遍历的这个文件夹的本身的地址
    • dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
    • files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
  • topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top文件夹中每一个子目录。
  • onerror – 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
  • followlinks – 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link> )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。
     

  遍历后将后缀名为jpg的图片文件提取名字第一个“_”前的字为类名,根据类名创建文件夹,再复制图片到相应分类文件夹里。
 
query为query里的图片分类
multi-query为gt_bbox里的图片分类
gallery为bounding_box_test里的图片分类
train_all为bounding_box_train里的图片分类
val为bounding_box_train里每个类的第一张图片
test为bounding_box_train每个类里除了第一张以外的图片

  • 运行结果是在数据集里对图片分类如下,
    分类
  • 查看model.py文件,通过from torchvision import modelsmodel = models.resnet50(pretrained=True)可以很方便地调用常用模型。此处对ResNet模型做了修改,因为Market-1501中有751个分类,而ResNet是在ImageNet中训练的,有1,000个分类。

插班生补课:了解卷积神经网络的初学者指南

深度残差网络(Deep residual network, ResNet)
 
深度网络出现了退化问题(Degradation problem):网络深度增加时,网络准确度出现饱和,甚至出现下降。
 
深度残差网络的一个堆积层结构有输入特征连接到输出特征,解决退化问题
resnet
resnet

参考:https://zhuanlan.zhihu.com/p/31852747

__init__(self)函数中对要进行的计算进行初始化,即设置每层输入输出的数量,每层的计算类型。
__forward__(self,x)函数中定义具体的计算关系,即每层之间如何连接,是否要pool,relu还是sigmoid等

nn.AdaptiveAvgPool2d()nn.AvgPool2d()
 
两者都是做二维的平均池化,但是它们关注的参数却不一样
 
nn.AvgPool2d()使用时一般关注 kernel_size 、stride 与 padding 三个参数

  • kernel_size为池化窗口大小
  • stride为max pooling的窗口移动步长
  • padding为输入的每一条边补充0的层数
  • 最后输出的尺寸由以上三个参数决定
     

nn.AdaptiveAvgPool2d()的特点是自适应,只需要关注输出维度的大小output_size,具体的实现过程和参数选择自动帮你确定了,更方便使用

ft_net模型由model_ft和classifier组成。有两种初始化参数方法。对于model_ft,设置参数pretrained = True,该参数设置为ImageNet上预训练的模型的参数。对于classifier,在ClassBlock中使用 weights_init_kaiming

  • 打开train.py,输入python train.py --gpu_ids 0 --name ft_ResNet50 --train_all --batchsize 32 --data_dir your_data_path可以跑一跑训练。

    • –gpu_ids 要运行哪个GPU。

    • –name 模型的名称。

    • –data_dir 训练数据的路径。

    • –train_all 使用所有图像进行训练。

    • –batchsize 批量大小。

    • –erasing_p 随机擦除概率

  • 此时发现了问题,ValueError: signal number 32 out of range,查找发现这是Python中的错误( https://bugs.python.org/issue33329 )。

    • 对于Python 3.6 ,它已在2019年7月左右发布的3.6.6中修复。但我用的是python3.6.2,为什么我的版本这么低呢,因为我用的清华源,里头的conda install python=3.6 只能安装到3.6.2版本,没找到什么好办法,只能换回默认源,试图重新创建一个pytorch环境,新环境为python3.6.12,但是下载非常慢。
    • 又出现了CondaHTTPError: HTTP 000 CONNECTION FAILED for url https://repo.anaconda.com/pkgs/main/linux-64/python-3.6.12-hcff3b4d_2.conda,直接cd进入路径/home/jychen/anaconda3/pkgs/,输入wget -c https://repo.anaconda.com/pkgs/main/linux-64/python-3.6.12-hcff3b4d_2.conda将它下载到本地(不知道为啥这样就下的很快),进入pytorch环境,conda install python-3.6.12-hcff3b4d_2.conda安装新的python版本,输入conda list可以看到python版本覆盖为3.6.12了
  • 重新跑train.py,发现警告

    • /home/jychen/anaconda3/envs/pytorch/lib/python3.6/site-packages/torch/optim/lr_scheduler.py:136: UserWarning: Detected call of lr_scheduler.step() before optimizer.step(). In PyTorch 1.1.0 and later, you should call them in the opposite order: optimizer.step() before lr_scheduler.step(). Failure to do this will result in PyTorch skipping the first value of the learning rate schedule. See more details at https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate)
    • 因为我用的是pytorch 1.7.1,Warning说代码第233行的optimizer.step()要在代码第170行的scheduler.step()执行之前,但我发现还是不改动跑的效果好

train.py理解

  • 使用了命令行工具argparse,使运行代码时能额外传入参数,参数名字前带“–”可以将参数变为可选参数,就不用按顺序传参,可以通过名字传参。action='store_true’的意思为:如果不触发,默认为FALSE的,触发才置为TRUE。
  • cudnn.benchmark = True,对模型里的卷积层进行预先的优化,可以提升运行速度,要求网络模型和输入大小不变
transform_train_list = [
        transforms.Resize((256,128), interpolation=3),    #重置图像大小(分辨率),interpolation为插值方法
        transforms.Pad(10),                               #填充
        transforms.RandomCrop((256,128)),                 #按指定尺寸随机裁剪图像(中心坐标随机)
        transforms.RandomHorizontalFlip(),                #以0.5概率使图像随机水平翻转  (这些都是增强数据的实际效果,泛化性等)
        transforms.ToTensor(),                            #将数据归一化到[0,1]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])      #数据归一化到[-1,1]
  • erasing_p随机擦除概率,color_jitter对颜色的数据增强:图像亮度、饱和度、对比度变化。
  • ImageFolder 数据加载器,指定路径下加载并执行组合好的transforms操作
  • torch.utils.data.DataLoader:
    该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,后续只需要再包装成Variable即可作为模型的输入
    shuffle:是否将图片打乱
    num_workers:使用多少个子进程来导入数据
    pin_memory: 在数据返回前,是否将数据复制到CUDA内存中
  • optimizer.zero_grad(),是将变量的梯度设置为零。在每一次迭代中都使用梯度来更新网络,所以更新后需要清除梯度。否则,梯度将累积。
  • with torch.no_grad()中的数据不需要计算梯度,也不会进行反向传播
  • 核心步骤:前向传播,计算loss,反向传播(计算所有参数的梯度),更新参数
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
  • optim.SGD神经网络优化器
    params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    lr (float) – 学习率
    momentum (float, 可选) – 动量因子(默认:0)
    weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
    dampening (float, 可选) – 动量的抑制因子(默认:0)
    nesterov (bool, 可选) – 使用Nesterov动量(默认:False)
  • 转到test.py,python test.py --gpu_ids 0 --name ft_ResNet50 --test_dir your_data_path --batchsize 32 --which_epoch 59,加载我们刚刚训练过的网络权重以提取每个图像的视觉特征。
    • –gpu_ids 要运行哪个GPU

    • –name 训练模型的目录名称

    • –batchsize 批量大小

    • –which_epoch 选择第i个模型

    • –test_dir 测试数据的路径

multiple_scale将图片进行不同尺度的缩放,得到图像金字塔,然后对每层图片提取不同尺度的特征,得到特征图。最后对每个尺度的特征都进行单独的预测。
特点:不同尺度的特征都可以包含很丰富的语义信息,精度高 ,但 速度慢。

  • 出现Warning,yaml现在用新用法了
    yaml警告
    加入Loader=yaml.FullLoader
    修改yaml
  • test.py里的os.system(‘python evaluate_gpu.py | tee -a %s’%result)调用了evaluate_gpu.py 并将结果写入result.txt中
  • rank-n:搜索结果中最靠前(置信度最高)的n张图有正确结果的概率
  • 平均精度均值(mAP):对于一些数据集来说,一张probe图像在gallery中可能有多张相匹配的图像,而mAP则是同时考虑了准确率和召回率,更能客观反映模型的性能。
  • torch.mul(a, b)是矩阵a和b对应位相乘,a和b的维度必须相等,比如a的维度是(1, 2),b的维度是(1, 2),返回的仍是(1, 2)的矩阵
  • torch.mm(a, b)是矩阵a和b矩阵相乘,比如a的维度是(1, 2),b的维度是(2, 3),返回的就是(1, 3)的矩阵
  • squeeze()实现降维
  • 转到demo.py,python demo.py --query_index 777 --test_dir your_dir
    –query_index 要查询的索引,可以选择0~3367之间的数字
    –test_dir 数据集路径
### 回答1: person_reid_baseline_pytorch是一个基于PyTorch框架的人员识别基线模型。它可以用于训练和测试人员识别模型,以识别不同人员之间的差异和相似之处。该模型提供了一些基本的功能,如数据加载、模型训练、模型测试等,可以帮助用户快速搭建和测试自己的人员识别模型。 ### 回答2: person_reid_baseline_pytorch是一个基于PyTorch框架的人体重识别模型。该模型采用卷积神经网络(Convolutional Neural Network,简称CNN)架构,采用多个卷积层和池化层进行特征提取,最后经过全连接层得到人物特征向量,实现了对人体进行识别。 该模型的训练数据集一般采用Market1501数据集,它包含超过1501个不同身份的超过32000张图片,是一个非常大且具有代表性的数据集,训练出的模型能够具有很好的泛化能力。 在训练过程中,除了使用标准的交叉熵损失作为损失函数外,还使用Triplet Loss作为损失函数的一种变形。该损失函数能够比较好地处理重识别中的最大间隔问题,并且能够实现对同一身份的多张图片之间的特征相似度比较。 对于测试集的预测部分,该模型采用的是余弦相似度进行特征向量相似度计算,相似度越高则说明两个图片中的人物越有可能是同一个人,可以实现良好的识别结果。 总的来说,person_reid_baseline_pytorch基于PyTorch框架实现的人体重识别模型,通过CNN架构进行特征提取,使用Triplet Loss进行训练,使用余弦相似度进行特征向量相似度计算,能够实现对人体进行高效准确的识别。 ### 回答3: person_reid_baseline_pytorch 是一个基于 PyTorch 框架的行人重识别算法基线模型,它实现了一个简单但功能齐全的行人重识别框架,可以训练和测试基于清晰照片的行人重识别任务。 该模型包含了基本卷积神经网络(CNN)的搭建和训练,其中包括几个关键部分:数据加载、模型定义、训练和测试。它使用数据增强技术和三元损失函数来训练模型,目的是使相同人的图像对与不同人的图像对之间的距离最大化。 person_reid_baseline_pytorch 采用 Market-1501 数据集进行测试,并在该数据集上取得了不错的结果。该数据集包含 1501 个行人,共有 12936 张图像,其中包括 6 种视角和多种行为。该算法读取图像数据并将之前处理后的行人图像输入神经网络,以便为每个图像计算行人的特征向量。然后,使用相关算法来比较图像对的距离,并确定它们是否属于同一人。该算法的性能指标包括准确度、精度和召回率等。 总之,person_reid_baseline_pytorch 提供了一个简单但完整的框架和基线模型,可以作为进一步解决行人重识别问题的基础。无论是学术界还是商业界,这种算法都有广泛的应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值