天天看点

caffe基础学习(基于Faster RCNN源码)

一、整体介绍

神经网络(net)是一个组合模型,它由许多相互连接的层(layers)组合而成,每一层又会涉及到很多参数(定义在caffe.proto文件中)。

Caffe就是组建深度网络的这样一种工具,它按照一定的策略,一层一层的搭建出自己的模型。它将所有的信息数据定义为blobs,从而进行便利的操作和通讯。

1.blob

blob是caffe框架中一种标准的数组,一种统一的内存接口,它详细描述了信息是如何存储的,以及如何在层之间通讯的。

2.layer

layer有多种类型,例如:Data,Python,Convolution,Pooling等,从bottom进行数据的输入,计算后通过top进行输出,layer之间的数据流动是以blobs的方式进行的。

每种layer都定义了三种关键计算:setup,forward,backward

  • setup: 层的建立和初始化,以及在整个模型中的连接初始化。
  • forward: 从bottom得到输入数据,进行计算,并将计算结果送到top,进行输出。
  • backward: 从层的输出端top得到数据的梯度,计算当前层的梯度,并将计算结果送到bottom,向前传递。

    这里以rpn/anchor_target_layer.py的部分代码为例,显而易见包含以上几个部分

class AnchorTargetLayer(caffe.Layer):
    """
    Assign anchors to ground-truth targets. Produces anchor classification
    labels and bounding-box regression targets.
    """

    def setup(self, bottom, top):
        layer_params = yaml.load(self.param_str_)
        anchor_scales = layer_params.get('scales', (8, 16, 32))
        self._anchors = generate_anchors(scales=np.array(anchor_scales))
        self._num_anchors = self._anchors.shape[0]
        self._feat_stride = layer_params['feat_stride']
        # …………………………省略
        
    def forward(self, bottom, top):
        # Algorithm:
        #
        # for each (H, W) location i
        #   generate 9 anchor boxes centered on cell i
        #   apply predicted bbox deltas at cell i to each of the 9 anchors
        # filter out-of-image anchors
        # measure GT overlap

        assert bottom[0].data.shape[0] == 1, \
            'Only single item batches are supported'

        # map of shape (..., H, W)
        height, width = bottom[0].data.shape[-2:]
        # GT boxes (x1, y1, x2, y2, label)
        gt_boxes = bottom[1].data
        # im_info
        im_info = bottom[2].data[0, :]
		# …………………………省略
    def backward(self, top, propagate_down, bottom):
        """This layer does not propagate gradients."""
        pass

    def reshape(self, bottom, top):
        """Reshaping happens during the call to forward."""
        pass
#……………………省略
           
3.net

即由多个layer组合而成,不再赘述

二、自定义Python层

(以下均以models/pascal_voc/VGG16/faster_rcnn_alt_opt/stage1_fast_rcnn_train.pt中的layer为例)

