caffe prototxt


原文链接: caffe prototxt

浅谈caffe中train_val.prototxt和deploy.prototxt文件的区别

在刚开始学习的时候,觉得train_val.prototxt文件和deploy.prototxt文件很相似,然后当时想尝试利用deploy.prototxt还原出train_val.prototxt文件,所以就进行了一下对比,水平有限,可能很多地方说的不到位,希望大神们指点批评~~

本文以CaffeNet为例:

1. train_val.prototxt 
首先,train_val.prototxt文件是网络配置文件。该文件是在训练的时候用的。
2.deploy.prototxt
该文件是在测试时使用的文件。

区别:
首先deploy.prototxt文件都是在train_val.prototxt文件的基础上删除了一些东西,所形成的。
由于两个文件的性质,train_val.prototxt文件里面训练的部分都会在deploy.prototxt文件中删除。

train_val.prototxt文件中,开头要加入一下训练设置文件和准备文件。例如,
transform_param中的

mirror: true(开启镜像);
crop_size: ***(图像尺寸);
mean_file: ""(求解均值的文件),

还有data_param中的

source:""(处理过得数据训练集文件);
batch_size: ***(训练图片每批次输入图片的数量);
backend: LMDB(数据格式设置)。

然后接下来,训练的时候还有一个测试的设置,测试和训练模式的设置通过一个include{phase: TEST/TRAIN}来设置。接下来就是要设置TEST模块内容。然后其他设置跟上面一样,里面有个batch_size可以调小一点,因为测试的话不需要特别多的图片数量。
而以上这一块的内容在deploy里表现出来的只有一个数据层的设置。只需设置name,type,top,input_param这些即可。
接下来,第一个卷积层的设置,train_val.prototxt文件中多了param(反向传播学习率的设置),这里需要设置两个param一个时weight的学习率,一个时bias的学习率,其中一般bias的学习率是weight学习率的两倍。然后就是设置convolution_param,但是在train_val里面需要有对weight_filler的初始化和对bias_filler的初始化。
然后就是设置激活激活函数。这一块由于没有初始化,所以两个文件都是一样的。
再接下来就是池化层,由于池化就是降低分辨率,所以这两边是一样的,只需要设置kernel_size,stride,pool即可。无需参数的初始化。
再下来时LRN层,该层的全称是Local Response Normalization(局部响应值归一化),该层的作用就是对局部输入进行一个归一化操作,不过现在有论文表明,这一层加不加对结果影响不是很大。但这一层的定义都是相同的。
再接下来就是"conv2"、"relu2"、"pool2"、"LRN2"这样的循环,具体跟之前说的一样,train_val主要多的就是参数的初始化和学习率的设置。
在第五个卷积层之后,进入了"fc6"层,该层是全连接层,这里train_val里面还是多两个param学习率的设置,和weight_filler、bias_filler的初始化设置,而两者共同的是有一个输出向量元素个数的设置:inner_product_param。
再接下来就是激活函数RELU。
再接下来就是Dropout层,该层的目的就是为了防止模型过拟合。这其中有一个dropout_ration的设置一般为0.5即可。
再接下来就是"fc7",这一层跟"fc6"相同。然后就是"relu7"、"drop7"都是相同的。然后就是"fc8"也与之前相同。
再接下来就是Accuracy,这个层是用来计算网络输出相对目标值的准确率,它实际上并不是一个损失层,所以没有反传操作。但是在caffe官网中,它在损失层这一部分。所以在deploy.prototxt文件中,这一层的定义是没有的。
再接下来train_val的最后一个层是"SoftmaxWithLoss"层,也是简单的定义了name,type,bottom,top就完了。而这一块的内容也不在deploy.prototxt文件中。
而在deploy.prototxt文件中直接定义了一个type:"Softmax"。

通过对CaffeNet这两个文件的查看发现deploy.prototxt文件和train_val.prototxt文件之间的差异在很多层里面牵扯到训练部分的都会被删除,然后就是反向传播训练部分会被删除。

其中,这里面有一个区别在里头,就是为什么train_val里面的是SoftmaxWithLoss而deploy里面的是Softmax层(两个都是损失层,都没有任何参数):
这里面其实都是softmax回归的应用,只是在定义成Softmax时直接计算了概率室友forward部分,而在SoftmaxWithLoss部分时是还有backward的部分。所以这里就出现了区别,具体的区别可以看这两个文件的C++定义。

下表左边的是train_val.prototxt文件,右边是deploy.prototxt文件。
————————————————
版权声明:本文为CSDN博主「不破楼兰终不还」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fx409494616/article/details/53008971

lenet_solver.prototxt

solver.prototxt的主要作用就是交替调用前向算法和后向算法来更新参数,从而最小化loss,实际上就是一种迭代的优化算法。
solver.prototxt中定义了loss优化器、模型保存路径、最大迭代次数、基础学习率、学习率衰减策略、模型运算是GPU还是CPU等超参数。

