Fixed Forward() and Backward() to match Layer API
This commit is contained in:
@@ -33,31 +33,25 @@ class TripletMarginLoss
|
||||
/**
|
||||
* Computes the Triplet Margin Loss function.
|
||||
*
|
||||
* @param input The propagated input activation.
|
||||
* @param target The target vector.
|
||||
* @param input The propagated input activation. It should be
|
||||
* concatenated anchor and positive samples.
|
||||
* @param target The target vector. It should be negative samples.
|
||||
*/
|
||||
template<typename AnchorType, typename PositiveType, typename NegativeType>
|
||||
double Forward(const AnchorType& anchor,
|
||||
const PositiveType& positive,
|
||||
const NegativeType& negative);
|
||||
template<typename InputType, typename TargetType>
|
||||
double Forward(const InputType& input, const TargetType& target);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network.
|
||||
*
|
||||
* @param input The propagated input activation.
|
||||
* @param target The target vector.
|
||||
* @param input The propagated input activation. It should be
|
||||
* concatenated anchor and positive samples.
|
||||
* @param target The target vector. It should be negative samples.
|
||||
* @param output The calculated error.
|
||||
*/
|
||||
template <
|
||||
typename AnchorType,
|
||||
typename PositiveType,
|
||||
typename NegativeType,
|
||||
typename OutputType
|
||||
>
|
||||
void Backward(const AnchorType& anchor,
|
||||
const PositiveType& positive,
|
||||
const NegativeType& negative,
|
||||
OutputType&& output);
|
||||
template<typename InputType, typename TargetType, typename OutputType>
|
||||
void Backward(const InputType& input,
|
||||
const TargetType& target,
|
||||
OutputType& output);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType& OutputParameter() const { return outputParameter; }
|
||||
|
||||
@@ -26,30 +26,30 @@ TripletMarginLoss<InputDataType, OutputDataType>::TripletMarginLoss(
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename AnchorType, typename PositiveType, typename NegativeType>
|
||||
template<typename InputType, typename TargetType>
|
||||
double TripletMarginLoss<InputDataType, OutputDataType>::Forward(
|
||||
const AnchorType& anchor,
|
||||
const PositiveType& positive,
|
||||
const NegativeType& negative)
|
||||
const InputType& input,
|
||||
const TargetType& target)
|
||||
{
|
||||
arma::mat anchor = input.submat(0, 0, input.n_rows / 2 - 1, input.n_cols - 1);
|
||||
arma::mat positive = input.submat(input.n_rows / 2, 0, input.n_rows - 1, input.n_cols - 1);
|
||||
return std::max(0.0, arma::accu(arma::pow(anchor - positive, 2)) -
|
||||
arma::accu(arma::pow(anchor - negative, 2)) + margin) / anchor.n_cols;
|
||||
arma::accu(arma::pow(anchor - target, 2)) + margin) / anchor.n_cols;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template <
|
||||
typename AnchorType,
|
||||
typename PositiveType,
|
||||
typename NegativeType,
|
||||
typename InputType,
|
||||
typename TargetType,
|
||||
typename OutputType
|
||||
>
|
||||
void TripletMarginLoss<InputDataType, OutputDataType>::Backward(
|
||||
const AnchorType& anchor,
|
||||
const PositiveType& positive,
|
||||
const NegativeType& negative,
|
||||
OutputType&& output)
|
||||
const InputType& input,
|
||||
const TargetType& target,
|
||||
OutputType& output)
|
||||
{
|
||||
output = 2 * (negative - positive) / anchor.n_cols;
|
||||
arma::mat positive = input.submat(input.n_rows / 2, 0, input.n_rows - 1, input.n_cols - 1);
|
||||
output = 2 * (target - positive) / target.n_cols;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
|
||||
@@ -904,7 +904,8 @@ TEST_CASE("MeanAbsolutePercentageErrorTest", "[LossFunctionsTest]")
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(TripletMarginLossTest)
|
||||
{
|
||||
arma::mat anchor, positive, negative, output;
|
||||
arma::mat anchor, positive, negative;
|
||||
arma::mat input, target, output;
|
||||
TripletMarginLoss<> module;
|
||||
|
||||
// Test the Forward function on a user generator input and compare it against
|
||||
@@ -912,13 +913,17 @@ BOOST_AUTO_TEST_CASE(TripletMarginLossTest)
|
||||
anchor = arma::mat("2 3 5");
|
||||
positive = arma::mat("10 12 13");
|
||||
negative = arma::mat("4 5 7");
|
||||
double error = module.Forward(std::move(anchor),
|
||||
std::move(positive), std::move(negative));
|
||||
|
||||
input = {
|
||||
{2, 3, 5},
|
||||
{10, 12, 13}
|
||||
};
|
||||
|
||||
double error = module.Forward(input, negative);
|
||||
BOOST_REQUIRE_EQUAL(error, 66);
|
||||
|
||||
// Test the Backward function.
|
||||
module.Backward(std::move(anchor),
|
||||
std::move(positive), std::move(negative), std::move(output));
|
||||
module.Backward(input, negative, output);
|
||||
// According to the used backward formula:
|
||||
// output = 2 * (negative - positive) / anchor.n_cols,
|
||||
// output * nofColumns / 2 + positive should be equal to negative.
|
||||
@@ -930,13 +935,16 @@ BOOST_AUTO_TEST_CASE(TripletMarginLossTest)
|
||||
anchor = arma::mat("4");
|
||||
positive = arma::mat("7");
|
||||
negative = arma::mat("1");
|
||||
error = module.Forward(std::move(anchor),
|
||||
std::move(positive), std::move(negative));
|
||||
|
||||
input = arma::mat(2, 1);
|
||||
input[0] = 4;
|
||||
input[1] = 7;
|
||||
|
||||
error = module.Forward(input, negative);
|
||||
BOOST_REQUIRE_EQUAL(error, 1.0);
|
||||
|
||||
// Test the Backward function on a single input.
|
||||
module.Backward(std::move(anchor),
|
||||
std::move(positive), std::move(negative), std::move(output));
|
||||
module.Backward(input, negative, output);
|
||||
// Test whether the output is negative.
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), -12);
|
||||
BOOST_REQUIRE_EQUAL(output.n_elem, 1);
|
||||
|
||||
Reference in New Issue
Block a user