#ifndef TH_GENERIC_FILE #define TH_GENERIC_FILE "generic/ClassNLLCriterion.c" #else void THNN_(ClassNLLCriterion_updateOutput)( THNNState *state, THTensor *input, THIndexTensor *target, THTensor *output, bool sizeAverage, THTensor *weights, THTensor *total_weight, long ignore_index) { THNN_CHECK_DIM_SIZE(output, 1, 0, 1); THNN_CHECK_DIM_SIZE(total_weight, 1, 0, 1); int n_dims = THTensor_(nDimension)(input); int n_classes = THTensor_(size)(input, n_dims - 1); ignore_index -= TH_INDEX_BASE; if (THIndexTensor_(nDimension)(target) > 1) { THError("multi-target not supported"); } if (THTensor_(nDimension)(input) > 2) { THError("input tensor should be 1D or 2D"); } if (weights && THTensor_(nElement)(weights) != n_classes) { THDescBuff s1 = THTensor_(sizeDesc)(weights); THError("weight tensor should be defined either for all %d classes or no classes" " but got weight tensor of shape: %s", n_classes, s1.str); } input = THTensor_(newContiguous)(input); target = THIndexTensor_(newContiguous)(target); weights = weights ? THTensor_(newContiguous)(weights) : NULL; real *input_data = THTensor_(data)(input); THIndex_t *target_data = THIndexTensor_(data)(target); real *weights_data = weights ? THTensor_(data)(weights) : NULL; real *output_data = THTensor_(data)(output); real *total_weight_data = THTensor_(data)(total_weight); output_data[0] = total_weight_data[0] = 0.0; if (THTensor_(nDimension)(input) == 1) { int cur_target = target_data[0] - TH_INDEX_BASE; if (cur_target != ignore_index) { THAssert(cur_target >= 0 && cur_target < n_classes); total_weight_data[0] = weights ? weights_data[cur_target] : 1.0f; output_data[0] = -input_data[cur_target] * total_weight_data[0]; } } else if (THTensor_(nDimension)(input) == 2) { int batch_size = THTensor_(size)(input, 0); THAssert(THIndexTensor_(size)(target, 0) == batch_size); int n_target = THTensor_(size)(input, 1); int i; for (i = 0; i < batch_size; i++) { int cur_target = target_data[i] - TH_INDEX_BASE; if (cur_target != ignore_index) { THAssert(cur_target >= 0 && cur_target < n_classes); real cur_weight = weights ? weights_data[cur_target] : 1.0f; total_weight_data[0] += cur_weight; output_data[0] -= input_data[i * n_target + cur_target] * cur_weight; } } } if (sizeAverage && total_weight_data[0]) { output_data[0] /= total_weight_data[0]; } if (weights) { THTensor_(free)(weights); } THTensor_(free)(input); THIndexTensor_(free)(target); } void THNN_(ClassNLLCriterion_updateGradInput)( THNNState *state, THTensor *input, THIndexTensor *target, THTensor *gradInput, bool sizeAverage, THTensor *weights, THTensor *total_weight, long ignore_index) { int n_dims = THTensor_(nDimension)(input); int n_classes = THTensor_(size)(input, n_dims - 1); ignore_index -= TH_INDEX_BASE; if (!THTensor_(isContiguous)(gradInput)) { THError("gradInput must be contiguous"); } real *total_weight_data = THTensor_(data)(total_weight); if (!(*total_weight_data > 0)) { return; } if (THIndexTensor_(nDimension)(target) > 1) { THError("multi-target not supported"); } if (THTensor_(nDimension)(input) > 2) { THError("input tensor should be 1D or 2D"); } if (weights && THTensor_(nElement)(weights) != n_classes) { THError("weight tensor should be defined either for all or no classes"); } target = THIndexTensor_(newContiguous)(target); weights = weights ? THTensor_(newContiguous)(weights) : NULL; THIndex_t *target_data = THIndexTensor_(data)(target); real *weights_data = weights ? THTensor_(data)(weights) : NULL; real *gradInput_data = THTensor_(data)(gradInput); if (THTensor_(nDimension)(input) == 1) { int cur_target = target_data[0] - TH_INDEX_BASE; if (cur_target != ignore_index) { THAssert(cur_target >= 0 && cur_target < n_classes); gradInput_data[cur_target] = (!sizeAverage && weights) ? -weights_data[cur_target] : -1; } } else if (THTensor_(nDimension)(input) == 2) { int batch_size = THTensor_(size)(input, 0); THAssert(THIndexTensor_(size)(target, 0) == batch_size); int n_target = THTensor_(size)(input, 1); int i; for (i = 0; i < batch_size; i++){ int cur_target = target_data[i] - TH_INDEX_BASE; if (cur_target != ignore_index) { THAssert(cur_target >= 0 && cur_target < n_classes); gradInput_data[i * n_target + cur_target] = -(weights ? weights_data[cur_target] : 1.0f); if (sizeAverage && *total_weight_data) { gradInput_data[i * n_target + cur_target] /= *total_weight_data; } } } } THIndexTensor_(free)(target); if (weights) { THTensor_(free)(weights); } } #endif