1. 程式人生 > >caffe原始碼分析-ReLULayer

caffe原始碼分析-ReLULayer

啟用函式如:ReLuSigmoidlayer相對較為簡單,所以在分析InnerProductLayer前,我們先看下啟用函式層。

常見啟用層ReLU的使用示例如下:


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

我們可以看到bottomtop是同一個,那是因為啟用層運算均為同址計算
NeuronLayer作為啟用層的基類, 繼承Layer,定義如下:


template <typename Dtype>
class NeuronLayer : public Layer<Dtype> {
public:
    explicit NeuronLayer(const LayerParameter& param)
            : Layer<Dtype>(param) {}

    virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
                         const vector<Blob<Dtype>*>& top);

    virtual inline int ExactNumBottomBlobs() const { return 1; }
    virtual inline int ExactNumTopBlobs() const { return 1; }
    
};

由於每個啟用layer的bottom, top的shape一樣,因此NeuronLayer定義了Reshape函式:


template <typename Dtype>
void NeuronLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
                                 const vector<Blob<Dtype>*>& top) {
    top[0]->ReshapeLike(*bottom[0]);
}

ReLULayer的核心函式在與Forward_cpu,Backward_cpu,而且相對也比較簡單(簡單起見刪除了negative_slope運算):


template<typename Dtype>
void ReLULayer<Dtype>::Forward_cpu(const vector<Blob<Dtype> *> &bottom,
                                   const vector<Blob<Dtype> *> &top) {

    const Dtype* bottom_data = bottom[0]->cpu_data();
    Dtype* top_data = top[0]->mutable_cpu_data();

    const int count = bottom[0]->count();
    Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
    for (int i = 0; i < count; ++i) {
        top_data[i] = std::max(bottom_data[i], Dtype(0));
    }
}

反向傳播主要是更新blob中的diff_反向傳遞梯度:

Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();

template <typename Dtype>
void ReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
                                    const vector<bool>& propagate_down,
                                    const vector<Blob<Dtype>*>& bottom) {
    if (propagate_down[0]) {
        const Dtype* bottom_data = bottom[0]->cpu_data();
        const Dtype* top_diff = top[0]->cpu_diff();

        Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
        const int count = bottom[0]->count();

        for (int i = 0; i < count; ++i) {
            bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0);
        }

    }
}

caffe系列原始碼分析介紹

本系列深度學習框架caffe 原始碼分析主要內容如下:

自己從頭構建一遍工程,這樣能讓我更好的瞭解大型的專案的構建。當然原始的caffe的構建感覺還是比較複雜(主要是cmake),我這裡僅僅使用cmake構建,而且簡化點,當然最重要的是支援CLion直接執行除錯(如果需要這個工程可以評論留下你的郵箱,我給你傳送過去)。

這裡寫圖片描述

2. caffe的資料記憶體分配類SyncedMemory, 以及類Blob資料傳輸的媒介.

主要內容:
caffe原始碼分析-SyncedMemory
caffe原始碼分析-Blob
其中Blob分析給出了其直接與opencv的圖片相互轉化以及操作,可以使得我們更好的理解Blob.

3. caffe layer的原始碼分析,包括從整體上說明了layer類別以及其proto定義與核心函式.

首先分析了最簡單的layer Relu,然後在是inner_product_layer全連線層, 最後是layer_factorycaffe中 以此工廠模式create各種Layer.

4. 資料輸入層,主要是多執行緒+BlockingQueue的方式讀取資料訓練:
5. IO處理例如讀取proto檔案轉化為網路,以及網路引數的序列化
6. 最後給出了使用純C++結合多層感知機網路訓練mnist的示例

內容如下:

類似與caffe一樣按照layer、solver、loss、net等模組構建的神經網路實現可以見下面這篇blog,相信看懂了這個python的程式碼理解caffe框架會更簡單點.

最後如果需要cmake + CLion直接執行除錯caffe的程式碼工程,可以評論留下你的郵箱,我給你傳送過去.