Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
354a025
Disabled spatial anomaly leads to terrible score for HTMcore
breznak Jul 30, 2019
a51f60d
Revert "Disabled spatial anomaly leads to terrible score for HTMcore"
breznak Aug 3, 2019
d6023e3
Htmcore detector: remove artificial spatial-anomaly code
breznak Aug 3, 2019
3a0c513
WIP tuning score
breznak Aug 3, 2019
ae2e699
htmcore: added date-time encoder fields
breznak Aug 3, 2019
4fe8b48
htmcore: tune params 2
breznak Aug 3, 2019
387b744
tuning SP
breznak Aug 9, 2019
34d369d
Merge branch 'master' into fixing_spatial_anomaly
breznak Oct 4, 2019
09f2839
updating configs
breznak Oct 4, 2019
1767a98
Revert "updating configs"
breznak Oct 4, 2019
353fc81
improve import
breznak Oct 9, 2019
c93715e
Merge branch 'master_community' into fixing_spatial_anomaly
breznak Apr 16, 2020
eaa5828
Merge branch 'master_community' into fixing_spatial_anomaly
breznak Apr 16, 2020
ce9d08e
Merge branch 'master_community' into fixing_spatial_anomaly
breznak Apr 16, 2020
a9bbb7a
optimized params
psteinroe Apr 19, 2020
df537b0
Merge pull request #25 from steinroe/fixing_spatial_anomaly
breznak Apr 19, 2020
5063805
Merge remote-tracking branch 'community/fixing_spatial_anomaly' into …
breznak Apr 19, 2020
fe28a8a
slightly tune SP params
breznak Apr 19, 2020
de2b318
update SP params 2
breznak Apr 19, 2020
aa1d27c
Merge pull request #26 from htm-community/tuning_2
breznak Apr 19, 2020
26fa621
results with SP w numActiveColumnsPerInhArea
breznak Apr 20, 2020
855bb47
Merge branch 'fixing_spatial_anomaly' into fix_sp_anomaly2
breznak Apr 20, 2020
61328b5
update results with the new params
breznak Apr 20, 2020
ea01da4
use original numenta params
psteinroe Apr 20, 2020
31b4a61
Merge pull request #28 from steinroe/fix_sp_anomaly2
breznak Apr 20, 2020
673c8f0
Merge pull request #27 from htm-community/fix_sp_anomaly2
breznak Apr 20, 2020
0f571f4
reintroducing fake spatial anomaly score
psteinroe Apr 20, 2020
05373ac
make spatial tolerance a parameter
psteinroe Apr 20, 2020
a35f872
Merge pull request #29 from steinroe/fixing_spatial_anomaly
breznak Apr 20, 2020
65a61b3
minor fix to enable "reset"
psteinroe Apr 21, 2020
8ad844a
Merge pull request #30 from steinroe/fixing_spatial_anomaly
breznak Apr 21, 2020
20452e4
optimization results
psteinroe Apr 22, 2020
7f73723
Merge pull request #32 from steinroe/fixing_spatial_anomaly
breznak Apr 22, 2020
6e758ca
Merge branch 'master_community' into fixing_spatial_anomaly
breznak Apr 23, 2020
0cc8545
Revert "Merge pull request #33 from Zbysekz/pandaVisImplementation"
breznak Apr 30, 2020
7ee95cd
Merge branch 'undoPandaVis' into fixing_spatial_anomaly
Zbysekz Sep 15, 2020
d72fbe3
Merge pull request #42 from Zbysekz/fixing_spatial_anomaly
breznak Sep 15, 2020
9ef15d4
undo pandaVis implementation
Zbysekz Sep 15, 2020
4d4e594
Merge branch 'fixing_spatial_anomaly' into undo_PandaVis
Zbysekz Sep 15, 2020
755027e
Not using spatial anomaly
Zbysekz Sep 15, 2020
e835f88
Merge pull request #44 from Zbysekz/undo_PandaVis_and_mergeFixSpatial
breznak Sep 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions config/thresholds.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@
},
"htmcore": {
"reward_low_FN_rate": {
"score": -1.6511067861578468,
"threshold": 0.5014187204194446
"score": -20.23461825455344,
"threshold": 0.4984827817170541
},
"reward_low_FP_rate": {
"score": 20.39992539458499,
"threshold": 0.5122987896930875
"score": -10.605039633669087,
"threshold": 0.5005860098292023
},
"standard": {
"score": 30.348893213842153,
"threshold": 0.5014187204194446
"score": 12.765381745446561,
"threshold": 0.4984827817170541
}
},
"htmjava": {
Expand Down
193 changes: 93 additions & 100 deletions nab/detectors/htmcore/htmcore_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -34,50 +34,57 @@

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': {
"value" : # RDSE for value
{'resolution': 0.001,
'size': 4000,
'sparsity': 0.10
},
"time": { # DateTime for timestamps
'timeOfDay': (21, 9.49),
'weekend': 0 #21 TODO try impact of weekend
}},
'predictor': {'sdrc_alpha': 0.1},
'sp': {
'boostStrength': 0.0,
'columnCount': 2048,
'localAreaDensity': 40/2048,
'potentialPct': 0.4,
'synPermActiveInc': 0.003,
'synPermConnected': 0.2,
'synPermInactiveDec': 0.0005},
'tm': {
'activationThreshold': 13,
'cellsPerColumn': 32,
'initialPerm': 0.21,
'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):
Expand All @@ -96,7 +103,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
Expand Down Expand Up @@ -138,59 +144,61 @@ 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.
self.encTimestamp = DateEncoder(timeOfDay= parameters["enc"]["time"]["timeOfDay"],
weekend = parameters["enc"]["time"]["weekend"])
self.encTimestamp = DateEncoder(timeOfDay=parameters["enc"]["time"]["timeOfDay"])

scalarEncoderParams = RDSE_Parameters()
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 = RDSE( 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["columnCount"],),
potentialPct = spParams["potentialPct"],
potentialRadius = encodingWidth,
globalInhibition = True,
localAreaDensity = spParams["localAreaDensity"],
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 )

Expand Down Expand Up @@ -245,22 +253,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
Expand All @@ -271,13 +264,13 @@ 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:
# 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)
6 changes: 3 additions & 3 deletions results/final_results.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": 60.852121191220256,
"reward_low_FP_rate": 45.428862226866734,
"standard": 55.50231971786488
},
"htmjava": {
"reward_low_FN_rate": 70.42407766520115,
Expand Down