ubuntu下跑通CornerNet的流程步骤
-
- 环境配置
-
- 写这篇博客原因?
- 更改conda_packagelist.txt
- conda下基于conda_packagelist.txt创建新环境
- 安装pytorch 1.2 和torchvision
- 编译Corner Pooling-(用pytorch=1.x的这里是个大坑,请注意!)
-
- 按照原始代码直接编译,error
- 初次修改,测试阶段OK,训练阶段不OK
- 最终修改,训练和测试阶段均OK
- 编译nms(非极大值抑制)
- 安装MS COCO API
- 下载MS COCO数据集
- MSCOCO数据集存放位置(大坑)
-
- 问题描述:
- 问题解决
- CornerNet模型训练
-
- GPU数量和显存限制代码修改
- 成功训练结果,没有训练完成,时间太久了呀
- Cornernet模型测试
-
- 生成可视化检测照片代码修改
- 输出结果
-
- 随便放几张效果不错的。
- 不好的结果
- 使用新的配置文件说明
CornerNet 官方github链接
CornerNet 论文地址
环境配置
写这篇博客原因?
为什么要写这样一篇博客?
一是记录自己的学习过程,二是因为CornerNet是基于pytorch 0.4.0写的,其中的某些C++和Cuda API在1.0之后已经变化,所以在编译corner pooling的时候会遇到问题,真让人头大,不过没关系,这篇博客将教你如何解决该问题。
下载下来官方github代码后,根目录下有这样一个文件:
里面含有跑通CornerNet所需要的的第三方库,但是你仔细看其中的关于cuda和pytorch的第三方库,你会发现,其安装的是基于cuda8.0和pytorch 0.4.0的第三方库,万一你不幸装的是cuda 9.0及以上,难道你为了跑通个CornerNet再去重装cuda吗?虽然这样也可以,但是就有点太麻烦了。
更改conda_packagelist.txt
不过,如果不想重装的话,接着往下看。

