【Caffe】网络参数详解(Alexnet举例)1

							<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
    								            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
					<div class="htmledit_views" id="content_views">
            <p>本文为博主学习caffe的相关笔记。</p>

在caffe框架中,网络的各个层的参数可以自己配置。文件名一般是train_val.prototxt。


一、Alexnet:

1. 数据层。

数据层一般作为网络的第一层,由cpu读取数据库中的数据,后面的层的计算由gpu进行。


 
 
  1. #数据层(第一层)
  2. layer {
  3. name: "cifar"
  4. type: "Data"
  5. top: "data" #一般用bottom表示输入,top表示输出,第一层没有输入
  6. top: "label" #多个top多个输出
  7. include {
  8. phase: TRAIN #训练网络分为训练和测试阶段,如果没写include则表示该层在测试中,又在训练中
  9. }
  10. transform_param { #计算所有数据RGB通道上的均值mean
  11. #scale:0.00390625,为1/255,把1到255压缩到0到1,这行可以不写
  12. mirror: true #mirror:1 #1表示开启镜像,0表示关闭,也可以用true和false来表示
  13. crop_size: 227 #假设原始数据都resize成256*256,可以随机裁227*227,也相当于做数据增强,随机crop出一系列小区域
  14. mean_file: "examples/imagenet/project/imagenet_mean.binaryproto" #用一个配置文件来计算均值
  15. }
  16. data_param {
  17. source: "examples/imagenet/project/train_lmdb" #数据库来源路径,支持lmdb,hdf5,方便caffe读取。数据是由cpu从数据库取,如果取的太慢,gpu的计算即使再快,整体速度也是慢的
  18. batch_size: 64 #每次批处理的个数,一般是越大越好,越大的话过拟合越小,大的更有共性,一般被显存限制
  19. backend: LMDB #选用数据的名称
  20. }
  21. }

caffe一般处理的数据是lmdb或hdf5格式,上面的注释详细解释了每段代码的含义,使用的数据是lmdb格式。

如果使用HDF5数据源:


 
 
  1. ###使用HDF5数据源
  2. layer{
  3. name: "data"
  4. type: "HDF5Data"
  5. top: "data"
  6. top: "label"
  7. hdf5_data_param{
  8. source: "examples/imagenet/project/train.txt"
  9. batch_size:16
  10. }
  11. }

如果数据直接来源于图片(不推荐,速度慢):


 
 
  1. ###数据直接来源于图片
  2. /path/to/images/img3423.jpg 2 #文件的路径和类别
  3. /path/to/images/img3424.jpg 13
  4. /path/to/images/img3425.jpg 8
  5. ###不推荐,速度慢。把图片做成txt文件,前面写路径,后面写类别,中间用空格隔开
  6. layer{
  7. name: "data"
  8. type: "ImageData" #类型
  9. top: "data"
  10. top: "label"
  11. transform_param{
  12. mirror: false
  13. crop_size:227
  14. mean_file: "examples/imagenet/project/imagenet_mean.binaryproto"
  15. }
  16. image_data_param{
  17. source: "examples/imagenet/project/file_list.txt"
  18. batch_size:16
  19. new_height:256 #对图片进行resize操作
  20. new_width:256
  21. }
  22. }

2.卷积层。


 
 
  1. #卷积层
  2. layer {
  3. name: "conv1"
  4. type: "Convolution"
  5. bottom: "data" #前面输入是data层
  6. top: "conv1" #输出卷积后的结果
  7. param {
  8. lr_mult: 1 #lr_mult:学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult,则第一个表示权值的学习率,第二个表示偏置项对学习率。一般偏置项对学习率是权值学习率的两倍。
  9. decay_mult: 1
  10. }
  11. param {
  12. lr_mult: 2 #如果要让某一层不做更新,就把这两个lr_mult改成0
  13. decay_mult: 0
  14. }
  15. convolution_param {
  16. num_output: 96 #卷积核(filter)的个数
  17. kernel_size: 11 #卷积核的大小
  18. stride: 4 #卷积核的步长,默认为1
  19. #pad:0 #边缘扩充,默认为0,不扩充(因为扩充的值本来是没有的,设为0对本来不干扰)
  20. weight_filler {
  21. type: "gaussian" #权值初始化。默认为“constant”,值全为0。可以用“xavier”或“gaussian”算法
  22. std: 0.01
  23. }
  24. bias_filler { #偏置项的初始化,一般为“constant”,值全为0
  25. type: "constant"
  26. value: 0
  27. }
  28. }
  29. }

