REQUIRE_TRUE(labels->isSameShape(predictions),0,"ABSOLUTE_DIFFERENCE_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labels).c_str(),ShapeUtils::shapeAsString(predictions).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(weights->isScalar()||weights->rankOf()==labels->rankOf(),0,"ABSOLUTE_DIFFERENCE_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",weights->rankOf(),labels->rankOf());
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(weights->isScalar()||ShapeUtils::areShapesBroadcastable(*weights,*labels),0,"ABSOLUTE_DIFFERENCE_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weights).c_str(),ShapeUtils::shapeAsString(labels).c_str());
// only 4 possible reduction modes exist
REQUIRE_TRUE(reductionMode==0||reductionMode==1||reductionMode==2||reductionMode==3,0,"ABSOLUTE_DIFFERENCE_LOSS OP: reduction mode value is not acceptable, possible values are 0, 1, 2, 3, but got %i instead!",reductionMode);
// perform weights broadcasting/tile to labels if needed
case0:// 0 - "none", un-reduced weighted losses with the same shape as labels.
output->assign(E);
break;
case1:{// 1 - "weighted_sum", output is scalar and equal to sum of all elements of E array
E.reduceNumber(reduce::Sum,*output);
break;
}
case2:{// 2 - "weighted_mean", output is scalar and equal to sum of all elements of E array divided by sum of all elements of weightsBroad array
NDArraysum;
if(weights->isScalar())
sum=(*weights)*E.lengthOf();
else
sum=weightsBroad->reduceNumber(reduce::Sum);
if(sum.e<double>(0)==0.)
(*output)=0.;
else
output->assign(E.reduceNumber(reduce::Sum)/sum);
break;
}
case3:{// 3 - "weighted_sum_by_nonzero_weights", output is scalar and equal to scalar sum of all elements of E array divided by number of non-zero weights
// labels and predictions must have the same shapes
REQUIRE_TRUE(shape::shapeEquals(labelsShapeInfo,predictionsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labelsShapeInfo).c_str(),ShapeUtils::shapeAsString(predictionsShapeInfo).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||shape::rank(weightsShapeInfo)==shape::rank(labelsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",shape::rank(weightsShapeInfo),shape::rank(labelsShapeInfo));
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||ShapeUtils::areShapesBroadcastable(weightsShapeInfo,labelsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weightsShapeInfo).c_str(),ShapeUtils::shapeAsString(labelsShapeInfo).c_str());
// take into account Alex's proposition to treat "none" the same as "weighted_sum" mode when calculating gradients
if(reductionMode==0)
reductionMode=1;
// inputs validation
REQUIRE_TRUE(labels->isSameShape(predictions),0,"ABSOLUTE_DIFFERENCE_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labels).c_str(),ShapeUtils::shapeAsString(predictions).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(weights->isScalar()||weights->rankOf()==labels->rankOf(),0,"ABSOLUTE_DIFFERENCE_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",weights->rankOf(),labels->rankOf());
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(weights->isScalar()||ShapeUtils::areShapesBroadcastable(*weights,*labels),0,"ABSOLUTE_DIFFERENCE_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weights).c_str(),ShapeUtils::shapeAsString(labels).c_str());
// only 4 possible reduction modes exist
REQUIRE_TRUE(reductionMode==0||reductionMode==1||reductionMode==2||reductionMode==3,0,"ABSOLUTE_DIFFERENCE_LOSS OP: reduction mode value is not acceptable, possible values are 0, 1, 2, 3, but got %i instead!",reductionMode);
// perform weights broadcasting/tile to labels if needed
case3:{// 3 - "weighted_sum_by_nonzero_weights", output is scalar and equal to scalar sum of all elements of E array divided by number of non-zero weights
// labels and predictions must have the same shapes
REQUIRE_TRUE(shape::shapeEquals(labelsShapeInfo,predictionsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: labels and predictions arrays must have the same shapes, but got %s and %s correspondingly !",ShapeUtils::shapeAsString(labelsShapeInfo).c_str(),ShapeUtils::shapeAsString(predictionsShapeInfo).c_str());
// weights array can be single scalar or has the same rank as labels, and must be broadcastable to labels
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||shape::rank(weightsShapeInfo)==shape::rank(labelsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: weights array should be scalar or have the same rank as labels array, but got %i and %i correspondingly!",shape::rank(weightsShapeInfo),shape::rank(labelsShapeInfo));
// check whether broadcast operation is possible for weights array
REQUIRE_TRUE(shape::isScalar(weightsShapeInfo)||ShapeUtils::areShapesBroadcastable(weightsShapeInfo,labelsShapeInfo),0,"ABSOLUTE_DIFFERENCE_LOSS OP: shapes of weights and labels arrays should be broadcastable, but got weights = %s and labels = %s instead!",ShapeUtils::shapeAsString(weightsShapeInfo).c_str(),ShapeUtils::shapeAsString(labelsShapeInfo).c_str());