近期在尝试使用FastReID,期间对FastReID架构、损失函数、数据集准备、模型训练/评估/可视化/特征向量输出、调试debug记录等进行记录。
FastReID架构理解
关于FastReID的介绍,可点击此链接前往查询。
ReID和FastReID架构
对于模型架构、损失函数、实验Tricks可点击访问下述两个链接:
行人重识别02-03:fast-reid(BoT)-白话给你讲论文-翻译无死角_reid bot算法-CSDN博客
详解ReID的各部分组成及Trick——基于FastReID_fastreid trick-CSDN博客
ReID网络训练和测试的输出不同
注:ReID网络训练和测试的输出不同:训练的输出执行到最后一步,进行Triplet loss+Center loss+ID lossID损失函数的计算并反向梯度传播,从而迭代更新网络参数;测试inference阶段只执行到特征向量的输出(可见上图inference stage),这也对应后文的demo.py脚本所执行的操作。
一般神经网络训练和测试的输出是同一个东西,但是基于表征学习的ReID方法比较特殊:ReID训练时候的输出是每张图片对应不同ID的预测概率(也就是输出此图片识别的ID/类别),测试模式输出的是每张图片ReID的特征向量(比如对于多个摄像头,用不同摄像头检测到的多个物体进行ReID后的特征向量进行后续运算,特征向量相似的给定同一个ID,ReID测试网络不直接输出识别的ID/分类)
损失函数
笔者没有扒源代码,但从上图FastReID架构可以看出,其损失函数有三部分组成:Triplet loss + Center loss + ID loss。其中Triplet loss和Center loss属于基于度量学习的ReID方法范畴,因为其度量的是特征向量的距离/相似度;ID loss属于基于表征学习的ReID方法范畴,类似softmax层后的分类损失。
Triplet loss和Cicle loss
数据集准备
复制数据集到fast-reid\datasets下
用户自定义数据集训练参考:
How to train Custom Dataset · Issue #220 · JDAI-CV/fast-reid (github.com)
模型训练
直接训练
键入:
python tools\train_net.py --config-file .\configs\VeRi\sbs_R50-ibn.yml
使用预训练模型权重训练
键入:
python tools\train_net.py --config-file .\configs\VeRi\sbs_R50-ibn.yml MODEL.WEIGHTS model_weights/veri_sbs_R50-ibn.pth
下载地址:
在fast-reid/MODEL_ZOO.md文件下提供了不同数据集下不同方法得到的sota模型。
不同数据集训练权重下载
增加预训练模型权重地址
.yml文件增加中文注释
修改:注释不能写中文,否则会报错
.yml文件增加中文注释报错
.yml文件去除中文注释
模型评估eval-only
键入:
python tools/train_net.py --config-file .\logs\veri\sbs_R50-ibn\config.yaml --eval-only MODEL.WEIGHTS model_weights/veri_sbs_R50-ibn.pth MODEL.DEVICE "cuda:0"
模型评估
细节理解:
行人重识别02-09:fast-reid(BoT)-pytorch编程规范(fast-reid为例)6-模型测试评估-1_rexnet fast-reid-CSDN博客
fastreid\engine\defaults.py,找到类class DefaultTrainer(SimpleTrainer) 中的函数 def test(self),该函数就是对数据进行评估的总体逻辑。
对datasets.test进行评估。
结果可视化
visualize_result.py 可视化结果
参考理解:
行人重识别02-11:fast-reid(BoT)-实用技巧分享(1)-visualize_result,demo_visualize_result.py 特征距离约大-CSDN博客
键入:
python demo/visualize_result.py --config-file .\logs\veri\sbs_R50-ibn\config.yaml --parallel --vis-label --output logs/mgn_duke_vis --dataset-name VeRi --opts MODEL.WEIGHTS .\model_weights\veri_sbs_R50-ibn.pth
行人识别fastreid项目官方数据训练测试 - 知乎 (zhihu.com)
文件生成在logs/mgn_duke_vis
结果可视化,别人训练好的结果,可对照理解图片上方的参数
结果可视化,自己尝试的结果(没训练,加载的权重也不对,所以这个图并不对)
为何识别效果如此之差呢,查看下图报错信息,因为下载的预训练权重不包含head.weights,因此要用上还是需要重新train一下,但是我理解的是这并不会影响demo.py输出的特征向量,因为那个不需要用到head.weights。
visualize_result.py加载预训练权重情况
demo.py 输出query图片的特征向量
针对某一张图片
键入:
python demo/demo.py --config-file .\logs\veri\sbs_R50-ibn\config.yaml --parallel --input .\datasets\VeRi\image_query\xx.jpg --output ./logs/demo_output --opts MODEL.WEIGHTS .\model_weights\veri_sbs_R50-ibn.pth
在./logs/demo_output/文件夹下,可以看到如下特征向量文件(.npy格式)
注:以下示例只对.\datasets\VeRi\image_query文件夹下的两张图片进行操作出,所以示例只有2个.npy文件。执行--input .\datasets\VeRi\image_query\*.jp,文件夹中有几张图片,输出几个特征向量(每个的尺寸为:1x2048)。
特征向量输出
针对指定文件夹下的所有jpg图片
键入:
python demo/demo.py --config-file .\logs\veri\sbs_R50-ibn\config.yaml --parallel --input .\datasets\VeRi\image_query --output ./logs/demo_output --opts MODEL.WEIGHTS .\model_weights\veri_sbs_R50-ibn.pth
输出结果为:
特征向量输出
调试debug
CUDA out of memory
要修改Batch size或者输入图片尺寸,具体修改config文件夹下:
sbs_R50-ibn.yml文件中的IMS_PER_BATCH、SIZE_TRAIN
Base-SBS.yml中的NUM_INSTANCE
ZeroDivisionError: integer division or modulo by zero
这里要保证num_pids_per_batch不为0,也就是说sbs_R50-ibn.yml文件中的IMS_PER_BATCH要大于Base-SBS.yml中的NUM_INSTANCE
报错提示
理解:
给定batch size,随机采集P个ID,然后每个ID选择K(num_instances)个实例图像。
num_pids_per_batch = batch_size // self.num_instances指每个batch需要采集多少个(P个)身份ID,因此num_pids_per_batch必须大于1.
ReID中的Batch Size设置与其他的深度学习任务有一些区别,它涉及到两个参数P(一个batch中涉及到的不同类别的样本数量)和K(一个batch中涉及到的同一个类别的样本的样本数量)。在BoT的工作中,对Batch Size的大小和P、K的设置做了探究,实验如下表,不同的数值对最终的实验结果还是有很大的影响的。
Batch size中P、K探究实验
理论理解可点击链接,前往b站查看。
Triplet loss理解
AssertionError: No inf checks were recorded for this optimizer.
报错提示
问题解决可参考:
No inf checks were recorded for this optimizer. · Issue #700 · JDAI-CV/fast-reid (github.com)
解决办法1:
在defaults.py文件中增加 contiguous=False
解决办法2:
安装低版本的Pytorch,未实践。
tools/train_net.py --eval-only报错no module
解决方法1:编译make
使用eval前要先编译make(核心是文件夹下的makefile文件),而make需要gcc
可查询本人之前文章链接,查询Windows具体编译makefile文件流程。
GettingStarted文档编译要求
在windows下,用MinGW代替gcc,可参考:
Windows安装g++和gcc,含环境变量配置(图文教程)_windows系统 gcc g++-CSDN博客
修改makefile文件,否则一直报错:
- 将python3改为python
- 去掉rm这句话,因为不是linux系统,没这个命令,可改为del
原makefile文档
修改后的makefile文档
虽然编译成功,但后续运行还是会报错,ValueError: Buffer dtype mismatch, expected 'long' but got 'long long' · Issue #74 · JDAI-CV/fast-reid (github.com),可能需要在linux下编译才行(我的wsl没装Cython.Build,故放弃了此方法,后续可以在wsl下安装pip、Cython,然后执行python setup.py build_ext --inplace)。
成功编译后仍报错
解决方法2:不使用cython
No module named ‘fastreid.evaluation.rank_cylib.rank_cy‘_no module named 'fastreid-CSDN博客
如果成功make,不需要注释此处
将use_cython改为False,虽然速度变慢,但解决了很多麻烦
demo.py--input .\*.jpg 报错
当键入下式,会报错:
python demo/demo.py --parallel --input .\datasets\VeRi\image_query\*.jpg
报错提示
究其原因,是因为在demo.py原代码中,args.input为\image_query\*.jpg,无法使用for path in args.input,无法遍历此文件夹下的所有jpg图片。
原文件demo.py
因此,更改代码的if else逻辑,实现需求。
修改后的文件
注:目前代码仅可以遍历所有jpg文件,对于png文件的话需要改动上图line 95。