layer {
  name: 'data'
  type: 'Python'
  top: 'data'
  top: 'rois'
  top: 'labels'
  top: 'bbox_targets'
  top: 'bbox_inside_weights'
  top: 'bbox_outside_weights'
  python_param {
    module: 'roi_data_layer.layer'	# python module名字
    layer: 'RoIDataLayer'	# 其中定义的类的名字
    param_str: "'num_classes': 21" 
  }
           

roi_data_layer/layer.py中包含setup,forward,backward,reshape等函数。

三、视觉层及参数

1.Convolution层
layer {
  name: "conv4_1"
  type: "Convolution"
  bottom: "pool3"
  top: "conv4_1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 512
    pad: 1
    kernel_size: 3
  }
           
  • lr_mult:学习率的参数,最终的学习率是lr_mult×base_lr(在solver.prototxt配置文件中)。上方有两个lr_mult,则第一个表示权值的学习率,第二个表示偏置项的学习率,一般偏执项的学习率是权值学习率的两倍。
  • num_output(必设):卷积核(filter)的个数
  • kernel_size(必设):卷积核的大小
  • pad:扩充边缘
  • 此外,还有stride、weight_filler、bias_filler、bias_term、group等参数
2.Pooling层
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2_2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
           
  • kernel_size(必设):池化核的大小
  • pool:池化方法,默认为MAX
  • 此外,还有pad,stride等参数

四、激活层及参数

在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的。从bottom得到一个blob数据输入,运算后,从top输出一个blob数据。在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。

以ReLU为例
layer {
  name: "relu6"
  type: "ReLU"
  bottom: "fc6"
  top: "fc6"
}
           

标准的ReLU函数为max(x,0),当x>0时,输出x;当x<=0时,输出0

  • 可选参数:negative_slope:默认为0,当设置了这个值之后,那么输出就不再为0,而是用原始数据×negative_slope
此外还有Sigmoid、TanH等激活层

五、其他常用层及参数

1.softmax-loss

注意softmax-loss层和softmax层计算大致相同,但也有区别,详见Softmax vs. Softmax-Loss

layer {
  name: "loss_cls"
  type: "SoftmaxWithLoss"
  bottom: "cls_score"
  bottom: "labels"
  top: "loss_cls"
  loss_weight: 1
}
           
2.InnerProduct

全连接层,把输入当作成一个向量,输出也是一个简单向量(把输入数据blobs的width和height全变为1)。

全连接层实际上也是一种卷积层,只是它的卷积核大小和原数据大小一致。因此它的参数基本和卷积层的参数一样。

layer {
  name: "fc6"
  type: "InnerProduct"
  bottom: "pool5"
  top: "fc6"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 4096
  }
}
           
  • num_output(必设):filter个数
3.Dropout

Dropout的作用是防止过拟合。可以随机让网络某些隐含层节点的权重不工作。

layer {
  name: "drop6"
  type: "Dropout"
  bottom: "fc6"
  top: "fc6"
  dropout_param {
    dropout_ratio: 0.5
  }
}
           
  • 只需设置一个dropout_ratio即可。

六、solver及其设置

在Deep Learning中,往往loss function是非凸的,没有解析解,我们需要通过优化方法来求解。solver的主要作用就是交替调用前向(forward)算法和后向(backward)算法来更新参数,从而最小化loss,实际上就是一种迭代的优化算法。

Solver的流程:

1.设计好需要优化的对象,以及用于学习的训练网络和用于评估的测试网络。

2.通过forward和backward迭代的进行优化来跟新参数。

3.定期的评价测试网络。

4.在优化过程中显示模型和solver的状态

在每一次的迭代过程中,solver所做工作:

1、调用forward算法来计算最终的输出值,以及对应的loss

2、调用backward算法来计算每层的梯度

3、根据选用的slover方法,利用梯度进行参数更新

4、记录并保存每次迭代的学习率、快照,以及对应的状态。

以stage1_fast_rcnn_solver30k40k.pt的内容为例

base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 30000
display: 20
average_loss: 100
momentum: 0.9
weight_decay: 0.0005

# We disable standard caffe solver snapshotting and implement our own snapshot function
snapshot: 0
# We still use the snapshot prefix, though
snapshot_prefix: "vgg16_fast_rcnn"

           
  • 其中,前4行是用于学习率的设置。base_lr用于设置基础学习率,在迭代过程中,可以对基础学习率进行调整。调整策略由lr_policy来设置。
  • lr_policy的设置以-step为例,如果设置为step,则还需要设置一个stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示当前的迭代次数
  • weight_decay:权重衰减项,防止过拟合的一个参数
  • snapshot:快照,将训练出来的model和solver状态进行保存。
  • snapshot_prefix:设置保存路径

    ……

参考:

https://blog.csdn.net/sinat_30071459/article/details/51723483

https://blog.csdn.net/sinat_30071459/article/details/51723544

https://blog.csdn.net/sinat_30071459/article/details/51723600等

继续阅读