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.useSpatialAnomaly = True self.verbose = True # Set this to true if you want to use the optimization. # If true, it reads the parameters from ./params.json # If false, it reads the parameters from ./best_params.json self.use_optimization = False ## 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, <any other fields specified in `getAdditionalHeaders()`>, ...) """ # Send it to Numenta detector and get back the results return self.modelRun(inputData["timestamp"], inputData["value"]) def initialize(self): # toggle parameters here if self.use_optimization: parameters = get_params('params.json') else: 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"]) scalarEncoderParams = RDSE_Parameters() scalarEncoderParams.size = parameters["enc"]["value"]["size"] scalarEncoderParams.sparsity = parameters["enc"]["value"]["sparsity"] scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] self.encValue = RDSE( 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 ) 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"] ) 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 # 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 @params ts - Timestamp @params val - float input value @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. # 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_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 # 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()
class Layer: def __init__(self, din=(10, 10), dout=(10, 10), temporal=True, setting=param.default_parameters): self.input_shape = din self.output_shape = dout self.temporal = temporal self.learn = True self.setting = AttrDict(setting) self.sp = SpatialPooler() self.tm = TemporalMemory() if temporal else None def compile(self): spParams = self.setting("sp") self.sp = SpatialPooler( inputDimensions=self.input_shape, columnDimensions=self.output_shape, potentialPct=spParams.potentialPct, potentialRadius=spParams.potentialRadius, globalInhibition=True if len(self.output_shape) == 1 else False, localAreaDensity=spParams.localAreaDensity, synPermInactiveDec=spParams.synPermInactiveDec, synPermActiveInc=spParams.synPermActiveInc, synPermConnected=spParams.synPermConnected, boostStrength=spParams.boostStrength, wrapAround=True, ) if self.temporal: tmParams = self.setting("tm") self.tm = TemporalMemory( columnDimensions=self.output_shape, 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) def forward(self, encoding): activeColumns = SDR(self.sp.getColumnDimensions()) self.sp.compute(encoding, self.learn, activeColumns) predictedColumns = None if self.temporal: self.tm.compute(activeColumns, self.learn) self.tm.activateDendrites(self.learn) predictedColumnIndices = { self.tm.columnForCell(i) for i in self.tm.getPredictiveCells().sparse } predictedColumns = SDR(self.sp.getColumnDimensions()) predictedColumns.sparse = list(predictedColumnIndices) return activeColumns, predictedColumns def train(self): self.learn = True def eval(self): self.learn = False def anomaly(self): return float(self.tm.anomaly) if self.temporal else None def reset(self): if self.temporal: self.tm.reset() def save(self, path): print('Saving Model...') print(str(self.sp)) self.sp.saveToFile(param.sp_model.format(path)) if self.temporal: print(str(self.tm)) self.tm.saveToFile(param.tm_model.format(path)) def load(self, path): print('Loading Model...') self.sp.loadFromFile(param.sp_model.format(path)) print(str(self.sp)) if self.temporal: self.tm.loadFromFile(param.tm_model.format(path)) print(str(self.tm))
def main(parameters=default_parameters, argv=None, verbose=True): modelParams = parameters if verbose: import pprint print("Parameters:") pprint.pprint(parameters, indent=4) print("") # Read the input file. records = [] with open(_INPUT_FILE_PATH, "r") as fin: reader = csv.reader(fin) headers = next(reader) next(reader) next(reader) for record in reader: records.append(record) # Make the Encoders. These will convert input data into binary representations. dateEncoder = DateEncoder( timeOfDay=parameters["enc"]["time"]["timeOfDay"], weekend=parameters["enc"]["time"]["weekend"], ) scalarEncoderParams = RDSE_Parameters() scalarEncoderParams.size = parameters["enc"]["value"]["size"] scalarEncoderParams.sparsity = parameters["enc"]["value"]["sparsity"] scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] scalarEncoder = RDSE(scalarEncoderParams) encodingWidth = dateEncoder.size + scalarEncoder.size enc_info = Metrics([encodingWidth], 999999999) # Make the HTM. SpatialPooler & TemporalMemory & associated tools. spParams = parameters["sp"] 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, ) sp_info = Metrics(sp.getColumnDimensions(), 999999999) tmParams = parameters["tm"] 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"], ) tm_info = Metrics([tm.numberOfCells()], 999999999) # setup likelihood, these settings are used in NAB anParams = parameters["anomaly"]["likelihood"] probationaryPeriod = int( math.floor(float(anParams["probationaryPct"]) * len(records))) learningPeriod = int(math.floor(probationaryPeriod / 2.0)) anomaly_history = AnomalyLikelihood( learningPeriod=learningPeriod, estimationSamples=probationaryPeriod - learningPeriod, reestimationPeriod=anParams["reestimationPeriod"], ) predictor = Predictor(steps=[1, 5], alpha=parameters["predictor"]["sdrc_alpha"]) predictor_resolution = 1 # Iterate through every datum in the dataset, record the inputs & outputs. inputs = [] anomaly = [] anomalyProb = [] predictions = {1: [], 5: []} iteration = 0 for count, record in enumerate(records): # Convert date string into Python date object. dateString = datetime.datetime.strptime(record[0], "%m/%d/%y %H:%M") # Convert data value string into float. consumption = float(record[1]) inputs.append(consumption) # Call the encoders to create bit representations for each value. These are SDR objects. dateBits = dateEncoder.encode(dateString) consumptionBits = scalarEncoder.encode(consumption) # Concatenate all these encodings into one large encoding for Spatial Pooling. encoding = SDR(encodingWidth).concatenate([consumptionBits, dateBits]) enc_info.addData(encoding) # 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(sp.getColumnDimensions()) # Execute Spatial Pooling algorithm over input space. sp.compute(encoding, True, activeColumns) sp_info.addData(activeColumns) # Execute Temporal Memory algorithm over active mini-columns. #tm.compute(activeColumns, learn=True) tm.activateDendrites(True) predictiveCellsSDR = tm.getPredictiveCells() tm.activateCells(activeColumns, True) tm_info.addData(tm.getActiveCells().flatten()) activeCells = tm.getActiveCells() #print("ACTIVE"+str(len(activeCells.sparse))) # Predict what will happen, and then train the predictor based on what just happened. pdf = predictor.infer(count, tm.getActiveCells()) for n in (1, 5): if pdf[n]: predictions[n].append(np.argmax(pdf[n]) * predictor_resolution) else: predictions[n].append(float("nan")) predictor.learn(count, tm.getActiveCells(), int(consumption / predictor_resolution)) anomalyLikelihood = anomaly_history.anomalyProbability( consumption, tm.anomaly) anomaly.append(tm.anomaly) anomalyProb.append(anomalyLikelihood) # connectedSynapses = np.zeros(sp.getNumInputs(), dtype=np.int32) # sp.getConnectedSynapses(1, connectedSynapses) # pandaServer.serverData.connectedSynapses = connectedSynapses # print("CONNECTED:") # print("len:"+str(len(connectedSynapses))) # print(connectedSynapses) iteration += 1 if iteration > 50: segments = [] for i in range(tmParams["cellsPerColumn"] * spParams["columnCount"]): segments = tm.connections.segmentsForCell(i) if len(segments) > 0: print("cell:" + str(i)) break presynapticCells = getPresynapticCellsBySegmentsForCell(tm, i) # if len(segments)>0: # print("Segments:"+str(segments)) # # synapses = [] # for seg in segments: # for syn in tm.connections.synapsesForSegment(seg): # synapses += [syn] # # #print("Cell for segment:"+str(tm.connections.cellForSegment(segments[0]))) # # print("Synapses:"+str(synapses)) # presynapticCells = [] # for syn in synapses: # presynapticCells += [tm.connections.presynapticCellForSynapse(syn)] print("Presynaptic cells for that cell:" + str(presynapticCells)) # Print information & statistics about the state of the HTM. print("Encoded Input", enc_info) print("") print("Spatial Pooler Mini-Columns", sp_info) print(str(sp)) print("") print("Temporal Memory Cells", tm_info) print(str(tm)) print("") # Shift the predictions so that they are aligned with the input they predict. for n_steps, pred_list in predictions.items(): for x in range(n_steps): pred_list.insert(0, float("nan")) pred_list.pop() # Calculate the predictive accuracy, Root-Mean-Squared accuracy = {1: 0, 5: 0} accuracy_samples = {1: 0, 5: 0} for idx, inp in enumerate(inputs): for ( n ) in predictions: # For each [N]umber of time steps ahead which was predicted. val = predictions[n][idx] if not math.isnan(val): accuracy[n] += (inp - val)**2 accuracy_samples[n] += 1 for n in sorted(predictions): accuracy[n] = (accuracy[n] / accuracy_samples[n])**0.5 print("Predictive Error (RMS)", n, "steps ahead:", accuracy[n]) # Show info about the anomaly (mean & std) print("Anomaly Mean", np.mean(anomaly)) print("Anomaly Std ", np.std(anomaly)) # Plot the Predictions and Anomalies. if verbose: try: import matplotlib.pyplot as plt except: print( "WARNING: failed to import matplotlib, plots cannot be shown.") return -accuracy[5] plt.subplot(2, 1, 1) plt.title("Predictions") plt.xlabel("Time") plt.ylabel("Power Consumption") plt.plot( np.arange(len(inputs)), inputs, "red", np.arange(len(inputs)), predictions[1], "blue", np.arange(len(inputs)), predictions[5], "green", ) plt.legend(labels=( "Input", "1 Step Prediction, Shifted 1 step", "5 Step Prediction, Shifted 5 steps", )) plt.subplot(2, 1, 2) plt.title("Anomaly Score") plt.xlabel("Time") plt.ylabel("Power Consumption") inputs = np.array(inputs) / max(inputs) plt.plot( np.arange(len(inputs)), inputs, "red", np.arange(len(inputs)), anomaly, "blue", ) plt.legend(labels=("Input", "Anomaly Score")) plt.show() return -accuracy[5]
def main(parameters=default_parameters, argv=None, verbose=True): if verbose: import pprint print("Parameters:") pprint.pprint(parameters, indent=4) print("") # Read the input file. records = [] with open(_INPUT_FILE_PATH, "r") as fin: reader = csv.reader(fin) headers = next(reader) next(reader) next(reader) for record in reader: records.append(record) # Make the Encoders. These will convert input data into binary representations. dateEncoder = DateEncoder(timeOfDay=parameters["enc"]["time"]["timeOfDay"], weekend=parameters["enc"]["time"]["weekend"]) scalarEncoderParams = RDSE_Parameters() scalarEncoderParams.size = parameters["enc"]["value"]["size"] scalarEncoderParams.sparsity = parameters["enc"]["value"]["sparsity"] scalarEncoderParams.resolution = parameters["enc"]["value"]["resolution"] scalarEncoder = RDSE(scalarEncoderParams) encodingWidth = (dateEncoder.size + scalarEncoder.size) enc_info = Metrics([encodingWidth], 999999999) # Make the HTM. SpatialPooler & TemporalMemory & associated tools. spParams = parameters["sp"] 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) sp_info = Metrics(sp.getColumnDimensions(), 999999999) tmParams = parameters["tm"] 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"]) tm_info = Metrics([tm.numberOfCells()], 999999999) # setup likelihood, these settings are used in NAB anParams = parameters["anomaly"]["likelihood"] probationaryPeriod = int( math.floor(float(anParams["probationaryPct"]) * len(records))) learningPeriod = int(math.floor(probationaryPeriod / 2.0)) anomaly_history = AnomalyLikelihood( learningPeriod=learningPeriod, estimationSamples=probationaryPeriod - learningPeriod, reestimationPeriod=anParams["reestimationPeriod"]) predictor = Predictor(steps=[1, 5], alpha=parameters["predictor"]['sdrc_alpha']) predictor_resolution = 1 # Iterate through every datum in the dataset, record the inputs & outputs. inputs = [] anomaly = [] anomalyProb = [] predictions = {1: [], 5: []} for count, record in enumerate(records): # Convert date string into Python date object. dateString = datetime.datetime.strptime(record[0], "%m/%d/%y %H:%M") # Convert data value string into float. consumption = float(record[1]) inputs.append(consumption) # Call the encoders to create bit representations for each value. These are SDR objects. dateBits = dateEncoder.encode(dateString) consumptionBits = scalarEncoder.encode(consumption) # Concatenate all these encodings into one large encoding for Spatial Pooling. encoding = SDR(encodingWidth).concatenate([consumptionBits, dateBits]) enc_info.addData(encoding) # 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(sp.getColumnDimensions()) # Execute Spatial Pooling algorithm over input space. sp.compute(encoding, True, activeColumns) sp_info.addData(activeColumns) # Execute Temporal Memory algorithm over active mini-columns. # tm.compute(activeColumns, learn=True) tm.activateDendrites(True) predictiveCellsSDR = tm.getPredictiveCells() # ------------------HTMpandaVis---------------------- # fill up values serverData.HTMObjects["HTM1"].inputs[ "SL_Consumption"].stringValue = "consumption: {:.2f}".format( consumption) serverData.HTMObjects["HTM1"].inputs[ "SL_Consumption"].bits = consumptionBits.sparse serverData.HTMObjects["HTM1"].inputs[ "SL_Consumption"].count = consumptionBits.size serverData.HTMObjects["HTM1"].inputs[ "SL_TimeOfDay"].stringValue = record[0] serverData.HTMObjects["HTM1"].inputs[ "SL_TimeOfDay"].bits = dateBits.sparse serverData.HTMObjects["HTM1"].inputs[ "SL_TimeOfDay"].count = dateBits.size serverData.HTMObjects["HTM1"].layers[ "SensoryLayer"].activeColumns = activeColumns.sparse serverData.HTMObjects["HTM1"].layers[ "SensoryLayer"].winnerCells = tm.getWinnerCells().sparse serverData.HTMObjects["HTM1"].layers[ "SensoryLayer"].predictiveCells = predictiveCellsSDR.sparse pandaServer.serverData = serverData pandaServer.spatialPoolers["HTM1"] = sp pandaServer.temporalMemories["HTM1"] = tm pandaServer.NewStateDataReady() print("One step finished") while not pandaServer.runInLoop and not pandaServer.runOneStep: pass pandaServer.runOneStep = False print("Proceeding one step...") # ------------------HTMpandaVis---------------------- tm.activateCells(activeColumns, True) tm_info.addData(tm.getActiveCells().flatten()) activeCells = tm.getActiveCells() print("ACTIVE" + str(len(activeCells.sparse))) # Predict what will happen, and then train the predictor based on what just happened. pdf = predictor.infer(tm.getActiveCells()) for n in (1, 5): if pdf[n]: predictions[n].append(np.argmax(pdf[n]) * predictor_resolution) else: predictions[n].append(float('nan')) rawAnomaly = Anomaly.calculateRawAnomaly( activeColumns, tm.cellsToColumns(predictiveCellsSDR)) print("aaa" + str(rawAnomaly)) anomalyLikelihood = anomaly_history.anomalyProbability( consumption, rawAnomaly ) # need to use different calculation as we are not calling sp.compute(..) anomaly.append(rawAnomaly) anomalyProb.append(anomalyLikelihood) predictor.learn(count, tm.getActiveCells(), int(consumption / predictor_resolution)) # Print information & statistics about the state of the HTM. print("Encoded Input", enc_info) print("") print("Spatial Pooler Mini-Columns", sp_info) print(str(sp)) print("") print("Temporal Memory Cells", tm_info) print(str(tm)) print("") # Shift the predictions so that they are aligned with the input they predict. for n_steps, pred_list in predictions.items(): for x in range(n_steps): pred_list.insert(0, float('nan')) pred_list.pop() # Calculate the predictive accuracy, Root-Mean-Squared accuracy = {1: 0, 5: 0} accuracy_samples = {1: 0, 5: 0} for idx, inp in enumerate(inputs): for n in predictions: # For each [N]umber of time steps ahead which was predicted. val = predictions[n][idx] if not math.isnan(val): accuracy[n] += (inp - val)**2 accuracy_samples[n] += 1 for n in sorted(predictions): accuracy[n] = (accuracy[n] / accuracy_samples[n])**.5 print("Predictive Error (RMS)", n, "steps ahead:", accuracy[n]) # Show info about the anomaly (mean & std) print("Anomaly Mean", np.mean(anomaly)) print("Anomaly Std ", np.std(anomaly)) # Plot the Predictions and Anomalies. if verbose: try: import matplotlib.pyplot as plt except: print( "WARNING: failed to import matplotlib, plots cannot be shown.") return -accuracy[5] plt.subplot(2, 1, 1) plt.title("Predictions") plt.xlabel("Time") plt.ylabel("Power Consumption") plt.plot( np.arange(len(inputs)), inputs, 'red', np.arange(len(inputs)), predictions[1], 'blue', np.arange(len(inputs)), predictions[5], 'green', ) plt.legend(labels=('Input', '1 Step Prediction, Shifted 1 step', '5 Step Prediction, Shifted 5 steps')) plt.subplot(2, 1, 2) plt.title("Anomaly Score") plt.xlabel("Time") plt.ylabel("Power Consumption") inputs = np.array(inputs) / max(inputs) plt.plot( np.arange(len(inputs)), inputs, 'red', np.arange(len(inputs)), anomaly, 'blue', ) plt.legend(labels=('Input', 'Anomaly Score')) plt.show() return -accuracy[5]