打开conda_packagelist.txt,删除如下四个第三方库链接,然后你可以自己去装最重要的pytroch和torchvision。
https://conda.anaconda.org/caffe2/linux-64/caffe2-cuda8.0-cudnn7-0.8.dev-py36_2018.05.14.tar.bz2
https://repo.continuum.io/pkgs/free/linux-64/cudatoolkit-8.0-3.tar.bz2
https://conda.anaconda.org/pytorch/linux-64/pytorch-0.4.0-py36_cuda8.0.61_cudnn7.1.2_1.tar.bz2
https://conda.anaconda.org/pytorch/linux-64/torchvision-0.2.1-py36_1.tar.bz2
conda下基于conda_packagelist.txt创建新环境
cd进入下载后的cornernet文件夹下:
打开terminal,执行:
conda create --name CornerNet --file conda_packagelist.txt
至此,cornernet所需要的大部分的第三库已经安装成功。
安装pytorch 1.2 和torchvision
这方面我们要参考pytorch官网:
不知道为什么,在我创建的虚拟环境cornernet中使用pip安装时,虽然是python3环境,但是需要将pip3改为pip,暂时不知道什么原因。
执行如下命令即可:
pip install torch==1.2.0+cu92 torchvision==0.4.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html
这个装的话,比较快,毕竟是从pytorch官网直接获取安装包。
编译Corner Pooling-(用pytorch=1.x的这里是个大坑,请注意!)
这一步确实遇到了问题,毕竟官方代码是基于pytorch 0.4.0写的,我装的是pytorch 1.2.0,有问题也在意料之中。
按照原始代码直接编译,error
执行:
cd <CornerNet dir>/models/py_utils/_cpools/
python setup.py install --user
问题如下:
src/top_pool.cpp: In function ‘std::vectorat::Tensor top_pool_backward(at::Tensor, at::Tensor)’:
src/top_pool.cpp:44:41: error: could not convert ‘at::CUDA((c10::ScalarType)6)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_val = at::zeros(torch::CUDA(at::kFloat), {batch, channel, width});
^
src/top_pool.cpp:45:41: error: could not convert ‘at::CUDA((c10::ScalarType)4)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_ind = at::zeros(torch::CUDA(at::kLong), {batch, channel, width});
^
src/top_pool.cpp:57:44: error: could not convert ‘at::CUDA((c10::ScalarType)0)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto gt_mask = at::zeros(torch::CUDA(at::kByte), {batch, channel, width
^
src/top_pool.cpp:58:44: error: could not convert ‘at::CUDA((c10::ScalarType)6)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_temp = at::zeros(torch::CUDA(at::kFloat), {batch, channel, width
初次修改,测试阶段OK,训练阶段不OK
好像是cuda接口的问题,应该是由于pytorch版本的改变,导致了cuda接口的变化,但是怎么改呢?接着看。。
终于让我在github上官方代码的issues上找到了,
只需要在 **/models/py_utils/_cpools/src/**目录下,将src下bottom_pool.cpp、left_pool.cpp、top_pool.cpp以及right_pool.cpp四个文件中四行代码改变一下即可,四个文件的更改都是一样的。
即将
改为:
即可。
- 需要改动的有以下四处:
44、45行代码处:
auto max_val = at::zeros(torch::CUDA(at::kFloat), {batch, channel, height});
auto max_ind = at::zeros(torch::CUDA(at::kLong), {batch, channel, height});
57、58行代码处:
auto gt_mask = at::zeros(torch::CUDA(at::kByte), {batch, channel, height});
auto max_temp = at::zeros(torch::CUDA(at::kFloat), {batch, channel, height});
如此可以编译成功,但是前期因为显卡和数据集问题,我只是对官方训练了500000次的模型进行了测试,在此情况修改下的xxx_pool.cpp确实可以使用,但是进行从0开始训练MS COCO数据集的时候就出现了问题。
output = right_pool.backward(input, grad_output)[0]
RuntimeError: Expected object of type Variable but found type CUDAByteType for argument #0 ‘out’ (checked_cast_variable at /pytorch/torch/csrc/autograd/VariableTypeManual.cpp:48)
最终修改,训练和测试阶段均OK
所以还是编译corner pooling时由于pytorch版本不同导致出现了问题,我在查找了资料之后,发现了最终的解决方案。
其可以正常进行训练。
方案如下:
下载CornerNet-Lite CornerNet-Lite Github 链接 源代码,将其代码包中的CornerNet-Lite/core/models/py_utils/_cpools文件夹复制替换CornerNet源代码下的CornerNet/models/py_utils/_cpools/,然后运行命令进行重新编译:
python setup.py install --user
按照此方法编译后,至少在corner pooling这里的环境配置是没有问题的。
我在查找资料时,还遇到另外一种修改corner pooling下cpp文件代码的方法,不过经过我试用,这种修改至少对我的系统无效,依然会蹦出上述问题。
修改方法贴在了下面,读者看到的话也可以试试,看看行不行。
编译nms(非极大值抑制)
这个没什么可说的,只要装了cmake即可,我装的是3.4版本的好像,版本不要太低应该都没事。
cd <CornerNet dir>/external
make
安装MS COCO API
应该需要创建一个data文件夹:
cd <CornerNet dir>/data
git clone [email protected]:cocodataset/cocoapi.git coco
cd <CornerNet dir>/data/coco/PythonAPI
make
如果,第一次是第一次git,那么需要安装git:
以及设置github上的ssh,否则无法git,具体过程请参考我另一篇博文:
git安装和使用
下载MS COCO数据集
我之前下载过train2017、val2017、test2017,但是好像cornernet自己split了一个2014trainval的标签,因为还没看源代码,我先下载数据。
这个链接是google的,不翻墙有可能进不去,有需要的可以评论邮箱,我看到会发的。
annotations文件下载链接
MS COCO 数据集下载地址
下载红框标记的即可。
MSCOCO数据集存放位置(大坑)
我在看github英文说明的时候,其实官方对于数据集的使用说的模棱两可,我于是就按照字面的意思将下载的train2014直接重命名为trainval2014,val2014重命名为minival2014,test2017重命名为testdev2017,并放置在dir>/data/coco/images/下(如果没有,新建即可)。
问题描述:
结果出现了以下问题:
print("image.shape", image.shape[:]) AttributeError: 'NoneType' object has no attribute 'shape'
但从图中也可以看出,图片路径名是可以打印出来的,那么为什么还会出现NoneType这种错误呢?最可能的答案就是路径下的图片缺少了,即annotation里定义的标签图片在路径下有的找不到,所以才会出现这种问题。那么缺少了哪些问题呢?
问题解决
最终我发现,其实官方是将train2014和val2014合在一起作为trainval2014的,minival2014时从其中split的,具体怎么split我不知道,因为空间足够,所以我直接复制了一份,并重命名为了minival2014。
经过后续的训练测试,证明我这样做可以的,不会再出现这种NoneType的问题了。
但是实际训练的时候,还是会出现因为GPU数量太少和GPU显存太小的问题。不过我都一一解决了,解决方案在训练和测试章节。
CornerNet模型训练
To train and evaluate a network, you will need to create a configuration file, which defines the hyperparameters, and a model file, which defines the network architecture. The configuration file should be in JSON format and placed in config/. Each configuration file should have a corresponding model file in models/. i.e. If there is a .json in config/, there should be a .py in models/. There is only one exception which we will mention later.
- 训练CornerNet模型:
为了训练和评价一个网络,你需要创建一个定义了超参数和模型文件的配置文件,这将定义网络的基本架构。配置文件应该是json格式,并且被放在config/文件夹下。每个配置文件都应该有一个相对应的在models/文件夹下的模型文件。就是说,如果config/下有一个json文件,那么models/需要有一个.py文件
官方提供了配置文件CornerNet.json和模型文件CornerNet.py。
GPU数量和显存限制代码修改
如果你不考虑自己的GPU数量和GPU显存直接执行该命令的话,估计还是可能会抛出类似于corner pooling没有编译正确时的错误,即这种。
output = right_pool.backward(input, grad_output)[0]
RuntimeError: Expected object of type Variable but found type CUDAByteType for argument #0 ‘out’ (checked_cast_variable at /pytorch/torch/csrc/autograd/VariableTypeManual.cpp:48)
笔者本人的电脑是一个1060ti显卡 6G显存,所以很惭愧,算力太紧张。所以官方是用的10块GPU训练的,对于我来说显然不成立,直接执行命令确然会报错。
- 因此GPU数量和显存紧张的情况下请这样修改:
如果你只有一块GPU,请将batch_size改为1,如果你的显存大于12G请将chunk_sizes改为[4 ],如果跟我一样只是6G的,请改为[1],改为[2]我试过了,还是会out of memory。chunk_sizes代表向GPU分配多少张图片。
同时,train.py代码中的命令行参数thread,请由默认参数4改为1。这个我不知道具体是做什么用的目前,但是应该和GPU的数量有关。
改到这一步,还是不能直接运行命令,否则会如下错误:
dist = tag_mean.unsqueeze(1) - tag_mean.unsqueeze(2) IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2)
如果出现这种错误,按照图示进行修改:
在kp_utils.py中加入红框中的代码即可。
成功训练结果,没有训练完成,时间太久了呀
最后执行这个命令:
python train.py CornerNet
结果:
可以正常进行迭代,迭代输出的上下还是因为pytorch版本不同出现的一些警告,不过应该问题不大。
我大概迭代了10000次,5000次保存一次模型,结果因为空间不够,导致进程中断,不过整个流程没有什么问题。
保存的5000次和10000次迭代模型。
Cornernet模型测试
官方同样提供了一个训练了500k迭代次数的CornerNet模型,不过其用了10个Titan X GPUs,所以代码里有个地方默认的是10个GPU,如果你没有10个GPU,你需要把那个地方更改一下,不然有可能会报错,还有配置文件里的batchsize也需要更改以适应你的gpu显存。怎么修改在下面。
我们可以从如下链接(500k迭代次数模型下载链接,同样需要google。
)下载,并将其放在**/cache/nnet/CornerNet**文件夹下,
- 执行如下代码进行测试:
split==testing表示测试testdev2017下的图片,在代码中有定义,有时间我会在github上更新一个annotation版本的CornerNet代码。
生成可视化检测照片代码修改
执行命令,CornerNet会自动生成results.json文件,其中存储了图像id和detection坐标点,但是如果想生成可视化后的object detection图片需要进行如下修改。
在CornerNet/test/coco.py代码中的kp_detection函数内第152行的
if debug
改为:
再在191行下加入一行代码:
然后在terminal下执行:
输出结果
随便放几张效果不错的。
不好的结果
仔细观察CornerNet输出的可视化结果,我们可以发现CornerNet检测的两个主要问题:
- 对于密集型的object经常会出现对两个同样object之间的区域也列为object,可能不太好描述,看图就明白了。
直接将两个car之间的区域也检测为car;
直接将两个person之间的区域也检测为person。
又或者将tennis racket中的区域也检测为object;
- 对于一些密集型object检测不准确
比如下面的sheep,很多没检测都,而且直接将很大一块草地也检测为sheep了。
- 其他的检测不到和检测定位差距较大问题
下图两个孩子的检测框明显和实际差距过大。
bird没有检测到。
fire hvdrant 没有检测到。
总之虽然,效果不错,但是还是有很大问题。
正因为,其是通过角点来判断,所以对于密集型object出现这种将object之间的区域也检测为object也不足为奇。
使用新的配置文件说明
如果想使用新的配置文件,按照如下方案,我还没试过。
- 使用新的配置文件:
如果想测试不同的超参数,但是又不想重写原始的配置文件,可以创建一个带后缀的配置文件(model-suffix.json),但是不需要在models/下创建一个带后缀的model-suffix.py文件。
- 使用官方重写的多尺度配置文件:
python test.py CornerNet --testiter <iter> --split <split> --suffix multi_scale
有空会补上训练和测试结果。已补上训练成功截图和测试结果,因为算力原因,就先不从头开始训CornerNet了。
2019.10.9,2019.10.12更新。
希望能帮到大家。随手点赞是对我最大的认可。