From d41aab4f6150dd8585efe33163dfbc8ff10613dd Mon Sep 17 00:00:00 2001 From: AbdealiJK Date: Sat, 3 Dec 2016 14:06:51 +0530 Subject: [PATCH] tests/cpp: Add tests for regression_obj.cc Test the objective functions in regression_obj.cc tests/cpp: Add tests for objective.cc and RegLossObj --- tests/cpp/helpers.cc | 25 ++++++++ tests/cpp/helpers.h | 11 ++++ tests/cpp/objective/test_objective.cc | 9 +++ tests/cpp/objective/test_regression_obj.cc | 67 ++++++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 tests/cpp/objective/test_objective.cc create mode 100644 tests/cpp/objective/test_regression_obj.cc diff --git a/tests/cpp/helpers.cc b/tests/cpp/helpers.cc index 24dee0c06..31349b3ab 100644 --- a/tests/cpp/helpers.cc +++ b/tests/cpp/helpers.cc @@ -24,3 +24,28 @@ std::string CreateSimpleTestData() { fo.close(); return tmp_file; } + +void CheckObjFunction(xgboost::ObjFunction * obj, + std::vector preds, + std::vector labels, + std::vector weights, + std::vector out_grad, + std::vector out_hess) { + xgboost::MetaInfo info; + info.num_row = labels.size(); + info.labels = labels; + info.weights = weights; + + std::vector gpair; + obj->GetGradient(preds, info, 1, &gpair); + + ASSERT_EQ(gpair.size(), preds.size()); + for (int i = 0; i < gpair.size(); ++i) { + EXPECT_NEAR(gpair[i].grad, out_grad[i], 0.01) + << "Unexpected grad for pred=" << preds[i] << " label=" << labels[i] + << " weight=" << weights[i]; + EXPECT_NEAR(gpair[i].hess, out_hess[i], 0.01) + << "Unexpected hess for pred=" << preds[i] << " label=" << labels[i] + << " weight=" << weights[i]; + } +} diff --git a/tests/cpp/helpers.h b/tests/cpp/helpers.h index 1d842a4c5..41945e3aa 100644 --- a/tests/cpp/helpers.h +++ b/tests/cpp/helpers.h @@ -5,11 +5,15 @@ #include #include #include +#include #include #include #include +#include +#include + std::string TempFileName(); bool FileExists(const std::string name); @@ -18,4 +22,11 @@ long GetFileSize(const std::string filename); std::string CreateSimpleTestData(); +void CheckObjFunction(xgboost::ObjFunction * obj, + std::vector preds, + std::vector labels, + std::vector weights, + std::vector out_grad, + std::vector out_hess); + #endif diff --git a/tests/cpp/objective/test_objective.cc b/tests/cpp/objective/test_objective.cc new file mode 100644 index 000000000..28a01f622 --- /dev/null +++ b/tests/cpp/objective/test_objective.cc @@ -0,0 +1,9 @@ +// Copyright by Contributors +#include + +#include "../helpers.h" + +TEST(Objective, UnknownFunction) { + EXPECT_ANY_THROW(xgboost::ObjFunction::Create("unknown_name")); + EXPECT_NO_THROW(xgboost::ObjFunction::Create("reg:linear")); +} diff --git a/tests/cpp/objective/test_regression_obj.cc b/tests/cpp/objective/test_regression_obj.cc new file mode 100644 index 000000000..607055396 --- /dev/null +++ b/tests/cpp/objective/test_regression_obj.cc @@ -0,0 +1,67 @@ +// Copyright by Contributors +#include + +#include "../helpers.h" + +TEST(Objective, LinearRegressionGPair) { + xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:linear"); + std::vector > args; + obj->Configure(args); + CheckObjFunction(obj, + {0, 0.1, 0.9, 1, 0, 0.1, 0.9, 1}, + {0, 0, 0, 0, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1}, + {0, 0.1, 0.9, 1.0, -1.0, -0.9, -0.1, 0}, + {1, 1, 1, 1, 1, 1, 1, 1}); + + ASSERT_NO_THROW(obj->DefaultEvalMetric()); +} + +TEST(Objective, LogisticRegressionGPair) { + xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic"); + std::vector > args; + obj->Configure(args); + CheckObjFunction(obj, + { 0, 0.1, 0.9, 1, 0, 0.1, 0.9, 1}, + { 0, 0, 0, 0, 1, 1, 1, 1}, + { 1, 1, 1, 1, 1, 1, 1, 1}, + { 0.5, 0.52, 0.71, 0.73, -0.5, -0.47, -0.28, -0.26}, + {0.25, 0.24, 0.20, 0.19, 0.25, 0.24, 0.20, 0.19}); +} + +TEST(Objective, LogisticRegressionBasic) { + xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic"); + std::vector > args; + obj->Configure(args); + + // test label validation + EXPECT_ANY_THROW(CheckObjFunction(obj, {0}, {10}, {1}, {0}, {0})) + << "Expected error when label not in range [0,1] for LogisticRegression"; + + // test ProbToMargin + EXPECT_NEAR(obj->ProbToMargin(0.1), -2.197, 0.01); + EXPECT_NEAR(obj->ProbToMargin(0.5), 0, 0.01); + EXPECT_NEAR(obj->ProbToMargin(0.9), 2.197, 0.01); + EXPECT_ANY_THROW(obj->ProbToMargin(10)) + << "Expected error when base_score not in range [0,1] for LogisticRegression"; + + // test PredTransform + std::vector preds = {0, 0.1, 0.5, 0.9, 1}; + std::vector out_preds = {0.5, 0.524, 0.622, 0.710, 0.731}; + obj->PredTransform(&preds); + for (int i = 0; i < preds.size(); ++i) { + EXPECT_NEAR(preds[i], out_preds[i], 0.01); + } +} + +TEST(Objective, LogisticRawGPair) { + xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("binary:logitraw"); + std::vector > args; + obj->Configure(args); + CheckObjFunction(obj, + { 0, 0.1, 0.9, 1, 0, 0.1, 0.9, 1}, + { 0, 0, 0, 0, 1, 1, 1, 1}, + { 1, 1, 1, 1, 1, 1, 1, 1}, + { 0.5, 0.52, 0.71, 0.73, -0.5, -0.47, -0.28, -0.26}, + {0.25, 0.24, 0.20, 0.19, 0.25, 0.24, 0.20, 0.19}); +}