输入:n*c0*w0*h0

输出:n*c1*w1*h1

其中,c1就是参数中的num_output,生成的特征图个数

w1=(w0+2*pad-kernel_size)/stride+1

h1=(h0+2*pad-kernel_size)/stride+1

3.激活层。

在激活层中,对输入数据进行激活操作,是逐元素进行运算的,在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。


 
 
  1. ###Sigmoid
  2. layer{
  3. name: "test"
  4. bottom: "conv"
  5. top: "test"
  6. type: "Sigmoid"
  7. }

Sigmoid可能会发生杀死梯度的现象,用的少。

ReLU是目前使用最多的激活函数,因为其收敛更快,并且能保持同样的效果。标准的ReLU函数为max(x,0),当x>0时,输出x;当x<=0时,输出0。


 
 
  1. #激活函数
  2. layer {
  3. name: "relu1"
  4. type: "ReLU"
  5. bottom: "conv1"
  6. top: "conv1"
  7. }

4.池化层。


 
 
  1. #池化层
  2. layer {
  3. name: "pool1"
  4. type: "Pooling"
  5. bottom: "norm1"
  6. top: "pool1"
  7. pooling_param {
  8. pool: MAX #池化方法,默认为MAX。目前可用的方法有MAX,AVE
  9. #MAX pooling为,假设一个pool中的值有1,2,5,7,保留最大的7
  10. kernel_size: 3 #池化的核大小
  11. stride: 2 #池化的步长,默认为1.一般设置成2,即不重叠
  12. }
  13. }

5.全连接层

输出的是一个简单向量,参数跟卷积层一样。

相当于做一个特征代提取的过程,最后需要做的任务都是通过全连接这个向量做的。


 
 
  1. layer {
  2. name: "fc6"
  3. type: "InnerProduct"
  4. bottom: "pool5"
  5. top: "fc6"
  6. param {
  7. lr_mult: 1
  8. decay_mult: 1
  9. }
  10. param {
  11. lr_mult: 2
  12. decay_mult: 0
  13. }
  14. inner_product_param {
  15. num_output: 4096
  16. weight_filler {
  17. type: "gaussian"
  18. std: 0.005
  19. }
  20. bias_filler {
  21. type: "constant"
  22. value: 0.1
  23. }
  24. }
  25. }

6.Accuracy。

测试的时候输入准确率,看当前迭代的准确率。


 
 
  1. layer {
  2. name: "accuracy"
  3. type: "Accuracy"
  4. bottom: "fc8" #分类的结果
  5. bottom: "label" #label
  6. #label和分类的结果需要看是否匹配
  7. top: "accuracy"
  8. include {
  9. phase: TEST
  10. }
  11. }
  12. #softmax·loss layer:输出loss值
  13. layer {
  14. name: "loss"
  15. type: "SoftmaxWithLoss" #计算loss
  16. bottom: "fc8" #由全连接层的计算结果和label输出loss
  17. bottom: "label"
  18. top: "loss"
  19. }
  20. #softmax layer:输出似然值
  21. #期望输出的是准确率的值,属于某一类的概率值
  22. layers{
  23. bottom: "cls3_fc"
  24. top: "prob"
  25. name: "prob"
  26. type: "Softmax"
  27. }

7.reshape层

有的时候需要在不改变数据的情况下,改变输入的维度。

假设原来的输入是32*3*28*28,代表批处理有32张图片,3个通道,w和h值为28和28。如果想把28*28变成14*56(改变长宽)。在不改变原值,只改变位置的时候,用到reshape。


 
 
  1. layer{
  2. name: "reshape"
  3. type: "Reshape"
  4. bottom: "input"
  5. top: "output"
  6. reshape_param{
  7. shape{
  8. dim:0 #copy the dimesion from below 等于0表示不变
  9. dim:2 #等于一个值为指定值
  10. dim:3
  11. dim:-1 #infer it from the other dimensions,等于-1表示自己推断
  12. }
  13. }
  14. }

有一个可选的参数组shape,用于指定blob数据的各维的值(blob是一个四维的数据:n*c*w*h)

dim:0 表示维度不变,即输入和输出是相同的维度

dim:2或dim:3 将原来的维度变成2或3

dim:-1 表示由系统自动计算维度。数据的总量不变,系统会根据blob数据的其它三维来自动计算当前的维度值。

