Skip to content

Commit c6cda5f

Browse files
authored
[6.4][ML] Correct the multimodal prior confidence interval calculation (#178)
Backport of #176.
1 parent 413d412 commit c6cda5f

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

docs/CHANGELOG.asciidoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ Fix corner case failing to calculate lgamma values and the correspoinding log er
5050
Influence count per bucket for metric population analyses was wrong and lead to wrong influencer scoring ({pull}#150[#150])
5151
Fix a possible SIGSEGV for jobs with multivariate by fields enabled which would lead to the job failing ({pull}#170[#170])
5252

53+
Correct the model bounds and typical value calculation for time series models which use a multimodal distribution.
54+
This issue could cause "Unable to bracket left percentile =..." errors to appear in the logs. ({pull}#176[#176])
55+
5356
=== Regressions
5457

5558
=== Known Issues

include/maths/CMultimodalPriorUtils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ class MATHS_EXPORT CMultimodalPriorUtils : private core::CNonInstantiatable {
206206
return support;
207207
}
208208

209-
double p1 = std::log((1.0 - percentage) / 2.0);
210-
double p2 = std::log((1.0 + percentage) / 2.0);
209+
double p1 = maths_t::count(weights) * std::log((1.0 - percentage) / 2.0);
210+
double p2 = maths_t::count(weights) * std::log((1.0 + percentage) / 2.0);
211211

212212
CLogCdf<PRIOR> fl(CLogCdf<PRIOR>::E_Lower, prior, weights);
213213
CLogCdf<PRIOR> fu(CLogCdf<PRIOR>::E_Upper, prior, weights);

lib/maths/unittest/CMultimodalPriorTest.cc

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -941,10 +941,10 @@ void CMultimodalPriorTest::testMarginalLikelihoodConfidenceInterval() {
941941

942942
using TMeanAccumulator = maths::CBasicStatistics::SSampleMean<double>::TAccumulator;
943943

944+
test::CRandomNumbers rng;
945+
944946
LOG_DEBUG(<< "Synthetic");
945947
{
946-
test::CRandomNumbers rng;
947-
948948
double w1 = 0.2;
949949
double location1 = 0.1;
950950
double squareScale1 = 0.2;
@@ -1047,6 +1047,33 @@ void CMultimodalPriorTest::testMarginalLikelihoodConfidenceInterval() {
10471047
CPPUNIT_ASSERT_DOUBLES_EQUAL(-111.0, i90.first, 0.5);
10481048
CPPUNIT_ASSERT_DOUBLES_EQUAL(158952.0, i90.second, 0.5);
10491049
}
1050+
1051+
LOG_DEBUG(<< "Non-unit count weight");
1052+
{
1053+
// The confidence interval should be independent of the sample
1054+
// count weight.
1055+
1056+
TDoubleVec modes[2];
1057+
rng.generateNormalSamples(10.0, 2.0, 50, modes[0]);
1058+
rng.generateNormalSamples(20.0, 2.0, 50, modes[1]);
1059+
TDoubleVec samples(modes[0].begin(), modes[0].end());
1060+
samples.insert(samples.end(), modes[1].begin(), modes[1].end());
1061+
1062+
CMultimodalPrior filter(makePrior());
1063+
filter.addSamples(samples);
1064+
1065+
CPPUNIT_ASSERT_EQUAL(std::size_t(2), filter.numberModes());
1066+
1067+
TDoubleDoublePr interval{filter.marginalLikelihoodConfidenceInterval(
1068+
90.0, maths_t::countWeight(1.0))};
1069+
TDoubleDoublePr weightedInterval{filter.marginalLikelihoodConfidenceInterval(
1070+
90.0, maths_t::countWeight(0.3))};
1071+
LOG_DEBUG(<< "interval = " << core::CContainerPrinter::print(interval));
1072+
LOG_DEBUG(<< "weightedInterval = "
1073+
<< core::CContainerPrinter::print(weightedInterval));
1074+
CPPUNIT_ASSERT_EQUAL(core::CContainerPrinter::print(interval),
1075+
core::CContainerPrinter::print(weightedInterval));
1076+
}
10501077
}
10511078

10521079
void CMultimodalPriorTest::testSampleMarginalLikelihood() {

0 commit comments

Comments
 (0)