#include <algorithm>#include <vector>#include "caffe/layers/loss_layer.hpp"namespace caffe {
template <typename Dtype>
void LossLayer<Dtype>::LayerSetUp(
constvector<Blob<Dtype>*>& bottom, constvector<Blob<Dtype>*>& top) {
// LossLayers have a non-zero (1) loss by default.if (this->layer_param_.loss_weight_size() == 0) {
this->layer_param_.add_loss_weight(Dtype(1));
}
}
template <typename Dtype>
void LossLayer<Dtype>::Reshape(
constvector<Blob<Dtype>*>& bottom, constvector<Blob<Dtype>*>& top) {
CHECK_EQ(bottom[0]->shape(0), bottom[1]->shape(0))
<< "The data and label should have the same first dimension.";
vector<int> loss_shape(0); // Loss layers output a scalar; 0 axes.
top[0]->Reshape(loss_shape);
}
template <typename Dtype>
Dtype LossLayer<Dtype>::GetNormalizer(
const LossParameter_NormalizationMode normalization_mode,
constint outer_num, constint inner_num, constint valid_count) {
Dtype normalizer;
switch (normalization_mode) {
case LossParameter_NormalizationMode_FULL:
normalizer = Dtype(outer_num * inner_num);
break;
case LossParameter_NormalizationMode_VALID:
if (valid_count == -1) {
normalizer = Dtype(outer_num * inner_num);
} else {
normalizer = Dtype(valid_count);
}
break;
case LossParameter_NormalizationMode_BATCH_SIZE:
normalizer = Dtype(outer_num);
break;
case LossParameter_NormalizationMode_NONE:
normalizer = Dtype(1);
break;
default:
LOG(FATAL) << "Unknown normalization mode: "
<< LossParameter_NormalizationMode_Name(normalization_mode);
}
// Some users will have no labels for some examples in order to 'turn off' a// particular loss in a multi-task setup. The max prevents NaNs in that case.returnstd::max(Dtype(1.0), normalizer);
}
INSTANTIATE_CLASS(LossLayer);
} // namespace caffe
loss_layer.hpp
#ifndef CAFFE_LOSS_LAYER_HPP_#define CAFFE_LOSS_LAYER_HPP_#include <vector>#include "caffe/blob.hpp"#include "caffe/layer.hpp"#include "caffe/proto/caffe.pb.h"namespace caffe {
constfloat kLOG_THRESHOLD = 1e-20;
/**
* @brief An interface for Layer%s that take two Blob%s as input -- usually
* (1) predictions and (2) ground-truth labels -- and output a
* singleton Blob representing the loss.
*
* LossLayers are typically only capable of backpropagating to their first input
* -- the predictions.
*/template <typename Dtype>
class LossLayer : public Layer<Dtype> {
public:
explicit LossLayer(const LayerParameter& param)
: Layer<Dtype>(param) {}
virtualvoid LayerSetUp(
constvector<Blob<Dtype>*>& bottom, constvector<Blob<Dtype>*>& top);
virtualvoid Reshape(
constvector<Blob<Dtype>*>& bottom, constvector<Blob<Dtype>*>& top);
/**
* Read the normalization mode parameter and compute the normalizer based
* on the blob size. If normalization_mode is VALID, the count of valid
* outputs will be read from valid_count, unless it is -1 in which case
* all outputs are assumed to be valid.
*/
Dtype GetNormalizer(
const LossParameter_NormalizationMode normalization_mode,
constint outer_num, constint inner_num, constint valid_count);
virtualinlineint ExactNumBottomBlobs() const { return2; }
/**
* @brief For convenience and backwards compatibility, instruct the Net to
* automatically allocate a single top Blob for LossLayers, into which
* they output their singleton loss, (even if the user didn't specify
* one in the prototxt, etc.).
*/virtualinlinebool AutoTopBlobs() const { returntrue; }
virtualinlineint ExactNumTopBlobs() const { return1; }
/**
* We usually cannot backpropagate to the labels; ignore force_backward for
* these inputs.
*/virtualinlinebool AllowForceBackward(constint bottom_index) const {
return bottom_index != 1;
}
};
} // namespace caffe#endif // CAFFE_LOSS_LAYER_HPP_
caffe.proto部分源码
// Message that stores parameters shared by loss layers
message LossParameter {
// If specified, ignore instances with the given label.
optional int32 ignore_label = 1;
// How to normalize the loss for loss layers that aggregate across batches,
// spatial dimensions, or other dimensions. Currently only implemented in// SoftmaxWithLoss and SigmoidCrossEntropyLoss layers.
enum NormalizationMode {
// Divide by the number of examples in the batch times spatial dimensions.
// Outputs that receive the ignore label will NOT be ignored in computing
// the normalization factor.
FULL = 0;
// Divide by the total number of output locations that donot take the
// ignore_label. If ignore_label isnot set, this behaves like FULL.
VALID = 1;
// Divide by the batch size.
BATCH_SIZE = 2;
// Do not normalize the loss.
NONE = 3;
}
// For historical reasons, the default normalization for// SigmoidCrossEntropyLoss is BATCH_SIZE and *not* VALID.
optional NormalizationMode normalization = 3 [default = VALID];
// Deprecated. Ignored if normalization is specified. If normalization
//isnot specified, then setting this to false will be equivalent to
// normalization = BATCH_SIZE to be consistent with previous behavior.
optional bool normalize = 2;
}