Add MultiSplit tests that ensure that tree learns obvious patterns in data

This commit is contained in:
Rishabh Garg
2021-07-12 10:32:56 +05:30
parent 8d8687a928
commit b7d2f22bdc
+105 -99
View File
@@ -26,6 +26,48 @@ using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::distribution;
/**
* Creates dataset with 5 groups with all the points in same group have exactly
* same label.
*/
void CreateMultiSplitData(arma::mat& d, arma::rowvec& l, const size_t count,
arma::rowvec& values)
{
d = arma::mat(10, count, arma::fill::randu);
l = arma::rowvec(count);
// Group 1.
for (size_t i = 0; i < count / 5; i++)
{
d(3, i) = i;
l(i) = values[0];
}
// Group 2.
for (size_t i = count / 5; i < (count / 5) * 2; i++)
{
d(3, i) = i;
l(i) = values[1];
}
// Group 3.
for (size_t i = (count / 5) * 2; i < (count / 5) * 3; i++)
{
d(3, i) = i;
l(i) = values[2];
}
// Group 4.
for (size_t i = (count / 5) * 3; i < (count / 5) * 4; i++)
{
d(3, i) = i;
l(i) = values[3];
}
// Group 5.
for (size_t i = (count / 5) * 4; i < count; i++)
{
d(3, i) = i;
l(i) = values[4];
}
}
/**
* Make sure the MSE gain is zero when the labels are perfect.
*/
@@ -899,139 +941,103 @@ TEST_CASE("SimpleGeneralizationTest_", "[DecisionTreeRegressorTest]")
// REQUIRE(mse == Approx(0.0).epsilon(1e-4));
// }
TEST_CASE("multisplittest", "[DecisionTreeRegressorTest]")
/**
* Test that the tree is able to perfectly fit all the obvious splits present
* in the data.
*
* |
* |
* 2 | xxxxxx
* |
* |
* 1 | xxxxxx xxxxxx
* |
* |
* 0 |xxxxxx xxxxxx
* |___________________________________
*/
TEST_CASE("MultiSplitTest1", "[DecisionTreeRegressorTest]")
{
arma::mat dataset(10, 500, arma::fill::randu);
arma::Row<double> labels(500);
arma::mat dataset;
arma::rowvec labels;
arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0};
for (size_t i = 0; i < 100; i++)
{
dataset(3, i) = i;
labels(i) = 0.0;
}
for (size_t i = 100; i < 200; i++)
{
dataset(3, i) = i;
labels(i) = 1.0;
}
for (size_t i = 200; i < 300; i++)
{
dataset(3, i) = i;
labels(i) = 2.0;
}
for (size_t i = 300; i < 400; i++)
{
dataset(3, i) = i;
labels(i) = 1.0;
}
for (size_t i = 400; i < 500; i++)
{
dataset(3, i) = i;
labels(i) = 0.0;
}
CreateMultiSplitData(dataset, labels, 1000, values);
arma::rowvec weights(labels.n_elem);
weights.ones();
// Minimum leaf size of 1.
std::cout << "****************Start**************\n";
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20);
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0);
arma::rowvec preds;
d.Predict(dataset, preds);
const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem;
REQUIRE(mse == Approx(0.0).epsilon(1e-4));
std::cout << "****************End****************\n";
for (size_t i = 0; i < labels.n_elem; ++i)
REQUIRE(preds[i] == labels[i]);
}
TEST_CASE("multisplittest1", "[DecisionTreeRegressorTest]")
/**
* Test that the tree is able to perfectly fit all the obvious splits present
* in the data. Same test as above, but with less data.
*/
TEST_CASE("MultiSplitTest2", "[DecisionTreeRegressorTest]")
{
arma::mat dataset(10, 250, arma::fill::randu);
arma::Row<double> labels(500);
arma::mat dataset;
arma::rowvec labels;
arma::rowvec values = {0.0, 1.0, 2.0, 1.0, 0.0};
for (size_t i = 0; i < 50; i++)
{
dataset(3, i) = i;
labels(i) = 0.0;
}
for (size_t i = 50; i < 100; i++)
{
dataset(3, i) = i;
labels(i) = 1.0;
}
for (size_t i = 100; i < 150; i++)
{
dataset(3, i) = i;
labels(i) = 2.0;
}
for (size_t i = 150; i < 200; i++)
{
dataset(3, i) = i;
labels(i) = 1.0;
}
for (size_t i = 200; i < 250; i++)
{
dataset(3, i) = i;
labels(i) = 0.0;
}
CreateMultiSplitData(dataset, labels, 100, values);
arma::rowvec weights(labels.n_elem);
weights.ones();
// Minimum leaf size of 1.
std::cout << "****************Start**************\n";
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20);
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0);
arma::rowvec preds;
d.Predict(dataset, preds);
const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem;
REQUIRE(mse == Approx(0.0).epsilon(1e-4));
std::cout << "****************End****************\n";
for (size_t i = 0; i < labels.n_elem; ++i)
REQUIRE(preds[i] == labels[i]);
}
TEST_CASE("multisplittest2", "[DecisionTreeRegressorTest]")
/**
* Test that the tree is able to perfectly fit all the obvious splits present
* in the data.
*
* |
* 20 | xxxxxx
* |
* |
* 15 | xxxxxx
* |
* |
* 10 | xxxxxx
* |
* |
* 5 | xxxxxx
* |
* |
* 0 |xxxxxx
* |________________________________________
*/
TEST_CASE("MultiSplitTest3", "[DecisionTreeRegressorTest]")
{
arma::mat dataset(10, 500, arma::fill::randu);
arma::Row<double> labels(500);
arma::mat dataset;
arma::Row<double> labels;
arma::rowvec values = {0.0, 5.0, 10.0, 15.0, 20.0};
for (size_t i = 0; i < 100; i++)
{
dataset(3, i) = i;
labels(i) = 0.0;
}
for (size_t i = 100; i < 200; i++)
{
dataset(3, i) = i;
labels(i) = 5.0;
}
for (size_t i = 200; i < 300; i++)
{
dataset(3, i) = i;
labels(i) = 10.0;
}
for (size_t i = 300; i < 400; i++)
{
dataset(3, i) = i;
labels(i) = 15.0;
}
for (size_t i = 400; i < 500; i++)
{
dataset(3, i) = i;
labels(i) = 20.0;
}
CreateMultiSplitData(dataset, labels, 500, values);
arma::rowvec weights(labels.n_elem);
weights.ones();
// Minimum leaf size of 1.
std::cout << "****************Start**************\n";
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0, 20);
DecisionTreeRegressor<> d(dataset, labels, weights, 2, 0.0);
arma::rowvec preds;
d.Predict(dataset, preds);
const double mse = arma::accu(arma::square(preds - labels)) / preds.n_elem;
REQUIRE(mse == Approx(0.0).epsilon(1e-4));
std::cout << "****************End****************\n";
for (size_t i = 0; i < labels.n_elem; ++i)
REQUIRE(preds[i] == labels[i]);
}
TEST_CASE("handmadedata", "[DecisionTreeRegressorTest]")