Caffe源码阅读笔记

部分内容参考自博客:http://blog.csdn.net/mounty_fsc/article/category/6136645

以下内容以Lenet网络为例子

一、train函数过程

1.1    main函数,在tools\caffe.cpp

解析命令,从而调用train、test、time、device_query中的一个,训练则调用train函数。

1.2    train函数,在tools\caffe.cpp

根据solver.prototxt信息实例化SolverParameter和caffe::Solver对象,整个网络初始化都在创建Solver对象时完成。

1.3    train函数调用solver.cpp的Solve函数,开始训练网络

Solve总入口为void Solver<Dtype>::Solve(const char* resume_file),调用Step函数。

1.4    Step函数,进行max_iter次迭代

迭代过程中,最开始测一次,然后每隔test_interval轮进行一次测试,调用TestAll函数。

每次迭代,都执行反向传播,前向计算损失loss,并计算loss关于权值的偏导,调用ForwardBackward函数。

调用UpdateSmoothedLoss来平滑loss。

调用ApplyUpdate通过反向传播计算的偏导更新权值。

每隔snapshot则保存训练结果。

1.5    TestAll函数

对于每个测试网络test_net(注意不是训练网络train_net),都进行测试,调用Test函数,在Lenet中,只有一个测试网络。

1.6    Test函数

测试集大小= test_iter* batchsize,测试时候进行test_iter次迭代。

主要做两件事:

1)执行前向计算网络,调用test_net的Forward函数获取loss。

2)通过测试网络的accuracy层与loss层结果统计accuracy与loss信息。

具体过程参考第二部分。

1.7    ForwardBackward函数,在net.hpp中

先Forward函数:计算网络损失loss。可参考第二部分Test函数过程。

再Backward函数:计算loss关于网络权值的偏导。具体过程参考第三部分。

1.8    UpdateSmoothedLoss函数

由于Caffe的训练方式是SGD,无法把所有的数据同时放入模型进行训练,那么部分数据产生的Loss就可能会和全样本的平均Loss不同,在必要时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题。方法较简单,就是求平均。

1.9    ApplyUpdate函数,在sgd_solver.cpp中

分别给网络的每一层layer都更新权值。

在caffe中,可以分为三个阶段:

  1. 前向计算阶段,这个阶段计算fW
  2. 反向传播阶段,这个阶段计算∇fW
  3. 权值更新阶段,这个阶段通过∇fW,∇r(W)等计算ΔW从而更新W

在lenet中,只有conv1、conv2、ip1、ip2四层有参数

1.10  Snapshot函数

保存训练的中间结果,caffemod  el文件和solverstate文件。

 

二、1.6Test函数过程

测试网络结构:


调用Forward函数,在\caffe\net.cpp中,Forward调用ForwardFromTo函数

2.1    ForwardFromTo函数

对每层网络前向计算,共12层网络,调用每层网络的Forward函数,根据配置情况选择调用Forward_gpu还是Forward_cpu。

2.2    第一层DataLayer

DataLayer未实现Forward_cpu或Forward_gpu,其父类BasePrefetchingDataLayer实现了,在src\caffe\layers\base_data_layer.cpp中。内容为从BasePrefetchingDataLayer的数据缓存队列BlockingQueue<Batch*>取出一个Batch的数据放入DataLayer的Top Blob中,其中Top[0]存放数据,Top[1]存放标签。

2.3    第二层SplitLayer

在src\caffe\layers\split_layer.cpp中,调用Forward_cpu函数。SplitLayer有两个Top Blob label_mnist_1_split_0和label_mnist_1_split_1,在其Forward_cpu中,从它的BottomBlob,也就是DataLayer的第二个Top Blob,label中把指向数据的指针复制到label_mnist_1_split_0和label_mnist_1_split_1中(即共享了数据)。

2.4    第三层ConvolutionLayer

在src\caffe\layers\conv_layer.cpp中,调用Forward_cpu函数。对每一个BottomBlob中的Batch的每一个样本进行卷积。对卷积进行了优化,把要卷积的局部图像和卷积核拉成列,然后求两矩阵内积。

lr_mult: 1 //学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr 

lr_mult: 2 //如果有两个lr_mult,则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍 

2.5    第四层PoolingLayer

Caffe中实现了Max Pooling和Average Pooling两种方法

2.6    第七层InnerProductLayer

在src\caffe\layers\inner_product_layer.cpp中,调用Forward_cpu函数。全连接层就是求两个矩阵的积。

2.7    第八层ReLUForward

在src\caffe\layers\relu_layer.cpp中,调用Forward_cpu函数。ReLu层很简单,就是实现了公式out=max(0,in),negative_slope一般取0。

2.8    第十一层AccuracyLayer

在src\caffe\layers\accuracy_layer.cpp中,调用Forward_cpu函数。

在ip2中输出100*10的blob,对应每个类的概率,统计最大的概率,计算与label相同的个数,个数除以总数就是accuracy。

2.9    第十二层SoftmaxWithLossLayer

在src\caffe\layers\softmax_loss_layer.cpp中,调用Forward_cpu函数。

在实现细节上,train时候在最后接上SoftmaxWithLossLayer,test的时候换成SoftmaxLayer即可。

SoftmaxLayer:100个样本,每个样本特征数量为10,计算这100个样本分别在10个类别上的概率。计算公式如下:

SoftmaxWithLossLayer:n个样本,y为样本对应的类别(标签),损失如下公式计算:

三、1.7Backward函数过程

net.cpp中,实现反向传播的计算过程。在Lenet中,训练网络共9层。训练网络结构:


3.1    Net::Backward()函数中调用BackwardFromTo函数

从网络最后一层到网络第一层反向调用每个网络层的Backward。

3.2    第九层SoftmaxWithLossLayer

softmax_loss_layer.cpp的Backward_cpu函数。SoftmaxWithLossLayer是没有学习参数的,因此不需要对该层的参数做调整,只需要计算bottom_diff(理解反向传播算法的链式求导,求bottom_diff对上一层的输出求导,是为了进一步计算调整上一层权值)。 

3.3    之后各层主要是求导数和偏导数,具体公式详见:

http://blog.csdn.net/mounty_fsc/article/details/51379395


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值