zoukankan      html  css  js  c++  java
  • caffe中全卷积层和全连接层训练参数如何确定

    今天来仔细讲一下卷基层和全连接层训练参数个数如何确定的问题。我们以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个。

    以上,只是我的个人见解,如果有错误,欢迎大家指正!

    文章出处: http://blog.csdn.net/sunshine_in_moon/article/details/51434908

    卷积中要注意的其他点:

    1)尽量使用多层fliter尺寸小的卷积层代替一层filter较大的卷积层。

        因为使用多层filter较小的卷积层所能观察到的区域大小和一层filter较大的卷积层是相同的,但是前者可以看到更加抽象的特征,提取的特征表达性能更佳。

        此外,前者引入的参数规模相比后者更小。比如,使用3层filter为3X3的卷积层代替1层filter为7X7的卷积层,假设输入的volume为C个通道则前者参数

        个数为3×(C×(3×3×C))=27C^2,而后者为C×(7×7×C)=49C^2,明显前者引入的参数更少。

     2)为什么使用padding?

         使用padding的好处是使得卷积前后的图像尺寸保持相同,可以保持边界的信息。一般padding的大小为P=(F-1)/2,其中F为filter的尺寸。如果不使用

         paddding,则要仔细跟踪图像尺寸的变化,确保每一层filter和stride正确的被使用。

      3)为什么stride一般设为1?

         stride设为1实际表现效果更好,将下采样的工作全部交给池化层。

       (4)输入层(input layer)尺寸一般应该能被2整除很多次,比如32(CIFAR-10),64,96(STL-10),224(common ImageNet ConvNets),384和512。

       (5)尽量使用filter较小(3x3 or 至多 5x5)的卷积层,如果要使用较大的filter(比如7x7),一般也只在第一个卷积层。

       (6)有时候由于参数太多,内存限制,会在第一个卷积层使用较大filter(7x7)和stride(2)(参考 ZF Net),或者filter(11x11),stride(4)

            (参考 AlexNet)。

     
     
  • 相关阅读:
    python正则去掉html标签里的css内容
    elasticsearch scroll
    js控制滚动条自动往下滑动
    Pandas导出Excel的时候出现openpyxl.utils.exceptions.IllegalCharacterError异常问题
    C# 动态构建表达式树(二)——构建 Select 和 GroupBy 的表达式
    C# 动态构建表达式树(一)—— 构建 Where 的 Lambda 表达式
    C# 中 async 和 await 的基本使用
    C# 中 AppDomain 的一些理解
    win10家庭版 无法修改hosts文件
    我的第一个Scala程序
  • 原文地址:https://www.cnblogs.com/guohaoyu110/p/7519279.html
Copyright © 2011-2022 走看看