激活函数如:ReLu
,Sigmoid
等layer
相对较为简单,所以在分析InnerProductLayer
前,我们先看下激活函数层。
常见激活层ReLU
的使用示例如下:
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
我们可以看到bottom
和top
是同一个,那是因为激活层运算均为同址计算
。
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
源码分析主要内容如下:
1. caffe源码分析-cmake 工程构建:
caffe源码分析-cmake 工程构建主要内容:
自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。
2. caffe的数据内存分配类SyncedMemory
, 以及类Blob
数据传输的媒介.
主要内容:
caffe源码分析-SyncedMemory
caffe源码分析-Blob
其中Blob
分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob
.
3. caffe layer
的源码分析,包括从整体上说明了layer
类别以及其proto定义与核心函数.
内容如下:
caffe源码分析-layer
caffe源码分析-ReLULayer
caffe源码分析-inner_product_layer
caffe源码分析-layer_factory
首先分析了最简单的layer
Relu
,然后在是inner_product_layer全连接层
, 最后是layer_factory
caffe中 以此工厂模式create各种Layer.
4. 数据输入层,主要是多线程+BlockingQueue的方式读取数据训练:
内容如下:
caffe源码分析-BlockingQueue
caffe源码分析-InternalThread
caffe源码分析-DataReader
5. IO处理例如读取proto文件转化为网络,以及网络参数的序列化
内容如下:
caffe源码分析-DataTransformer
caffe源码分析-db, io
6. 最后给出了使用纯C++结合多层感知机网络训练mnist的示例
内容如下:
caffe c++示例(mnist 多层感知机c++训练,测试)
类似与caffe
一样按照layer、solver、loss、net
等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.
最后如果需要cmake
+ CLion
直接运行调试caffe
的代码工程,可以评论留下你的邮箱,我给你发送过去.