假设原数据为32*3*28*28,代表批处理有32张彩色图片,3个通道,w和h值为28和28。


 
 
  1. shape{
  2. dim:0
  3. dim:0
  4. dim:14
  5. dim:-1
  6. }

输出数据为:32*3*14*56

8.Dropout层

Dropout是一个防止过拟合的层,只需要设置一个dropout_ratio就可以。(即杀死某些神经元)


 
 
  1. layer {
  2. name: "drop7"
  3. type: "Dropout"
  4. bottom: "fc7"
  5. top: "fc7"
  6. dropout_param {
  7. dropout_ratio: 0.5 #一次迭代杀死50%
  8. }
  9. }

二、mnist:lenet_train_test.prototxt(caffe自带,路径为/caffe⁩ / ⁨examples⁩ / ⁨mnist⁩/)

分析接下来整体分析一下mnist中的网络。


 
 
  1. name: "LeNet"
  2. #两个数据层,一个TRAIN,一个TEST,所以要指定两个数据源,一个用于训练一个用于测试。
  3. layer {
  4. name: "mnist"
  5. type: "Data"
  6. top: "data"
  7. top: "label"
  8. include {
  9. phase: TRAIN
  10. }
  11. transform_param {
  12. scale: 0.00390625
  13. }
  14. data_param {
  15. source: "examples/mnist/mnist_train_lmdb"
  16. batch_size: 64
  17. backend: LMDB
  18. }
  19. }
  20. layer {
  21. name: "mnist"
  22. type: "Data"
  23. top: "data"
  24. top: "label"
  25. include {
  26. phase: TEST
  27. }
  28. transform_param {
  29. scale: 0.00390625
  30. }
  31. data_param {
  32. source: "examples/mnist/mnist_test_lmdb"
  33. batch_size: 100
  34. backend: LMDB
  35. }
  36. }
  37. #数据层后接卷积层
  38. layer {
  39. name: "conv1"
  40. type: "Convolution"
  41. bottom: "data"
  42. top: "conv1"
  43. param {
  44. lr_mult: 1
  45. }
  46. param {
  47. lr_mult: 2
  48. }
  49. convolution_param {
  50. num_output: 20
  51. kernel_size: 5
  52. stride: 1
  53. weight_filler {
  54. type: "xavier"
  55. }
  56. bias_filler {
  57. type: "constant"
  58. }
  59. }
  60. }
  61. #卷积层后接池化层
  62. layer {
  63. name: "pool1"
  64. type: "Pooling"
  65. bottom: "conv1"
  66. top: "pool1"
  67. pooling_param {
  68. pool: MAX
  69. kernel_size: 2
  70. stride: 2
  71. }
  72. }
  73. #池化层后接了卷积层2
  74. layer {
  75. name: "conv2"
  76. type: "Convolution"
  77. bottom: "pool1"
  78. top: "conv2"
  79. param {
  80. lr_mult: 1
  81. }
  82. param {
  83. lr_mult: 2
  84. }
  85. convolution_param {
  86. num_output: 50
  87. kernel_size: 5
  88. stride: 1
  89. weight_filler {
  90. type: "xavier"
  91. }
  92. bias_filler {
  93. type: "constant"
  94. }
  95. }
  96. }
  97. #卷积层2后接池化层2
  98. layer {
  99. name: "pool2"
  100. type: "Pooling"
  101. bottom: "conv2"
  102. top: "pool2"
  103. pooling_param {
  104. pool: MAX
  105. kernel_size: 2
  106. stride: 2
  107. }
  108. }
  109. #全连接层
  110. layer {
  111. name: "ip1"
  112. type: "InnerProduct"
  113. bottom: "pool2"
  114. top: "ip1"
  115. param {
  116. lr_mult: 1
  117. }
  118. param {
  119. lr_mult: 2
  120. }
  121. inner_product_param {
  122. num_output: 500
  123. weight_filler {
  124. type: "xavier"
  125. }
  126. bias_filler {
  127. type: "constant"
  128. }
  129. }
  130. }
  131. #激活函数跟全连接层接在一起,一般跟卷积层接在一起更好
  132. layer {
  133. name: "relu1"
  134. type: "ReLU"
  135. bottom: "ip1"
  136. top: "ip1"
  137. }
  138. layer {
  139. name: "ip2"
  140. type: "InnerProduct"
  141. bottom: "ip1"
  142. top: "ip2"
  143. param {
  144. lr_mult: 1
  145. }
  146. param {
  147. lr_mult: 2
  148. }
  149. inner_product_param {
  150. num_output: 10
  151. weight_filler {
  152. type: "xavier"
  153. }
  154. bias_filler {
  155. type: "constant"
  156. }
  157. }
  158. }
  159. #Accuracy在test阶段,衡量label和分类结果
  160. layer {
  161. name: "accuracy"
  162. type: "Accuracy"
  163. bottom: "ip2"
  164. bottom: "label"
  165. top: "accuracy"
  166. include {
  167. phase: TEST
  168. }
  169. }
  170. #loss与最后的一个全连接层和label相连
  171. layer {
  172. name: "loss"
  173. type: "SoftmaxWithLoss"
  174. bottom: "ip2"
  175. bottom: "label"
  176. top: "loss"
  177. }

