在训练阶段有损失层,损失层需要两个输入的Blob,一个是网络的预测值,一个是真实的标签。
基类LossLayer,其他的loss继承自这个类。
这里以欧拉损失为例来说明
原理
欧拉损失
E=12N∑n=1N||yn−y‘n||2
前向传播
top:(1×1×1×1)维的欧氏距离损失E=12N∑Nn=1||yn−y‘n||2
反向传播
反向计算微分E=1N∑Nn=1(yn−y‘n)
代码如下
Forward_cpu
template <typename Dtype>
void EuclideanLossLayer<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());//diff_ = bottom[0] - bottom[1]
Dtype dot = caffe_cpu_dot(count, diff_.cpu_data(), diff_.cpu_data()); // dot = ||diff_||^2
Dtype loss = dot / bottom[0]->num() / Dtype(2);//输出的loss
top[0]->mutable_cpu_data()[0] = loss;
}
Backward_cpu
template <typename Dtype>
void EuclideanLossLayer<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]) {//对于输入的label bottom propagate_dowm 为0
const Dtype sign = (i == 0) ? 1 : -1;//由于diff_ = bottom[0] - bottom[1]
const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num();
caffe_cpu_axpby(
bottom[i]->count(), // count
alpha, // alpha
diff_.cpu_data(), // a
Dtype(0), // beta
bottom[i]->mutable_cpu_diff()); // b
}//bottom[i]->mutable_cpu_diff()) = alpha*diff_.cpu_data()
}
}