2020-10-29 16:44:34 登录注册 RSS

当前位置: 公理网 >> 网友举报 >> 如何在caffe中添加新的Layer

如何在caffe中添加新的Layer
发布时间:2019-06-15| 来源:公理网 | 点击发表评论
Addaclassdeclarationforyourlayertotheappropriateoneofcommon_layers.hpp,data_layers.hpp,loss_layers.hpp,neuron_layers.hpp,
orvision_layers.hpp.
Includeaninlineimplementationoftypeand
the*Blobs()methods
tospecifyblobnumberrequirements.Omitthe*_gpudeclarations
ifyou'llonlybeimplementingCPUcode.
Implementyourlayerinlayers/your_layer.cpp.

(Optional)ImplementtheGPUversionsForward_gpuandBackward_gpuinlayers/your_layer.cu.
Addyourlayertoproto/caffe.proto,
updatingthenextavailableID.Alsodeclareparameters,ifneeded,inthisfile.
Makeyourlayercreateablebyaddingittolayer_factory.cpp.
Writetestsintest/test_your_layer.cpp.
Usetest/test_gradient_check_util.hppto
checkthatyourForwardandBackwardimplementationsareinnumericalagreement.
上面是一个大致的流程,我就直接翻译过来吧,因为我自己琢磨出来的步骤跟这个是一样的。在这里,我们就添加一个Wtf_Layer,然后作用跟Convolution_Layer一模一样。注意这里的命名方式,Wtf第一个字母大写,剩下的小写,算是一个命名规范吧,强迫症表示很舒服。
1.首先确定要添加的layer的类型,是common_layer还是data_layer还是loss_layer,neuron_layer,vision_layer,这里的Wtf_Layer肯定是属vision_layer了,所以打开vision_layers.hpp
然后复制convolution_layer的相关代码,把类名还有构造函数的名字改为WtfLayer,如果没有用到GPU运算,那么把里面的带GPU的函数都删掉

2.将Wtf_layer.cpp添加到src\caffe\layers文件夹中,代码内容复制convolution_layer.cpp把对应的类名修改(可以搜一下conv关键字,然后改为Wtf)

3.假如有gpu的代码就添加响应的Wtf_layer.cu(这里不添加了)

4.修改proto/caffe.proto文件,找到LayerType,添加WTF,并更新ID(新的ID应该是34)。假如说Wtf_Layer有参数,比如Convolution肯定是有参数的,那么添加WtfParameter类

5.在layer_factory.cpp中添加响应的代码,就是一堆if...else的那片代码

6.这个可以不做,但是为了结果还是做一个,就是写一个测试文件,检查前向后向传播的数据是否正确。gradient_check的原理可以参考UFLDL教程的对应章节

之后我会更新我自己写的maxout_layer的demo,在这立一个flag以鞭策自己完成吧╮(╯▽╰)╭

(二)如何添加maxout_layer

表示被bengio的maxout给搞郁闷了,自己摆出一个公式巴拉巴拉说了一堆,结果用到卷积层的maxout却给的另一种方案,吐槽无力,不过后来又想了下应该是bengio没表述清楚的问题。

我的maxout的算法思路是这样的,首先要确定一个group_size变量,表示最大是在group_size这样一个规模的集合下挑选出来的,简而言之就是给定group_size个数,取最大。确定好group_size变量,然后让卷积层的output_num变为原来的group_size倍,这样输出的featuremap的个数就变为原来的group_size倍,然后以group_size为一组划分这些featuremap,每组里面挑出响应最大的点构成一个新的featuremap,这样就得到了maxout层的输出。

20141216100730828?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva3VhaXRvdWtpZA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center"align="middle"alt="">

要是还不明白我就拿上面的图来说一下,上面一共9张图,相当于卷积层输出9张featuremap,我们每3个为一组,那么maxout层输出9/3=3张featuremap,对于每组featuremaps,比如我们挑出绿色的三张featuremaps,每张大小为w*h,那么声明一个新的output_featuremap大小为w*h,遍历output_featuremap的每个点,要赋的数为三张绿色featuremap对应点的最大的那个,也就是三个数里面选最大的,这样就输出了一张output_featuremap,剩下的组类操作。

我觉得到这应该明白maxout的原理跟算法了吧==,下面就直接贴代码了

