下面是一个博友 对于NG课程的翻译:
接下来偷懒一下直接上传图片,caffe中的常用的loss函数(后面文章会梳理每一个Loss):
loss有一个细节问题就是Loss weights (损失权重),用来表征不同Layer产生的loss的重要性,Layer名称中以Loss结尾表示这是一个会产生loss的Layer,其他的Layer只是单纯的用于中间计算。任何一个Layer都可以被用于产生loss。反向迭代时,一个Layer可以赋予一个非零的loss weight,用于调整中间Layer产生的一些数据、参数。对于不止一个输出(top)的Layer(对应的有非零的loss weight),输出的loss是对所有输出blob的loss的和。Caffe最后输出的loss,是由Net中所有的loss加权得到的。 对于loss Layer,loss_weight为非0,对于非loss Layer,loss_weight都是0, 所以Layer对网络loss的贡献值也为0。
Pseudocode:
loss := 0 for layer in layers: for top, loss_weight in layer.tops, layer.loss_weights: loss += loss_weight * sum(top)
这个设置在layer.hpp文件中,
一个protected函数,
SetLossWeight()
:
inline void SetLossWeights( const vector<Blob<Dtype>*>& top) { const int num_loss_weights = layer_param_.loss_weight_size(); if (num_loss_weights) { CHECK_EQ(top.size(), num_loss_weights) << "loss_weight must be " "unspecified or specified once per top blob." ; for ( int top_id = 0; top_id < top.size(); ++top_id) { const Dtype loss_weight = layer_param_.loss_weight(top_id); if (loss_weight == Dtype(0)) { continue ; } this ->set_loss(top_id, loss_weight); const int count = top[top_id]->count(); Dtype* loss_multiplier = top[top_id]->mutable_cpu_diff(); caffe_set(count, loss_weight, loss_multiplier); } } }
caffe_set函数在math_function中有实现,对参数进行的初始化,
template < typename Dtype> void caffe_set( const int N, const Dtype alpha, Dtype* Y) { if (alpha == 0) { memset(Y, 0, sizeof (Dtype) * N); return ; } for ( int i = 0; i < N; ++i) { Y[i] = alpha; } }
功能:用常数 alpha 对 Y 进行初始化
函数 void *memset(void *buffer, char c, unsigned count) 一般为新申请的内存做初始化,功能是将buffer所指向内存中的每个字节的内容全部设置为c指定的ASCII值, count为块的大小。
配置文件protxt中的形式:
layer { name: "loss" type: "XXXXXXXXXXXLoss" bottom: "predict" bottom: "label1" bottom: "label2" top: "loss" loss_weight: xxxxx }