Added loss_multiclass_log_

This commit is contained in:
Davis King 2015-12-13 12:21:54 -05:00
parent 045266261f
commit 351a6331e9
1 changed files with 105 additions and 0 deletions

View File

@ -204,6 +204,111 @@ namespace dlib
template <typename SUBNET>
using loss_binary_log = add_loss_layer<loss_binary_log_, SUBNET>;
// ----------------------------------------------------------------------------------------
class loss_multiclass_log_
{
public:
const static unsigned int sample_expansion_factor = 1;
typedef unsigned long label_type;
template <
typename SUB_TYPE,
typename label_iterator
>
void to_label (
const tensor& input_tensor,
const SUB_TYPE& sub,
label_iterator iter
) const
{
const tensor& output_tensor = sub.get_output();
DLIB_CASSERT(output_tensor.nr() == 1 &&
output_tensor.nc() == 1 ,"");
DLIB_CASSERT(input_tensor.num_samples() == output_tensor.num_samples(),"");
// Note that output_tensor.k() should match the number of labels.
const float* out_data = output_tensor.host();
for (long i = 0; i < output_tensor.num_samples(); ++i)
{
// The index of the largest output for this sample is the label.
*iter++ = index_of_max(rowm(mat(output_tensor),i));
}
}
template <
typename const_label_iterator,
typename SUBNET
>
double compute_loss (
const tensor& input_tensor,
const_label_iterator truth,
SUBNET& sub
) const
{
const tensor& output_tensor = sub.get_output();
tensor& grad = sub.get_gradient_input();
DLIB_CASSERT(input_tensor.num_samples() != 0,"");
DLIB_CASSERT(input_tensor.num_samples()%sample_expansion_factor == 0,"");
DLIB_CASSERT(input_tensor.num_samples() == grad.num_samples(),"");
DLIB_CASSERT(input_tensor.num_samples() == output_tensor.num_samples(),"");
DLIB_CASSERT(output_tensor.nr() == 1 &&
output_tensor.nc() == 1,"");
DLIB_CASSERT(grad.nr() == 1 &&
grad.nc() == 1,"");
tt::softmax(grad, output_tensor);
// The loss we output is the average loss over the mini-batch.
const double scale = 1.0/output_tensor.num_samples();
double loss = 0;
float* g = grad.host();
for (long i = 0; i < output_tensor.num_samples(); ++i)
{
const long y = (long)*truth++;
// The network must produce a number of outputs that is equal to the number
// of labels when using this type of loss.
DLIB_CASSERT(y < output_tensor.k(), "y: " << y << ", output_tensor.k(): " << output_tensor.k());
for (long k = 0; k < output_tensor.k(); ++k)
{
const unsigned long idx = i*output_tensor.k()+k;
if (k == y)
{
loss += scale*-std::log(g[idx]);
g[idx] = scale*(g[idx]-1);
}
else
{
g[idx] = scale*g[idx];
}
}
}
return loss;
}
friend void serialize(const loss_multiclass_log_& , std::ostream& out)
{
serialize("loss_multiclass_log_", out);
}
friend void deserialize(loss_multiclass_log_& , std::istream& in)
{
std::string version;
deserialize(version, in);
if (version != "loss_multiclass_log_")
throw serialization_error("Unexpected version found while deserializing dlib::loss_multiclass_log_.");
}
};
template <typename SUBNET>
using loss_multiclass_log = add_loss_layer<loss_multiclass_log_, SUBNET>;
// ----------------------------------------------------------------------------------------
}