in lib/maths/analytics/unittest/CBoostedTreeLeafNodeStatisticsTest.cc [82:200]
void testDerivativesFor(std::size_t numberParameters) {
LOG_DEBUG(<< "Testing " << numberParameters << " parameters");
test::CRandomNumbers rng;
std::size_t numberGradients{numberParameters};
std::size_t numberCurvatures{numberParameters * (numberParameters + 1) / 2};
TDoubleVecVec gradients(numberGradients);
TDoubleVecVec curvatures(numberCurvatures);
for (std::size_t i = 0; i < numberGradients; ++i) {
rng.generateUniformSamples(-1.0, 1.5, 20, gradients[i]);
}
for (std::size_t i = 0; i < numberCurvatures; ++i) {
rng.generateUniformSamples(0.1, 0.5, 20, curvatures[i]);
}
LOG_DEBUG(<< "Accumulate");
std::size_t paddedNumberGradients{core::CAlignment::roundup<double>(
core::CAlignment::E_Aligned16, numberGradients)};
TAlignedDoubleVec storage1(
paddedNumberGradients + numberGradients * numberGradients + 1, 0.0);
TAlignedDoubleVec storage1Plus2(
paddedNumberGradients + numberGradients * numberGradients + 1, 0.0);
TDerivatives derivatives1(static_cast<int>(numberParameters), storage1.data(),
storage1.data() + paddedNumberGradients,
storage1.data() + storage1.size() - 1);
TDerivatives derivatives1Plus2(static_cast<int>(numberParameters),
storage1Plus2.data(),
storage1Plus2.data() + paddedNumberGradients,
storage1Plus2.data() + storage1Plus2.size() - 1);
for (std::size_t j = 0; j < 10; ++j) {
TAlignedFloatVec rowStorage;
for (std::size_t i = 0; i < numberGradients; ++i) {
rowStorage.push_back(gradients[i][j]);
}
for (std::size_t i = 0; i < numberCurvatures; ++i) {
rowStorage.push_back(curvatures[i][j]);
}
auto derivatives = makeAlignedVector<Eigen::Aligned16>(
rowStorage.data(), numberGradients + numberCurvatures);
derivatives1.add(1, derivatives);
derivatives1Plus2.add(1, derivatives);
}
derivatives1.remapCurvature();
BOOST_REQUIRE_EQUAL(10, derivatives1.count());
for (std::size_t i = 0; i < numberGradients; ++i) {
BOOST_REQUIRE_CLOSE(
std::accumulate(gradients[i].begin(), gradients[i].begin() + 10, 0.0),
derivatives1.gradient()(i), 1e-4);
}
for (std::size_t j = 0, k = 0; j < numberGradients; ++j) {
for (std::size_t i = j; i < numberGradients; ++i, ++k) {
BOOST_REQUIRE_CLOSE(std::accumulate(curvatures[k].begin(),
curvatures[k].begin() + 10, 0.0),
derivatives1.curvature()(i, j), 1e-4);
}
}
LOG_DEBUG(<< "Merge");
TAlignedDoubleVec storage2(
paddedNumberGradients + numberGradients * numberGradients + 1, 0.0);
TDerivatives derivatives2(static_cast<int>(numberParameters), storage2.data(),
storage2.data() + paddedNumberGradients,
storage2.data() + storage2.size() - 1);
for (std::size_t j = 10; j < 20; ++j) {
TAlignedFloatVec storage;
for (std::size_t i = 0; i < numberGradients; ++i) {
storage.push_back(gradients[i][j]);
}
for (std::size_t i = 0; i < numberCurvatures; ++i) {
storage.push_back(curvatures[i][j]);
}
auto derivatives = makeAlignedVector<Eigen::Aligned16>(
storage.data(), numberGradients + numberCurvatures);
derivatives2.add(1, derivatives);
}
derivatives1Plus2.add(derivatives2);
derivatives1Plus2.remapCurvature();
BOOST_REQUIRE_EQUAL(20, derivatives1Plus2.count());
for (std::size_t i = 0; i < numberGradients; ++i) {
BOOST_REQUIRE_CLOSE(std::accumulate(gradients[i].begin(), gradients[i].end(), 0.0),
derivatives1Plus2.gradient()(i), 1e-4);
}
for (std::size_t j = 0, k = 0; j < numberGradients; ++j) {
for (std::size_t i = j; i < numberGradients; ++i, ++k) {
BOOST_REQUIRE_CLOSE(
std::accumulate(curvatures[k].begin(), curvatures[k].end(), 0.0),
derivatives1Plus2.curvature()(i, j), 1e-4);
}
}
LOG_DEBUG(<< "Difference");
derivatives2.remapCurvature();
derivatives1Plus2.subtract(derivatives2);
BOOST_REQUIRE_EQUAL(10, derivatives1Plus2.count());
for (std::size_t i = 0; i < numberGradients; ++i) {
BOOST_REQUIRE_CLOSE(
std::accumulate(gradients[i].begin(), gradients[i].begin() + 10, 0.0),
derivatives1Plus2.gradient()(i), 1e-4);
}
for (std::size_t j = 0, k = 0; j < numberGradients; ++j) {
for (std::size_t i = j; i < numberGradients; ++i, ++k) {
BOOST_REQUIRE_CLOSE(std::accumulate(curvatures[k].begin(),
curvatures[k].begin() + 10, 0.0),
derivatives1Plus2.curvature()(i, j), 1e-4);
}
}
}