Files
ensmallen/tests/callbacks_test.cpp
T

859 lines
26 KiB
C++

/**
* @file callbacks_test.cpp
* @author Marcus Edel
*
* ensmallen is free software; you may redistribute it and/or modify it under
* the terms of the 3-clause BSD license. You should have received a copy of
* the 3-clause BSD license along with ensmallen. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <ensmallen.hpp>
#include "catch.hpp"
#include "test_function_tools.hpp"
using namespace ens;
using namespace ens::test;
using namespace ens::callbacks::traits;
/**
* Utility class with Evaluate(), Gradient(), BeginEpoch(), EndEpoch(),
* BeginOptimization(), EndOptimization(), EvaluateConstraint(),
* GradientConstraint(), StepTaken.
*/
class CompleteCallbackTestFunction
{
public:
CompleteCallbackTestFunction() :
calledEvaluate(false),
calledGradient(false),
calledBeginEpoch(false),
calledEndEpoch(false),
calledBeginOptimization(false),
calledEndOptimization(false),
calledEvaluateConstraint(false),
calledGradientConstraint(false),
calledStepTaken(false),
calledGenerationalStepTaken(false)
{ }
template<typename OptimizerType, typename FunctionType, typename MatType>
void Evaluate(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
const double /* objective */)
{ calledEvaluate = true; }
template<typename OptimizerType,
typename FunctionType,
typename MatType,
typename GradType>
void Gradient(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
GradType& /* objective */)
{ calledGradient = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void BeginEpoch(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
const size_t /* epoch */,
const double /* objective */)
{ calledBeginEpoch = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void EndEpoch(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
const size_t /* epoch */,
const double /* objective */)
{ calledEndEpoch = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void BeginOptimization(OptimizerType& /* optimizer */,
FunctionType& /* function */,
MatType& /* coordinates */)
{ calledBeginOptimization = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void EndOptimization(OptimizerType& /* optimizer */,
FunctionType& /* function */,
MatType& /* coordinates */)
{ calledEndOptimization = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void EvaluateConstraint(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
const size_t /* constraint */,
const double /* constraintValue */)
{ calledEvaluateConstraint = true; }
template<typename OptimizerType,
typename FunctionType,
typename MatType,
typename GradType>
void GradientConstraint(OptimizerType& /* optimizer */,
FunctionType& /* function */,
const MatType& /* coordinates */,
const size_t /* constraint */,
GradType& /* gradient */)
{ calledGradientConstraint = true; }
template<typename OptimizerType, typename FunctionType, typename MatType>
void StepTaken(OptimizerType& /* optimizer */,
FunctionType& /* function */,
MatType& /* coordinates */)
{ calledStepTaken = true; }
template<typename OptimizerType,
typename FunctionType,
typename MatType,
typename ObjectivesVecType,
typename IndicesType>
void GenerationalStepTaken(OptimizerType& /* optimizer */,
FunctionType& /* function */,
MatType& /* coordinates */,
ObjectivesVecType& /* objectives */,
IndicesType& /* frontIndices */)
{ calledGenerationalStepTaken = true; }
bool calledEvaluate;
bool calledGradient;
bool calledBeginEpoch;
bool calledEndEpoch;
bool calledBeginOptimization;
bool calledEndOptimization;
bool calledEvaluateConstraint;
bool calledGradientConstraint;
bool calledStepTaken;
bool calledGenerationalStepTaken;
};
template<typename OptimizerType>
void CallbacksFullFunctionTest(OptimizerType& optimizer,
bool calledEvaluate,
bool calledGradient,
bool calledBeginEpoch,
bool calledEndEpoch,
bool calledBeginOptimization,
bool calledEndOptimization,
bool calledEvaluateConstraint,
bool calledGradientConstraint,
bool calledStepTaken)
{
arma::mat data, testData, shuffledData;
arma::Row<size_t> responses, testResponses, shuffledResponses;
LogisticRegressionTestData(data, testData, shuffledData,
responses, testResponses, shuffledResponses);
LogisticRegression<> lr(shuffledData, shuffledResponses, 0.5);
CompleteCallbackTestFunction cb;
arma::mat coordinates = lr.GetInitialPoint();
optimizer.Optimize(lr, coordinates, cb);
REQUIRE(cb.calledEvaluate == calledEvaluate);
REQUIRE(cb.calledGradient == calledGradient);
REQUIRE(cb.calledBeginEpoch == calledBeginEpoch);
REQUIRE(cb.calledEndEpoch == calledEndEpoch);
REQUIRE(cb.calledBeginOptimization == calledBeginOptimization);
REQUIRE(cb.calledEndOptimization == calledEndOptimization);
REQUIRE(cb.calledEvaluateConstraint == calledEvaluateConstraint);
REQUIRE(cb.calledGradientConstraint == calledGradientConstraint);
REQUIRE(cb.calledStepTaken == calledStepTaken);
}
template<typename OptimizerType>
void CallbacksFullMultiobjectiveFunctionTest(OptimizerType& optimizer,
bool calledEvaluate,
bool calledGradient,
bool calledBeginEpoch,
bool calledEndEpoch,
bool calledBeginOptimization,
bool calledEndOptimization,
bool calledEvaluateConstraint,
bool calledGradientConstraint,
bool calledStepTaken,
bool calledGenerationalStepTaken)
{
SchafferFunctionN1<arma::mat> SCH;
typedef decltype(SCH.objectiveA) ObjectiveTypeA;
typedef decltype(SCH.objectiveB) ObjectiveTypeB;
CompleteCallbackTestFunction cb;
arma::mat coordinates = SCH.GetInitialPoint();
std::tuple<ObjectiveTypeA, ObjectiveTypeB> objectives = SCH.GetObjectives();
optimizer.Optimize(objectives, coordinates, cb);
REQUIRE(cb.calledEvaluate == calledEvaluate);
REQUIRE(cb.calledGradient == calledGradient);
REQUIRE(cb.calledBeginEpoch == calledBeginEpoch);
REQUIRE(cb.calledEndEpoch == calledEndEpoch);
REQUIRE(cb.calledBeginOptimization == calledBeginOptimization);
REQUIRE(cb.calledEndOptimization == calledEndOptimization);
REQUIRE(cb.calledEvaluateConstraint == calledEvaluateConstraint);
REQUIRE(cb.calledGradientConstraint == calledGradientConstraint);
REQUIRE(cb.calledStepTaken == calledStepTaken);
REQUIRE(cb.calledGenerationalStepTaken == calledGenerationalStepTaken);
}
template<typename OptimizerType>
void EarlyStopCallbacksLambdaFunctionTest(OptimizerType& optimizer)
{
arma::mat data, testData, shuffledData;
arma::Row<size_t> responses, testResponses, shuffledResponses;
LogisticRegressionTestData(data, testData, shuffledData,
responses, testResponses, shuffledResponses);
LogisticRegression<> lr(shuffledData, shuffledResponses, 0.5);
arma::mat coordinates = lr.GetInitialPoint();
EarlyStopAtMinLoss cb(
[&](const arma::mat& /* coordinates */)
{
return lr.ComputeAccuracy(testData, testResponses,
coordinates);
});
optimizer.Optimize(lr, coordinates, cb);
}
TEST_CASE("EarlyStopAtMinLossLambdaCallbackTest", "[CallbacksTest]")
{
SMORMS3 smorms3;
EarlyStopCallbacksLambdaFunctionTest(smorms3);
}
TEST_CASE("EarlyStopAtMinLossCustomLambdaTest", "[CallbacksTest]")
{
// Use the 50-dimensional Rosenbrock function.
GeneralizedRosenbrockFunction f(50);
// Start at some really large point.
arma::mat coordinates = f.GetInitialPoint();
coordinates.fill(100.0);
EarlyStopAtMinLoss cb(
[&](const arma::mat& coordinates)
{
// Terminate if any coordinate has a value less than 10.
double minValue = arma::abs(coordinates).min();
return (minValue < 10.0) ?
std::numeric_limits<double>::max() : minValue;
});
SMORMS3 smorms3;
smorms3.Optimize(f, coordinates, cb);
// Make sure that we did not get to the optimum.
for (size_t i = 0; i < coordinates.n_elem; ++i)
REQUIRE(std::abs(coordinates[i]) >= 3.0);
}
/**
* Make sure we invoke all callbacks (AdaBound).
*/
TEST_CASE("AdaBoundCallbacksFullFunctionTest", "[CallbacksTest]")
{
AdaBound optimizer(0.001, 2, 0.1, 1e-3, 0.9, 0.999, 1e-8, 1000,
1e-3, false);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (AdaDelta).
*/
TEST_CASE("AdaDeltaCallbacksFullFunctionTest", "[CallbacksTest]")
{
AdaDelta optimizer(1.0, 1, 0.99, 1e-8, 2000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (AdaGrad).
*/
TEST_CASE("AdaGradCallbacksFullFunctionTest", "[CallbacksTest]")
{
AdaGrad optimizer(0.99, 1, 1e-8, 2000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (Adam).
*/
TEST_CASE("AdamCallbacksFullFunctionTest", "[CallbacksTest]")
{
Adam optimizer(0.5, 2, 0.7, 0.999, 1e-8, 2000, 1e-3, false);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (BigBatchSGD).
*/
TEST_CASE("BigBatchSGDCallbacksFullFunctionTest", "[CallbacksTest]")
{
BBS_BB optimizer(1, 0.01, 0.1, 2000, 1e-4);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (CMAES).
*/
TEST_CASE("CMAESCallbacksFullFunctionTest", "[CallbacksTest]")
{
CMAES<> optimizer(0, -1, 1, 32, 3, 1e-3);
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (CNE).
*/
TEST_CASE("CNECallbacksFullFunctionTest", "[CallbacksTest]")
{
CNE optimizer(200, 6, 0.2, 0.2, 0.2, 1e-5);
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (DE).
*/
TEST_CASE("DECallbacksFullFunctionTest", "[CallbacksTest]")
{
DE optimizer(200, 6, 0.6, 0.8, 1e-5);
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (Eve).
*/
TEST_CASE("EveCallbacksFullFunctionTest", "[CallbacksTest]")
{
Eve optimizer(1e-3, 1, 0.9, 0.999, 0.999, 1e-8, 10000, 2000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (FTML).
*/
TEST_CASE("FTMLCallbacksFullFunctionTest", "[CallbacksTest]")
{
FTML optimizer(0.001, 1, 0.9, 0.999, 1e-8, 2000, 1e-5, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (GradientDescent).
*/
TEST_CASE("GradientDescentCallbacksFullFunctionTest", "[CallbacksTest]")
{
GradientDescent optimizer(0.001, 3, 1e-15);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (IQN).
*/
TEST_CASE("IQNCallbacksFullFunctionTest", "[CallbacksTest]")
{
IQN optimizer(0.01, 1, 3, 1e-3);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (Katyusha).
*/
TEST_CASE("KatyushaCallbacksFullFunctionTest", "[CallbacksTest]")
{
Katyusha optimizer(1.0, 10.0, 1, 3, 0, 1e-10, true);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (NSGA2).
*/
TEST_CASE("NSGA2CallbacksFullFunctionTest", "[CallbackTest]")
{
arma::vec lowerBound = {-1000};
arma::vec upperBound = {1000};
NSGA2 optimizer(20, 5000, 0.5, 0.5, 1e-3, 1e-6, lowerBound, upperBound);
CallbacksFullMultiobjectiveFunctionTest(optimizer, false, false, false, false,
true, true, false, false, false, true);
}
/**
* Make sure we invoke all callbacks (MOEA/D-DE).
*/
TEST_CASE("MOEADCallbacksFullFunctionTest", "[CallbackTest]")
{
arma::vec lowerBound = {-1000};
arma::vec upperBound = {1000};
DefaultMOEAD optimizer(150, 300, 1.0, 0.9, 20, 20, 0.5, 2, 1E-10, lowerBound, upperBound);
CallbacksFullMultiobjectiveFunctionTest(optimizer, false, false, false, false,
true, true, false, false, false, true);
}
/**
* Make sure we invoke all callbacks (Lookahead).
*/
TEST_CASE("LookaheadCallbacksFullFunctionTest", "[CallbacksTest]")
{
Adam adam(0.001, 1, 0.9, 0.999, 1e-8, 100, 1e-10, false, true);
Lookahead<Adam> optimizer(adam, 0.5, 1000, 10, -10, NoDecay(),
false, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (Padam).
*/
TEST_CASE("PadamCallbacksFullFunctionTest", "[CallbacksTest]")
{
Padam optimizer(1e-2, 1, 0.9, 0.99, 0.25, 1e-5, 1000);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (QHAdam).
*/
TEST_CASE("QHAdamCallbacksFullFunctionTest", "[CallbacksTest]")
{
QHAdam optimizer(0.02, 2, 0.6, 0.9, 0.9, 0.999, 1e-8, 1000, 1e-7, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (RMSProp).
*/
TEST_CASE("RMSPropCallbacksFullFunctionTest", "[CallbacksTest]")
{
RMSProp optimizer(1e-3, 1, 0.99, 1e-8, 1000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SARAH).
*/
TEST_CASE("SARAHCallbacksFullFunctionTest", "[CallbacksTest]")
{
SARAH optimizer(0.01, 2, 3, 0, 1e-5, true);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SCD).
*/
TEST_CASE("SCDCallbacksFullFunctionTest", "[CallbacksTest]")
{
SCD<> optimizer(0.4, 4);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SGD).
*/
TEST_CASE("SGDCallbacksFullFunctionTest", "[CallbacksTest]")
{
StandardSGD optimizer(0.0003, 1, 2000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SGDR).
*/
TEST_CASE("SGDRCallbacksFullFunctionTest", "[CallbacksTest]")
{
SGDR<> optimizer(50, 2.0, 1, 0.01, 2000, 1e-3);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SMORMS3).
*/
TEST_CASE("SMORMS3CallbacksFullFunctionTest", "[CallbacksTest]")
{
SMORMS3 optimizer(0.001, 1, 1e-16, 1000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SPALeRASGD).
*/
TEST_CASE("SPALeRASGDCallbacksFullFunctionTest", "[CallbacksTest]")
{
SPALeRASGD<> optimizer(0.05, 30, 2000, 1e-4);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SPSA).
*/
TEST_CASE("SPSACallbacksFullFunctionTest", "[CallbacksTest]")
{
SPSA optimizer(0.1, 0.102, 0.16, 0.3, 10, 0);
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SVRG).
*/
TEST_CASE("SVRGCallbacksFullFunctionTest", "[CallbacksTest]")
{
SVRG optimizer(0.005, 2, 4, 0, 1e-5, true);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SWATS).
*/
TEST_CASE("SWATSCallbacksFullFunctionTest", "[CallbacksTest]")
{
SWATS optimizer(0.01, 10, 0.9, 0.999, 1e-6, 1000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (WNGrad).
*/
TEST_CASE("WNGradCallbacksFullFunctionTest", "[CallbacksTest]")
{
WNGrad optimizer(0.56, 1, 1000, 1e-9, true);
CallbacksFullFunctionTest(optimizer, true, true, true, true, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (ParallelSGD).
*/
TEST_CASE("ParallelSGDCallbacksFullFunctionTest", "[CallbacksTest]")
{
ConstantStep decayPolicy(0.4);
ParallelSGD<ConstantStep> optimizer(4, 2, 1e-5, true, decayPolicy);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (LBestPSO).
*/
TEST_CASE("LBestPSOCallbacksFullFunctionTest", "[CallbacksTest]")
{
LBestPSO optimizer;
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (L_BFGS).
*/
TEST_CASE("L_BFGSCallbacksFullFunctionTest", "[CallbacksTest]")
{
L_BFGS optimizer(10, 4);
CallbacksFullFunctionTest(optimizer, true, true, false, false, true, true,
false, false, true);
}
/**
* Make sure we invoke all callbacks (SA).
*/
TEST_CASE("SACallbacksFullFunctionTest", "[CallbacksTest]")
{
ExponentialSchedule schedule;
SA<> optimizer(schedule, 10, 1000., 1000, 100, 1e-11, 3, 1.5, 0.3, 0.3);
CallbacksFullFunctionTest(optimizer, true, false, false, false, true, true,
false, false, true);
}
/**
* Make sure the EarlyStopAtMinLoss callback will stop the optimization process.
*/
TEST_CASE("EarlyStopAtMinLossCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
// Instantiate the optimizer with a number of iterations that will take a
// long time to finish.
StandardSGD s(0.0003, 1, 2000000000, -10);
s.ExactObjective() = true;
// The optimization process should return in one second.
const double result = s.Optimize(f, coordinates, EarlyStopAtMinLoss(100));
REQUIRE(result == Approx(-1.0).epsilon(0.0005));
REQUIRE(coordinates(0) == Approx(0.0).margin(1e-3));
REQUIRE(coordinates(1) == Approx(0.0).margin(1e-7));
REQUIRE(coordinates(2) == Approx(0.0).margin(1e-7));
}
/**
* Make sure the PrintLoss callback will print the loss to the specified
* output stream.
*/
TEST_CASE("PrintLossCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 10, 1e-9, true);
std::stringstream stream;
s.Optimize(f, coordinates, PrintLoss(stream));
REQUIRE(stream.str().length() > 0);
}
/**
* Make sure the ProgressBar callback will show the progress on the specified
* output stream.
*/
TEST_CASE("ProgressBarCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 10, 1e-9, true);
std::stringstream stream;
s.Optimize(f, coordinates, ProgressBar(10, stream));
REQUIRE(stream.str().length() > 0);
}
/**
* Make sure the StoreBestCoordinates callback will store the best coordinates
* and objective.
*/
TEST_CASE("StoreBestCoordinatesCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 5000000, 1e-9, true);
StoreBestCoordinates<decltype(coordinates)> cb;
const double result = s.Optimize(f, coordinates, cb);
REQUIRE(cb.BestObjective() <= result);
REQUIRE(cb.BestObjective() == Approx(-1.0).epsilon(0.0005));
REQUIRE(cb.BestCoordinates()(0) == Approx(0.0).margin(1e-3));
REQUIRE(cb.BestCoordinates()(1) == Approx(0.0).margin(1e-7));
}
/**
* Make sure the TimerStop callback will stop the optimization process.
*/
TEST_CASE("TimerStopCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
// Instantiate the optimizer with a number of iterations that will take a
// long time to finish.
Adam opt(0.5, 2, 0.7, 0.999, 1e-8, 2000000000, -100, false);
arma::wall_clock timer;
timer.tic();
// The optimization process should return in one second.
opt.Optimize(f, coordinates, TimerStop(0.5));
// Add some time to account for the function to return.
REQUIRE(timer.toc() < 2);
}
/**
* Make sure the ProgressBar callback will show the progress on the specified
* output stream if the MaxIterations parameter of the optimizer is 0.
*/
TEST_CASE("ProgressBarCallbackNoMaxIterationsTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 0, DBL_MAX, true);
std::stringstream stream;
s.Optimize(f, coordinates, ProgressBar(10, stream));
REQUIRE(stream.str().length() > 0);
}
/**
* Make sure the ProgressBar callback will show the progress on the specified
* output stream with the correct epoch number if the MaxIterations parameter
* of the optimizer is 0.
*/
TEST_CASE("ProgressBarCallbackNoMaxIterationsEpochTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 0, DBL_MAX, true);
std::stringstream stream;
s.Optimize(f, coordinates, ProgressBar(10, stream));
REQUIRE(stream.str().find("Epoch 1") != std::string::npos);
REQUIRE(stream.str().find("Epoch 1/") == std::string::npos);
}
/**
* Make sure the ProgressBar callback will show the progress on the specified
* output stream with the correct epoch number if the MaxIterations parameter
* of the optimizer is not equal to 0.
*/
TEST_CASE("ProgressBarCallbackEpochTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 1, 1e-9, true);
std::stringstream stream;
s.Optimize(f, coordinates, ProgressBar(10, stream));
REQUIRE(stream.str().find("Epoch 1/1") != std::string::npos);
}
/**
* Make sure the Report callback will show the report on the specified
* output stream.
*/
TEST_CASE("ReportCallbackTest", "[CallbacksTest]")
{
std::stringstream stream;
SGDTestFunction f0;
StandardSGD s(0.0003, 1, 10000, 1e-9, true);
arma::mat coordinates = f0.GetInitialPoint();
s.Optimize(f0, coordinates, Report(0.1, stream));
REQUIRE(stream.str().length() > 0);
stream.str("");
RosenbrockWoodFunction f1;
L_BFGS lbfgs;
lbfgs.MaxIterations() = 100;
coordinates = f1.GetInitialPoint();
lbfgs.Optimize(f1, coordinates, Report(0.1, stream));
REQUIRE(stream.str().length() > 0);
stream.str("");
SchafferFunctionN2 f2;
CNE cne;
cne.MaxGenerations() = 100;
coordinates = f2.GetInitialPoint();
cne.Optimize(f2, coordinates, Report(0.1, stream));
REQUIRE(stream.str().length() > 0);
stream.str("");
AugLagrangianTestFunction f3;
AugLagrangian aug;
coordinates = f3.GetInitialPoint();
aug.Optimize(f3, coordinates, Report(0.1, stream));
REQUIRE(stream.str().length() > 0);
}
/**
* Make sure the GradClipByNorm callback will clip the gradient.
*/
TEST_CASE("GradClipByNormCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 10, 1e-9, true);
std::stringstream stream;
s.Optimize(f, coordinates, GradClipByNorm(0.5), Report(0.1, stream));
// We don't store the gradient during the optimization process, so we use the
// output of the Report callback function to check if the gradient is
// clipped.
std::string line;
bool gradientInfo = false;
double gradient = 1;
while (std::getline(stream, line, '\n'))
{
if (gradientInfo)
{
size_t iter;
double loss, lossChange, stepSize, totalTime;
std::stringstream stream(line);
stream >> iter >> loss >> lossChange >> gradient >> stepSize >> totalTime;
break;
}
gradientInfo = line.find("|gradient|") != std::string::npos;
}
REQUIRE(gradient == 0.5);
}
/**
* Make sure the GradClipByValue callback will clip the gradient.
*/
TEST_CASE("GradClipByValueCallbackTest", "[CallbacksTest]")
{
SGDTestFunction f;
arma::mat coordinates = f.GetInitialPoint();
StandardSGD s(0.0003, 1, 10, 1e-9, true);
std::stringstream stream;
s.Optimize(f, coordinates, GradClipByValue(0, 0), Report(0.1, stream));
// We don't store the gradient during the optimization process, so we use the
// output of the Report callback function to check if the gradient is
// clipped.
std::string line;
bool gradientInfo = false;
double gradient = 1;
while (std::getline(stream, line, '\n'))
{
if (gradientInfo)
{
size_t iter;
double loss, lossChange, stepSize, totalTime;
std::stringstream stream(line);
stream >> iter >> loss >> lossChange >> gradient >> stepSize >> totalTime;
break;
}
gradientInfo = line.find("|gradient|") != std::string::npos;
}
REQUIRE(gradient == 0);
}