# the definition of neural network model
net: "train_val.prototxt"              						 # 网络结构路径
# test_iter is related to batch_size in test layer, test_iter * batch_size = the number of test data
test_iter: 2000												 # 测试次数
# carry out test once every 5 training iterations
test_interval: 50											 # 每多少次进行一次测试
# exclude test phase when test_initialization = false
# test_initialization: false
# display information once every 10 training iterations
display: 10													   # 训练多少次显示一次
average_loss: 40											
# the initial learning rate
base_lr: 0.0000001										 # 基础学习率
lr_policy: "poly"											 # 学习率更新策略
stepsize: 1000										     # 每1000次学习率更新一次
gamma: 0.96													   # 学习率更新的超参
# The max number of iterations
max_iter: 50000											   # 最大迭代次数
power: 1.0													   # 学习率更新超参
momentum: 0.9										       # 动量设置
# weight decay item, in case of overfitting
weight_decay: 0.0002									 # 正则化设置
# save once every 50 training iterations
snapshot: 400												   # 训练多少次保存一次模型
# save path
snapshot_prefix: "snapshot/resnet_50_ft"	 			     # 训练模型保存路径
solver_mode: GPU											 # 采用GPU训练,也可改为CPU

lenet_train_test.prototxt

name: "LeNet"
layer {
  name: "mnist"       #输入层的名称mnist
  type: "Data"        #输入层的类型data层
  top: "data"         #层的输出blob有两个:data和label
  top: "label"
  include {
    phase: TRAIN      #训练阶段,该层参数只在训练阶段有效
  }
  transform_param {
    scale: 0.00390625 #输入像素归一化到【0,1】 1/256=0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"  #LMDB的路径
    batch_size: 64                             #一次读取64张图
    backend: LMDB                              #数据格式为LMDB
  }
}
layer { #一个新数据层,名字也叫作mnist,输出blob也是data和label,但是这里定义的参数只在分类阶段有效
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST   #测试阶段
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_test_lmdb"
    batch_size:100                 #batchsize大小,乘以test_iter = 测试集大小
    backend: LMDB
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"     #本层使用上一层的data,生成下一层conv1的blob
  top: "conv1"
  param {
    lr_mult: 1       #权重参数w的学习率倍数,1表示保持与全局参数一致
  }
  param {
    lr_mult: 2       #偏置参数b的学习率倍数,是全局参数的2倍
  }
  convolution_param {
    num_output: 20      #输出单元数20
    kernel_size: 5      #卷积核大小为5*5
    stride: 1           #步长为1
    weight_filler {     #权值使用xavier填充器
      type: "xavier"    
    }
    bias_filler {       #bias使用常数填充器,默认为0
      type: "constant"  
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"      #本层的上一层是conv1,生成下一层Pool1的blob
  top: "pool1"
  pooling_param {     #下采样参数
    pool: MAX         #使用最大值下采样方法
    kernel_size: 2    #pooling核是2*2
    stride: 2        #pooling步长是2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {                    #新的全连接层,输入blob为pool2,输出blob为ip1
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {    #全连接层的参数
    num_output: 5      #输出500个节点
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {                   #新的非线性层,用RELU方法
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {                  #第二个全连接层
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10      #输出10个单元
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {    #分类准确率层(计算网络输出相对目标值的准确率),只在testing阶段有效,输入blob为iP2和label,输出blob为accuracy
  name: "accuracy"     #该层用于计算分类准确率
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {   #损失层,损失函数采用softmaxloss,输入blob为iP2和label,输出blob为loss
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}
deploy.prototxt

name: "LeNet"
layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param {shape:{dim:1 dim:1 dim:28  dim:28}}
  # dim:1 batchsize  dim:1 number of colour channels - rgb
  # dim:28 width dim:28 height 
}
layer{
  name: "conv1"  
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
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"
}
结尾loss部分:

 layer {
      name: "loss1/loss1"
      type: "SoftmaxWithLoss"					   # 采用SoftmaxWithLoss
      bottom: "my-classifier"
      bottom: "label"
      top: "loss1/loss1"
      loss_weight: 0.3                             # 训练输出的loss所占的权重
    }
    layer {
      name: "test/loss"
      type: "SoftmaxWithLoss"					  # 采用SoftmaxWithLoss
      bottom: "my-classifier"
      bottom: "label"
      top: "test/loss"
      include {
        phase: TEST								  # 验证时的loss参与训练权重参数的更新
      }
    }
    layer {
      name: "accuracy"
      type: "Accuracy"							 # 测试时的精度输出
      bottom: "my-classifier"
      bottom: "label"
      top: "accuracy"
      include {
        phase: TEST
      }
    }

deploy.prototxt是测试时用的文件。可以看出,lenet_train_test.prototxt删除再改变一些东西就变成了deploy.prototxt文件,最大的区别就是deploy.prototxt文件删除了lenet_train_test.prototxt文件开始的输入数据test部分;删除了分类准确率层accuracy;把trian部分的输入数据部分修改,告诉我们输入维度;将损失层loss改成了prob。

`