数学解释
在深度学习中,ReLU层通常被用作激活函数,因为它可以有效地减少神经网络中的梯度消失问题。ReLU层的导数公式如下所示:
f ′ ( x ) = { 1 if x ≥ 0 0 if x < 0 f'(x)=\begin{cases}1 & \text{if } x\geq 0 \\ 0 & \text{if } x < 0 \end{cases} f′(x)={10if x≥0if x<0
这个公式的意思是,当 x x x大于零时,ReLU函数的导数为 f ( max ( 0 , x ) ) f(\max(0,x)) f(max(0,x)),否则为零。这个导数公式可以帮助神经网络更好地学习非线性特征,并且可以避免梯度消失的问题。
caffee代码实现
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();
Dtype negative_slope = this->layer_param_.relu_param().negative_slope();// negative_slope一般取0
for (int i = 0; i < count; ++i) {
bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0)
+ negative_slope * (bottom_data[i] <= 0));
}
}
}
Blob
-
Caffe2 的 Data 是以 blobs 的形式组织的.blob 即是内存中被命名的 data chunk(数据块).
protected:
shared_ptr<SyncedMemory> data_;// 存放数据
shared_ptr<SyncedMemory> diff_;//存放梯度
vector<int> shape_; //存放形状
int count_; //数据个数
int capacity_; //数据容量
// 成员变量 https://blog.csdn.net/dengheCSDN/article/details/78018578
- 总之,带mutable_开头的意味着可以对返回的指针内容进行更改,而不带mutable_开头的返回const 指针,不能对其指针的内容进行修改,
解释
- caffe中的数据是用blobs的形式进行数据流动的,每一层用bottom来输入数据,用top来输出数据。
- 根据链式法则:bottom_diff =top_diff * 导函数,其中,bottom_diff是 δ l \delta_l δl,而top_diff是 δ l + 1 \delta_{l+1} δl+1,要传播到第0层的x值
- bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0)
+negative_slope * (bottom_data[i] <= 0))
;(标红的部分是因为negative_slope 不为0时表示LeakyReLU激活函数) - 这个代码片段展示了ReLU层在CPU上的反向传播过程。具体来说,它使用了ReLU层的导数公式来计算每个神经元的导数值。在这个过程中,如果该层是激活状态的,那么它会计算输出值与负梯度之积。