caffe是现在运用广泛的深度学习框架,最近也在阅读caffe源码,将layer的原理个人理解跟大家分享一下。
看完需要点耐心,分析的自认为比较清楚了,代码不多。
caffe要实现神经网络的前向以及反向传播计算需要两个要素:一个是数据,一个是算法。
先说数据:caffe定义了blob类,用来存储训练时的数据,在此不细讲,以后有机会再分享吧。
然后是算法:首先我们知道深度学习有很多种类型的层,比如卷积,pooling,RELU等。那么要实现这么多种层的算法该怎么实现。(本文是自底向上的结构)
caffe运用的正是c++面对对象的动态多态。首先定义了一个基类layer,在layer.hpp文件里面。
并且包含了如下的文件:
#include <algorithm>
#include <string>
#include <vector>
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/math_functions.hpp"
可以看到blob也被包含,which means这里就是算法部分。
layer类里面看一下有哪些成员(挑重要的):
inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
inline void Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom);
首先是两个函数:一个是前向,一个是后向。
上面是声明,下面看定义:
template <typename Dtype>
inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// Lock during forward to ensure sequential forward
Lock();
Dtype loss = 0;
Reshape(bottom, top);
switch (Caffe::mode()) {
case Caffe::CPU:
Forward_cpu(bottom, top);
for (int top_id = 0; top_id < top.size(); ++top_id) {
if (!this->loss(top_id)) { continue; }
const int count = top[top_id]->count();
const Dtype* data = top[top_id]->cpu_data();
const Dtype* loss_weights = top[top_id]->cpu_diff();
loss += caffe_cpu_dot(count, data, loss_weights);
}
break;
case Caffe::GPU:
Forward_gpu(bottom, top);
template <typename Dtype>
inline void Layer<Dtype>::Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
switch (Caffe::mode()) {
case Caffe::CPU:
Backward_cpu(top, propagate_down, bottom);
break;
case Caffe::GPU:
Backward_gpu(top, propagate_down, bottom);
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
}
可以看到,特分别调用了Forward_cpu以及Forward_gpu两