新建一个maxout_layer.cpp放到src/caffe/layer文件夹下



voidMaxoutLayerDtype::SetUp(constvectorBlobDtype*bottom,

vectorBlobDtype**top){

LayerDtype::SetUp(bottom,top);

printf(===============================================================hasgointosetup!==============================================\n);

MaxoutParametermaxout_param=this-layer_param_.maxout_param();





//maxout_size

//CHECK(!maxout_param.has_num_output())

//maxoutsizearerequired.

//if(maxout_param.has_num_output()){

//num_output_=maxout_param.num_output();

//}

num_output_=this-layer_param_.maxout_param().num_output();

CHECK_GT(num_output_,0)outputnumbercannotbezero.;



//bottomê?FEATURE_MAP

num_=bottom[0]-num();

channels_=bottom[0]-channels();

height_=bottom[0]-height();

width_=bottom[0]-width();



//?2???????a??if2??á?ü??è¥

//TODO:generalizetohandleinputsofdifferentshapes.

for(intbottom_id=1;bottom_idbottom.size();bottom_id){

CHECK_EQ(num_,bottom[bottom_id]-num())Inputsmusthavesamenum.;

CHECK_EQ(channels_,bottom[bottom_id]-channels())

Inputsmusthavesamechannels.;

CHECK_EQ(height_,bottom[bottom_id]-height())

Inputsmusthavesameheight.;

CHECK_EQ(width_,bottom[bottom_id]-width())

Inputsmusthavesamewidth.;

}



//Settheparameters?3?μ2?êy

CHECK_EQ(channels_%num_output_,0)

Numberofchannelshouldbemultiplesofoutputnumber.;



group_size_=channels_/num_output_;



//Figureoutthedimensionsforindividualgemms.???????óμ?DDáD



//??êμBengioμ??????D??óúK_μ??óD???ò?oü?£oy£???óúí???????ê???á?e.g.

//ò2??óD?μμ?μ×êμ?êê?2?ê??a??2ù×÷μ?£?òò?aè?1???μ?ê?channel?±?ó??DD±è??

//?????í?úàí??μ?1?ê???o?μ?2?o?£?μ?ê??ü1??aêíí???£?±èè??μ??3?×?o?μ?ò?2?

//???òí????ú·?í???μ?maxoutμ?×?·?2?ì??àá?°??£?ùè?×?μ???èYμ??°???üè??°ò?2?

//μ?output_num??o?maxout



//for(inttop_id=0;top_idtop-size();top_id){

(*top)[0]-Reshape(num_,num_output_,height_,width_);//????ê???±?μ?channel??êy
max_idx_.Reshape(num_,num_output_,height_,width_);

//}

}





templatetypenameDtype

DtypeMaxoutLayerDtype::Forward_cpu(constvectorBlobDtype*bottom,

vectorBlobDtype**top){



intfeatureSize=height_*width_;

Dtype*mask=NULL;

mask=max_idx_.mutable_cpu_data();



//printf(1.maxout_forward\n

constinttop_count=(*top)[0]-count();

caffe_set(top_count,Dtype(0),mask);



//printf(2.maxout_forward\n




for(inti=0;ibottom.size();i){

constDtype*bottom_data=bottom[i]-cpu_data();

Dtype*top_data=(*top)[i]-mutable_cpu_data();



for(intn=0;nnum_;n){

//è?μún??í???

for(into=0;onum_output_;o){

for(intg=0;ggroup_size_;g){

if(g==0){

for(inth=0;hheight_;h){//á?2??-?·óDμ??ùaà?

for(intw=0;wwidth_;w){

intindex=wh*width_;

top_data[index]=bottom_data[index];

mask[index]=index;

}

}

}

else{

for(inth=0;hheight_;h){

for(intw=0;wwidth_;w){

intindex0=wh*width_;

intindex1=index0g*featureSize;

if(top_data[index0]bottom_data[index1]){

top_data[index0]=bottom_data[index1];

mask[index0]=index1;

}

}

}

}

}

bottom_data=featureSize*group_size_;

top_data=featureSize;

mask=featureSize;

}

}

}



returnDtype(0.);

}



templatetypenameDtype

