1. 首先,我们先看一个完整的文件:lenet_train_test.prototxt
1 name: "LeNet" #整个网络的名称 2 layer { #数据层——训练数据 3 name: "mnist" 4 type: "Data" 5 top: "data" 6 top: "label" 7 include { 8 phase: TRAIN 9 } 10 transform_param { 11 scale: 0.00390625 12 } 13 data_param { 14 source: "examples/mnist/mnist_train_lmdb" 15 batch_size: 64 16 backend: LMDB 17 } 18 } 19 20 #数据层-这里表示测试数据 21 layer { 22 name: "mnist" 23 type: "Data" 24 top: "data" 25 top: "label" 26 include { 27 phase: TEST 28 } 29 transform_param { 30 scale: 0.00390625 31 } 32 data_param { 33 source: "examples/mnist/mnist_test_lmdb" 34 batch_size: 100 35 backend: LMDB 36 } 37 } 38 39 #第一层卷积层 40 layer { 41 name: "conv1" 42 type: "Convolution" 43 bottom: "data" 44 top: "conv1" 45 param { 46 lr_mult: 1 47 } 48 param { 49 lr_mult: 2 50 } 51 convolution_param { 52 num_output: 20 53 kernel_size: 5 54 stride: 1 55 weight_filler { 56 type: "xavier" 57 } 58 bias_filler { 59 type: "constant" 60 } 61 } 62 } 63 64 #第一层池化层 65 layer { 66 name: "pool1" 67 type: "Pooling" 68 bottom: "conv1" 69 top: "pool1" 70 pooling_param { 71 pool: MAX 72 kernel_size: 2 73 stride: 2 74 } 75 } 76 77 78 #第二层卷积 79 layer { 80 name: "conv2" 81 type: "Convolution" 82 bottom: "pool1" 83 top: "conv2" 84 param { 85 lr_mult: 1 86 } 87 param { 88 lr_mult: 2 89 } 90 convolution_param { 91 num_output: 50 92 kernel_size: 5 93 stride: 1 94 weight_filler { 95 type: "xavier" 96 } 97 bias_filler { 98 type: "constant" 99 } 100 } 101 } 102 103 #第二层池化 104 layer { 105 name: "pool2" 106 type: "Pooling" 107 bottom: "conv2" 108 top: "pool2" 109 pooling_param { 110 pool: MAX 111 kernel_size: 2 112 stride: 2 113 } 114 } 115 116 117 #第一层全连接层 118 layer { 119 name: "ip1" 120 type: "InnerProduct" 121 bottom: "pool2" 122 top: "ip1" 123 param { 124 lr_mult: 1 125 } 126 param { 127 lr_mult: 2 128 } 129 inner_product_param { 130 num_output: 500 131 weight_filler { 132 type: "xavier" 133 } 134 bias_filler { 135 type: "constant" 136 } 137 } 138 } 139 140 141 #第一层激活层 142 layer { 143 name: "relu1" 144 type: "ReLU" 145 bottom: "ip1" 146 top: "ip1" 147 } 148 149 150 #第二层全连接层 151 layer { 152 name: "ip2" 153 type: "InnerProduct" 154 bottom: "ip1" 155 top: "ip2" 156 param { 157 lr_mult: 1 158 } 159 param { 160 lr_mult: 2 161 } 162 inner_product_param { 163 num_output: 10 164 weight_filler { 165 type: "xavier" 166 } 167 bias_filler { 168 type: "constant" 169 } 170 } 171 } 172 173 174 #测试准确率层 175 layer { 176 name: "accuracy" 177 type: "Accuracy" 178 bottom: "ip2" 179 bottom: "label" 180 top: "accuracy" 181 include { 182 phase: TEST 183 } 184 } 185 186 187 #损失函数层 188 layer { 189 name: "loss" 190 type: "SoftmaxWithLoss" 191 bottom: "ip2" 192 bottom: "label" 193 top: "loss" 194 }
2. 数据层
1 layer { 2 name: "cifar" #cifar数据的名称 3 type: "Data" 4 top: "data" #一般用bottom表示输入,top表示输出,多个top代表有多个输出 5 top: "label" #数据输出包含两部分:图像和标签 6 include { 7 phase: TRAIN #训练网络分为训练阶段和自测试阶段,如果没写include则表示该层即在测试中,又在训练中 8 } 9 transform_param { 10 mean_file: "examples/cifar10/mean.binaryproto" #用一个配置文件来进行均值的操作 11 transform_param { 12 scale: 0.00390625 #归一化处理1/255,将图像的像素值归一化到0-1之间
#这里表示数据增强
13 mirror: 1 # 1表示开启镜像,0表示关闭,也可用ture和false来表示 14 # 剪裁一个 227*227的图块,在训练阶段随机剪裁,在测试阶段从中间裁剪 15 crop_size: 227 16 } 17 } 18 data_param { 19 source: "examples/cifar10/cifar10_train_lmdb" #数据库来源,也就是训练数据集所在路径 20 batch_size: 64 #每次批处理的个数 21 backend: LMDB #选用数据的类型名称 22 } 23 } 24 25 ### 使用LMDB源 26 layer { 27 name: "mnist" 28 type: "Data" 29 top: "data" 30 top: "label" 31 include { 32 phase: TRAIN 33 } 34 transform_param { 35 scale: 0.00390625 36 } 37 data_param { 38 source: "examples/mnist/mnist_train_lmdb" 39 batch_size: 64 40 backend: LMDB 41 } 42 } 43 44 ###使用HDF5数据源 45 layer { 46 name: "data" 47 type: "HDF5Data" 48 top: "data" 49 top: "label" 50 hdf5_data_param { 51 source: "examples/hdf5_classification/data/train.txt" 52 batch_size: 10 53 } 54 } 55 56 ###数据直接来源与图片 57 #/path/to/images/img3423.jpg 2 58 #/path/to/images/img3424.jpg 13 59 #/path/to/images/img3425.jpg 8 60 61 layer { 62 name: "data" 63 type: "ImageData" #类型 64 top: "data" 65 top: "label" 66 transform_param { 67 mirror: false 68 crop_size: 227 69 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" 70 } 71 image_data_param { 72 source: "examples/_temp/file_list.txt" 73 batch_size: 50 74 new_height: 256 #如果设置就对图片进行resize操作 75 new_ 256 76 }
3. 卷积层
1 layer { 2 name: "conv1" #卷积层名称 3 type: "Convolution" #表示该层是卷积操作 4 bottom: "data" #bottom表示输入,输入的是“Data”,也就是数据层的输出。 5 top: "conv1" #Top表示输出,该层的输出名称就是“conv1”,它表示第一层卷积操作的输出 6 param { 7 lr_mult: 1 #lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。 8 } 9 param { 10 lr_mult: 2 11 } 12 convolution_param { 13 num_output: 20 #卷积核(filter)的个数,也就是通道数(channels)。 14 kernel_size: 5 #卷积核的大小 15 stride: 1 #卷积核的步长,默认为1 16 pad: 0 #扩充边缘,默认为0,不扩充 17 weight_filler { 18 type: "xavier" #权值初始化。 默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian" 19 } 20 bias_filler { 21 type: "constant" #偏置项的初始化。一般设置为"constant",值全为0 22 } 23 } 24 } 25 26 输入:n*c0*w0*h0 27 输出:n*c1*w1*h1 28 其中,c1就是参数中的num_output,生成的特征图个数 29 w1=(w0+2*pad-kernel_size)/stride+1; 30 h1=(h0+2*pad-kernel_size)/stride+1;
4. 池化层(pooling layer)
1 layer { 2 name: "pool1" #池化层的名称“pool1” 3 type: "Pooling" #表示这一层是池化操作 4 bottom: "conv1" #输入来自于第一层的卷积“conv1” 5 top: "pool1" #输出的就是第一层池化,其名称是“pool1” 6 pooling_param { 7 pool: MAX #池化操作的方法,默认为MAX-pooling。目前可用的方法有MAX-pooling, AVE-pooling 8 kernel_size: 3 #池化的核大小 9 stride: 2 #池化的步长,默认为1。一般我们设置为2,即不重叠。 10 } 11 } 12 13 #pooling层的运算方法基本是和卷积层是一样的。
5. 激活函数层
1 #在激活层中,对输入数据进行激活操作,是逐元素进行运算的,在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。 2 3 ###Sigmoid 4 5 6 layer { 7 name: "test" 8 bottom: "conv" 9 top: "test" 10 type: "Sigmoid" 11 } 12 13 #ReLU是目前使用最多的激活函数,主要因为其收敛更快,并且能保持同样效果。标准的ReLU函数为max(x, 0),当x>0时,输出x; 当x<=0时,输出0 14 f(x)=max(x,0) 15 16 17 18 layer { 19 name: "relu1" #该层的名称“reLu1” 20 type: "ReLU" #这一层操作的激活函数ReLu 21 bottom: "pool1" #这一层数据输入是pool1 22 top: "pool1" 23 }
6. 全连接层(FC Layer)
1 #全连接层,输出的是一个简单向量 参数跟卷积层一样 2 layer { 3 name: "ip1" #该层的名称,叫做ip1,其实是计算向量内积的操作,也就是我们常说的全连接层 4 type: "InnerProduct" #这里的类型表示操作的作用是计算前后向量的内积,即全连接 5 bottom: "pool2" #这一层的输入来自于池化层“pool2” 6 top: "ip1" #输出层的名字叫做“ip1” 7 param { 8 lr_mult: 1 #这里表示权重学习率系数,还需要和基础学习率相乘 9 } 10 param { 11 lr_mult: 2 #这里表示偏置的学习率系数,也需要和基础学习率相乘,它一般是权重学习率系数的2倍 12 } 13 inner_product_param { 14 num_output: 500 #这里表示 全连接层的输出为500个神经元 15 weight_filler { 16 type: "xavier" #这里是一种权重初始化的方法 17 } 18 bias_filler { #这里表示了偏置的初始化方式 19 type: "constant" 20 } 21 } 22 } 23 #测试的时候输入准确率 24 layer { 25 name: "accuracy" #该层的名称是“accuracy” 26 type: "Accuracy" #这一层操作的作用就是计算测试集在模型上的准确率 27 bottom: "ip2" #这一层的输入:第二个全连接层的输出 28 bottom: "label" #这一层的第二个输入:一个batch_size图片的类别标签 29 top: "accuracy" #该层的输出的名称是“accuracy” 30 include { 31 phase: TEST #这里说明该层只在测试时起作用 32 } 33 }
7. soft-max loss层
1 #softmax-loss layer:输出loss值 2 3 layer { 4 name: "loss" #该层的名称是“loss” 5 type: "SoftmaxWithLoss" #这一层操作的作用是计算交叉熵损失 6 bottom: "ip1" #输入是全连接层的输出 7 bottom: "label" #输入是类别标签 8 top: "loss" #输出的损失,其名称是“loss” 9 } 10 #softmax layer: 输出似然值 11 layers { 12 bottom: "cls3_fc" 13 top: "prob" 14 name: "prob" 15 type: “Softmax" 16 }
7. reshape层
1 #在不改变数据的情况下,改变输入的维度 2 3 layer { 4 name: "reshape" 5 type: "Reshape" 6 bottom: "input" 7 top: "output" 8 reshape_param { 9 shape { 10 dim: 0 # copy the dimension from below 11 dim: 2 12 dim: 3 13 dim: -1 # infer it from the other dimensions 14 } 15 } 16 } 17 18 有一个可选的参数组shape, 用于指定blob数据的各维的值(blob是一个四维的数据:n*c*w*h)。 19 20 dim:0 表示维度不变,即输入和输出是相同的维度。 21 22 dim:2 或 dim:3 将原来的维度变成2或3 23 24 dim:-1 表示由系统自动计算维度。数据的总量不变,系统会根据blob数据的其它三维来自动计算当前维的维度值 。 25 26 假设原数据为:32*3*28*28, 表示32张3通道的28*28的彩色图片 27 shape { 28 dim: 0 29 dim: 0 30 dim: 14 31 dim: -1 32 } 33 输出数据为:32*3*14*56 34
35 #Dropout是一个防止过拟合的层,表示神经元随机失活 36 #只需要设置一个dropout_ratio就可以了。 37 layer { 38 name: "drop7" 39 type: "Dropout" 40 bottom: "fc7-conv" 41 top: "fc7-conv" 42 dropout_param { 43 dropout_ratio: 0.5 44 } 45 }
8. solver文件解析
1 #往往loss function是非凸的,没有解析解,我们需要通过优化方法来求解。 2 #caffe提供了六种优化算法来求解最优参数,在solver配置文件中,通过设置type类型来选择。 3 4 Stochastic Gradient Descent (type: "SGD"), 5 AdaDelta (type: "AdaDelta"), 6 Adaptive Gradient (type: "AdaGrad"), 7 Adam (type: "Adam"), 8 Nesterov’s Accelerated Gradient (type: "Nesterov") 9 RMSprop (type: "RMSProp")
10 net: "examples/mnist/lenet_train_test.prototxt" #这里表示训练的网络结构文件和测试文件的路径 11 test_iter: 100 #这里的表示测试的时候,batch_size= 测试样本总量/test_iter 12 test_interval: 500 #测试间隔,表示每训练500步,进行一次测试 13 base_lr: 0.01 #基础的学习率 14 momentum: 0.9 #动量 15 type: SGD #优化方法选择:随机梯度下降 16 weight_decay: 0.0005 #权重衰减率 17 lr_policy: "inv" #学习率调整策略 18 gamma: 0.0001 19 power: 0.75 20 display: 100 #显示,每训练100步,在屏幕上显示一次。 21 max_iter: 20000 #最大的迭代次数20000步,到达20000次自动停止 22 snapshot: 5000 #每隔5000步进行一次模型输出 23 snapshot_prefix: "examples/mnist/lenet" #模型的保存位置 24 solver_mode: CPU #模型训练在CPU上进行
#详细解释如下: 25 net: "examples/mnist/lenet_train_test.prototxt" #网络位置 26 train_net: "examples/hdf5_classification/logreg_auto_train.prototxt" #也可以分别设定train和test 27 test_net: "examples/hdf5_classification/logreg_auto_test.prototxt" 28 test_iter: 100 #迭代了多少个测试样本呢? batch*test_iter 假设有5000个测试样本,一次测试想跑遍这5000个则需要设置test_iter×batch=5000 29 30 test_interval: 500 #测试间隔。也就是每训练500次,才进行一次测试。 31 32 33 base_lr: 0.01 #base_lr用于设置基础学习率 34 35 lr_policy: "inv" #学习率调整的策略 36 37 - fixed: #保持base_lr不变. 38 - step: #如果设置为step,则还需要设置一个stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数 39 - exp: #返回base_lr * gamma ^ iter, iter为当前迭代次数 40 - inv: #如果设置为inv,还需要设置一个power, 返回base_lr * (1 + gamma * iter) ^ (- power) 41 - multistep: #如果设置为multistep,则还需要设置一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep则是根据stepvalue值变化 42 - poly: #学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power) 43 - sigmoid: #学习率进行sigmod衰减,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize)))) 44 45 momentum :0.9 #动量 46 47 display: 100 #每训练100次,在屏幕上显示一次。如果设置为0,则不显示。 48 49 max_iter: 20000 #最大迭代次数,2W次就停止了 50 51 snapshot: 5000 #快照。将训练出来的model和solver状态进行保存,snapshot用于设置训练多少次后进行保存 52 snapshot_prefix: "examples/mnist/lenet" 53 54 solver_mode: CPU #设置运行模式。默认为GPU,如果你没有GPU,则需要改成CPU,否则会出错。