From 7fb691279e2f15cd9f98c4f6a22524443fe846f1 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Mon, 16 Sep 2019 18:19:01 +0200 Subject: [PATCH 1/2] TM.anomaly: improve doc for anomaly modes --- src/htm/algorithms/TemporalMemory.cpp | 2 +- src/htm/algorithms/TemporalMemory.hpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/htm/algorithms/TemporalMemory.cpp b/src/htm/algorithms/TemporalMemory.cpp index 38d7b7cb8c..7d49d701fe 100644 --- a/src/htm/algorithms/TemporalMemory.cpp +++ b/src/htm/algorithms/TemporalMemory.cpp @@ -515,7 +515,7 @@ void TemporalMemory::compute(const SDR &activeColumns, cellsToColumns( getPredictiveCells() )); const Real like = tmAnomaly_.anomalyLikelihood_.anomalyProbability(raw); const Real log = tmAnomaly_.anomalyLikelihood_.computeLogLikelihood(like); - tmAnomaly_.anomaly_ = log; + tmAnomaly_.anomaly_ = log; //TODO loglike is `log(1 - likelihood)/log(epsilon)`, should we return 1-loglike to be consistent with "anomalies"? (high score for anomalous inputs). } break; // TODO: Update mean & standard deviation of anomaly here. }; diff --git a/src/htm/algorithms/TemporalMemory.hpp b/src/htm/algorithms/TemporalMemory.hpp index 4eedb4f8e2..fa8ab58a26 100644 --- a/src/htm/algorithms/TemporalMemory.hpp +++ b/src/htm/algorithms/TemporalMemory.hpp @@ -688,8 +688,23 @@ class TemporalMemory : public Serializable * anomaly score computed for the current inputs * (auto-updates after each call to TM::compute()) * - * @return a float value from computeRawAnomalyScore() - * from Anomaly.hpp + * Note, if you use manual learning methods for TM (activateDendrites, etc.) the scores + * will not be in sync (works only if `TM.compute` is used). + * + * Options `ANMode` {DISABLED, RAW, LIKELIHOOD, LOGLIKELIHOOD} passed during constructor + * of this class affect the computation of anomaly here. + * - "DISABLED": always returns 0.5f, no computation is performed (use if you don't care for anomaly + * and need maximum speed). + * - "RAW": return value from `computeRawAnomalyScore()` from `Anomaly.hpp`, default. + * - "LIKELIHOOD": Compute the probability that the current anomaly score represents + * an anomaly given the historical distribution of anomaly scores. The closer + * the number is to 1, the higher the chance it is an anomaly. + * Computed from `anomalyProbability()` in `AnomalyLikelihood.hpp`. + * - "LOGLIKELIHOOD": Compute a log scale representation of the likelihood value. This mode performs + * `computeLogLikelihood()` from `AnomalyLikelihood.hpp` + * + * @return a float value based on `ANMode` argument used in constructor of the TM class. + * By default return value from `computeRawAnomalyScore()` from `Anomaly.hpp` */ const Real &anomaly = tmAnomaly_.anomaly_; //this is position dependant, the struct anomaly_tm must be defined before this use, // otherwise this surprisingly compiles, but a call to `tmAnomaly_.anomaly` segfaults! From 9e0245f39ef0010583f9d2bce4fd38c6b161bc49 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 18 Sep 2019 10:51:44 +0200 Subject: [PATCH 2/2] TM.anomaly: fix scores for likelihoods we returned likelihoods, but TM.anomaly should return anomaly scores, thus we need to return 1.0-likelihood Thanks @Thanh-Binh for reporting this issue! --- src/htm/algorithms/TemporalMemory.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/htm/algorithms/TemporalMemory.cpp b/src/htm/algorithms/TemporalMemory.cpp index 7d49d701fe..655a3e6314 100644 --- a/src/htm/algorithms/TemporalMemory.cpp +++ b/src/htm/algorithms/TemporalMemory.cpp @@ -506,7 +506,8 @@ void TemporalMemory::compute(const SDR &activeColumns, const Real raw = computeRawAnomalyScore( activeColumns, cellsToColumns( getPredictiveCells() )); - tmAnomaly_.anomaly_ = tmAnomaly_.anomalyLikelihood_.anomalyProbability(raw); + tmAnomaly_.anomaly_ = 1.0f - tmAnomaly_.anomalyLikelihood_.anomalyProbability(raw); // AnomalyLikelihood returs a likelihood of the score (given past scores), + // and we want to detect unlikely scores, aka big changes -> 1.0-likelihood represents "anomaly" } break; case ANMode::LOGLIKELIHOOD: { @@ -515,7 +516,7 @@ void TemporalMemory::compute(const SDR &activeColumns, cellsToColumns( getPredictiveCells() )); const Real like = tmAnomaly_.anomalyLikelihood_.anomalyProbability(raw); const Real log = tmAnomaly_.anomalyLikelihood_.computeLogLikelihood(like); - tmAnomaly_.anomaly_ = log; //TODO loglike is `log(1 - likelihood)/log(epsilon)`, should we return 1-loglike to be consistent with "anomalies"? (high score for anomalous inputs). + tmAnomaly_.anomaly_ = 1.0f - log; } break; // TODO: Update mean & standard deviation of anomaly here. };