caffe 本身并不支持 多类标的输入, 该框架主要用于解决图片分类的问题,而目前,两个重要的问题需要多标签的输入:多任务学习(multi-task)和多标签分类(multi-label),本文针对这两个问题,实现了多标签的输入
目前,网上流行的多标签输入方法主要有以下四种:
1. 最简单,使用mxnet,它本身支持了多标签分类的问题,因此也自带了多标签的输入
2. 用HDF5 + Slice Layer的方法完成,这种方法实现上没有什么难度,但是当数据量很大时,HDF5的存储方式会产生数十倍于图片的硬盘消耗,而且生成的过程也非常缓慢,本人一开始就主要使用这种方法,往往事倍功半
3. 用两个data的输入(两个LMDB),一个只输出图片,一个只输出标签,这种方法相对前面两种要难一些,不过应该效果也不错
4. 直接修改caffe的网络使其满足多标签的输入,为了方便以后的实验,本人实现了这种方法
方法描述:注意到caffe的大多数数据转换都是从./.build_release/tools/convert_imageset 这种方法开始的,因此,从convert_iamgeset开始入手应该是正确的选择,通过跟踪数据的输入,依次修改了convert_imageset.cpp、io.hpp、 io.cpp、data_layers.hpp、caffe.proto、data_layer.cpp、image_data_layer.cpp、memory_data_layer.cpp等。因为本次是工程需要,因此我直接在py-faster-rcnn的caffe上进行修改
主要方法:(该博客上所有图片,左边是修改后的,右边是原有的)
1. 修改convert_imageset:lines是读入的信息,包括图片路径和label,这里改成vector以支持多标签输入
2. 修改io.hpp:下图里面,主要就是各种label改为vector
3. 同理修改io.cpp:主要修改ReadImageToDatum和ReadFileToDatum两个函数,主要是set_label要逐个set进去
4. 修改caffe.proto,主要需要满足多标签输入,以及增加一些输入网络层的参数
5. 修改data_layer.cpp,实现Data这种网络层类型的多标签输入,主要修改DataLayerSetup和load_batch两个函数
6. 修改data_layer.hpp,主要是修改部分网络的参数,增加标签数量的变量等
7. 修改image_data_layer.cpp
8. 修改memory_data_layer.cpp
至此,完成所有修改,编译之后进行测试:
从实验结果可以看出,输入的标签和train.txt的一致。
总结:本文通过修改caffe的内部代码,实现了caffe的多标签输入,主要实现了DataLayer、ImageDataLayer、MemoryDataLayer三种输入层,但是需要注意,本人仅在DataLayer和ImageDataLayer下进行过测试,未对MemoryDataLayer或其他的输入类型进行测试
最后,感谢实验室的大神师兄lxionghao,在实现过程中,本人主要通过不断编译定位错误逐个修改以及借鉴他的修改方法完成任务。
下面贴出他的blog,比较有借鉴价值:
讲解:http://blog.csdn.net/baobei0112/article/details/47606559
工程:https://gitcafe.com/lxiongh/Caffe_for_Multi-label
本人工程将稍后上传到github,之后再公布给大家