以Mnist为例,首先贴出网络配置文件:
1. name: \"LeNet\" 2. layer {
3. name: \"mnist\" 4. type: \"Data\" 5. top: \"data\" 6. top: \"label\" 7. data_param {
8. source: \"examples/mnist/mnist-train-leveldb\" 9. backend: LEVELDB 10. batch_size: 64 11. }
12. transform_param { 13. scale: 0.00390625 14. }
15. include: { phase: TRAIN } 16. } 17. layer {
18. name: \"mnist\" 19. type: \"Data\" 20. top: \"data\" 21. top: \"label\" 22. data_param {
23. source: \"examples/mnist/mnist-test-leveldb\" 24. backend: LEVELDB 25. batch_size: 100 26. }
27. transform_param { 28. scale: 0.00390625 29. }
30. include: { phase: TEST } 31. } 32. layer {
33. name: \"conv1\" 34. type: \"Convolution\" 35. bottom: \"data\" 36. top: \"conv1\" 37. param { 38. lr_mult: 1 39. }
40. param { 41. lr_mult: 2 42. }
43. convolution_param { 44. num_output: 20 45. kernel_size: 5 46. stride: 1 47. weight_filler { 48. type: \"xavier\" 49. }
50. bias_filler { 51. type: \"constant\" 52. } 53. } 54. } 55. layer {
56. bottom: \"conv1\" 57. top: \"conv1\" 58. name: \"bn_conv1\" 59. type: \"BatchNorm\" 60. param { 61. lr_mult: 0 62. decay_mult: 0 63. } 64. param { 65. lr_mult: 0 66. decay_mult: 0 67. } 68. param { 69. lr_mult: 0 70. decay_mult: 0 71. } 72. } 73. layer {
74. bottom: \"conv1\" 75. top: \"conv1\" 76. name: \"scale_conv1\" 77. type: \"Scale\" 78. scale_param { 79. bias_term: true 80. } 81. } 82. layer {
83. name: \"pool1\"
84. type: \"Pooling\" 85. bottom: \"conv1\" 86. top: \"pool1\" 87. pooling_param { 88. pool: MAX 89. kernel_size: 2 90. stride: 2 91. } 92. } 93. layer {
94. name: \"relu_pool1\" 95. type: \"ReLU\" 96. bottom: \"pool1\" 97. top: \"pool1\" 98. } 99. layer {
100. name: \"conv2\" 101. type: \"Convolution\" 102. bottom: \"pool1\" 103. top: \"conv2\" 104. param { 105. lr_mult: 1 106. } 107. param { 108. lr_mult: 2 109. }
110. convolution_param { 111. num_output: 50 112. kernel_size: 5 113. stride: 1 114. weight_filler { 115. type: \"xavier\" 116. }
117. bias_filler { 118. type: \"constant\" 119. } 120. } 121. } 122. layer {
123. bottom: \"conv2\" 124. top: \"conv2\" 125. name: \"bn_conv2\" 126. type: \"BatchNorm\" 127. param {
128. lr_mult: 0 129. decay_mult: 0 130. } 131. param { 132. lr_mult: 0 133. decay_mult: 0 134. } 135. param { 136. lr_mult: 0 137. decay_mult: 0 138. } 139. } 140. layer {
141. bottom: \"conv2\" 142. top: \"conv2\" 143. name: \"scale_conv2\" 144. type: \"Scale\" 145. scale_param { 146. bias_term: true 147. } 148. } 149. layer {
150. name: \"pool2\" 151. type: \"Pooling\" 152. bottom: \"conv2\" 153. top: \"pool2\" 154. pooling_param { 155. pool: MAX 156. kernel_size: 2 157. stride: 2 158. } 159. } 160. layer {
161. name: \"relu_pool2\" 162. type: \"ReLU\" 163. bottom: \"pool2\" 164. top: \"pool2\" 165. } 166. layer { 167. name: \"ip1\"
168. type: \"InnerProduct\" 169. bottom: \"pool2\" 170. top: \"ip1\" 171. param {
172. lr_mult: 1 173. } 174. param { 175. lr_mult: 2 176. }
177. inner_product_param { 178. num_output: 500 179. weight_filler { 180. type: \"xavier\" 181. }
182. bias_filler { 183. type: \"constant\" 184. } 185. } 186. } 187. layer {
188. name: \"relu1\" 189. type: \"ReLU\" 190. bottom: \"ip1\" 191. top: \"ip1\" 192. } 193. layer { 194. name: \"ip2\"
195. type: \"InnerProduct\" 196. bottom: \"ip1\" 197. top: \"ip2\" 198. param { 199. lr_mult: 1 200. } 201. param { 202. lr_mult: 2 203. }
204. inner_product_param { 205. num_output: 10 206. weight_filler { 207. type: \"xavier\" 208. }
209. bias_filler { 210. type: \"constant\" 211. } 212. } 213. } 214. layer {
215. name: \"accuracy\"
216. type: \"Accuracy\" 217. bottom: \"ip2\" 218. bottom: \"label\" 219. top: \"accuracy\" 220. include { 221. phase: TEST 222. } 223. } 224. layer { 225. name: \"loss\"
226. type: \"SoftmaxWithLoss\" 227. bottom: \"ip2\" 228. bottom: \"label\" 229. top: \"loss\" 230. }
OK,在开始讲解之前我们先说明几个问题: 1、输入的图片大小是28*28,;
2、我们将分三部分讲解,因为三部分计算方式不同;
3、由于偏置量b的个数与卷积核的个数相同,因此我们讲解的主要是权重,偏置量个数加上就可以了。
1、第一个卷积conv1,之所把第一个卷积单独拿出来,是因为他和后面的卷积计算方式不同,他训练参数个数计算并不关心输入,这里的数据就是指data层中batch_size大小。也可以说第一个卷基层并不关心特征组合,只是提取特征。
在每一个卷积层中都以一个参数num_output,这个参数怎么理解呢?两种理解方式1、卷积的种类个数;2、输出特征图的个数,我么可以认为一种卷积核提取一种特征,然后输出一张特征。
由于第一个卷积层只是简单的提取特征,并没有进行特征组合,因此训练参数个数计算只是num_output*kernel_size^2.这里怎么理解呢?(由于我不会画图,需要大家一点想象力)假设我们的输入有5张图,num_output=3,kernel_size=5。没有进行特征组合,只是简单提取特征,指的是一种卷积核对5张图的同一区域使用相同的权重进行卷积计算,这样每幅图使用相同的卷积核就能提取到相同的特征,然后相同的特征组成一张特征图。
2、第二个卷积至全连接层之间的卷积,这些卷积层的训练参数个数和输入特征图的数量有关,因为这些卷积层需要进行特征组合。举个例子:conv1的num_output=20,说明卷积1层输出了20个特征图,那么卷积2层的输入就是20。conv2的num_output=50,kernel_size=5,那么计算公式是20*50*5*5.
为什么这些卷积层的训练个数和输入的特征图的数量有关呢?重点还是在特征组合。输入的20个特征图,每个特征图代表一种特征,如果我们给每种特征不同的权重那是不是就进行了特征组合呢?conv2的卷积核是5*5,对20个特征图进行卷积,那就会有20组(5*5)个连接(每张特征图是一组),如果这20组卷积核的权重相同,那就回到了第一个卷积层的情况,没有对20个特征进行组合,因为权重相同嘛!
只能看成简单的相加,如果20组权重不同,是不是就进行了线性相加了呢?所以对于一个卷积核(5*5)我们要学习的参数不是25个,而是25*20个。说到这里我相信你应该已经明白了吧!
3、全连接层,全连接层就是普通的神经网络,全连接层的num_output和卷积层中num_output的理解不同,全连接层的num_output应该看成神经元的个数。
3.1、这里要细分一下,先说IP1也就是第一个全连接层。先讲一下ip1的输入,比如最后一个卷积层的num_output=50,那么IP1的输入是50吗?注意这里不是,要理解这个问题,我们只需将全连接层看成是一些列的普通神经网络就可以。比如IP1的num_output=500,也就是有500个神经元,每个神经元都和输入的每一个像素相连,最后一个卷积层输出了50个特征图,每个特征图大小是4*4(输入图像是28*28)那么每个神经元连接的个数就是50*16=800个,也就有800个参数需要学习。总共有500个神经元,因此对于IP1层共需要学习800*500=400,000个参数。
3.2、对于iP2层,iP2的输入就是IP1的输出了,因为IP1输出的不是图像了(或矩阵)而是500个数字。比如ip2的num_output=10,也就是输出数据500维,输出10维的普通神经网络,那么需要学习的参数就是500*10=5000个。
因篇幅问题不能全部显示,请点此查看更多更全内容