可以根据自己的逻辑,设计各层的连接,组合后写在配置文件,就可以定义网络。


三、超参数配置

一般超参数在solver.prototxt中配置。


 
 
  1. net: "examples/imagenet/project/train_val.prototxt" #网络配置文件的路径,如果使用不同的网络进行训练,可以指定train_net和test_net,但是不推荐这么做
  2. test_iter: 1000 #一次迭代的样本数。在训练和测试中,是按batch数进行训练的,要测试100*batch,假设batch=32,一次就测试100*32个样本。假设有3200个样本,batch=32,iter值就等于3200/32
  3. test_interval: 1000 #测试间隔。每训练1000次,进行一次测试。
  4. base_lr: 0.01 #基础学习率,实际学习率=每一层指定的学习率*base学习率,训练时主要就改这个。如果网络不收敛或过拟合,一般是base值太高,需要改低。
  5. #迭代时,刚开始希望学习率较高,迭代速率能快些。希望学习率能不断降低(训练到后期希望学习率小调整)
  6. lr_policy: "step" #学习策略
  7. gamma: 0.1
  8. stepsize: 100000
  9. display: 20 #每迭代20次打印结果看一看
  10. max_iter: 10000 #最大迭代次数
  11. momentum: 0.9 #动量,为了能更快的朝最优解方向移动,不推荐修改
  12. weight_decay: 0.0001
  13. snapshot: 1000 #快照,每迭代1000次保存模型,保存的模型多利于后面做分析。因为loss一般是震荡下降。
  14. snapshot_prefix: "examples/imagenet/project" #model保存的文件夹
  15. solver_mode: CPU #设置运行模式,CPU或GPU

1. type

caffe中自带的Alexnet中的solver.prototxt没有给type。由于loss function是非凸的,没有解析解,所以需要通过优化方法求解。caffe提供了六种优化算法来求解最优擦单数,在solver配置文件中,通过设置type类型来选择。

六种优化算法:

Stochastic Gradient Descent(type:"SGD"),

AdaDelta(type:AdaDelta),

Adaptive Gradient(type:"AdaGrad"),

Adam(type:"Adam"),

Nesterov's Accelerated Gradient(type:"Nesterov")

RMSprop(type:"RMSProp")

一般SGD,SGD不能优化的,别的算法也不太好用。

2. 学习策略(lr_policy)

caffe也提供了几种学习策略可供选择:

fixed:保持base_lr不变

step:如果设置为stepm,则还需要设置一个stepsize,返回base_lr*gamma^(floor(Iter/stepsize)),其中iter表示当前的迭代次数

exp:返回base_lr*gamma^iter,iter为当前迭代次数

inv:如果设置成inv,还需设置一个power,返回base_lr*(1+gamma*iter)^(-power)

multistep:如果设置为multistep,则还需要设置成一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep是根据stepvalue值变化

poly:学习率进行多项式误差,返回base_lr(1-iter/max_iter)^(power)

sigmoid:学习率进行sigmoid衰减,返回base_lr(1/(1+exp(-gamma*(iter-stepsize))))

在实际训练中,如果网络不收敛,如果被认为是学习率的问题,可以调整学习率,一般用inv。

3. 其它参数的具体用法见注释


四、过拟合

发生原因:数据不符合网络要求。一般是网络架构层次太深。

解决方法:

1.修改学习率。比如从第20000次开始发生过拟合现象,就拿第20000次的结果来当成第一次,调整学习率(调小)。

2.调整网络架构。可以选择其它架构。

3.数据预处理。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值