Skip to content

Commit fcd5085

Browse files
authored
[ML] Fix possible cause for "Bad variance scale nan" log errors (#1229)
Backport #1225.
1 parent c5608f2 commit fcd5085

File tree

4 files changed

+27
-11
lines changed

4 files changed

+27
-11
lines changed

docs/CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
{ml-pull}1197[#1197].)
8181
* Improve the initialization of seasonal components for anomaly detection. (See
8282
{ml-pull}1201[#1201], issue: {ml-issue}#1178[#1178].)
83+
* Fix possible root cause for "Bad variance scale nan" log errors. (See {ml-pull}1225[#1225].)
8384

8485
== {es} version 7.7.1
8586

lib/maths/CAdaptiveBucketing.cc

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ bool CAdaptiveBucketing::initialize(double a, double b, std::size_t n) {
246246
void CAdaptiveBucketing::initialValues(core_t::TTime start,
247247
core_t::TTime end,
248248
const TFloatMeanAccumulatorVec& values) {
249-
if (!this->initialized()) {
249+
if (this->initialized() == false) {
250250
return;
251251
}
252252

@@ -406,7 +406,7 @@ void CAdaptiveBucketing::refine(core_t::TTime time) {
406406
LOG_TRACE(<< "totalAveragingError = " << totalAveragingError);
407407

408408
double n_{static_cast<double>(n)};
409-
double step{(1 - n_ * EPS) * totalAveragingError / n_};
409+
double step{(1.0 - n_ * EPS) * totalAveragingError / n_};
410410
TFloatVec endpoints{m_Endpoints};
411411
LOG_TRACE(<< "step = " << step);
412412

@@ -505,7 +505,7 @@ bool CAdaptiveBucketing::knots(core_t::TTime time,
505505
double a{m_Endpoints[i]};
506506
double b{m_Endpoints[i + 1]};
507507
double c{m_Centres[i]};
508-
double c0{c};
508+
double c0{c - m_Endpoints[0]};
509509
knots.push_back(m_Endpoints[0]);
510510
values.push_back(this->predict(i, time, c));
511511
variances.push_back(this->variance(i));
@@ -549,26 +549,37 @@ bool CAdaptiveBucketing::knots(core_t::TTime time,
549549
double alpha{m_Endpoints[n] - m_Centres[j]};
550550
double beta{c0};
551551
double Z{alpha + beta};
552+
if (Z == 0.0) {
553+
alpha = beta = 0.5;
554+
} else {
555+
alpha /= Z;
556+
beta /= Z;
557+
}
552558
double lastPeriodValue{
553559
this->predict(j, time, m_Centres[j] - m_Endpoints[n])};
554560
double lastPeriodVariance{this->variance(j)};
555561
knots[0] = m_Endpoints[0];
556-
values[0] = (alpha * values[0] + beta * lastPeriodValue) / Z;
557-
variances[0] = (alpha * variances[0] + beta * lastPeriodVariance) / Z;
562+
values[0] = alpha * values[0] + beta * lastPeriodValue;
563+
variances[0] = alpha * variances[0] + beta * lastPeriodVariance;
558564
break;
559565
}
560566
}
561-
for (std::size_t j = 0u; j < n; ++j) {
567+
for (std::size_t j = 0; j < n; ++j) {
562568
if (this->bucketCount(j) > 0.0) {
563569
double alpha{m_Centres[j]};
564570
double beta{m_Endpoints[n] - knots.back()};
565571
double Z{alpha + beta};
572+
if (Z == 0.0) {
573+
alpha = beta = 0.5;
574+
} else {
575+
alpha /= Z;
576+
beta /= Z;
577+
}
566578
double nextPeriodValue{
567579
this->predict(j, time, m_Endpoints[n] + m_Centres[j])};
568580
double nextPeriodVariance{this->variance(j)};
569-
values.push_back((alpha * values.back() + beta * nextPeriodValue) / Z);
570-
variances.push_back(
571-
(alpha * variances.back() + beta * nextPeriodVariance) / Z);
581+
values.push_back(alpha * values.back() + beta * nextPeriodValue);
582+
variances.push_back(alpha * variances.back() + beta * nextPeriodVariance);
572583
knots.push_back(m_Endpoints[n]);
573584
break;
574585
}

lib/maths/CCalendarComponentAdaptiveBucketing.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ void CCalendarComponentAdaptiveBucketing::refresh(const TFloatVec& oldEndpoints)
276276
static_cast<double>(oldCentres[l - 1]));
277277
largeErrorCount += w * oldLargeErrorCounts[l - 1];
278278
count += w * w * CBasicStatistics::count(m_Values[l - 1]);
279-
double scale{count / CBasicStatistics::count(value)};
279+
// Defend against 0 / 0: if CBasicStatistics::count(value)
280+
// is zero then count must be too.
281+
double scale{count == CBasicStatistics::count(value)
282+
? 1.0
283+
: count / CBasicStatistics::count(value)};
280284
newValues.push_back(CBasicStatistics::scaled(value, scale));
281285
newCentres.push_back(CTools::truncate(CBasicStatistics::mean(centre), yl, yr));
282286
newLargeErrorCounts.push_back(largeErrorCount);

lib/maths/CTimeSeriesDecomposition.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ TDoubleDoublePr CTimeSeriesDecomposition::scale(core_t::TTime time,
417417
}
418418

419419
double mean{this->meanVariance()};
420-
if (mean == 0.0) {
420+
if (mean == 0.0 || variance == 0.0) {
421421
return {1.0, 1.0};
422422
}
423423

0 commit comments

Comments
 (0)