在caffe中添加新层 L1 Loss layer
2018-01-15 22:38
260 查看
本文地址:http://blog.csdn.net/ismarvellous/article/details/79069661,转载请注明出处。
L1 Loss的前向和后向都比较简单,下面简单概括一下。
L=1N∑iN||x(i)1−x(i)2||1
这里,N代表输入样本对的数量。
∂L∂x(i)1=⎧⎩⎨1N,−1N,x(i)1>x(i)2x(i)1<x(i)2
∂L∂x(i)2=⎧⎩⎨−1N,1N,x(i)1>x(i)2x(i)1<x(i)2
1. 在
2. 在
3. 如果需要GPU版本,在
4. 在cpp文件中用
在
编译:
CPU版本:
GPU版本:
CPU版本:
解释一下上面函数中的
类似的,GPU版本:
1. L1 Loss的计算推导
与欧式距离(L2 Loss)相似,L1 Loss也是两个输入向量直接距离的一种度量。但L2 Loss的梯度在接近零点的时候梯度值也会接近于0,使学习进程变慢,而L1 Loss的梯度是一个常数,不存在这个问题。L1 Loss 和 L2 Loss 还有一些不同的特点,各有使用的场合,不过这不是本文的重点。本文主要关注如何在caffe中实现 L1 Loss。L1 Loss的前向和后向都比较简单,下面简单概括一下。
1.1 前向计算
L1 Loss的前向计算就是两个输入向量x1,x2的L1距离,具体地:L=1N∑iN||x(i)1−x(i)2||1
这里,N代表输入样本对的数量。
1.2 反向计算
L1 Loss本身没有参数,所以只需要计算对输入数据导数即可:∂L∂x(i)1=⎧⎩⎨1N,−1N,x(i)1>x(i)2x(i)1<x(i)2
∂L∂x(i)2=⎧⎩⎨−1N,1N,x(i)1>x(i)2x(i)1<x(i)2
2. caffe实现
在caffe中添加层一般需要以下几个步骤:1. 在
include/caffe/layers/l1_loss_layer.hpp中添加声明。
2. 在
src/caffe/layers/l1_loss_layer.cpp中进行实现。
3. 如果需要GPU版本,在
src/caffe/layers/l1_loss_layer.cu中进行实现。
4. 在cpp文件中用
layer_factory.hpp提供的宏实例化并注册新的层。假如新的层叫做
L1LossLayer:
INSTANTIATE_CLASS(L1LossLayer); REGISTER_LAYER_CLASS(L1Loss);
在
src/caffe/test/test_l1_loss_layer.cpp中写测试。
编译:
make -j make test -j make runtest GTEST_FILTER='L1LossLayerTest/*'
2.1 前向计算
前向计算主要是实现Forward_cpu和Forward_gpu两个函数。CPU版本:
// src/caffe/layers/l1_loss_layer.cpp template <typename Dtype> void L1LossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { int count = bottom[0]->count(); caffe_sub( count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), diff_.mutable_cpu_data()); Dtype loss = caffe_cpu_asum(count, diff_.cpu_data()) / bottom[0]->num(); top[0]->mutable_cpu_data()[0] = loss; }
GPU版本:
template <typename Dtype> void L1LossLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { int count = bottom[0]->count(); caffe_gpu_sub( count, bottom[0]->gpu_data(), bottom[1]->gpu_data(), diff_.mutable_gpu_data()); Dtype asum; caffe_gpu_asum(count, diff_.gpu_data(), &asum); // gpu函数,使用gpu_data() Dtype loss = asum / bottom[0]->num(); top[0]->mutable_cpu_data()[0] = loss; // 这里没有使用gpu函数,是普通的cpu运算,所以使用cpu_data() }
2.2 反向计算
反向计算主要是实现Backward_cpu和Backward_gpu两个函数。CPU版本:
template <typename Dtype> void L1LossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { const Dtype sign = (i == 0) ? 1 : -1; // 对两个输入的反向计算的差异仅是正负号,所以根据输入blob的序号确定一个符号即可 const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num(); // alpha = 1/N. top[0]->cpu_diff()[0]是weight_loss // 使用diff_的符号来判断两个输入blob哪个大 caffe_cpu_sign(bottom[i]->count(), diff_.cpu_data(), bottom[i]->mutable_cpu_diff()); // caffe_cpu_scale(n, alpha, x, y): y = alpha * x caffe_cpu_scale(bottom[i]->count(), alpha, bottom[i]->cpu_diff(), bottom[i]->mutable_cpu_diff()); } } }
解释一下上面函数中的
top[0]->cpu_diff()[0]。我们知道,每一层回传的梯度是由上一层传回来的梯度乘以本层的梯度得到的。但我们现在本来就是loss层了,后面没有层了,那这个
top[0]->cpu_diff()[0]是什么呢?注意,这里只是取了
top[0]->cpu_diff()的第一个元素,其实它就是我们在prototxt中定义的
loss_weight。
类似的,GPU版本:
template <typename Dtype> void L1LossLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { const Dtype sign = (i == 0) ? 1 : -1; const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num(); // 这里是cpu运算,使用cpu_diff() caffe_gpu_sign(bottom[i]->count(), diff_.gpu_data(), bottom[i]->mutable_gpu_diff()); caffe_gpu_scale(bottom[i]->count(), alpha, bottom[i]->gpu_diff(), bottom[i]->mutable_gpu_diff()); } } }
相关文章推荐
- 深度学习_caffe (4) 基于mnist实例搭建新的神经网络&在caffe中添加层
- 在caffe 中添加Scale-invariant loss
- caffe中添加新层(差分层)
- 在caffe中添加新的层
- caffe添加C++层和python层定义
- 【Caffe实践】 添加自己的网络层
- caffe中添加新层
- caffe框架下添加自己的MFC程序(下)
- 【caffe-Windows】添加工程-以classification为例(2017-04-11)
- 如何在新版本caffe里添加新的一层
- caffe SSD 添加新层时出现的问题
- caffe添加新层教程
- caffe添加自己的层
- caffe中添加新层
- 在caffe中添加自定义层
- 如何在caffe中添加新的Layer
- ubuntu caffe框架下测试ssd并添加跟踪代码
- caffe添加python数据层(ImageData)
- caffe中添加新层
- 怎样在caffe中添加layer以及caffe中triplet loss layer的实现