根据 train_test.prototxt文件生成 deploy.prototxt文件
本文参考博文
(1)介绍 *_train_test.prototxt文件与 *_deploy.prototxt文件的不同:http://blog.csdn.net/sunshine_in_moon/article/details/49472901
(2)生成deploy文件的Python代码:http://www.cnblogs.com/denny402/p/5685818.html
*_train_test.prototxt文件
这是训练与测试网络配置文件
*_deploy.prototxt文件
这是模型构造文件
在博文http://www.cnblogs.com/denny402/p/5685818.html 中给出了生成 deploy.prototxt文件的Python源代码,但是每个网络不同,修改起来比较麻烦,下面给出该博文中以mnist为例生成deploy文件的源代码,可根据自己网络的设置做出相应修改:(下方代码未测试)
# -*- coding: utf-8 -*- from caffe import layers as L,params as P,to_proto root='/home/xxx/' deploy=root+'mnist/deploy.prototxt' #文件保存路径 def create_deploy(): #少了第一层,data层 conv1=L.Convolution(bottom='data', kernel_size=5, stride=1,num_output=20, pad=0,weight_filler=dict(type='xavier')) pool1=L.Pooling(conv1, pool=P.Pooling.MAX, kernel_size=2, stride=2) conv2=L.Convolution(pool1, kernel_size=5, stride=1,num_output=50, pad=0,weight_filler=dict(type='xavier')) pool2=L.Pooling(conv2, pool=P.Pooling.MAX, kernel_size=2, stride=2) fc3=L.InnerProduct(pool2, num_output=500,weight_filler=dict(type='xavier')) relu3=L.ReLU(fc3, in_place=True) fc4 = L.InnerProduct(relu3, num_output=10,weight_filler=dict(type='xavier')) #最后没有accuracy层,但有一个Softmax层 prob=L.Softmax(fc4) return to_proto(prob) def write_deploy(): with open(deploy, 'w') as f: f.write('name:"Lenet"\n') f.write('input:"data"\n') f.write('input_dim:1\n') f.write('input_dim:3\n') f.write('input_dim:28\n') f.write('input_dim:28\n') f.write(str(create_deploy())) if __name__ == '__main__': write_deploy()
用代码生成deploy文件还是比较麻烦。我们在构建深度学习网络时,肯定会先定义好训练与测试网络的配置文件——*_train_test.prototxt文件,我们可以通过修改*_train_test.prototxt文件 来生成 deploy 文件。以cifar10为例先简单介绍一下两者的区别。
(1)deploy 文件中的数据层更为简单,即将*_train_test.prototxt文件中的输入训练数据lmdb与输入测试数据lmdb这两层删除,取而代之的是,
layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 1 dim: 3 dim: 32 dim: 32 } } }
注:shape: { dim: 1 dim: 3 dim: 32 dim: 32 }代表含义:
shape { dim: 1 #num,对待识别样本进行数据增广的数量,可自行定义。一般会进行5次crop,之后分别flip。如果该值为10则表示一个样本会变成10个,之后输入到网络进行识别。如果不进行数据增广,可以设置成1 dim: 3 #通道数,表示RGB三个通道 dim: 32 #图像的长和宽,通过 *_train_test.prototxt文件中数据输入层的crop_size获取 dim: 32}
(2)卷积层和全连接层中weight_filler{}与bias_filler{}两个参数不用再填写,因为这两个参数的值,由已经训练好的模型*.caffemodel文件提供。如下所示代码,将*_train_test.prototxt文件中的weight_filler、bias_filler全部删除。
layer { # weight_filler、bias_filler删除 name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" param { lr_mult: 1 #权重w的学习率倍数 } param { lr_mult: 2 #偏置b的学习率倍数 } inner_product_param { num_output: 10 weight_filler { type: "gaussian" std: 0.1 } bias_filler { type: "constant" } } }
删除后变为
layer { name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 10 } }
(3)输出层的变化
1)没有了test模块测试精度 ,将该层删除
2)输出层
1)*_deploy.prototxt文件的构造和*_train_test.prototxt文件的构造最为明显的不同点是,deploy文件没有test网络中的test模块,只有训练模块,即将*_train_test.prototxt中最后部分的test模块测试精度删除,即将如下代码删除。
layer { #删除该层 name: "accuracy" type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" include { phase: TEST } }
2) 输出层
*_train_test.prototxt文件
layer{ name: "loss" #注意此处层名称与下面的不同 type: "SoftmaxWithLoss" #注意此处与下面的不同 bottom: "ip2" bottom: "label" #注意标签项在下面没有了,因为下面的预测属于哪个标签,因此不能提供标签 top: "loss" }
*_deploy.prototxt文件
layer { name: "prob" type: "Softmax" bottom: "ip2" top: "prob" }
注意在两个文件中输出层的类型都发生了变化一个是SoftmaxWithLoss,另一个是Softmax。另外为了方便区分训练与应用输出,训练是输出时是loss,应用时是prob。
下面给出CIFAR10中的配置文件cifar10_quick_train_test.prototxt与其模型构造文件 cifar10_quick.prototxt 直观展示两者的区别。
cifar10_quick_train_test.prototxt文件代码
name: "CIFAR10_quick" layer { #该层去掉 name: "cifar" type: "Data" top: "data" top: "label" include { phase: TRAIN } transform_param { mean_file: "examples/cifar10/mean.binaryproto" } data_param { source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 backend: LMDB } } layer { #该层去掉 name: "cifar" type: "Data" top: "data" top: "label" include { phase: TEST } transform_param { mean_file: "examples/cifar10/mean.binaryproto" } data_param { source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 backend: LMDB } } layer { #将下方的weight_filler、bias_filler全部删除 name: "conv1" type: "Convolution" bottom: "data" top: "conv1" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 32 pad: 2 kernel_size: 5 stride: 1 weight_filler { type: "gaussian" std: 0.0001 } bias_filler { type: "constant" } } } layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 3 stride: 2 } } layer { name: "relu1" type: "ReLU" bottom: "pool1" top: "pool1" } layer { #weight_filler、bias_filler删除 name: "conv2" type: "Convolution" bottom: "pool1" top: "conv2" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 32 pad: 2 kernel_size: 5 stride: 1 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" } } } layer { name: "relu2" type: "ReLU" bottom: "conv2" top: "conv2" } layer { name: "pool2" type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { pool: AVE kernel_size: 3 stride: 2 } } layer { #weight_filler、bias_filler删除 name: "conv3" type: "Convolution" bottom: "pool2" top: "conv3" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 64 pad: 2 kernel_size: 5 stride: 1 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" } } } layer { name: "relu3" type: "ReLU" bottom: "conv3" top: "conv3" } layer { name: "pool3" type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { pool: AVE kernel_size: 3 stride: 2 } } layer { #weight_filler、bias_filler删除 name: "ip1" type: "InnerProduct" bottom: "pool3" top: "ip1" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 64 weight_filler { type: "gaussian" std: 0.1 } bias_filler { type: "constant" } } } layer { # weight_filler、bias_filler删除 name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 10 weight_filler { type: "gaussian" std: 0.1 } bias_filler { type: "constant" } } } layer { #将该层删除 name: "accuracy" type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" include { phase: TEST } } layer { #修改 name: "loss" #---loss 修改为 prob type: "SoftmaxWithLoss" # SoftmaxWithLoss 修改为 softmax bottom: "ip2" bottom: "label" #去掉 top: "loss" }
以下为cifar10_quick.prototxt
layer { #将两个输入层修改为该层 name: "data" type: "Input" top: "data" input_param { shape: { dim: 1 dim: 3 dim: 32 dim: 32 } } #注意shape中变量值的修改,CIFAR10中的 *_train_test.protxt文件中没有 crop_size } layer { name: "conv1" type: "Convolution" bottom: "data" top: "conv1" param { lr_mult: 1 #权重W的学习率倍数 } param { lr_mult: 2 #偏置b的学习率倍数 } convolution_param { num_output: 32 pad: 2 #加边为2 kernel_size: 5 stride: 1 } } layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX #Max Pooling kernel_size: 3 stride: 2 } } layer { name: "relu1" type: "ReLU" bottom: "pool1" top: "pool1" } layer { name: "conv2" type: "Convolution" bottom: "pool1" top: "conv2" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 32 pad: 2 kernel_size: 5 stride: 1 } } layer { name: "relu2" type: "ReLU" bottom: "conv2" top: "conv2" } layer { name: "pool2" type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { pool: AVE #均值池化 kernel_size: 3 stride: 2 } } layer { name: "conv3" type: "Convolution" bottom: "pool2" top: "conv3" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 64 pad: 2 kernel_size: 5 stride: 1 } } layer { name: "relu3" type: "ReLU" #使用ReLU激励函数,这里需要注意的是,本层的bottom和top都是conv3> bottom: "conv3" top: "conv3" } layer { name: "pool3" type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { pool: AVE kernel_size: 3 stride: 2 } } layer { name: "ip1" type: "InnerProduct" bottom: "pool3" top: "ip1" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 64 } } layer { name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 10 } } layer { name: "prob" type: "Softmax" bottom: "ip2" top: "prob" }
---------------------
作者:修炼打怪的小乌龟
来源:CSDN
原文:https://blog.csdn.net/u010417185/article/details/52137825
版权声明:本文为博主原创文章,转载请附上博文链接!
如果这篇文章帮助到了你,你可以请作者喝一杯咖啡