voidMaxoutLayerDtype::Backward_cpu(constvectorBlobDtype*top,

constvectorboolpropagate_down,vectorBlobDtype**bottom){

if(!propagate_down[0]){

return;

}

constDtype*top_diff=top[0]-cpu_diff();

Dtype*bottom_diff=(*bottom)[0]-mutable_cpu_diff();

caffe_set((*bottom)[0]-count(),Dtype(0),bottom_diff);

constDtype*mask=max_idx_.mutable_cpu_data();

intfeatureSize=height_*width_;


for(inti=0;itop.size();i){

constDtype*top_diff=top[i]-cpu_diff();

Dtype*bottom_diff=(*bottom)[i]-mutable_cpu_diff();



for(intn=0;nnum_;n){

//è?μún??í???

for(into=0;onum_output_;o){

for(inth=0;hheight_;h){//á?2??-?·óDμ??ùaà?

for(intw=0;wwidth_;w){

intindex=wh*width_;

intbottom_index=mask[index];

bottom_diff[bottom_index]=top_diff[index];

}

}

bottom_diff=featureSize*group_size_;

top_diff=featureSize;

mask=featureSize;

}

}

}

}



//#ifdefCPU_ONLY

//STUB_GPU(MaxoutLayer);

//#endif



INSTANTIATE_CLASS(MaxoutLayer);



}//namespacecaffe
里面的乱码是中文,到了linux里面就乱码了,不影响,还一个printf是测试用的(要被笑话用printf了==)
vision_layers.hpp里面添加下面的代码


templatetypenameDtype
classMaxoutLayer:publicLayerDtype{
public:
explicitMaxoutLayer(constLayerParameterparam)
:LayerDtype(param){}
virtualvoidSetUp(constvectorBlobDtype*bottom,
vectorBlobDtype**top);//为什么需要bottom与top,肯定的啊,
//要初始化bottomtop的形状
virtualinlineLayerParameter_LayerTypetype()const{
returnLayerParameter_LayerType_MAXOUT;
}

protected:
virtualDtypeForward_cpu(constvectorBlobDtype*bottom,
vectorBlobDtype**top);
//virtualDtypeForward_gpu(constvectorBlobDtype*bottom,
//vectorBlobDtype**top);
virtualvoidBackward_cpu(constvectorBlobDtype*top,
constvectorboolpropagate_down,vectorBlobDtype**bottom);
//virtualvoidBackward_gpu(constvectorBlobDtype*top,
//constvectorboolpropagate_down,vectorBlobDtype**bottom);

intnum_output_;
intnum_;
intchannels_;
intheight_;
intwidth_;
intgroup_size_;
BlobDtypemax_idx_;

};
剩下的是layer_factory.cpp的改动,不说明了,然后是proto文件的改动

messageMaxoutParameter{
optionaluint32num_output=1;//Thenumberofoutputsforthelayer
}
额,当然还有proto文件的其他改动也不说明了,还有test文件,我没写,因为我自己跑了下demo,没啥问题,所以代码可以说是正确的。

不过要说明的是,目前的代码不能接在全连接层后面,是我里面有几句代码写的有问题,之后我会改动一下,问题不大。

然后就是NIN的实现了,表示自己写的渣一样的代码啊,效率目测很低。哦对了,这些都是CPU算的,GPU不大会,还没打算写。

NIN_layer的实现

我之前一直以为Github上的networkinnetwork是有问题的,事实证明,我最后也写成了Github上面的样子==所以大家自行搜索caffenetworkinnetwork吧……不过得翻墙下载,所以我就把网络式的代码直接贴出来(cifar10数据库的网络结构)


top:accuracy
include:{phase:TEST}
}
layers{
name:loss
type:SOFTMAX_LOSS
bottom:pool3
bottom:label
top:loss
}




151506879/article/details/52073392">hdf5文件读取和写入
40994657"target="_blank">weixin_40994657:[reply]m0_37407756[/reply]
您好!您的问题解决了吗?我和您出现了一样的问题,错误使用h5infoc
指定的文件名要么在MATLAB路径中未找到,要么包含不支持的字符。请问是怎么解决的呢?谢谢

最新新闻

手机浏览

公理网 版权所有

公理网 Total 0.019957(s) query 6, 报料QQ:点击这里

给我发消息