Caffe(学习2)--隐藏层详解

    xiaoxiao2023-11-07  149

         在学习了上一节数据层中的参数详解后,本文内容讲主要讲述Caffe网络模型中隐藏层的独有的参数信息(name, type, bottom, top和transform_param是所有层共有参数)。

    1、Convolution

    卷积层是卷积神经网络(CNN)的核心层,但在这之前希望你了解卷积操作。

    拓展:在Pytorch中主要是通过nn.Conv2d(input_ch,output_ch,kernelsize,stride,padding)来实现的与Caffe中实现的原理一致。

    层类型:Convolution

      lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。--表示该层的学习率

    在后面的convolution_param中,我们可以设定卷积层的特有参数。

    必须设置的参数:

       num_output: 卷积核(filter)的个数

       kernel_size: 卷积核的大小。如果卷积核的长和宽不等,需要用kernel_h和kernel_w分别设定

    其它参数:

       stride: 卷积核的步长,默认为1。也可以用stride_h和stride_w来设置。

       pad: 扩充边缘,默认为0,不扩充。 扩充的时候是左右、上下对称的,比如卷积核的大小为5*5,那么pad设置为2,则四个边缘都扩充2个像素,即宽度和高度都扩充了4个像素,这样卷积运算之后的特征图就不会变小。也可以通过pad_h和pad_w来分别设定。

         weight_filler: 权值初始化。 默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian"

         bias_filler: 偏置项的初始化。一般设置为"constant",值全为0。

         bias_term: 是否开启偏置项,默认为true, 开启

          group: 分组,默认为1组。如果大于1,我们限制卷积的连接操作在一个子集内。如果我们根据图像的通道来分组,那么第i个输出分组只能与第i个输入分组进行连接。

    输出层size计算公式 

    输入:n*c0*w0*h0  [N,C,W,H]输出:n*c1*w1*h1其中,c1就是参数中的num_output,生成的feature_map个数 w1=(w0+2*pad-kernel_size)/stride+1; h1=(h0+2*pad-kernel_size)/stride+1;如果设置stride为1,前后两次卷积部分存在重叠。如果设置pad=(kernel_size-1)/2,则运算后,宽度和高度不变。

    示例: 

    layer { name: "conv1" type: "Convolution" bottom: "data" top: "conv1" param { lr_mult: 1 #lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。 } param { lr_mult: 2 } convolution_param { num_output: 20 #卷积核(filter)的个数 kernel_size: 5 #卷积核的大小 stride: 1 #卷积核的步长,默认为1 pad: 0 #扩充边缘,默认为0,不扩充 weight_filler { type: "xavier" #权值初始化。 默认为“constant",值全为0,很多时候我们用"xavier"算法来进行初始化,也可以设置为”gaussian" } bias_filler { type: "constant" #偏置项的初始化。一般设置为"constant",值全为0 } } }

      2、Pooling层

    也叫池化层,为了减少运算量和数据维度而设置的一种层。在Pytorch中使用MaxPool2d或者AvgPool2d等方法来实现。

    层类型:Pooling

    必须设置的参数:

        kernel_size: 池化的核大小。也可以用kernel_h和kernel_w分别设定。

    其它参数:

          pool: 池化方法,默认为MAX。目前可用的方法有MAX, AVE, 或STOCHASTIC 

       pad: 和卷积层的pad的一样,进行边缘扩充。默认为0

       *stride: 池化的步长,默认为1。一般我们设置为2,即不重叠。也可以用stride_h和stride_w来设置。这个参数很重要,决定最终输出size的大小

     示例:

    layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX #池化方法,默认为MAX。目前可用的方法有MAX, AVE kernel_size: 3 #池化的核大小 stride: 2 #池化的步长,默认为1。一般我们设置为2,即不重叠。 } } #pooling层的运算方法基本是和卷积层是一样的。  H1/C1=(h0/w0+2*pad-kernel_size)/stride+1;

    3、激活函数

      对于激活函数,目前绝大多数论文中都是用的是ReLU,对于sigmoid,tanh等函数使用较少,详细对于可以参考我的这篇文章 f(x)=max(x,0)

    layer {   name: "relu1"   type: "ReLU"   bottom: "pool1"   top: "pool1" }

    4、reshape 

       作用是在不改变数据的情况下,改变输入的维度和pytorch中x.view(x.view(0)[1],-1)用法相似,主要是对数据的维度进行调整。

    有一个可选的参数组shape, 用于指定blob数据的各维的值(blob是一个四维的数据:[N,C,W,H])

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

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

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

    假设原数据为:32*3*28*28, 表示32张3通道的28*28的彩色图片     shape {     dim: 0      dim: 0     dim: 14     dim: -1      } 输出数据为:32*3*14*56

    示例: 

    layer {     name: "reshape"     type: "Reshape"     bottom: "input"     top: "output"     reshape_param {       shape {         dim: 0  # copy the dimension from below         dim: 2         dim: 3         dim: -1 # infer it from the other dimensions       }     }   }

    5、Dropout

        Dropout是一个防止过拟合的层,只需要设置一个dropout_ratio就可以了。

        Dropout说的简单一点就是:我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征,如图1所示。

                                              图1:使用Dropout的神经网络模型 2. Dropout工作流程及使用

    2.1 Dropout具体工作流程

    假设我们要训练这样一个神经网络,如图2所示。

                                                                           

                                                                                 图2:标准的神经网络

    输入是x输出是y,正常的流程是:我们首先把x通过网络前向传播,然后把误差反向传播以决定如何更新参数让网络进行学习。使用Dropout之后,过程变成如下:

    (1)首先随机(临时)删掉网络中一半的隐藏神经元,输入输出神经元保持不变(图3中虚线为部分临时被删除的神经元)

                                                                                       

                                                                                       图3:部分临时被删除的神经元

    (2) 然后把输入x通过修改后的网络前向传播,然后把得到的损失结果通过修改的网络反向传播。一小批训练样本执行完这个过程后,在没有被删除的神经元上按照随机梯度下降法更新对应的参数(w,b)。

    (3)然后继续重复这一过程:

         恢复被删掉的神经元(此时被删除的神经元保持原样,而没有被删除的神经元已经有所更新)      从隐藏层神经元中随机选择一个一半大小的子集临时删除掉(备份被删除神经元的参数)。      对一小批训练样本,先前向传播然后反向传播损失并根据随机梯度下降法更新参数(w,b) (没有被删除的那一部分参数得到更新,删除的神经元参数保持被删除前的结果)。       不断重复这一过程。 示例:

    layer {   name: "drop7"   type: "Dropout"   bottom: "fc7-conv"   top: "fc7-conv"   dropout_param {     dropout_ratio: 0.5   } }

    6、全连接和softmax

         经过上一层的reshape操作一般会得到一个C*W*H 的一维向量,之后进行全连接,在Pytorch中使用nn.Linker进行实现,Caffe中实现方法如下。

    #全连接层,输出的是一个简单向量 参数跟卷积层一样 layer { name: "ip1" type: "InnerProduct" bottom: "pool2" top: "ip1" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 500 weight_filler { type: "xavier" } bias_filler { type: "constant" } } } #测试的时候输入准确率 layer { name: "accuracy" type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" include { phase: TEST } }

        之后用softmax输出各个label的confidence,softmax和softmax-loss的区别

    softmax计算公式:

    而softmax-loss计算公式:

    #softmax-loss layer:输出loss值 layer { name: "loss" type: "SoftmaxWithLoss" bottom: "ip1" bottom: "label" top: "loss" } #softmax layer: 输出似然值 layers { bottom: "cls3_fc" top: "prob" name: "prob" type: “Softmax" }

          网络输出的结果,通过prob获取模型的最后输出,并进行后续的分类以及检测操作。

    最新回复(0)