RTFSC | Caffe 源码阅读 (其一)

建议安装scitools套装的understand对源码进行阅读。可以对整个工程的代码进行解析后以整个工程都可以快速地jump to definition。以及可以对整体代码进行更近一步的解析。反正无比好用,墙裂推荐。

Overview

RTFSC | Caffe 源码阅读 (其一)_第1张图片
Overview

我们今天主要讲一下layers的源码

layers

RTFSC | Caffe 源码阅读 (其一)_第2张图片
layers overview

我们发现每一种layer都分成.cpp和.cu两种。其实很好理解,.cpp的是cpu版本的,.cu是cuda版本的。

RTFSC | Caffe 源码阅读 (其一)_第3张图片
RTFSC | Caffe 源码阅读 (其一)_第4张图片
conv_layer.cpp

我们先来看看INSTANTIATE_CLASS(ConvolutionLayer);这个宏操作干了什么

INSTANTIATE_CLASS

简要介绍一下这个宏操作涉及的##(concatenate)和template specialization.

宏操作##

简单来说就是把signal的字符链接起来
举个例子

#define cat(a, b) a##b

辣么

printf("%d\n", cat(a,1));

就等价于

printf("%d\n", a1);

template instantiation

我们使用template的时候实际上是implicitly实例化了template的一个class,然而我们也有explicit version.

类似于

template class SampleClass;

注意区别于template specialization.(模板类/函数特化是定义在规定了特定typename的template的定义)

好吧其实这些都没什么卵用。我们其实更在乎Forward和Backward。

总所周知,CNN主要有一个end to end的过程,遵循bp网络的定义,有forward也有backward。我们来简单看看这个forward和backward的过程应该怎么写

CPU version

forward
RTFSC | Caffe 源码阅读 (其一)_第5张图片
cpu forward

计算forward的被分成了两个部分。实际上就是

o = w*i + b

第一部分的w*i对应的就是

this->forward_cpu_gemm(bottom_data + n * this->bottom_dim_, 
          weight, top_data + n * this->top_dim_);

第二部分(bias)对应的就是

if (this->bias_term_) { 
    const Dtype* bias = this->blobs_[1]->cpu_data(); 
    this->forward_cpu_bias(top_data + n * this->top_dim_, bias);
}

出于好奇我们再进一步看看这两个函数是怎么做的

RTFSC | Caffe 源码阅读 (其一)_第6张图片
cpu_gemm cpu_bias

首先介绍一下什么是im2col
http://www.zhihu.com/question/28385679

相当于把运算分解成两部,首先第一步把矩阵变成一个一个的col,然后再相乘。特别的当矩阵是1x1的时候或者需要skip im2col的时候(后面一个什么鬼我还不太清楚,总之一般情况下先理解第一个)不需要im2col(废话)。

为什么要这么做呢?
相当于卷积被分解成了

o = col2im(w*im2col(i)) + b)

为什么要这么做呢?
好求导啊!
可以参考
http://zhangliliang.com/2015/02/11/about-caffe-code-convolutional-layer/
(啥时候才能赶上人家的水平。。。。

至于细节部分,我想讲讲我在阅读中有困难的地方,那就是维数的问题。在conv_layer.cpp部分中,其实只是用到了batch_size那一个维度以及之前和多少个前面的层连接。没有涉及到后面三维ChannelxWeightxHeight。

而在后面的部分,使用了im2col把WxH两个维度压成一个维度V, 于是就有了CxV的一个矩阵。convolution网络层的参数大小是C_bottom(上一层channel数)xC_top(输出channel数),正好对应一个矩阵乘法。

接下来forward部分的代码属于很好理解但是文字不好表述的部分(各种offset以及矩阵乘法函数的各种参数等等)。所以就不赘述了。

backward
RTFSC | Caffe 源码阅读 (其一)_第7张图片
backward

结构和forward类似。由于backward的原因应该考虑top的size。

RTFSC | Caffe 源码阅读 (其一)_第8张图片
backward_cpu_gemm backward_cpu_bias

有了上面所说的,其实这一步也是通过im2col把卷积变成全连接层的形式,类似于普通o=ai+b进行求导。

GPU version

外层的套路和CPU version几乎是一样的

RTFSC | Caffe 源码阅读 (其一)_第9张图片
conv_layer.cu
RTFSC | Caffe 源码阅读 (其一)_第10张图片
gpu_gemm gpu_bias
RTFSC | Caffe 源码阅读 (其一)_第11张图片
gpu_gemm gpu_bias

Titan X 3000多个核心呢。。。。快得飞起来,一般Caffe的网络GPU都是CPU的30倍左右。

你可能感兴趣的:(RTFSC | Caffe 源码阅读 (其一))