From 354a02513c0a6a654b28d07c95326fb2ca2a5518 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Tue, 30 Jul 2019 12:47:37 +0200 Subject: [PATCH 01/23] Disabled spatial anomaly leads to terrible score for HTMcore --- config/thresholds.json | 34 +++++++++++------------ nab/detectors/htmcore/htmcore_detector.py | 2 +- nab/detectors/numenta/numenta_detector.py | 2 +- results/final_results.json | 18 ++++++------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index f3099ebc1..41dd76b98 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -1.6511067861578468, - "threshold": 0.5014187204194446 + "score": -131.59491715795843, + "threshold": 0.4245631351291845 }, "reward_low_FP_rate": { - "score": 20.39992539458499, - "threshold": 0.5122987896930875 + "score": -61.26700105675802, + "threshold": 0.50773323457344 }, "standard": { - "score": 30.348893213842153, - "threshold": 0.5014187204194446 + "score": -53.862473972881986, + "threshold": 0.50773323457344 } }, "htmjava": { @@ -113,30 +113,30 @@ }, "numenta": { "reward_low_FN_rate": { - "score": 26.634450197137568, - "threshold": 0.5421876907348634 + "score": 26.634450197137596, + "threshold": 0.543099145074 }, "reward_low_FP_rate": { - "score": 30.431072517124093, - "threshold": 0.5751955032348636 + "score": 30.645309205798327, + "threshold": 0.543099145074 }, "standard": { "score": 46.634450197137596, - "threshold": 0.5421876907348634 + "threshold": 0.543099145074 } }, "numentaTM": { "reward_low_FN_rate": { - "score": 8.764037437134272, - "threshold": 0.5126953125 + "score": 9.428858702713455, + "threshold": 0.49424913259099995 }, "reward_low_FP_rate": { - "score": 15.463515082084744, - "threshold": 0.65076904296875 + "score": 15.463515082084768, + "threshold": 0.651047950287 }, "standard": { - "score": 33.76403743713426, - "threshold": 0.5126953125 + "score": 33.764037437134334, + "threshold": 0.512734098949 } }, "random": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 9b60412d1..abfc7ceff 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -248,7 +248,7 @@ def modelRun(self, ts, val): # handle spatial, contextual (raw, likelihood) anomalies # -Spatial spatialAnomaly = 0.0 #TODO optional: make this computed in SP (and later improve) - if self.useSpatialAnomaly: + if False and self.useSpatialAnomaly: # Update min/max values and check if there is a spatial anomaly if self.minVal != self.maxVal: tolerance = (self.maxVal - self.minVal) * SPATIAL_TOLERANCE diff --git a/nab/detectors/numenta/numenta_detector.py b/nab/detectors/numenta/numenta_detector.py index 782333ac1..87c6a023c 100644 --- a/nab/detectors/numenta/numenta_detector.py +++ b/nab/detectors/numenta/numenta_detector.py @@ -104,7 +104,7 @@ def handleRecord(self, inputData): else: finalScore = rawScore - if spatialAnomaly: + if False and spatialAnomaly: finalScore = 1.0 return (finalScore, rawScore) diff --git a/results/final_results.json b/results/final_results.json index 295cef20b..6904f9bdb 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 66.1922106936328, - "reward_low_FP_rate": 58.7930712907694, - "standard": 63.081419488725054 + "reward_low_FN_rate": 28.85203529943721, + "reward_low_FP_rate": 23.591809889328452, + "standard": 26.783416390999154 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, @@ -35,14 +35,14 @@ "standard": 0.0 }, "numenta": { - "reward_low_FN_rate": 74.3202443095115, - "reward_low_FP_rate": 63.11684160219828, - "standard": 70.10105611943965 + "reward_low_FN_rate": 74.32024430952228, + "reward_low_FP_rate": 63.20918500249927, + "standard": 70.10105611945585 }, "numentaTM": { - "reward_low_FN_rate": 69.18506822906035, - "reward_low_FP_rate": 56.665308225043105, - "standard": 64.55346441254311 + "reward_low_FN_rate": 69.37610882261879, + "reward_low_FP_rate": 56.665308225036526, + "standard": 64.55346441255789 }, "random": { "reward_low_FN_rate": 25.876351314080456, From a51f60dae4f81e82aedfb79338eded6a1cf13301 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 3 Aug 2019 15:13:29 +0200 Subject: [PATCH 02/23] Revert "Disabled spatial anomaly leads to terrible score for HTMcore" This reverts commit 354a02513c0a6a654b28d07c95326fb2ca2a5518. --- config/thresholds.json | 34 +++++++++++------------ nab/detectors/htmcore/htmcore_detector.py | 2 +- nab/detectors/numenta/numenta_detector.py | 2 +- results/final_results.json | 18 ++++++------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 41dd76b98..f3099ebc1 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -131.59491715795843, - "threshold": 0.4245631351291845 + "score": -1.6511067861578468, + "threshold": 0.5014187204194446 }, "reward_low_FP_rate": { - "score": -61.26700105675802, - "threshold": 0.50773323457344 + "score": 20.39992539458499, + "threshold": 0.5122987896930875 }, "standard": { - "score": -53.862473972881986, - "threshold": 0.50773323457344 + "score": 30.348893213842153, + "threshold": 0.5014187204194446 } }, "htmjava": { @@ -113,30 +113,30 @@ }, "numenta": { "reward_low_FN_rate": { - "score": 26.634450197137596, - "threshold": 0.543099145074 + "score": 26.634450197137568, + "threshold": 0.5421876907348634 }, "reward_low_FP_rate": { - "score": 30.645309205798327, - "threshold": 0.543099145074 + "score": 30.431072517124093, + "threshold": 0.5751955032348636 }, "standard": { "score": 46.634450197137596, - "threshold": 0.543099145074 + "threshold": 0.5421876907348634 } }, "numentaTM": { "reward_low_FN_rate": { - "score": 9.428858702713455, - "threshold": 0.49424913259099995 + "score": 8.764037437134272, + "threshold": 0.5126953125 }, "reward_low_FP_rate": { - "score": 15.463515082084768, - "threshold": 0.651047950287 + "score": 15.463515082084744, + "threshold": 0.65076904296875 }, "standard": { - "score": 33.764037437134334, - "threshold": 0.512734098949 + "score": 33.76403743713426, + "threshold": 0.5126953125 } }, "random": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index abfc7ceff..9b60412d1 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -248,7 +248,7 @@ def modelRun(self, ts, val): # handle spatial, contextual (raw, likelihood) anomalies # -Spatial spatialAnomaly = 0.0 #TODO optional: make this computed in SP (and later improve) - if False and self.useSpatialAnomaly: + if self.useSpatialAnomaly: # Update min/max values and check if there is a spatial anomaly if self.minVal != self.maxVal: tolerance = (self.maxVal - self.minVal) * SPATIAL_TOLERANCE diff --git a/nab/detectors/numenta/numenta_detector.py b/nab/detectors/numenta/numenta_detector.py index 87c6a023c..782333ac1 100644 --- a/nab/detectors/numenta/numenta_detector.py +++ b/nab/detectors/numenta/numenta_detector.py @@ -104,7 +104,7 @@ def handleRecord(self, inputData): else: finalScore = rawScore - if False and spatialAnomaly: + if spatialAnomaly: finalScore = 1.0 return (finalScore, rawScore) diff --git a/results/final_results.json b/results/final_results.json index 6904f9bdb..295cef20b 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 28.85203529943721, - "reward_low_FP_rate": 23.591809889328452, - "standard": 26.783416390999154 + "reward_low_FN_rate": 66.1922106936328, + "reward_low_FP_rate": 58.7930712907694, + "standard": 63.081419488725054 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, @@ -35,14 +35,14 @@ "standard": 0.0 }, "numenta": { - "reward_low_FN_rate": 74.32024430952228, - "reward_low_FP_rate": 63.20918500249927, - "standard": 70.10105611945585 + "reward_low_FN_rate": 74.3202443095115, + "reward_low_FP_rate": 63.11684160219828, + "standard": 70.10105611943965 }, "numentaTM": { - "reward_low_FN_rate": 69.37610882261879, - "reward_low_FP_rate": 56.665308225036526, - "standard": 64.55346441255789 + "reward_low_FN_rate": 69.18506822906035, + "reward_low_FP_rate": 56.665308225043105, + "standard": 64.55346441254311 }, "random": { "reward_low_FN_rate": 25.876351314080456, From d6023e3c452f666f629d1dcaf2df8f37b71870df Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 3 Aug 2019 15:18:43 +0200 Subject: [PATCH 03/23] Htmcore detector: remove artificial spatial-anomaly code which is "fake" and non-biological, not HTM related. Unfortunately, with the current settings the code affected the results the most. --- nab/detectors/htmcore/htmcore_detector.py | 31 ++--------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 9b60412d1..a2863616f 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -34,12 +34,6 @@ from nab.detectors.base import AnomalyDetector -# Fraction outside of the range of values seen so far that will be considered -# a spatial anomaly regardless of the anomaly likelihood calculation. This -# accounts for the human labelling bias for spatial values larger than what -# has been seen so far. -SPATIAL_TOLERANCE = 0.05 - parameters_numenta_comparable = { # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { @@ -96,7 +90,6 @@ def __init__(self, *args, **kwargs): # useful for checking the efficacy of AnomalyLikelihood. You will need # to re-optimize the thresholds when running with this setting. self.useLikelihood = True - self.useSpatialAnomaly = True self.verbose = True ## internal members @@ -138,11 +131,6 @@ def initialize(self): #parameters = default_parameters parameters = parameters_numenta_comparable - # setup spatial anomaly - if self.useSpatialAnomaly: - # Keep track of value range for spatial anomaly detection - self.minVal = None - self.maxVal = None ## setup Enc, SP, TM, Likelihood # Make the Encoders. These will convert input data into binary representations. @@ -245,22 +233,7 @@ def modelRun(self, ts, val): #TODO optional: also return an error metric on predictions (RMSE, R2,...) # 4.2 Anomaly - # handle spatial, contextual (raw, likelihood) anomalies - # -Spatial - spatialAnomaly = 0.0 #TODO optional: make this computed in SP (and later improve) - if self.useSpatialAnomaly: - # Update min/max values and check if there is a spatial anomaly - if self.minVal != self.maxVal: - tolerance = (self.maxVal - self.minVal) * SPATIAL_TOLERANCE - maxExpected = self.maxVal + tolerance - minExpected = self.minVal - tolerance - if val > maxExpected or val < minExpected: - spatialAnomaly = 1.0 - if self.maxVal is None or val > self.maxVal: - self.maxVal = val - if self.minVal is None or val < self.minVal: - self.minVal = val - + # handle contextual (raw, likelihood) anomalies # -temporal (raw) raw = self.tm.anomaly temporalAnomaly = raw @@ -271,7 +244,7 @@ def modelRun(self, ts, val): logScore = self.anomalyLikelihood.computeLogLikelihood(like) temporalAnomaly = logScore #TODO optional: TM to provide anomaly {none, raw, likelihood}, compare correctness with the py anomaly_likelihood - anomalyScore = max(spatialAnomaly, temporalAnomaly) # this is the "main" anomaly, compared in NAB + anomalyScore = temporalAnomaly # this is the "main" anomaly, compared in NAB # 5. print stats if self.verbose and self.iteration_ % 1000 == 0: From 3a0c513e28895ef42780acaea6d196681fc7eb4b Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 3 Aug 2019 16:57:01 +0200 Subject: [PATCH 04/23] WIP tuning score --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 23 ++++++++++++----------- results/final_results.json | 6 +++--- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index f3099ebc1..310bf9bb6 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -1.6511067861578468, - "threshold": 0.5014187204194446 + "score": -120.58759714271227, + "threshold": 0.50337314439962 }, "reward_low_FP_rate": { - "score": 20.39992539458499, - "threshold": 0.5122987896930875 + "score": -61.274883256439466, + "threshold": 0.5886281706634007 }, "standard": { - "score": 30.348893213842153, - "threshold": 0.5014187204194446 + "score": -49.58759714271227, + "threshold": 0.50337314439962 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index a2863616f..556a3cbc8 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -38,12 +38,13 @@ # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { "value" : # RDSE for value - {'resolution': 0.001, - 'size': 4000, + {'resolution': 0.9, + 'size': 800, 'sparsity': 0.10 }, "time": { # DateTime for timestamps - 'timeOfDay': (21, 9.49), + 'timeOfDay': (20, 1), + 'dayOfWeek': 80, 'weekend': 0 #21 TODO try impact of weekend }}, 'predictor': {'sdrc_alpha': 0.1}, @@ -52,13 +53,13 @@ 'columnCount': 2048, 'localAreaDensity': 40/2048, 'potentialPct': 0.4, - 'synPermActiveInc': 0.003, - 'synPermConnected': 0.2, - 'synPermInactiveDec': 0.0005}, + 'synPermActiveInc': 0.1, + 'synPermConnected': 0.5, + 'synPermInactiveDec': 0.05}, 'tm': { 'activationThreshold': 13, - 'cellsPerColumn': 32, - 'initialPerm': 0.21, + 'cellsPerColumn': 4, + 'initialPerm': 0.51, 'maxSegmentsPerCell': 128, 'maxSynapsesPerSegment': 32, 'minThreshold': 10, @@ -248,9 +249,9 @@ def modelRun(self, ts, val): # 5. print stats if self.verbose and self.iteration_ % 1000 == 0: - # print(self.enc_info) - # print(self.sp_info) - # print(self.tm_info) + print(self.enc_info) + print(self.sp_info) + print(self.tm_info) pass return (anomalyScore, raw) diff --git a/results/final_results.json b/results/final_results.json index 295cef20b..deb4955b9 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 66.1922106936328, - "reward_low_FP_rate": 58.7930712907694, - "standard": 63.081419488725054 + "reward_low_FN_rate": 32.01505829232405, + "reward_low_FP_rate": 23.58841238946575, + "standard": 28.626035714348134 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From ae2e699a719921665a153e9c9c451f354dec848e Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 3 Aug 2019 23:08:19 +0200 Subject: [PATCH 05/23] htmcore: added date-time encoder fields --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 13 ++++++++----- results/final_results.json | 6 +++--- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 310bf9bb6..2394b8e53 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -120.58759714271227, - "threshold": 0.50337314439962 + "score": -106.61798342124197, + "threshold": 0.5060424851490891 }, "reward_low_FP_rate": { - "score": -61.274883256439466, - "threshold": 0.5886281706634007 + "score": -61.80612018627088, + "threshold": 0.5683023049854312 }, "standard": { - "score": -49.58759714271227, - "threshold": 0.50337314439962 + "score": -42.61798342124197, + "threshold": 0.5060424851490891 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 556a3cbc8..c7800b489 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -39,13 +39,14 @@ 'enc': { "value" : # RDSE for value {'resolution': 0.9, - 'size': 800, + 'size': 400, 'sparsity': 0.10 }, "time": { # DateTime for timestamps - 'timeOfDay': (20, 1), - 'dayOfWeek': 80, - 'weekend': 0 #21 TODO try impact of weekend + 'season': (1, 30), # represents months, each "season" is 30 days + 'timeOfDay': (1, 8), #40 on bits for each hour + 'dayOfWeek': 20, + 'weekend': 0, #TODO try impact of weekend }}, 'predictor': {'sdrc_alpha': 0.1}, 'sp': { @@ -136,7 +137,9 @@ def initialize(self): ## setup Enc, SP, TM, Likelihood # Make the Encoders. These will convert input data into binary representations. self.encTimestamp = DateEncoder(timeOfDay= parameters["enc"]["time"]["timeOfDay"], - weekend = parameters["enc"]["time"]["weekend"]) + weekend = parameters["enc"]["time"]["weekend"], + season = parameters["enc"]["time"]["season"], + dayOfWeek= parameters["enc"]["time"]["dayOfWeek"]) scalarEncoderParams = RDSE_Parameters() scalarEncoderParams.size = parameters["enc"]["value"]["size"] diff --git a/results/final_results.json b/results/final_results.json index deb4955b9..21ffbc1d3 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 32.01505829232405, - "reward_low_FP_rate": 23.58841238946575, - "standard": 28.626035714348134 + "reward_low_FN_rate": 36.0293151088385, + "reward_low_FP_rate": 23.35943095419358, + "standard": 31.63017955980948 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 4fe8b485b09b3f81475c04f5c6ab509886ce8930 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 3 Aug 2019 23:32:26 +0200 Subject: [PATCH 06/23] htmcore: tune params 2 --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 14 ++++++++------ results/final_results.json | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 2394b8e53..1aada404e 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -106.61798342124197, - "threshold": 0.5060424851490891 + "score": -103.55900205263757, + "threshold": 0.5022391742521605 }, "reward_low_FP_rate": { - "score": -61.80612018627088, - "threshold": 0.5683023049854312 + "score": -57.654371449007584, + "threshold": 0.5285090778522251 }, "standard": { - "score": -42.61798342124197, - "threshold": 0.5060424851490891 + "score": -39.55900205263757, + "threshold": 0.5022391742521605 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index c7800b489..1cf465ca5 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -43,20 +43,22 @@ 'sparsity': 0.10 }, "time": { # DateTime for timestamps + # fields with 1 bit encoding are effectively disabled (have no implact on SP, take little input space) + # it is possible to totaly ignore the timestamp (this encoder) input, and results are not much worse. 'season': (1, 30), # represents months, each "season" is 30 days - 'timeOfDay': (1, 8), #40 on bits for each hour - 'dayOfWeek': 20, + 'timeOfDay': (1, 1), #40 on bits for each hour + 'dayOfWeek': 20, #this field has most significant impact, as incorporates (day + hours) 'weekend': 0, #TODO try impact of weekend }}, 'predictor': {'sdrc_alpha': 0.1}, 'sp': { 'boostStrength': 0.0, - 'columnCount': 2048, - 'localAreaDensity': 40/2048, + 'columnCount': 1024*1, + 'localAreaDensity': 40/1024, #TODO accuracy extremely sensitive to this value (??) 'potentialPct': 0.4, - 'synPermActiveInc': 0.1, + 'synPermActiveInc': 0.05, 'synPermConnected': 0.5, - 'synPermInactiveDec': 0.05}, + 'synPermInactiveDec': 0.01}, 'tm': { 'activationThreshold': 13, 'cellsPerColumn': 4, diff --git a/results/final_results.json b/results/final_results.json index 21ffbc1d3..ff39d2888 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 36.0293151088385, - "reward_low_FP_rate": 23.35943095419358, - "standard": 31.63017955980948 + "reward_low_FN_rate": 36.908332743494924, + "reward_low_FP_rate": 25.148977823703607, + "standard": 32.94870601179413 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 387b7449cebc149dc3c35cb34cc4c2085f57dd9f Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Fri, 9 Aug 2019 15:12:42 +0200 Subject: [PATCH 07/23] tuning SP --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 7 +++++-- results/final_results.json | 6 +++--- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 1aada404e..b23ec23ec 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -103.55900205263757, - "threshold": 0.5022391742521605 + "score": -95.5532953197746, + "threshold": 0.4966527315874496 }, "reward_low_FP_rate": { - "score": -57.654371449007584, - "threshold": 0.5285090778522251 + "score": -55.368299152063024, + "threshold": 0.5060680527062744 }, "standard": { - "score": -39.55900205263757, - "threshold": 0.5022391742521605 + "score": -34.95573548375616, + "threshold": 0.5060680527062744 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 1cf465ca5..88f9b9132 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -54,8 +54,10 @@ 'sp': { 'boostStrength': 0.0, 'columnCount': 1024*1, - 'localAreaDensity': 40/1024, #TODO accuracy extremely sensitive to this value (??) + 'localAreaDensity': 40/(1024*1), #TODO accuracy extremely sensitive to this value (??) + 'potentialRadius': 999999, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local 'potentialPct': 0.4, + 'stimulusThreshold': 4, 'synPermActiveInc': 0.05, 'synPermConnected': 0.5, 'synPermInactiveDec': 0.01}, @@ -159,9 +161,10 @@ def initialize(self): inputDimensions = (encodingWidth,), columnDimensions = (spParams["columnCount"],), potentialPct = spParams["potentialPct"], - potentialRadius = encodingWidth, + potentialRadius = spParams["potentialRadius"], globalInhibition = True, localAreaDensity = spParams["localAreaDensity"], + stimulusThreshold = spParams["stimulusThreshold"], synPermInactiveDec = spParams["synPermInactiveDec"], synPermActiveInc = spParams["synPermActiveInc"], synPermConnected = spParams["synPermConnected"], diff --git a/results/final_results.json b/results/final_results.json index ff39d2888..c37d0f6a2 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 36.908332743494924, - "reward_low_FP_rate": 25.148977823703607, - "standard": 32.94870601179413 + "reward_low_FN_rate": 39.20882318397281, + "reward_low_FP_rate": 26.134353813765905, + "standard": 34.932872636311984 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 09f2839239d9ca1808458099b1dafc5e5f124664 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Fri, 4 Oct 2019 23:13:12 +0200 Subject: [PATCH 08/23] updating configs --- nab/detectors/htmcore/htmcore_detector.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 88f9b9132..9aba12f84 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -38,24 +38,24 @@ # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { "value" : # RDSE for value - {'resolution': 0.9, - 'size': 400, - 'sparsity': 0.10 + {'resolution': 0.8, + 'size': 1000, + 'sparsity': 0.30 }, "time": { # DateTime for timestamps # fields with 1 bit encoding are effectively disabled (have no implact on SP, take little input space) # it is possible to totaly ignore the timestamp (this encoder) input, and results are not much worse. 'season': (1, 30), # represents months, each "season" is 30 days 'timeOfDay': (1, 1), #40 on bits for each hour - 'dayOfWeek': 20, #this field has most significant impact, as incorporates (day + hours) + 'dayOfWeek': 50, #this field has most significant impact, as incorporates (day + hours) 'weekend': 0, #TODO try impact of weekend }}, 'predictor': {'sdrc_alpha': 0.1}, 'sp': { 'boostStrength': 0.0, - 'columnCount': 1024*1, - 'localAreaDensity': 40/(1024*1), #TODO accuracy extremely sensitive to this value (??) - 'potentialRadius': 999999, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local + 'columnCount': 1024*4, + 'localAreaDensity': 0.04, #40/(1024*2), #TODO accuracy extremely sensitive to this value (??) + 'potentialRadius': 100, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local 'potentialPct': 0.4, 'stimulusThreshold': 4, 'synPermActiveInc': 0.05, From 1767a98d12fcca480adb8c0b82a1213fe61df522 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sat, 5 Oct 2019 00:33:50 +0200 Subject: [PATCH 09/23] Revert "updating configs" This reverts commit 09f2839239d9ca1808458099b1dafc5e5f124664. --- nab/detectors/htmcore/htmcore_detector.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 9aba12f84..88f9b9132 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -38,24 +38,24 @@ # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { "value" : # RDSE for value - {'resolution': 0.8, - 'size': 1000, - 'sparsity': 0.30 + {'resolution': 0.9, + 'size': 400, + 'sparsity': 0.10 }, "time": { # DateTime for timestamps # fields with 1 bit encoding are effectively disabled (have no implact on SP, take little input space) # it is possible to totaly ignore the timestamp (this encoder) input, and results are not much worse. 'season': (1, 30), # represents months, each "season" is 30 days 'timeOfDay': (1, 1), #40 on bits for each hour - 'dayOfWeek': 50, #this field has most significant impact, as incorporates (day + hours) + 'dayOfWeek': 20, #this field has most significant impact, as incorporates (day + hours) 'weekend': 0, #TODO try impact of weekend }}, 'predictor': {'sdrc_alpha': 0.1}, 'sp': { 'boostStrength': 0.0, - 'columnCount': 1024*4, - 'localAreaDensity': 0.04, #40/(1024*2), #TODO accuracy extremely sensitive to this value (??) - 'potentialRadius': 100, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local + 'columnCount': 1024*1, + 'localAreaDensity': 40/(1024*1), #TODO accuracy extremely sensitive to this value (??) + 'potentialRadius': 999999, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local 'potentialPct': 0.4, 'stimulusThreshold': 4, 'synPermActiveInc': 0.05, From 353fc81e5b149bdbc436e072051e183b87d99a23 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 9 Oct 2019 14:14:33 +0200 Subject: [PATCH 10/23] improve import --- nab/detectors/htmcore/htmcore_detector.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 88f9b9132..12e4c9d67 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -25,7 +25,7 @@ # htm.core imports from htm.bindings.sdr import SDR, Metrics -from htm.encoders.rdse import RDSE, RDSE_Parameters +from htm.encoders.rdse import RDSE as Encoder, RDSE_Parameters as EncParameters from htm.encoders.date import DateEncoder from htm.bindings.algorithms import SpatialPooler from htm.bindings.algorithms import TemporalMemory @@ -145,12 +145,12 @@ def initialize(self): season = parameters["enc"]["time"]["season"], dayOfWeek= parameters["enc"]["time"]["dayOfWeek"]) - scalarEncoderParams = RDSE_Parameters() + scalarEncoderParams = EncParameters() scalarEncoderParams.size = parameters["enc"]["value"]["size"] scalarEncoderParams.sparsity = parameters["enc"]["value"]["sparsity"] scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] - self.encValue = RDSE( scalarEncoderParams ) + self.encValue = Encoder( scalarEncoderParams ) encodingWidth = (self.encTimestamp.size + self.encValue.size) self.enc_info = Metrics( [encodingWidth], 999999999 ) From a9bbb7ae7f1b3a17ad1955603cafaef3820aa5b2 Mon Sep 17 00:00:00 2001 From: steinroe Date: Sun, 19 Apr 2020 10:07:25 +0200 Subject: [PATCH 11/23] optimized params --- config/thresholds.json | 12 +- nab/detectors/htmcore/htmcore_detector.py | 161 ++++++++++++---------- results/final_results.json | 6 +- 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index b23ec23ec..d60a62d08 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -95.5532953197746, - "threshold": 0.4966527315874496 + "score": -20.23461825455344, + "threshold": 0.4984827817170541 }, "reward_low_FP_rate": { - "score": -55.368299152063024, - "threshold": 0.5060680527062744 + "score": -10.605039633669087, + "threshold": 0.5005860098292023 }, "standard": { - "score": -34.95573548375616, - "threshold": 0.5060680527062744 + "score": 12.765381745446561, + "threshold": 0.4984827817170541 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 12e4c9d67..cd1d9caea 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -35,49 +35,56 @@ from nab.detectors.base import AnomalyDetector parameters_numenta_comparable = { - # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) - 'enc': { - "value" : # RDSE for value - {'resolution': 0.9, - 'size': 400, - 'sparsity': 0.10 - }, - "time": { # DateTime for timestamps - # fields with 1 bit encoding are effectively disabled (have no implact on SP, take little input space) - # it is possible to totaly ignore the timestamp (this encoder) input, and results are not much worse. - 'season': (1, 30), # represents months, each "season" is 30 days - 'timeOfDay': (1, 1), #40 on bits for each hour - 'dayOfWeek': 20, #this field has most significant impact, as incorporates (day + hours) - 'weekend': 0, #TODO try impact of weekend - }}, - 'predictor': {'sdrc_alpha': 0.1}, - 'sp': { - 'boostStrength': 0.0, - 'columnCount': 1024*1, - 'localAreaDensity': 40/(1024*1), #TODO accuracy extremely sensitive to this value (??) - 'potentialRadius': 999999, # 2 * 20 -> 40 of 400 (input size) = 10% #TODO this is global all-to-all connection, try more local - 'potentialPct': 0.4, - 'stimulusThreshold': 4, - 'synPermActiveInc': 0.05, - 'synPermConnected': 0.5, - 'synPermInactiveDec': 0.01}, - 'tm': { - 'activationThreshold': 13, - 'cellsPerColumn': 4, - 'initialPerm': 0.51, - 'maxSegmentsPerCell': 128, - 'maxSynapsesPerSegment': 32, - 'minThreshold': 10, - 'newSynapseCount': 20, - 'permanenceDec': 0.1, - 'permanenceInc': 0.1}, - 'anomaly': { - 'likelihood': { - #'learningPeriod': int(math.floor(self.probationaryPeriod / 2.0)), - #'probationaryPeriod': self.probationaryPeriod-default_parameters["anomaly"]["likelihood"]["learningPeriod"], - 'probationaryPct': 0.1, - 'reestimationPeriod': 100}} -} + "enc": { + "value": { + # "resolution": 0.9, calculate by max(0.001, (maxVal - minVal) / numBuckets) where numBuckets = 130 + "size": 400, + "activeBits": 21, + "seed": 5, + }, + "time": { + "timeOfDay": (21, 9.49), + } + }, + "sp": { + # inputDimensions: use width of encoding + "columnDimensions": 2048, + # "potentialRadius": use width of encoding + "potentialPct": 0.8, + "globalInhibition": True, + "localAreaDensity": 0.025049634479368352, # optimize this one + "stimulusThreshold": 0, + "synPermInactiveDec": 0.0005, + "synPermActiveInc": 0.003, + "synPermConnected": 0.2, + "boostStrength": 0.0, + "wrapAround": True, + "minPctOverlapDutyCycle": 0.001, + "dutyCyclePeriod": 1000, + "seed": 5, + }, + "tm": { + "columnDimensions": 2048, + "cellsPerColumn": 32, + "activationThreshold": 20, + "initialPermanence": 0.24, + "connectedPermanence": 0.5, + "minThreshold": 13, + "maxNewSynapseCount": 31, + "permanenceIncrement": 0.04, + "permanenceDecrement": 0.008, + "predictedSegmentDecrement": 0.001, + "maxSegmentsPerCell": 128, + "maxSynapsesPerSegment": 128, + "seed": 5, + }, + "anomaly": { + "likelihood": { + "probationaryPct": 0.1, + "reestimationPeriod": 100 + } + } + } class HtmcoreDetector(AnomalyDetector): @@ -140,15 +147,15 @@ def initialize(self): ## setup Enc, SP, TM, Likelihood # Make the Encoders. These will convert input data into binary representations. - self.encTimestamp = DateEncoder(timeOfDay= parameters["enc"]["time"]["timeOfDay"], - weekend = parameters["enc"]["time"]["weekend"], - season = parameters["enc"]["time"]["season"], - dayOfWeek= parameters["enc"]["time"]["dayOfWeek"]) + self.encTimestamp = DateEncoder(timeOfDay=parameters["enc"]["time"]["timeOfDay"]) - scalarEncoderParams = EncParameters() - scalarEncoderParams.size = parameters["enc"]["value"]["size"] - scalarEncoderParams.sparsity = parameters["enc"]["value"]["sparsity"] - scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] + scalarEncoderParams = EncParameters() + scalarEncoderParams.size = parameters["enc"]["value"]["size"] + scalarEncoderParams.activeBits = parameters["enc"]["value"]["activeBits"] + # scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] + scalarEncoderParams.resolution = max(0.001, (self.inputMax - self.inputMin) / 130) + #scalarEncoderParams.seed = parameters["enc"]["value"]["seed"] + self.encValue = Encoder(scalarEncoderParams) self.encValue = Encoder( scalarEncoderParams ) encodingWidth = (self.encTimestamp.size + self.encValue.size) @@ -158,36 +165,40 @@ def initialize(self): # SpatialPooler spParams = parameters["sp"] self.sp = SpatialPooler( - inputDimensions = (encodingWidth,), - columnDimensions = (spParams["columnCount"],), - potentialPct = spParams["potentialPct"], - potentialRadius = spParams["potentialRadius"], - globalInhibition = True, - localAreaDensity = spParams["localAreaDensity"], - stimulusThreshold = spParams["stimulusThreshold"], - synPermInactiveDec = spParams["synPermInactiveDec"], - synPermActiveInc = spParams["synPermActiveInc"], - synPermConnected = spParams["synPermConnected"], - boostStrength = spParams["boostStrength"], - wrapAround = True + inputDimensions=(encodingWidth,), + columnDimensions=(spParams["columnDimensions"],), + potentialRadius=encodingWidth, + potentialPct=spParams["potentialPct"], + globalInhibition=spParams["globalInhibition"], + localAreaDensity=spParams["localAreaDensity"], + stimulusThreshold=spParams["stimulusThreshold"], + synPermInactiveDec=spParams["synPermInactiveDec"], + synPermActiveInc=spParams["synPermActiveInc"], + synPermConnected=spParams["synPermConnected"], + boostStrength=spParams["boostStrength"], + wrapAround=spParams["wrapAround"], + minPctOverlapDutyCycle=spParams["minPctOverlapDutyCycle"], + dutyCyclePeriod=spParams["dutyCyclePeriod"], + #seed=spParams["seed"], ) self.sp_info = Metrics( self.sp.getColumnDimensions(), 999999999 ) # TemporalMemory tmParams = parameters["tm"] self.tm = TemporalMemory( - columnDimensions = (spParams["columnCount"],), - cellsPerColumn = tmParams["cellsPerColumn"], - activationThreshold = tmParams["activationThreshold"], - initialPermanence = tmParams["initialPerm"], - connectedPermanence = spParams["synPermConnected"], - minThreshold = tmParams["minThreshold"], - maxNewSynapseCount = tmParams["newSynapseCount"], - permanenceIncrement = tmParams["permanenceInc"], - permanenceDecrement = tmParams["permanenceDec"], - predictedSegmentDecrement = 0.0, - maxSegmentsPerCell = tmParams["maxSegmentsPerCell"], - maxSynapsesPerSegment = tmParams["maxSynapsesPerSegment"] + columnDimensions=(tmParams["columnDimensions"],), + cellsPerColumn=tmParams["cellsPerColumn"], + activationThreshold=tmParams["activationThreshold"], + initialPermanence=tmParams["initialPermanence"], + connectedPermanence=tmParams["connectedPermanence"], + minThreshold=tmParams["minThreshold"], + maxNewSynapseCount=tmParams["maxNewSynapseCount"], + permanenceIncrement=tmParams["permanenceIncrement"], + permanenceDecrement=tmParams["permanenceDecrement"], + predictedSegmentDecrement=tmParams["predictedSegmentDecrement"], + maxSegmentsPerCell=tmParams["maxSegmentsPerCell"], + maxSynapsesPerSegment=tmParams["maxSynapsesPerSegment"], + #seed=tmParams["seed"] ) self.tm_info = Metrics( [self.tm.numberOfCells()], 999999999 ) diff --git a/results/final_results.json b/results/final_results.json index c37d0f6a2..06a9bf828 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 39.20882318397281, - "reward_low_FP_rate": 26.134353813765905, - "standard": 34.932872636311984 + "reward_low_FN_rate": 60.852121191220256, + "reward_low_FP_rate": 45.428862226866734, + "standard": 55.50231971786488 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From fe28a8a74cbad3a77c9cfb22786252486dbba97d Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sun, 19 Apr 2020 14:25:47 +0200 Subject: [PATCH 12/23] slightly tune SP params --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 10 +++++----- results/final_results.json | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index d60a62d08..8fa420293 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -20.23461825455344, - "threshold": 0.4984827817170541 + "score": -13.729152330559167, + "threshold": 0.5088354562348507 }, "reward_low_FP_rate": { - "score": -10.605039633669087, - "threshold": 0.5005860098292023 + "score": -6.888790669686649, + "threshold": 0.5088354562348507 }, "standard": { - "score": 12.765381745446561, - "threshold": 0.4984827817170541 + "score": 17.270847669440833, + "threshold": 0.5088354562348507 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index cd1d9caea..5036c2cb4 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -39,7 +39,7 @@ "value": { # "resolution": 0.9, calculate by max(0.001, (maxVal - minVal) / numBuckets) where numBuckets = 130 "size": 400, - "activeBits": 21, + "activeBits": 21, #results very sensitive to the size/active bits in the input encoders "seed": 5, }, "time": { @@ -52,8 +52,8 @@ # "potentialRadius": use width of encoding "potentialPct": 0.8, "globalInhibition": True, - "localAreaDensity": 0.025049634479368352, # optimize this one - "stimulusThreshold": 0, + "localAreaDensity": 0.025, # optimize this one + "stimulusThreshold": 2, "synPermInactiveDec": 0.0005, "synPermActiveInc": 0.003, "synPermConnected": 0.2, @@ -64,7 +64,7 @@ "seed": 5, }, "tm": { - "columnDimensions": 2048, + #"columnDimensions": 2048, #must match SP "cellsPerColumn": 32, "activationThreshold": 20, "initialPermanence": 0.24, @@ -186,7 +186,7 @@ def initialize(self): # TemporalMemory tmParams = parameters["tm"] self.tm = TemporalMemory( - columnDimensions=(tmParams["columnDimensions"],), + columnDimensions=(spParams["columnDimensions"],), cellsPerColumn=tmParams["cellsPerColumn"], activationThreshold=tmParams["activationThreshold"], initialPermanence=tmParams["initialPermanence"], diff --git a/results/final_results.json b/results/final_results.json index 06a9bf828..18a6b4c21 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 60.852121191220256, - "reward_low_FP_rate": 45.428862226866734, - "standard": 55.50231971786488 + "reward_low_FN_rate": 62.72150795098874, + "reward_low_FP_rate": 47.03069367685916, + "standard": 57.44433089200034 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From de2b318156c44ddd807af3a639254a59d20b89ce Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Sun, 19 Apr 2020 14:53:28 +0200 Subject: [PATCH 13/23] update SP params 2 --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 8 ++++---- results/final_results.json | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 8fa420293..2ae459a4a 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -13.729152330559167, - "threshold": 0.5088354562348507 + "score": -7.698864811160355, + "threshold": 0.4880776051000826 }, "reward_low_FP_rate": { - "score": -6.888790669686649, - "threshold": 0.5088354562348507 + "score": 0.22668468764268823, + "threshold": 0.5005859805259314 }, "standard": { - "score": 17.270847669440833, - "threshold": 0.5088354562348507 + "score": 21.55054903945632, + "threshold": 0.4929672219539603 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 5036c2cb4..97f3dbb08 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -54,10 +54,10 @@ "globalInhibition": True, "localAreaDensity": 0.025, # optimize this one "stimulusThreshold": 2, - "synPermInactiveDec": 0.0005, - "synPermActiveInc": 0.003, - "synPermConnected": 0.2, - "boostStrength": 0.0, + "synPermInactiveDec": 0.001, + "synPermActiveInc": 0.006, + "synPermConnected": 0.5, #this shouldn't make any effect, keep as intended by Connections + "boostStrength": 0.0, #so far, boosting negatively affects results. Suggest leaving OFF (0.0) "wrapAround": True, "minPctOverlapDutyCycle": 0.001, "dutyCyclePeriod": 1000, diff --git a/results/final_results.json b/results/final_results.json index 18a6b4c21..f1a51e2f5 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 62.72150795098874, - "reward_low_FP_rate": 47.03069367685916, - "standard": 57.44433089200034 + "reward_low_FN_rate": 64.45434919219528, + "reward_low_FP_rate": 50.09770891708733, + "standard": 59.289029758386334 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 26fa6218b5e1edc2225843afb54e19ccd8e578b1 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Mon, 20 Apr 2020 13:11:57 +0200 Subject: [PATCH 14/23] results with SP w numActiveColumnsPerInhArea now the params are directly comparable to Numenta's. --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 4 +++- requirements.txt | 2 +- results/final_results.json | 6 +++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index d60a62d08..be865568b 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -20.23461825455344, - "threshold": 0.4984827817170541 + "score": -5.093477977097415, + "threshold": 0.5197175251148237 }, "reward_low_FP_rate": { - "score": -10.605039633669087, - "threshold": 0.5005860098292023 + "score": 2.8600708590096495, + "threshold": 0.5197175251148237 }, "standard": { - "score": 12.765381745446561, - "threshold": 0.4984827817170541 + "score": 23.906522022902585, + "threshold": 0.5197175251148237 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index cd1d9caea..618ec819c 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -52,7 +52,8 @@ # "potentialRadius": use width of encoding "potentialPct": 0.8, "globalInhibition": True, - "localAreaDensity": 0.025049634479368352, # optimize this one + "localAreaDensity": 0, ## MUTEX #0.025049634479368352, # optimize this one + "numActiveColumnsPerInhArea": 40, ##MUTEX "stimulusThreshold": 0, "synPermInactiveDec": 0.0005, "synPermActiveInc": 0.003, @@ -171,6 +172,7 @@ def initialize(self): potentialPct=spParams["potentialPct"], globalInhibition=spParams["globalInhibition"], localAreaDensity=spParams["localAreaDensity"], + numActiveColumnsPerInhArea=spParams["numActiveColumnsPerInhArea"], stimulusThreshold=spParams["stimulusThreshold"], synPermInactiveDec=spParams["synPermInactiveDec"], synPermActiveInc=spParams["synPermActiveInc"], diff --git a/requirements.txt b/requirements.txt index 4ca2e8553..7c472bfd3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pandas>=0.20.3 simplejson>=3.11.1 plotly>=3.10.0 #required for scripts/plot -htm.core>=2.0.18 +htm.core>=2.1.1 diff --git a/results/final_results.json b/results/final_results.json index 06a9bf828..f7edc0f5a 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 60.852121191220256, - "reward_low_FP_rate": 45.428862226866734, - "standard": 55.50231971786488 + "reward_low_FN_rate": 65.20302356979958, + "reward_low_FP_rate": 51.2327891633662, + "standard": 60.304535354699375 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 61328b5ef097f5990344b971d700f71ce885338f Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Mon, 20 Apr 2020 13:38:56 +0200 Subject: [PATCH 15/23] update results with the new params --- config/thresholds.json | 14 +++++++------- results/final_results.json | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 6a3a6277c..43d44802a 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -7.698864811160355, - "threshold": 0.4880776051000826 + "score": -23.189272568956113, + "threshold": 0.5023570944451671 }, "reward_low_FP_rate": { - "score": 0.22668468764268823, - "threshold": 0.5005859805259314 + "score": -10.6443875889641, + "threshold": 0.5023570944451671 }, "standard": { - "score": 21.55054903945632, - "threshold": 0.4929672219539603 + "score": 11.810727431043887, + "threshold": 0.5023570944451671 } }, "htmjava": { @@ -223,4 +223,4 @@ "threshold": 1.0 } } -} +} \ No newline at end of file diff --git a/results/final_results.json b/results/final_results.json index e34a7f9f6..b0c66df61 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 64.45434919219528, - "reward_low_FP_rate": 50.09770891708733, - "standard": 59.289029758386334 + "reward_low_FN_rate": 60.00308259512753, + "reward_low_FP_rate": 45.41190190130854, + "standard": 55.09083078924303 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, @@ -74,4 +74,4 @@ "reward_low_FP_rate": 20.86798582474138, "standard": 39.649523496077585 } -} +} \ No newline at end of file From ea01da42ec2579709ae094e7b72b1a41e970299d Mon Sep 17 00:00:00 2001 From: steinroe Date: Mon, 20 Apr 2020 16:13:13 +0200 Subject: [PATCH 16/23] use original numenta params --- config/thresholds.json | 12 ++++++------ nab/detectors/htmcore/htmcore_detector.py | 8 ++++---- results/final_results.json | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 43d44802a..66bccd5b0 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -23.189272568956113, - "threshold": 0.5023570944451671 + "score": -13.79442880070686, + "threshold": 0.4849987604778112 }, "reward_low_FP_rate": { - "score": -10.6443875889641, - "threshold": 0.5023570944451671 + "score": -7.999519633877718, + "threshold": 0.5076249271618024 }, "standard": { - "score": 11.810727431043887, - "threshold": 0.5023570944451671 + "score": 16.771631491695032, + "threshold": 0.5076249271618024 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 021696be0..a01a29c1f 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -54,10 +54,10 @@ "globalInhibition": True, "localAreaDensity": 0, ## MUTEX #0.025049634479368352, # optimize this one "numActiveColumnsPerInhArea": 40, ##MUTEX - "stimulusThreshold": 2, - "synPermInactiveDec": 0.001, - "synPermActiveInc": 0.006, - "synPermConnected": 0.5, #this shouldn't make any effect, keep as intended by Connections + "stimulusThreshold": 0, + "synPermInactiveDec": 0.0005, + "synPermActiveInc": 0.003, + "synPermConnected": 0.2, #this shouldn't make any effect, keep as intended by Connections "boostStrength": 0.0, #so far, boosting negatively affects results. Suggest leaving OFF (0.0) "wrapAround": True, "minPctOverlapDutyCycle": 0.001, diff --git a/results/final_results.json b/results/final_results.json index b0c66df61..13359460c 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 60.00308259512753, - "reward_low_FP_rate": 45.41190190130854, - "standard": 55.09083078924303 + "reward_low_FN_rate": 62.70275034462445, + "reward_low_FP_rate": 46.55193119229405, + "standard": 57.22915150504096 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 0f571f4e4b0191476c5dfd5a32919810611ce655 Mon Sep 17 00:00:00 2001 From: steinroe Date: Mon, 20 Apr 2020 21:30:10 +0200 Subject: [PATCH 17/23] reintroducing fake spatial anomaly score --- nab/detectors/htmcore/htmcore_detector.py | 460 ++++++++++++---------- 1 file changed, 241 insertions(+), 219 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index a01a29c1f..81ebb60a8 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -35,190 +35,197 @@ from nab.detectors.base import AnomalyDetector parameters_numenta_comparable = { - "enc": { - "value": { - # "resolution": 0.9, calculate by max(0.001, (maxVal - minVal) / numBuckets) where numBuckets = 130 - "size": 400, - "activeBits": 21, #results very sensitive to the size/active bits in the input encoders - "seed": 5, - }, - "time": { - "timeOfDay": (21, 9.49), - } - }, - "sp": { - # inputDimensions: use width of encoding - "columnDimensions": 2048, - # "potentialRadius": use width of encoding - "potentialPct": 0.8, - "globalInhibition": True, - "localAreaDensity": 0, ## MUTEX #0.025049634479368352, # optimize this one - "numActiveColumnsPerInhArea": 40, ##MUTEX - "stimulusThreshold": 0, - "synPermInactiveDec": 0.0005, - "synPermActiveInc": 0.003, - "synPermConnected": 0.2, #this shouldn't make any effect, keep as intended by Connections - "boostStrength": 0.0, #so far, boosting negatively affects results. Suggest leaving OFF (0.0) - "wrapAround": True, - "minPctOverlapDutyCycle": 0.001, - "dutyCyclePeriod": 1000, - "seed": 5, - }, - "tm": { - #"columnDimensions": 2048, #must match SP - "cellsPerColumn": 32, - "activationThreshold": 20, - "initialPermanence": 0.24, - "connectedPermanence": 0.5, - "minThreshold": 13, - "maxNewSynapseCount": 31, - "permanenceIncrement": 0.04, - "permanenceDecrement": 0.008, - "predictedSegmentDecrement": 0.001, - "maxSegmentsPerCell": 128, - "maxSynapsesPerSegment": 128, + "enc": { + "value": { + # "resolution": 0.9, calculate by max(0.001, (maxVal - minVal) / numBuckets) where numBuckets = 130 + "size": 400, + "activeBits": 21, # results very sensitive to the size/active bits in the input encoders "seed": 5, }, - "anomaly": { - "likelihood": { - "probationaryPct": 0.1, - "reestimationPeriod": 100 - } + "time": { + "timeOfDay": (21, 9.49), + } + }, + "sp": { + # inputDimensions: use width of encoding + "columnDimensions": 2048, + # "potentialRadius": use width of encoding + "potentialPct": 0.8, + "globalInhibition": True, + "localAreaDensity": 0, ## MUTEX #0.025049634479368352, # optimize this one + "numActiveColumnsPerInhArea": 40, ##MUTEX + "stimulusThreshold": 0, + "synPermInactiveDec": 0.0005, + "synPermActiveInc": 0.003, + "synPermConnected": 0.2, # this shouldn't make any effect, keep as intended by Connections + "boostStrength": 0.0, # so far, boosting negatively affects results. Suggest leaving OFF (0.0) + "wrapAround": True, + "minPctOverlapDutyCycle": 0.001, + "dutyCyclePeriod": 1000, + "seed": 5, + }, + "tm": { + # "columnDimensions": 2048, #must match SP + "cellsPerColumn": 32, + "activationThreshold": 20, + "initialPermanence": 0.24, + "connectedPermanence": 0.5, + "minThreshold": 13, + "maxNewSynapseCount": 31, + "permanenceIncrement": 0.04, + "permanenceDecrement": 0.008, + "predictedSegmentDecrement": 0.001, + "maxSegmentsPerCell": 128, + "maxSynapsesPerSegment": 128, + "seed": 5, + }, + "anomaly": { + "likelihood": { + "probationaryPct": 0.1, + "reestimationPeriod": 100 } } +} + +# Fraction outside of the range of values seen so far that will be considered +# a spatial anomaly regardless of the anomaly likelihood calculation. This +# accounts for the human labelling bias for spatial values larger than what +# has been seen so far. +SPATIAL_TOLERANCE = 0.05 class HtmcoreDetector(AnomalyDetector): - """ + """ This detector uses an HTM based anomaly detection technique. """ - def __init__(self, *args, **kwargs): - - super(HtmcoreDetector, self).__init__(*args, **kwargs) - - ## API for controlling settings of htm.core HTM detector: - - # Set this to False if you want to get results based on raw scores - # without using AnomalyLikelihood. This will give worse results, but - # useful for checking the efficacy of AnomalyLikelihood. You will need - # to re-optimize the thresholds when running with this setting. - self.useLikelihood = True - self.verbose = True - - ## internal members - # (listed here for easier understanding) - # initialized in `initialize()` - self.encTimestamp = None - self.encValue = None - self.sp = None - self.tm = None - self.anLike = None - # optional debug info - self.enc_info = None - self.sp_info = None - self.tm_info = None - # internal helper variables: - self.inputs_ = [] - self.iteration_ = 0 - - - def getAdditionalHeaders(self): - """Returns a list of strings.""" - return ["raw_score"] #TODO optional: add "prediction" - - - def handleRecord(self, inputData): - """Returns a tuple (anomalyScore, rawScore). + def __init__(self, *args, **kwargs): + + super(HtmcoreDetector, self).__init__(*args, **kwargs) + + ## API for controlling settings of htm.core HTM detector: + + # Set this to False if you want to get results based on raw scores + # without using AnomalyLikelihood. This will give worse results, but + # useful for checking the efficacy of AnomalyLikelihood. You will need + # to re-optimize the thresholds when running with this setting. + self.useLikelihood = True + self.useSpatialAnomaly = True + self.verbose = True + + ## internal members + # (listed here for easier understanding) + # initialized in `initialize()` + self.encTimestamp = None + self.encValue = None + self.sp = None + self.tm = None + self.anLike = None + # optional debug info + self.enc_info = None + self.sp_info = None + self.tm_info = None + # internal helper variables: + self.inputs_ = [] + self.iteration_ = 0 + + def getAdditionalHeaders(self): + """Returns a list of strings.""" + return ["raw_score"] # TODO optional: add "prediction" + + def handleRecord(self, inputData): + """Returns a tuple (anomalyScore, rawScore). @param inputData is a dict {"timestamp" : Timestamp(), "value" : float} @return tuple (anomalyScore, , ...) """ - # Send it to Numenta detector and get back the results - return self.modelRun(inputData["timestamp"], inputData["value"]) - - - - def initialize(self): - # toggle parameters here - #parameters = default_parameters - parameters = parameters_numenta_comparable - - - ## setup Enc, SP, TM, Likelihood - # Make the Encoders. These will convert input data into binary representations. - self.encTimestamp = DateEncoder(timeOfDay=parameters["enc"]["time"]["timeOfDay"]) - - scalarEncoderParams = EncParameters() - scalarEncoderParams.size = parameters["enc"]["value"]["size"] - scalarEncoderParams.activeBits = parameters["enc"]["value"]["activeBits"] - # scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] - scalarEncoderParams.resolution = max(0.001, (self.inputMax - self.inputMin) / 130) - #scalarEncoderParams.seed = parameters["enc"]["value"]["seed"] - self.encValue = Encoder(scalarEncoderParams) - - self.encValue = Encoder( scalarEncoderParams ) - encodingWidth = (self.encTimestamp.size + self.encValue.size) - self.enc_info = Metrics( [encodingWidth], 999999999 ) - - # Make the HTM. SpatialPooler & TemporalMemory & associated tools. - # SpatialPooler - spParams = parameters["sp"] - self.sp = SpatialPooler( - inputDimensions=(encodingWidth,), - columnDimensions=(spParams["columnDimensions"],), - potentialRadius=encodingWidth, - potentialPct=spParams["potentialPct"], - globalInhibition=spParams["globalInhibition"], - localAreaDensity=spParams["localAreaDensity"], - numActiveColumnsPerInhArea=spParams["numActiveColumnsPerInhArea"], - stimulusThreshold=spParams["stimulusThreshold"], - synPermInactiveDec=spParams["synPermInactiveDec"], - synPermActiveInc=spParams["synPermActiveInc"], - synPermConnected=spParams["synPermConnected"], - boostStrength=spParams["boostStrength"], - wrapAround=spParams["wrapAround"], - minPctOverlapDutyCycle=spParams["minPctOverlapDutyCycle"], - dutyCyclePeriod=spParams["dutyCyclePeriod"], - #seed=spParams["seed"], - ) - self.sp_info = Metrics( self.sp.getColumnDimensions(), 999999999 ) - - # TemporalMemory - tmParams = parameters["tm"] - self.tm = TemporalMemory( - columnDimensions=(spParams["columnDimensions"],), - cellsPerColumn=tmParams["cellsPerColumn"], - activationThreshold=tmParams["activationThreshold"], - initialPermanence=tmParams["initialPermanence"], - connectedPermanence=tmParams["connectedPermanence"], - minThreshold=tmParams["minThreshold"], - maxNewSynapseCount=tmParams["maxNewSynapseCount"], - permanenceIncrement=tmParams["permanenceIncrement"], - permanenceDecrement=tmParams["permanenceDecrement"], - predictedSegmentDecrement=tmParams["predictedSegmentDecrement"], - maxSegmentsPerCell=tmParams["maxSegmentsPerCell"], - maxSynapsesPerSegment=tmParams["maxSynapsesPerSegment"], - #seed=tmParams["seed"] - ) - self.tm_info = Metrics( [self.tm.numberOfCells()], 999999999 ) - - # setup likelihood, these settings are used in NAB - if self.useLikelihood: - anParams = parameters["anomaly"]["likelihood"] - learningPeriod = int(math.floor(self.probationaryPeriod / 2.0)) - self.anomalyLikelihood = AnomalyLikelihood( - learningPeriod= learningPeriod, - estimationSamples= self.probationaryPeriod - learningPeriod, - reestimationPeriod= anParams["reestimationPeriod"]) - # Predictor - # self.predictor = Predictor( steps=[1, 5], alpha=parameters["predictor"]['sdrc_alpha'] ) - # predictor_resolution = 1 - - - def modelRun(self, ts, val): - """ + # Send it to Numenta detector and get back the results + return self.modelRun(inputData["timestamp"], inputData["value"]) + + def initialize(self): + # toggle parameters here + # parameters = default_parameters + parameters = parameters_numenta_comparable + + # setup spatial anomaly + if self.useSpatialAnomaly: + # Keep track of value range for spatial anomaly detection + self.minVal = None + self.maxVal = None + + ## setup Enc, SP, TM, Likelihood + # Make the Encoders. These will convert input data into binary representations. + self.encTimestamp = DateEncoder(timeOfDay=parameters["enc"]["time"]["timeOfDay"]) + + scalarEncoderParams = EncParameters() + scalarEncoderParams.size = parameters["enc"]["value"]["size"] + scalarEncoderParams.activeBits = parameters["enc"]["value"]["activeBits"] + # scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] + scalarEncoderParams.resolution = max(0.001, (self.inputMax - self.inputMin) / 130) + # scalarEncoderParams.seed = parameters["enc"]["value"]["seed"] + self.encValue = Encoder(scalarEncoderParams) + + self.encValue = Encoder(scalarEncoderParams) + encodingWidth = (self.encTimestamp.size + self.encValue.size) + self.enc_info = Metrics([encodingWidth], 999999999) + + # Make the HTM. SpatialPooler & TemporalMemory & associated tools. + # SpatialPooler + spParams = parameters["sp"] + self.sp = SpatialPooler( + inputDimensions=(encodingWidth,), + columnDimensions=(spParams["columnDimensions"],), + potentialRadius=encodingWidth, + potentialPct=spParams["potentialPct"], + globalInhibition=spParams["globalInhibition"], + localAreaDensity=spParams["localAreaDensity"], + numActiveColumnsPerInhArea=spParams["numActiveColumnsPerInhArea"], + stimulusThreshold=spParams["stimulusThreshold"], + synPermInactiveDec=spParams["synPermInactiveDec"], + synPermActiveInc=spParams["synPermActiveInc"], + synPermConnected=spParams["synPermConnected"], + boostStrength=spParams["boostStrength"], + wrapAround=spParams["wrapAround"], + minPctOverlapDutyCycle=spParams["minPctOverlapDutyCycle"], + dutyCyclePeriod=spParams["dutyCyclePeriod"], + # seed=spParams["seed"], + ) + self.sp_info = Metrics(self.sp.getColumnDimensions(), 999999999) + + # TemporalMemory + tmParams = parameters["tm"] + self.tm = TemporalMemory( + columnDimensions=(spParams["columnDimensions"],), + cellsPerColumn=tmParams["cellsPerColumn"], + activationThreshold=tmParams["activationThreshold"], + initialPermanence=tmParams["initialPermanence"], + connectedPermanence=tmParams["connectedPermanence"], + minThreshold=tmParams["minThreshold"], + maxNewSynapseCount=tmParams["maxNewSynapseCount"], + permanenceIncrement=tmParams["permanenceIncrement"], + permanenceDecrement=tmParams["permanenceDecrement"], + predictedSegmentDecrement=tmParams["predictedSegmentDecrement"], + maxSegmentsPerCell=tmParams["maxSegmentsPerCell"], + maxSynapsesPerSegment=tmParams["maxSynapsesPerSegment"], + # seed=tmParams["seed"] + ) + self.tm_info = Metrics([self.tm.numberOfCells()], 999999999) + + # setup likelihood, these settings are used in NAB + if self.useLikelihood: + anParams = parameters["anomaly"]["likelihood"] + learningPeriod = int(math.floor(self.probationaryPeriod / 2.0)) + self.anomalyLikelihood = AnomalyLikelihood( + learningPeriod=learningPeriod, + estimationSamples=self.probationaryPeriod - learningPeriod, + reestimationPeriod=anParams["reestimationPeriod"]) + # Predictor + # self.predictor = Predictor( steps=[1, 5], alpha=parameters["predictor"]['sdrc_alpha'] ) + # predictor_resolution = 1 + + def modelRun(self, ts, val): + """ Run a single pass through HTM model @params ts - Timestamp @@ -226,53 +233,68 @@ def modelRun(self, ts, val): @return rawAnomalyScore computed for the `val` in this step """ - ## run data through our model pipeline: enc -> SP -> TM -> Anomaly - self.inputs_.append( val ) - self.iteration_ += 1 - - # 1. Encoding - # Call the encoders to create bit representations for each value. These are SDR objects. - dateBits = self.encTimestamp.encode(ts) - valueBits = self.encValue.encode(float(val)) - # Concatenate all these encodings into one large encoding for Spatial Pooling. - encoding = SDR( self.encTimestamp.size + self.encValue.size ).concatenate([valueBits, dateBits]) - self.enc_info.addData( encoding ) - - # 2. Spatial Pooler - # Create an SDR to represent active columns, This will be populated by the - # compute method below. It must have the same dimensions as the Spatial Pooler. - activeColumns = SDR( self.sp.getColumnDimensions() ) - # Execute Spatial Pooling algorithm over input space. - self.sp.compute(encoding, True, activeColumns) - self.sp_info.addData( activeColumns ) - - # 3. Temporal Memory - # Execute Temporal Memory algorithm over active mini-columns. - self.tm.compute(activeColumns, learn=True) - self.tm_info.addData( self.tm.getActiveCells().flatten() ) - - # 4.1 (optional) Predictor #TODO optional - #TODO optional: also return an error metric on predictions (RMSE, R2,...) - - # 4.2 Anomaly - # handle contextual (raw, likelihood) anomalies - # -temporal (raw) - raw = self.tm.anomaly - temporalAnomaly = raw - - if self.useLikelihood: - # Compute log(anomaly likelihood) - like = self.anomalyLikelihood.anomalyProbability(val, raw, ts) - logScore = self.anomalyLikelihood.computeLogLikelihood(like) - temporalAnomaly = logScore #TODO optional: TM to provide anomaly {none, raw, likelihood}, compare correctness with the py anomaly_likelihood - - anomalyScore = temporalAnomaly # this is the "main" anomaly, compared in NAB - - # 5. print stats - if self.verbose and self.iteration_ % 1000 == 0: - print(self.enc_info) - print(self.sp_info) - print(self.tm_info) - pass - - return (anomalyScore, raw) + ## run data through our model pipeline: enc -> SP -> TM -> Anomaly + self.inputs_.append(val) + self.iteration_ += 1 + + # 1. Encoding + # Call the encoders to create bit representations for each value. These are SDR objects. + dateBits = self.encTimestamp.encode(ts) + valueBits = self.encValue.encode(float(val)) + # Concatenate all these encodings into one large encoding for Spatial Pooling. + encoding = SDR(self.encTimestamp.size + self.encValue.size).concatenate([valueBits, dateBits]) + self.enc_info.addData(encoding) + + # 2. Spatial Pooler + # Create an SDR to represent active columns, This will be populated by the + # compute method below. It must have the same dimensions as the Spatial Pooler. + activeColumns = SDR(self.sp.getColumnDimensions()) + # Execute Spatial Pooling algorithm over input space. + self.sp.compute(encoding, True, activeColumns) + self.sp_info.addData(activeColumns) + + # 3. Temporal Memory + # Execute Temporal Memory algorithm over active mini-columns. + self.tm.compute(activeColumns, learn=True) + self.tm_info.addData(self.tm.getActiveCells().flatten()) + + # 4.1 (optional) Predictor #TODO optional + # TODO optional: also return an error metric on predictions (RMSE, R2,...) + + # 4.2 Anomaly + # handle spatial, contextual (raw, likelihood) anomalies + # -Spatial + spatialAnomaly = 0.0 # TODO optional: make this computed in SP (and later improve) + if self.useSpatialAnomaly: + # Update min/max values and check if there is a spatial anomaly + if self.minVal != self.maxVal: + tolerance = (self.maxVal - self.minVal) * SPATIAL_TOLERANCE + maxExpected = self.maxVal + tolerance + minExpected = self.minVal - tolerance + if val > maxExpected or val < minExpected: + spatialAnomaly = 1.0 + if self.maxVal is None or val > self.maxVal: + self.maxVal = val + if self.minVal is None or val < self.minVal: + self.minVal = val + + # -temporal (raw) + raw = self.tm.anomaly + temporalAnomaly = raw + + if self.useLikelihood: + # Compute log(anomaly likelihood) + like = self.anomalyLikelihood.anomalyProbability(val, raw, ts) + logScore = self.anomalyLikelihood.computeLogLikelihood(like) + temporalAnomaly = logScore # TODO optional: TM to provide anomaly {none, raw, likelihood}, compare correctness with the py anomaly_likelihood + + anomalyScore = max(spatialAnomaly, temporalAnomaly) # this is the "main" anomaly, compared in NAB + + # 5. print stats + if self.verbose and self.iteration_ % 1000 == 0: + print(self.enc_info) + print(self.sp_info) + print(self.tm_info) + pass + + return anomalyScore, raw From 05373ac46405e868de0989acf484ab611ac6362a Mon Sep 17 00:00:00 2001 From: steinroe Date: Mon, 20 Apr 2020 21:34:17 +0200 Subject: [PATCH 18/23] make spatial tolerance a parameter --- nab/detectors/htmcore/htmcore_detector.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 81ebb60a8..559aec15a 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -79,6 +79,7 @@ "maxSynapsesPerSegment": 128, "seed": 5, }, + "spatial_tolerance": 0.05, "anomaly": { "likelihood": { "probationaryPct": 0.1, @@ -87,12 +88,6 @@ } } -# Fraction outside of the range of values seen so far that will be considered -# a spatial anomaly regardless of the anomaly likelihood calculation. This -# accounts for the human labelling bias for spatial values larger than what -# has been seen so far. -SPATIAL_TOLERANCE = 0.05 - class HtmcoreDetector(AnomalyDetector): """ @@ -116,6 +111,9 @@ def __init__(self, *args, **kwargs): ## internal members # (listed here for easier understanding) # initialized in `initialize()` + self.spatial_tolerance = None + self.minVal = None # Keep track of value range for spatial anomaly detection + self.maxVal = None # Keep track of value range for spatial anomaly detection self.encTimestamp = None self.encValue = None self.sp = None @@ -150,9 +148,10 @@ def initialize(self): # setup spatial anomaly if self.useSpatialAnomaly: - # Keep track of value range for spatial anomaly detection - self.minVal = None - self.maxVal = None + self.spatial_tolerance = parameters.get("spatial_tolerance") + if self.spatial_tolerance is None: + self.spatial_tolerance = 0.05 + ## setup Enc, SP, TM, Likelihood # Make the Encoders. These will convert input data into binary representations. @@ -268,7 +267,7 @@ def modelRun(self, ts, val): if self.useSpatialAnomaly: # Update min/max values and check if there is a spatial anomaly if self.minVal != self.maxVal: - tolerance = (self.maxVal - self.minVal) * SPATIAL_TOLERANCE + tolerance = (self.maxVal - self.minVal) * self.spatial_tolerance maxExpected = self.maxVal + tolerance minExpected = self.minVal - tolerance if val > maxExpected or val < minExpected: From 65a61b353bb57343d7c9b6fb63cc69ae38da3ce1 Mon Sep 17 00:00:00 2001 From: steinroe Date: Tue, 21 Apr 2020 11:52:27 +0200 Subject: [PATCH 19/23] minor fix to enable "reset" --- nab/detectors/htmcore/htmcore_detector.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 559aec15a..b8234456b 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -151,6 +151,8 @@ def initialize(self): self.spatial_tolerance = parameters.get("spatial_tolerance") if self.spatial_tolerance is None: self.spatial_tolerance = 0.05 + self.minVal = None + self.maxVal = None ## setup Enc, SP, TM, Likelihood From 20452e45eb8c5fad0391050566cc807f4d1bb9ca Mon Sep 17 00:00:00 2001 From: steinroe Date: Wed, 22 Apr 2020 09:46:53 +0200 Subject: [PATCH 20/23] optimization results --- config/thresholds.json | 12 +-- nab/detectors/htmcore/htmcore_detector.py | 111 +++++++++++++++++++++- results/final_results.json | 6 +- 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/config/thresholds.json b/config/thresholds.json index 66bccd5b0..ee6092dec 100644 --- a/config/thresholds.json +++ b/config/thresholds.json @@ -57,16 +57,16 @@ }, "htmcore": { "reward_low_FN_rate": { - "score": -13.79442880070686, - "threshold": 0.4849987604778112 + "score": 34.43795016270592, + "threshold": 0.5029326032024234 }, "reward_low_FP_rate": { - "score": -7.999519633877718, - "threshold": 0.5076249271618024 + "score": 26.355029506794175, + "threshold": 0.5059866296414081 }, "standard": { - "score": 16.771631491695032, - "threshold": 0.5076249271618024 + "score": 49.43795016270592, + "threshold": 0.5029326032024234 } }, "htmjava": { diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index b8234456b..d3cfc63fe 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -34,6 +34,109 @@ from nab.detectors.base import AnomalyDetector + +parameters_best_localAreaDensity = { + 'anomaly': { + 'likelihood': { + 'probationaryPct': 0.09361038526767583, + 'reestimationPeriod': 93 + } + }, + 'enc': { + 'time': { + 'timeOfDay': (19, 9.862972978884644) + }, + 'value': { + 'activeBits': 23, + 'size': 367, + 'seed': 5, + } + }, + 'sp': { + 'boostStrength': 0.0, + "wrapAround": True, + 'columnDimensions': 2171, + 'dutyCyclePeriod': 943, + 'localAreaDensity': 0.02733832231380256, + 'numActiveColumnsPerInhArea': 0, + 'minPctOverlapDutyCycle': 0.001040083435774549, + 'potentialPct': 0.7478919367674115, + "globalInhibition": True, + 'stimulusThreshold': 0, + 'synPermActiveInc': 0.0032112342797752484, + 'synPermConnected': 0.19592033087796534, + 'synPermInactiveDec': 0.000530091821888105, + 'seed': 5, + }, + 'spatial_tolerance': 0.050687542110463626, + 'tm': { + 'activationThreshold': 21, + 'cellsPerColumn': 32, + 'connectedPermanence': 0.5209199947449604, + 'initialPermanence': 0.23475728280908847, + 'maxNewSynapseCount': 33, + 'maxSegmentsPerCell': 116, + 'maxSynapsesPerSegment': 126, + 'minThreshold': 14, + 'permanenceDecrement': 0.007442196498047676, + 'permanenceIncrement': 0.042228304892119754, + 'predictedSegmentDecrement': 0.0009738201927211279, + 'seed': 5, + } +} + + +parameters_best_numActiveColumnsPerInhArea = { + 'anomaly': { + 'likelihood': { + 'probationaryPct': 0.10793172183908652, + 'reestimationPeriod': 72 + } + }, + 'enc': { + 'time': { + 'timeOfDay': (21, 6.456740123240503) + }, + 'value': { + 'activeBits': 23, + 'size': 400, + 'seed': 5, + } + }, + 'sp': { + 'boostStrength': 0.0, + "wrapAround": True, + 'columnDimensions': 1487, + 'dutyCyclePeriod': 1017, + 'minPctOverlapDutyCycle': 0.0009087943213583929, + 'localAreaDensity': 0, + 'numActiveColumnsPerInhArea': 40, + 'potentialPct': 0.9281708146689587, + "globalInhibition": True, + 'stimulusThreshold': 0, + 'synPermActiveInc': 0.003892649892638879, + 'synPermConnected': 0.22110323252238637, + 'synPermInactiveDec': 0.0006151856346474387, + 'seed': 5, + }, + 'spatial_tolerance': 0.04115653095415344, + 'tm': { + 'activationThreshold': 14, + 'cellsPerColumn': 32, + 'connectedPermanence': 0.43392460530288607, + 'initialPermanence': 0.2396689292225759, + 'maxNewSynapseCount': 27, + 'maxSegmentsPerCell': 161, + 'maxSynapsesPerSegment': 141, + 'minThreshold': 13, + 'permanenceDecrement': 0.008404653537413292, + 'permanenceIncrement': 0.046393736556088694, + 'predictedSegmentDecrement': 0.0009973866301803873, + 'seed': 5, + } +} + + parameters_numenta_comparable = { "enc": { "value": { @@ -144,7 +247,7 @@ def handleRecord(self, inputData): def initialize(self): # toggle parameters here # parameters = default_parameters - parameters = parameters_numenta_comparable + parameters = parameters_best_numActiveColumnsPerInhArea # setup spatial anomaly if self.useSpatialAnomaly: @@ -164,7 +267,7 @@ def initialize(self): scalarEncoderParams.activeBits = parameters["enc"]["value"]["activeBits"] # scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] scalarEncoderParams.resolution = max(0.001, (self.inputMax - self.inputMin) / 130) - # scalarEncoderParams.seed = parameters["enc"]["value"]["seed"] + scalarEncoderParams.seed = parameters["enc"]["value"]["seed"] self.encValue = Encoder(scalarEncoderParams) self.encValue = Encoder(scalarEncoderParams) @@ -190,7 +293,7 @@ def initialize(self): wrapAround=spParams["wrapAround"], minPctOverlapDutyCycle=spParams["minPctOverlapDutyCycle"], dutyCyclePeriod=spParams["dutyCyclePeriod"], - # seed=spParams["seed"], + seed=spParams["seed"], ) self.sp_info = Metrics(self.sp.getColumnDimensions(), 999999999) @@ -209,7 +312,7 @@ def initialize(self): predictedSegmentDecrement=tmParams["predictedSegmentDecrement"], maxSegmentsPerCell=tmParams["maxSegmentsPerCell"], maxSynapsesPerSegment=tmParams["maxSynapsesPerSegment"], - # seed=tmParams["seed"] + seed=tmParams["seed"] ) self.tm_info = Metrics([self.tm.numberOfCells()], 999999999) diff --git a/results/final_results.json b/results/final_results.json index 13359460c..519491acb 100644 --- a/results/final_results.json +++ b/results/final_results.json @@ -15,9 +15,9 @@ "standard": 16.43666922426724 }, "htmcore": { - "reward_low_FN_rate": 62.70275034462445, - "reward_low_FP_rate": 46.55193119229405, - "standard": 57.22915150504096 + "reward_low_FN_rate": 76.5626293570994, + "reward_low_FP_rate": 61.359926511549155, + "standard": 71.3094612770284 }, "htmjava": { "reward_low_FN_rate": 70.42407766520115, From 0cc8545d40b56bc4f296d0579ec08a8b9463c683 Mon Sep 17 00:00:00 2001 From: breznak Date: Thu, 30 Apr 2020 08:57:14 +0000 Subject: [PATCH 21/23] Revert "Merge pull request #33 from Zbysekz/pandaVisImplementation" This reverts commit e34e6f47f6b5c5325eb103c200dbb53b74944513. --- README.md | 1 - nab/detectors/htmcore/htmcore_detector.py | 104 +--------------------- 2 files changed, 1 insertion(+), 104 deletions(-) diff --git a/README.md b/README.md index 77582e03e..33bb8f72d 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ was a lack of developer activity in the upstream repo. - [x] additional community-provided detectors: - `htmcore`: currently the only HTM implementation able to run in NAB natively in python 3. (with many improvements in [Community HTM implementation, successor of nupic.core](https://github.com/htm-community/htm.core/). - `numenta`, `numenta_TM` detectors (original from Numenta) made compatible with the Py3 codebase (only requires Py2 installed) -- [x] the HTM visualization tool [HTMPandaVis](https://github.com/htm-community/HTMpandaVis) could be used with htm_core_detector (set PANDA_VIS_ENABLED flag to True) - [ ] additional datasets - TBD, none so far diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 9786b6efb..020708187 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -41,14 +41,6 @@ # has been seen so far. SPATIAL_TOLERANCE = 0.05 -PANDA_VIS_ENABLED = False # if we want to run pandaVis tool (repo at https://github.com/htm-community/HTMpandaVis ) - -if PANDA_VIS_ENABLED: - from PandaVis.pandaComm.server import PandaServer - from PandaVis.pandaComm.dataExchange import ServerData, dataHTMObject, dataLayer, dataInput - - pandaServer = PandaServer() - parameters_numenta_comparable = { # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { @@ -143,11 +135,6 @@ def __init__(self, *args, **kwargs): self.inputs_ = [] self.iteration_ = 0 - # initialize pandaVis server - if PANDA_VIS_ENABLED: - pandaServer.Start() - self.BuildPandaSystem(parameters_numenta_comparable) - def getAdditionalHeaders(self): """Returns a list of strings.""" @@ -273,25 +260,9 @@ def modelRun(self, ts, val): # 3. Temporal Memory # Execute Temporal Memory algorithm over active mini-columns. - - # the tm.compute() execute activateDendrites() - calculateAnomaly()/getPredictiveCells() - activateCells() - # but to get insight into system with visTool, we need to have different execution order - # Note: pandaVis retrieves synapses etc. by requesting data from sp/tm python objects, so data validity is crucial - if PANDA_VIS_ENABLED: - # activates cells in columns by TM algorithm (winners, bursting...) - self.tm.activateCells(activeColumns, learn=True) - # activateDendrites calculates active segments - self.tm.activateDendrites(learn=True) - # predictive cells are calculated directly from active segments - predictiveCells = self.tm.getPredictiveCells() - else: - self.tm.compute(activeColumns, learn=True) - + self.tm.compute(activeColumns, learn=True) self.tm_info.addData( self.tm.getActiveCells().flatten() ) - if PANDA_VIS_ENABLED: - self.PandaUpdateData(ts, val, valueBits, dateBits , activeColumns, predictiveCells) - # 4.1 (optional) Predictor #TODO optional #TODO optional: also return an error metric on predictions (RMSE, R2,...) @@ -331,77 +302,4 @@ def modelRun(self, ts, val): # print(self.tm_info) pass - if PANDA_VIS_ENABLED: - pandaServer.BlockExecution() - - return (anomalyScore, raw) - - def BuildPandaSystem(self,modelParams): - global serverData - serverData = ServerData() - serverData.HTMObjects["HTM1"] = dataHTMObject() - serverData.HTMObjects["HTM1"].inputs["Value"] = dataInput() - serverData.HTMObjects["HTM1"].inputs["TimeOfDay"] = dataInput() - - serverData.HTMObjects["HTM1"].layers["Layer1"] = dataLayer( - modelParams["sp"]["columnCount"], - modelParams["tm"]["cellsPerColumn"], - ) - serverData.HTMObjects["HTM1"].layers["Layer1"].proximalInputs = ["Value","TimeOfDay"] - serverData.HTMObjects["HTM1"].layers["Layer1"].distalInputs = ["Layer1"] - - - def PandaUpdateData(self, timestamp, value, valueSDR, datetimeSDR, activeColumns, predictiveCells): - - pandaServer.currentIteration = self.iteration_ # update server's iteration number - # do not update if we are running GOTO iteration command - if (not pandaServer.cmdGotoIteration or ( - pandaServer.cmdGotoIteration and pandaServer.gotoIteration == pandaServer.currentIteration)): - # ------------------HTMpandaVis---------------------- - # fill up values - serverData.iterationNo = pandaServer.currentIteration - serverData.HTMObjects["HTM1"].inputs["Value"].stringValue = "VALUE:" + str(value) - serverData.HTMObjects["HTM1"].inputs["Value"].bits = valueSDR.sparse - serverData.HTMObjects["HTM1"].inputs["Value"].count = valueSDR.size - - serverData.HTMObjects["HTM1"].inputs["TimeOfDay"].stringValue = "TIME OF DAY:" + str(timestamp) - serverData.HTMObjects["HTM1"].inputs["TimeOfDay"].bits = datetimeSDR.sparse - serverData.HTMObjects["HTM1"].inputs["TimeOfDay"].count = datetimeSDR.size - - serverData.HTMObjects["HTM1"].layers["Layer1"].activeColumns = activeColumns.sparse - - serverData.HTMObjects["HTM1"].layers["Layer1"].winnerCells = self.tm.getWinnerCells().sparse - serverData.HTMObjects["HTM1"].layers["Layer1"].activeCells = self.tm.getActiveCells().sparse - serverData.HTMObjects["HTM1"].layers["Layer1"].predictiveCells = predictiveCells.sparse - - # print("ACTIVECOLS:"+str(serverData.HTMObjects["HTM1"].layers["SensoryLayer"].activeColumns )) - # print("WINNERCELLS:"+str(serverData.HTMObjects["HTM1"].layers["SensoryLayer"].winnerCells)) - # print("ACTIVECELLS:" + str(serverData.HTMObjects["HTM1"].layers["SensoryLayer"].activeCells)) - # print("PREDICTCELLS:"+str(serverData.HTMObjects["HTM1"].layers["SensoryLayer"].predictiveCells)) - - pandaServer.serverData = serverData - - pandaServer.spatialPoolers["HTM1"] = self.sp - pandaServer.temporalMemories["HTM1"] = self.tm - pandaServer.NewStateDataReady() - - -# WHILE USING PANDAVIS -# SPECIFY HERE FOR WHAT DATA YOU WANT TO RUN THIS DETECTOR -if PANDA_VIS_ENABLED: - import pandas as pd - import os.path as path - from nab.corpus import Corpus - dataDir = path.abspath(path.join(__file__ ,"../../../..","data")) - - corpus = Corpus(dataDir) - - dataSet = corpus.dataFiles["artificialWithAnomaly/art_daily_flatmiddle.csv"] - - detector = HtmcoreDetector(dataSet=dataSet, - probationaryPercent=0.15) - - detector.initialize() - - detector.run() From 9ef15d4061216d0642168ead2eacc2ef9d3a1373 Mon Sep 17 00:00:00 2001 From: Zbysekz Date: Tue, 15 Sep 2020 10:46:28 +0200 Subject: [PATCH 22/23] undo pandaVis implementation --- nab/detectors/htmcore/htmcore_detector.py | 109 +--------------------- 1 file changed, 1 insertion(+), 108 deletions(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 7e3bd3232..b60ba175b 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -41,16 +41,6 @@ # has been seen so far. SPATIAL_TOLERANCE = 0.05 -PANDA_VIS_BAKE_DATA = False # if we want to bake data for pandaVis tool (repo at https://github.com/htm-community/HTMpandaVis ) - -if PANDA_VIS_BAKE_DATA: - from pandaBaker.pandaBaker import PandaBaker - from pandaBaker.pandaBaker import cLayer, cInput, cDataStream - - BAKE_DATABASE_FILE_PATH = os.path.join(os.getcwd(), 'bakedDatabase', 'htmcore_detector.db') - - pandaBaker = PandaBaker(BAKE_DATABASE_FILE_PATH) - parameters_numenta_comparable = { # there are 2 (3) encoders: "value" (RDSE) & "time" (DateTime weekend, timeOfDay) 'enc': { @@ -238,10 +228,6 @@ def initialize(self): # self.predictor = Predictor( steps=[1, 5], alpha=parameters["predictor"]['sdrc_alpha'] ) # predictor_resolution = 1 - # initialize pandaBaker - if PANDA_VIS_BAKE_DATA: - self.BuildPandaSystem(self.sp, self.tm, parameters["enc"]["value"]["size"], self.encTimestamp.size) - def modelRun(self, ts, val): """ Run a single pass through HTM model @@ -273,17 +259,7 @@ def modelRun(self, ts, val): # 3. Temporal Memory # Execute Temporal Memory algorithm over active mini-columns. - - # to get predictive cells we need to call activateDendrites & activateCells separately - if PANDA_VIS_BAKE_DATA: - # activateDendrites calculates active segments - self.tm.activateDendrites(learn=True) - # predictive cells are calculated directly from active segments - predictiveCells = self.tm.getPredictiveCells() - # activates cells in columns by TM algorithm (winners, bursting...) - self.tm.activateCells(activeColumns, learn=True) - else: - self.tm.compute(activeColumns, learn=True) + self.tm.compute(activeColumns, learn=True) self.tm_info.addData( self.tm.getActiveCells().flatten() ) @@ -326,89 +302,6 @@ def modelRun(self, ts, val): # print(self.tm_info) pass - # 6. panda vis - if PANDA_VIS_BAKE_DATA: - # ------------------HTMpandaVis---------------------- - # see more about this structure at https://github.com/htm-community/HTMpandaVis/blob/master/pandaBaker/README.md - # fill up values - pandaBaker.inputs["Value"].stringValue = "value: {:.2f}".format(val) - pandaBaker.inputs["Value"].bits = valueBits.sparse - - pandaBaker.inputs["TimeOfDay"].stringValue = str(ts) - pandaBaker.inputs["TimeOfDay"].bits = dateBits.sparse - - pandaBaker.layers["Layer1"].activeColumns = activeColumns.sparse - pandaBaker.layers["Layer1"].winnerCells = self.tm.getWinnerCells().sparse - pandaBaker.layers["Layer1"].predictiveCells = predictiveCells.sparse - pandaBaker.layers["Layer1"].activeCells = self.tm.getActiveCells().sparse - - # customizable datastreams to be show on the DASH PLOTS - pandaBaker.dataStreams["rawAnomaly"].value = temporalAnomaly - pandaBaker.dataStreams["value"].value = val - pandaBaker.dataStreams["numberOfWinnerCells"].value = len(self.tm.getWinnerCells().sparse) - pandaBaker.dataStreams["numberOfPredictiveCells"].value = len(predictiveCells.sparse) - pandaBaker.dataStreams["valueInput_sparsity"].value = valueBits.getSparsity() - pandaBaker.dataStreams["dateInput_sparsity"].value = dateBits.getSparsity() - - pandaBaker.dataStreams["Layer1_SP_overlap_metric"].value = self.sp_info.overlap.overlap - pandaBaker.dataStreams["Layer1_TM_overlap_metric"].value = self.sp_info.overlap.overlap - pandaBaker.dataStreams["Layer1_SP_activation_frequency"].value = self.sp_info.activationFrequency.mean() - pandaBaker.dataStreams["Layer1_TM_activation_frequency"].value = self.tm_info.activationFrequency.mean() - pandaBaker.dataStreams["Layer1_SP_entropy"].value = self.sp_info.activationFrequency.mean() - pandaBaker.dataStreams["Layer1_TM_entropy"].value = self.tm_info.activationFrequency.mean() - - pandaBaker.StoreIteration(self.iteration_-1) - print("ITERATION: " + str(self.iteration_-1)) - - # ------------------HTMpandaVis---------------------- - return (anomalyScore, raw) - # with this method, the structure for visualization is defined - def BuildPandaSystem(self, sp, tm, consumptionBits_size, dateBits_size): - - # we have two inputs connected to proximal synapses of Layer1 - pandaBaker.inputs["Value"] = cInput(consumptionBits_size) - pandaBaker.inputs["TimeOfDay"] = cInput(dateBits_size) - - pandaBaker.layers["Layer1"] = cLayer(sp, tm) # Layer1 has Spatial Pooler & Temporal Memory - pandaBaker.layers["Layer1"].proximalInputs = [ - "Value", - "TimeOfDay", - ] - pandaBaker.layers["Layer1"].distalInputs = ["Layer1"] - - # data for dash plots - streams = ["rawAnomaly", "value", "numberOfWinnerCells", "numberOfPredictiveCells", - "valueInput_sparsity", "dateInput_sparsity", "Layer1_SP_overlap_metric", "Layer1_TM_overlap_metric", - "Layer1_SP_activation_frequency", "Layer1_TM_activation_frequency", "Layer1_SP_entropy", - "Layer1_TM_entropy" - ] - - pandaBaker.dataStreams = dict((name, cDataStream()) for name in streams) # create dicts for more comfortable code - # could be also written like: pandaBaker.dataStreams["myStreamName"] = cDataStream() - - pandaBaker.PrepareDatabase() - - - -# WHILE USING PANDAVIS -# SPECIFY HERE FOR WHAT DATA YOU WANT TO RUN THIS DETECTOR -if PANDA_VIS_BAKE_DATA: - import pandas as pd - import os.path as path - from nab.corpus import Corpus - dataDir = path.abspath(path.join(__file__ ,"../../../..","data")) - - corpus = Corpus(dataDir) - - dataSet = corpus.dataFiles["artificialWithAnomaly/art_daily_flatmiddle.csv"] - - detector = HtmcoreDetector(dataSet=dataSet, - probationaryPercent=0.15) - - detector.initialize() - - detector.run() - pandaBaker.CommitBatch() From 755027e4de63bf9d745e6e44cd22c281b08cb92c Mon Sep 17 00:00:00 2001 From: Zbysekz Date: Tue, 15 Sep 2020 11:00:45 +0200 Subject: [PATCH 23/23] Not using spatial anomaly --- nab/detectors/htmcore/htmcore_detector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nab/detectors/htmcore/htmcore_detector.py b/nab/detectors/htmcore/htmcore_detector.py index 7a1dbf4b4..c2dca50d8 100644 --- a/nab/detectors/htmcore/htmcore_detector.py +++ b/nab/detectors/htmcore/htmcore_detector.py @@ -223,7 +223,7 @@ def __init__(self, *args, **kwargs): # useful for checking the efficacy of AnomalyLikelihood. You will need # to re-optimize the thresholds when running with this setting. self.useLikelihood = True - self.useSpatialAnomaly = True + self.useSpatialAnomaly = False self.verbose = True ## internal members