Caffe softmax_layer.cpp学习
来源:互联网 发布:电脑怎么连接宽带网络 编辑:程序博客网 时间:2024/05/21 00:17
目录
- 目录
- 首先需要注意的
- Forward_cpu函数
- backward_cpu函数
- backward_cpu函数实现说明
首先需要注意的:
整个网络的参数的 gradient 的计算方法是从顶层出发向后,在 层的时候,会拿到从 得到的 也就是 ,然后需要做两个计算:首先是自己层内的参数的 gradient,比如如果是一个普通的全连通内积层,则会有参数 和 bias 参数 ,根据刚才的 Chain Rule 式子直接计算就可以了,如果 层没有参数 (例如 Softmax 或者 Softmax-Loss 层就是没有参数的。),这一步可以省略;其次就是“向后传递”的步骤,同样地,根据 Chain Rule 我们可以计算. 即当对输入数据bottom求导时,仅仅是为了“向后传递”,这个导数并不参与该层的参数的gradient descent 参数更新,因为该层就没有参数,何须更新参数呢?
Forward_cpu函数
template <typename Dtype>void SoftmaxLayer<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(); Dtype* scale_data = scale_.mutable_cpu_data(); int channels = bottom[0]->shape(softmax_axis_); int dim = bottom[0]->count() / outer_num_; caffe_copy(bottom[0]->count(), bottom_data, top_data); // We need to subtract the max to avoid numerical issues, compute the exp, // and then normalize. for (int i = 0; i < outer_num_; ++i) { // initialize scale_data to the first plane caffe_copy(inner_num_, bottom_data + i * dim, scale_data);//注意,inner_num_和dim的值并不相等,dim是inner_num_的倍数,为通道数channels倍 for (int j = 0; j < channels; j++) { for (int k = 0; k < inner_num_; k++) { scale_data[k] = std::max(scale_data[k], bottom_data[i * dim + j * inner_num_ + k]); } }//在每张图像中,沿着通道轴上取最大像素值。虽然scale_data所指向内存区域可存储的数据量为outer_num_×1×inner_num_,但每次也只是更新scale_data最前面的inner_num_个元素。scale_只是用来存储中间变量。 // subtraction caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, channels, inner_num_, 1, -1., sum_multiplier_.cpu_data(), scale_data, 1., top_data);//在caffe_cpu_gemm函数中,从top_data所指的内存区域选取channels×inner_num_=dim个元素进行更新,其他函数类似 // exponentiation caffe_exp<Dtype>(dim, top_data, top_data); // sum after exp caffe_cpu_gemv<Dtype>(CblasTrans, channels, inner_num_, 1., top_data, sum_multiplier_.cpu_data(), 0., scale_data); // division for (int j = 0; j < channels; j++) { caffe_div(inner_num_, top_data, scale_data, top_data); top_data += inner_num_;//更新top_data指针 } }}
backward_cpu函数
template <typename Dtype>void SoftmaxLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); const Dtype* top_data = top[0]->cpu_data(); Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); Dtype* scale_data = scale_.mutable_cpu_data(); int channels = top[0]->shape(softmax_axis_); int dim = top[0]->count() / outer_num_; caffe_copy(top[0]->count(), top_diff, bottom_diff);//从top_diff拷贝到bottom_diff for (int i = 0; i < outer_num_; ++i) { // compute dot(top_diff, top_data) and subtract them from the bottom diff for (int k = 0; k < inner_num_; ++k) { scale_data[k] = caffe_cpu_strided_dot<Dtype>(channels, bottom_diff + i * dim + k, inner_num_, top_data + i * dim + k, inner_num_);//因为bottom_diff是从top_diff拷贝而来,所以caffe_cpu_strided_dot的参数不用top_diff,用bottom_diff即可,而且,这样的话就可以在下面的代码("caffe_cpu_gemm<Dtype>()")中直接更新bottom_diff. } // subtraction caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, channels, inner_num_, 1, -1., sum_multiplier_.cpu_data(), scale_data, 1., bottom_diff + i * dim);//实现的非常巧妙 } // elementwise multiplication caffe_mul(top[0]->count(), bottom_diff, top_data, bottom_diff);}
backward_cpu函数实现说明
参考Softmax vs. Softmax-Loss: Numerical Stability, 我们可以得到
∂oi∂zk :
∂oi∂zk=δikok−oiok={(1−ok)ok(0−oi)oki=ki≠k
但是,所谓BP,则必须获取上一层diff,即top_diff, 然后相乘,以完成“向后传播”。也就是说∂oi∂zk⋅top_diff
画张图以表示:图中假设一张图像只有2个通道,inner_num_=4.
可见,图中a1−α 与∂oi∂zk 是一致的,最后bottom_diff中的元素是∂oi∂zk 关于i的求和,即
∑i=0n∂oi∂zk⋅top_diff
0 0
- Caffe softmax_layer.cpp学习
- caffe源码分析--softmax_layer.cpp
- caffe源码分析:softmax_layer.cpp && softmax_loss_layer.cpp
- 学习笔记: 源码 softmax_layer.cpp 略通
- CAFFE源码学习笔记之softmax_layer
- Caffe Innerproduct.cpp学习
- caffe base_conv_layers.cpp 学习
- caffe Poolinglayer.cpp学习
- Caffe Relu_layer.cpp 学习
- Caffe softmax_loss_layer.cpp 学习
- caffe源码学习中-tools/caffe.cpp
- Caffe BaseDataLayer.cpp BasePrefetchingDataLayer.cpp DataLayer.cpp 学习
- Caffe net.hpp net.cpp学习
- caffe源码c++学习笔记Classifier.cpp
- 学习笔记: 源码 caffe.cpp 初探
- caffe学习笔记--写一个运行caffe.cpp的makefile
- caffe源码深入学习1:caffe.cpp解析
- caffe源码学习中--src/caffe/solver.cpp
- 1076. Forwards on Weibo (30)
- uva 11388 最大公约数与最小公倍数的关系
- Linux设备驱动模型 SPI之一
- 安卓TextView中的文本加上横线或者下划线
- vs2010如何检测内存泄漏
- Caffe softmax_layer.cpp学习
- hdu3555数位dp
- windows系统下安装ubuntu的方法
- redis安装步骤
- 统计思维:程序员数学之概率统计(第2版):第1章 探索性数据分析
- 蓝桥杯历届-猜年龄
- Android工程目录gen文件夹—笔记
- 第一章 CPU构架概述
- 设计模式