看到题目,可能有的朋友还不太理解这一篇博文主要是要干嘛的,下面我先来举一个简单的例子。
先做一个简单的假设:假设你已经看了我之前的博文:用 caffe 做回归(下),即使上面的假设不成立,也没有关系。该博文主要是讲解用caffe做回归任务的时候对data_layer.cpp的修改。此处我想让大家关注的是,里面用到的一个变量声明:
int labelNum = 4; //表示标签的数量为4
对于“强迫症”来说,在里面写这样的一个声明是很不美观的。另外,当标签的数量发生变化的时候(比如变成10),还需要在这里把4修改为10,然后重新编译caffe。这样对于使用的人来说是很不友好的。
于是我又看到了这样的一句代码:
const int batch_size = this->layer_param_.data_param().batch_size();
这里的batch_size
不就是我们的网络结构配置文件(比如:train_test.prototxt)中的data_param
中的参数吗?
那我能不能有下面的代码:
const int labelNum = this->layer_param_.data_param().label_num();
这样一来,我是不是直接在原来的 train_test.prototxt 文件中:
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
增加label_num: 4
一项,即:
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
label_num: 4
}
是不是就可以解决我上面遇到的问题了呢?当我需要把标签的数量从4改为10的时候,也只需要在 train_test.prototxt 文件中修改,并不需要打开 data_later.cpp,也不需要重新编译caffe。
经过一番验证,上面的猜想是完全可行的!哈哈,说的自己好像是第一个发现一样,其实早就有很多人这么做~~
那么下面我就来说一说具体的做法(其实很简单):
要想在data_param
中添加 label_num
这个参数,需要在 src/caffe/proto/caffe.proto
文件中对应的位置上加上对label_num
这一参数的声明:
- 打开
caffe.proto
文件,ctrl+F找到对message DataParameter
部分的定义,到这里会发现,原来我们在train_test.prototxt的数据层中看到的batch_size
mean_file
crop_size
等等这些熟悉的“面孔”都是在这里最初声明的(到这里似乎已经明白了什么,对的往下看); - 我们只需要在
optional uint32 prefetch = 10 [default = 4];
的后面加上:
optional uint32 label_num = 11;
就完成了对caffe.proto
的修改。
- 最后在重新在caffe的根目录下重新
make
编译一下caffe,就可以像上面说的那样使用label_num
了!
下面还有一些需要注意的地方:
- 如果定义的参数是float类型或者bool类型的,记得要将uint32改成相应的类型;
- 建议定义参数的时候使用小写字母。也就是像
label_num
,而不要label_Num
。我在实际使用的时候发现如果使用大写,则在后面的train_test.prototxt中也需要用大写,而在data_layer.cpp中使用的时候反而要用小写的函数名比如:label_num()
。貌似是这个规律~~
另外,这边博文的思想可以使用到我的另外一篇博文中:
在 caffe 的 data_later.cpp 中做数据增强
如果在做数据增强的过程中需要用到某些参数,也可以直接通过data_param
传递。
大概就是这样了~