public void LearningInLayerTest(int width, int height, string imageName) { // Prepare test output folder var outFolder = EnsureFolderExist(nameof(ImageEncoderTest)); // Prepare input file for test string inputImage = Path.Combine("TestFiles", imageName); // Initialize Image Encoder ImageEncoder encoder = new ImageEncoder(new BinarizerParams { ImageWidth = width, ImageHeight = height }); // Initialize HTMModules int inputBits = width * height; int numColumns = 1024; HtmConfig cfg = new HtmConfig(new int[] { inputBits }, new int[] { numColumns }); var mem = new Connections(cfg); SpatialPoolerMT sp = new SpatialPoolerMT(); sp.Init(mem); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp); //Test Compute method var computeResult = layer1.Compute(inputImage, true) as int[]; var activeCellList = GetActiveCells(computeResult); Debug.WriteLine($"Active Cells computed from Image {inputImage}: {activeCellList}"); }
public void SpatialSequenceLearningExperiment() { var parameters = GetDefaultParams(); parameters.Set(KEY.POTENTIAL_RADIUS, 64 * 64); parameters.Set(KEY.POTENTIAL_PCT, 1.0); parameters.Set(KEY.GLOBAL_INHIBITION, false); parameters.Set(KEY.STIMULUS_THRESHOLD, 0.5); parameters.Set(KEY.INHIBITION_RADIUS, (int)0.25 * 64 * 64); parameters.Set(KEY.LOCAL_AREA_DENSITY, -1); parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.1 * 64 * 64); parameters.Set(KEY.DUTY_CYCLE_PERIOD, 1000000); parameters.Set(KEY.MAX_BOOST, 5); parameters.setInputDimensions(new int[] { 32, 32 }); parameters.setColumnDimensions(new int[] { 64, 64 }); parameters.setNumActiveColumnsPerInhArea(0.02 * 64 * 64); var sp = new SpatialPoolerMT(); var mem = new Connections(); double[] inputSequence = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 }; var inputVectors = GetEncodedSequence(inputSequence, 0.0, 100.0); parameters.apply(mem); sp.Init(mem, UnitTestHelpers.GetMemory()); foreach (var inputVector in inputVectors) { for (int i = 0; i < 3; i++) { var activeIndicies = sp.Compute(inputVector, true, true) as int[]; var activeArray = sp.Compute(inputVector, true, false) as int[]; Debug.WriteLine(Helpers.StringifyVector(activeArray)); Debug.WriteLine(Helpers.StringifyVector(activeIndicies)); } } }
public void TestCortexLayer() { int inputBits = 100; double max = 20; int numColumns = 2048; List <double> inputValues = new List <double>(new double[] { 0.0, 1.0, 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 7.0, 1.0, 9.0, 12.0, 11.0, 12.0, 13.0, 14.0, 11.0, 12.0, 14.0, 5.0, 7.0, 6.0, 9.0, 3.0, 4.0, 3.0, 4.0, 3.0, 4.0 }); int numInputs = inputValues.Distinct().ToList().Count; var inputs = inputValues.ToArray(); Dictionary <string, object> settings = new Dictionary <string, object>() { { "W", 15 }, { "N", inputBits }, { "Radius", -1.0 }, { "MinVal", 0.0 }, { "Periodic", false }, { "Name", "scalar" }, { "ClipInput", false }, { "MaxVal", max } }; EncoderBase encoder = new ScalarEncoder(settings); HtmConfig htmConfig = new HtmConfig(new int[] { inputBits }, new int[] { numColumns }) { Random = new ThreadSafeRandom(42), CellsPerColumn = 25, GlobalInhibition = true, LocalAreaDensity = -1, NumActiveColumnsPerInhArea = 0.02 * numColumns, PotentialRadius = 50, InhibitionRadius = 15, MaxBoost = 10.0, DutyCyclePeriod = 25, MinPctOverlapDutyCycles = 0.75, MaxNewSynapseCount = (int)(0.02 * numColumns), ActivationThreshold = 15, ConnectedPermanence = 0.5, PermanenceDecrement = 0.25, PermanenceIncrement = 0.15, PredictedSegmentDecrement = 0.1 }; Connections memory = new Connections(htmConfig); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(memory, numInputs * 55, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { // Event should be fired when entering the stable state. Debug.WriteLine($"STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { // Ideal SP should never enter unstable state after stable state. Debug.WriteLine($"INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } }, numOfCyclesToWaitOnChange: 25); SpatialPoolerMT spatialPooler = new SpatialPoolerMT(hpa); spatialPooler.Init(memory, UnitTestHelpers.GetMemory()); TemporalMemory temporalMemory = new TemporalMemory(); temporalMemory.Init(memory); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", spatialPooler); layer1.HtmModules.Add("tm", temporalMemory); bool learn = true; int maxCycles = 3500; for (int i = 0; i < maxCycles; i++) { foreach (var input in inputs) { var lyrOut = layer1.Compute(input, learn) as ComputeCycle; } } }
public void InputBitsExperiment(int W, int InputB, int loop) { string filename = "InputBits" + InputB + ".csv"; using (StreamWriter writer = new StreamWriter(filename)) { Debug.WriteLine($"Learning Cycles: {460}"); Debug.WriteLine("Cycle;Similarity"); //Parent Loop for (int j = 0; j < loop; j++) { int inputBits = InputB; bool learn = true; Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.INPUT_DIMENSIONS, new int[] { inputBits }); p.Set(KEY.CELLS_PER_COLUMN, 5); p.Set(KEY.COLUMN_DIMENSIONS, new int[] { 500 }); CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); Dictionary <string, object> settings = new Dictionary <string, object>() { { "W", W }, { "N", inputBits }, { "Radius", -1.0 }, { "MinVal", 0.0 }, // { "MaxVal", 20.0 }, { "Periodic", false }, { "Name", "scalar" }, { "ClipInput", false }, }; double max = 10; List <double> lst = new List <double>(); for (double i = max - 1; i >= 0; i--) { lst.Add(i); } settings["MaxVal"] = max; EncoderBase encoder = new ScalarEncoder(settings); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); // // NewBorn learning stage. region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); HtmClassifier <double, ComputeCycle> cls = new HtmClassifier <double, ComputeCycle>(); double[] inputs = lst.ToArray(); // // This trains SP. foreach (var input in inputs) { Debug.WriteLine($" ** {input} **"); for (int i = 0; i < 3; i++) { var lyrOut = layer1.Compute(input, learn) as ComputeCycle; } } // Here we add TM module to the layer. layer1.HtmModules.Add("tm", tm1); int cycle = 0; int matches = 0; double lastPredictedValue = 0; // // Now, training with SP+TM. SP is pretrained on pattern. //Child loop for (int i = 0; i < 460; i++) { matches = 0; cycle++; foreach (var input in inputs) { var lyrOut = layer1.Compute(input, learn) as ComputeCycle; cls.Learn(input, lyrOut.ActiveCells.ToArray(), lyrOut.PredictiveCells.ToArray()); Debug.WriteLine($"-------------- {input} ---------------"); if (learn == false) { Debug.WriteLine($"Inference mode"); } Debug.WriteLine($"W: {Helpers.StringifyVector(lyrOut.WinnerCells.Select(c => c.Index).ToArray())}"); Debug.WriteLine($"P: {Helpers.StringifyVector(lyrOut.PredictiveCells.Select(c => c.Index).ToArray())}"); var predictedValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| - Predicted value in previous cycle: {lastPredictedValue} \t| Predicted Input for the next cycle: {predictedValue}"); if (input == lastPredictedValue) { matches++; Debug.WriteLine($"Match {input}"); } else { Debug.WriteLine($"Missmatch Actual value: {input} - Predicted value: {lastPredictedValue}"); } lastPredictedValue = predictedValue; } if (i == 500) { Debug.WriteLine("Stop Learning From Here. Entering inference mode."); learn = false; } //tm1.reset(mem); Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {matches / (double)inputs.Length * 100.0}%"); if (matches / (double)inputs.Length == 1) { writer.WriteLine($"{cycle}"); break; } } } Debug.WriteLine("New Iteration"); } //cls.TraceState(); Debug.WriteLine("------------------------------------------------------------------------\n----------------------------------------------------------------------------"); }
/// <summary> /// /// </summary> private void RunExperiment(int inputBits, Parameters p, EncoderBase encoder, List <double> inputValues) { Stopwatch sw = new Stopwatch(); sw.Start(); int maxMatchCnt = 0; bool learn = true; CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); var mem = new Connections(); p.apply(mem); //bool isInStableState = false; //HtmClassifier<double, ComputeCycle> cls = new HtmClassifier<double, ComputeCycle>(); HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); var numInputs = inputValues.Distinct().ToList().Count; TemporalMemory tm1 = new TemporalMemory(); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, numInputs * 55, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { // Event should be fired when entering the stable state. Debug.WriteLine($"STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { // Ideal SP should never enter unstable state after stable state. Debug.WriteLine($"INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } Assert.IsTrue(numPatterns == numInputs); //isInStableState = true; cls.ClearState(); tm1.Reset(mem); }, numOfCyclesToWaitOnChange: 25); SpatialPoolerMT sp1 = new SpatialPoolerMT(hpa); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); layer1.HtmModules.Add("tm", tm1); double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; string lastPredictedValue = "0"; Dictionary <double, List <List <int> > > activeColumnsLst = new Dictionary <double, List <List <int> > >(); foreach (var input in inputs) { if (activeColumnsLst.ContainsKey(input) == false) { activeColumnsLst.Add(input, new List <List <int> >()); } } int maxCycles = 3500; int maxPrevInputs = inputValues.Count - 1; List <string> previousInputs = new List <string>(); previousInputs.Add("-1.0"); // // Now training with SP+TM. SP is pretrained on the given input pattern. for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layer1.Compute(input, learn) as ComputeCycle; var activeColumns = layer1.GetResult("sp") as int[]; activeColumnsLst[input].Add(activeColumns.ToList()); previousInputs.Add(input.ToString()); if (previousInputs.Count > maxPrevInputs + 1) { previousInputs.RemoveAt(0); } string key = GetKey(previousInputs, input); List <Cell> actCells; if (lyrOut.ActiveCells.Count == lyrOut.WinnerCells.Count) { actCells = lyrOut.ActiveCells; } else { actCells = lyrOut.WinnerCells; } cls.Learn(key, actCells.ToArray()); if (learn == false) { Debug.WriteLine($"Inference mode"); } Debug.WriteLine($"Col SDR: {Helpers.StringifyVector(lyrOut.ActivColumnIndicies)}"); Debug.WriteLine($"Cell SDR: {Helpers.StringifyVector(actCells.Select(c => c.Index).ToArray())}"); if (key == lastPredictedValue) { matches++; Debug.WriteLine($"Match. Actual value: {key} - Predicted value: {lastPredictedValue}"); } else { Debug.WriteLine($"Missmatch! Actual value: {key} - Predicted value: {lastPredictedValue}"); } if (lyrOut.PredictiveCells.Count > 0) { var predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {predictedInputValue}"); lastPredictedValue = predictedInputValue; } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); lastPredictedValue = string.Empty; } } // The brain does not do that this way, so we don't use it. // tm1.reset(mem); double accuracy = matches / (double)inputs.Length * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {accuracy}%"); if (accuracy == 100.0) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); if (maxMatchCnt >= 30) { sw.Stop(); Debug.WriteLine($"Exit experiment in the stable state after 30 repeats with 100% of accuracy. Elapsed time: {sw.ElapsedMilliseconds / 1000 / 60} min."); learn = false; //var testInputs = new double[] { 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 7.0, 1.0, 9.0, 12.0, 11.0, 0.0, 1.0 }; // C-0, D-1, E-2, F-3, G-4, H-5 //var testInputs = new double[] { 0.0, 0.0, 4.0, 4.0, 5.0, 5.0, 4.0, 3.0, 3.0, 2.0, 2.0, 1.0, 1.0, 0.0 }; //// Traverse the sequence and check prediction. //foreach (var input in inputValues) //{ // var lyrOut = layer1.Compute(input, learn) as ComputeCycle; // predictedInputValue = cls.GetPredictedInputValue(lyrOut.predictiveCells.ToArray()); // Debug.WriteLine($"I={input} - P={predictedInputValue}"); //} /* * // * // Here we let the HTM predict sequence five times on its own. * // We start with last predicted value. * int cnt = 5 * inputValues.Count; * * Debug.WriteLine("---- Start Predicting the Sequence -----"); * * // * // This code snippet starts with some input value and tries to predict all next inputs * // as they have been learned as a sequence. * // We take a random value to start somwhere in the sequence. * var predictedInputValue = inputValues[new Random().Next(0, inputValues.Count - 1)].ToString(); * * List<string> predictedValues = new List<string>(); * * while (--cnt > 0) * { * //var lyrOut = layer1.Compute(predictedInputValue, learn) as ComputeCycle; * var lyrOut = layer1.Compute(double.Parse(predictedInputValue[predictedInputValue.Length - 1].ToString()), false) as ComputeCycle; * predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); * predictedValues.Add(predictedInputValue); * }; * * // Now we have a sequence of elements and watch in the trace if it matches to defined input set. * foreach (var item in predictedValues) * { * Debug.Write(item); * Debug.Write(" ,"); * }*/ break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } } Debug.WriteLine("---- cell state trace ----"); cls.TraceState($"cellState_MinPctOverlDuty-{p[KEY.MIN_PCT_OVERLAP_DUTY_CYCLES]}_MaxBoost-{p[KEY.MAX_BOOST]}.csv"); Debug.WriteLine("---- Spatial Pooler column state ----"); foreach (var input in activeColumnsLst) { using (StreamWriter colSw = new StreamWriter($"ColumState_MinPctOverlDuty-{p[KEY.MIN_PCT_OVERLAP_DUTY_CYCLES]}_MaxBoost-{p[KEY.MAX_BOOST]}_input-{input.Key}.csv")) { Debug.WriteLine($"------------ {input.Key} ------------"); foreach (var actCols in input.Value) { Debug.WriteLine(Helpers.StringifyVector(actCols.ToArray())); colSw.WriteLine(Helpers.StringifyVector(actCols.ToArray())); } } } Debug.WriteLine("------------ END ------------"); }
public void CategorySequenceExperiment() { bool learn = true; Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.INPUT_DIMENSIONS, new int[] { 100 }); p.Set(KEY.CELLS_PER_COLUMN, 30); string[] categories = new string[] { "A", "B", "C", "D" }; //string[] categories = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L" , "M", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Ö" }; CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); Dictionary <string, object> settings = new Dictionary <string, object>(); //settings.Add("W", 25); settings.Add("N", 100); //settings.Add("Radius", 1); EncoderBase encoder = new CategoryEncoder(categories, settings); //encoder.Encode() CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); //layer1.HtmModules.Add(tm1); //layer1.Compute(); //IClassifier<string, ComputeCycle> cls = new HtmClassifier<string, ComputeCycle>(); HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); HtmUnionClassifier <string, ComputeCycle> cls1 = new HtmUnionClassifier <string, ComputeCycle>(); //string[] inputs = new string[] { "A", "B", "C", "D" }; string[] inputs = new string[] { "A", "B", "C", "D" }; // // This trains SP. foreach (var input in inputs) { Debug.WriteLine($" ** {input} **"); for (int i = 0; i < 3; i++) { var lyrOut = layer1.Compute((object)input, learn) as ComputeCycle; } } // Here we add TM module to the layer. layer1.HtmModules.Add("tm", tm1); // // Now, training with SP+TM. SP is pretrained on pattern. for (int i = 0; i < 200; i++) { foreach (var input in inputs) { var lyrOut = layer1.Compute(input, learn) as ComputeCycle; //cls1.Learn(input, lyrOut.activeCells.ToArray(), learn); //Debug.WriteLine($"Current Input: {input}"); cls.Learn(input, lyrOut.ActiveCells.ToArray()); Debug.WriteLine($"Current Input: {input}"); if (learn == false) { Debug.WriteLine($"Predict Input When Not Learn: {cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray())}"); } else { Debug.WriteLine($"Predict Input: {cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray())}"); } Debug.WriteLine("-----------------------------------------------------------\n----------------------------------------------------------"); } if (i == 10) { Debug.WriteLine("Stop Learning From Here----------------------------"); learn = false; } // tm1.reset(mem); } Debug.WriteLine("------------------------------------------------------------------------\n----------------------------------------------------------------------------"); /* * learn = false; * for (int i = 0; i < 19; i++) * { * foreach (var input in inputs) * { * layer1.Compute((object)input, learn); * } * } */ }
/// <summary> /// /// </summary> private async Task RunExperimentNeuroVisualizer(int inputBits, Parameters p, EncoderBase encoder, List <double> inputValues) { Stopwatch sw = new Stopwatch(); sw.Start(); int maxMatchCnt = 0; bool learn = true; INeuroVisualizer vis = new WSNeuroVisualizer(); GenerateNeuroModel model = new GenerateNeuroModel(); await vis.ConnectToWSServerAsync(); await vis.InitModelAsync(model.CreateNeuroModel(new int[] { 1 }, (long[, ])p[KEY.COLUMN_DIMENSIONS], (int)p[KEY.CELLS_PER_COLUMN])); CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); // // NewBorn learning stage. region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); //HtmClassifier<double, ComputeCycle> cls = new HtmClassifier<double, ComputeCycle>(); HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int maxSPLearningCycles = 50; // // This trains SP on input pattern. // It performs some kind of unsupervised new-born learning. foreach (var input in inputs) { List <(int Cycle, double Similarity)> elementOscilationResult = new List <(int Cycle, double Similarity)>(); Debug.WriteLine($"Learning ** {input} **"); for (int i = 0; i < maxSPLearningCycles; i++) { var lyrOut = layer1.Compute((object)input, learn) as ComputeCycle; var activeColumns = layer1.GetResult("sp") as int[]; var actCols = activeColumns.OrderBy(c => c).ToArray(); var similarity = MathHelpers.CalcArraySimilarity(prevActiveCols, actCols); await vis.UpdateColumnAsync(GetColumns(actCols)); Debug.WriteLine($" {i.ToString("D4")} SP-OUT: [{actCols.Length}/{similarity.ToString("0.##")}] - {Helpers.StringifyVector(actCols)}"); prevActiveCols = activeColumns; } } // Here we add TM module to the layer. layer1.HtmModules.Add("tm", tm1); int cycle = 0; int matches = 0; string lastPredictedValue = "0"; Dictionary <double, List <List <int> > > activeColumnsLst = new Dictionary <double, List <List <int> > >(); foreach (var input in inputs) { if (activeColumnsLst.ContainsKey(input) == false) { activeColumnsLst.Add(input, new List <List <int> >()); } } int maxCycles = 3500; // // Now training with SP+TM. SP is pretrained on the given input pattern. for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Cycle {cycle} ---------------"); string prevInput = "-1.0"; // // Activate the 'New - Born' effect. //if (i == 300) //{ // mem.setMaxBoost(0.0); // mem.updateMinPctOverlapDutyCycles(0.0); // cls.ClearState(); //} foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layer1.Compute(input, learn) as ComputeCycle; var activeColumns = layer1.GetResult("sp") as int[]; activeColumnsLst[input].Add(activeColumns.ToList()); //cls.Learn(input, lyrOut.ActiveCells.ToArray()); cls.Learn(GetKey(prevInput, input), lyrOut.ActiveCells.ToArray()); List <Synapse> synapses = new List <Synapse>(); Cell cell = new Cell(0, 1, 6, 0, CellActivity.ActiveCell); // where to get all these values Synapse synap = new Synapse(cell, 1, 1, 0.78); // here is just supposed to update the permanence, all other values remains same; where do we get all other values synapses.Add(synap); await vis.UpdateSynapsesAsync(synapses); //update Synapse or add new ones await vis.UpdateCellsAsync(GetCells(lyrOut.ActiveCells)); if (learn == false) { Debug.WriteLine($"Inference mode"); } if (GetKey(prevInput, input) == lastPredictedValue) { matches++; Debug.WriteLine($"Match {input}"); } else { Debug.WriteLine($"Missmatch Actual value: {GetKey(prevInput, input)} - Predicted value: {lastPredictedValue}"); } if (lyrOut.PredictiveCells.Count > 0) { var predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {predictedInputValue}"); lastPredictedValue = predictedInputValue; } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); } prevInput = input.ToString(); } //tm1.reset(mem); double accuracy = (double)matches / (double)inputs.Length * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {accuracy}%"); if (accuracy == 100.0) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); if (maxMatchCnt >= 20) { sw.Stop(); Debug.WriteLine($"Exit experiment in the stable state after 10 repeats with 100% of accuracy. Elapsed time: {sw.ElapsedMilliseconds / 1000 / 60} min."); learn = false; //var testInputs = new double[] { 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 7.0, 1.0, 9.0, 12.0, 11.0, 0.0, 1.0 }; // C-0, D-1, E-2, F-3, G-4, H-5 //var testInputs = new double[] { 0.0, 0.0, 4.0, 4.0, 5.0, 5.0, 4.0, 3.0, 3.0, 2.0, 2.0, 1.0, 1.0, 0.0 }; //// Traverse the sequence and check prediction. //foreach (var input in inputValues) //{ // var lyrOut = layer1.Compute(input, learn) as ComputeCycle; // predictedInputValue = cls.GetPredictedInputValue(lyrOut.predictiveCells.ToArray()); // Debug.WriteLine($"I={input} - P={predictedInputValue}"); //} // // Here we let the HTM predict seuence five times on its own. // We start with last predicted value. int cnt = 5 * inputValues.Count; Debug.WriteLine("---- Start Predicting the Sequence -----"); // We take a random value to start somwhere in the sequence. var predictedInputValue = inputValues[new Random().Next(0, inputValues.Count - 1)].ToString(); List <string> predictedValues = new List <string>(); while (--cnt > 0) { //var lyrOut = layer1.Compute(predictedInputValue, learn) as ComputeCycle; var lyrOut = layer1.Compute(double.Parse(predictedInputValue[predictedInputValue.Length - 1].ToString()), learn) as ComputeCycle; predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); predictedValues.Add(predictedInputValue); } ; foreach (var item in predictedValues) { Debug.Write(item); Debug.Write(" ,"); } break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } } Debug.WriteLine("---- cell state trace ----"); cls.TraceState($"cellState_MinPctOverlDuty-{p[KEY.MIN_PCT_OVERLAP_DUTY_CYCLES]}_MaxBoost-{p[KEY.MAX_BOOST]}.csv"); Debug.WriteLine("---- column state trace ----"); foreach (var input in activeColumnsLst) { using (StreamWriter colSw = new StreamWriter($"ColumState_MinPctOverlDuty-{p[KEY.MIN_PCT_OVERLAP_DUTY_CYCLES]}_MaxBoost-{p[KEY.MAX_BOOST]}_input-{input.Key}.csv")) { Debug.WriteLine($"------------ {input} ------------"); foreach (var actCols in input.Value) { Debug.WriteLine(Helpers.StringifyVector(actCols.ToArray())); colSw.WriteLine(Helpers.StringifyVector(actCols.ToArray())); } } } Debug.WriteLine("------------ END ------------"); }
public void SimilarityExperimentWithEncoder() { int stableStateCnt = 100; double minOctOverlapCycles = 1.0; double maxBoost = 10.0; int inputBits = 100; var colDims = new int[] { 64 * 64 }; int numOfActCols = colDims[0]; int numColumns = colDims[0]; string TestOutputFolder = $"Output-{nameof(ImageSimilarityExperiment)}"; Directory.CreateDirectory($"{nameof(ImageSimilarityExperiment)}"); //int counter = 0; //var parameters = GetDefaultParams(); ////parameters.Set(KEY.DUTY_CYCLE_PERIOD, 20); ////parameters.Set(KEY.MAX_BOOST, 1); ////parameters.setInputDimensions(new int[] { imageSize[imSizeIndx], imageSize[imSizeIndx] }); ////parameters.setColumnDimensions(new int[] { topologies[topologyIndx], topologies[topologyIndx] }); ////parameters.setNumActiveColumnsPerInhArea(0.02 * numOfActCols); //parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.06 * 4096); // TODO. Experiment with different sizes //parameters.Set(KEY.POTENTIAL_RADIUS, inputBits); //parameters.Set(KEY.POTENTIAL_PCT, 1.0); //parameters.Set(KEY.GLOBAL_INHIBITION, true); // TODO: Experiment with local inhibition too. Note also the execution time of the experiment. //// Num of active synapces in order to activate the column. //parameters.Set(KEY.STIMULUS_THRESHOLD, 50.0); //parameters.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); //parameters.Set(KEY.SYN_PERM_ACTIVE_INC, 0.05); //parameters.Set(KEY.INHIBITION_RADIUS, (int)0.15 * inputBits); // TODO. check if this has influence in a case of the global inhibition. ALso check how this parameter influences the similarity of SDR. //parameters.Set(KEY.SYN_PERM_CONNECTED, 0.2); //parameters.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 1.0); //parameters.Set(KEY.MIN_PCT_ACTIVE_DUTY_CYCLES, 0.001); //parameters.Set(KEY.DUTY_CYCLE_PERIOD, 100); //parameters.Set(KEY.MAX_BOOST, 10); //parameters.Set(KEY.WRAP_AROUND, true); //parameters.Set(KEY.SEED, 1969); //parameters.setInputDimensions(new int[] {inputBits }); //parameters.setColumnDimensions(colDims); Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.INPUT_DIMENSIONS, new int[] { inputBits }); p.Set(KEY.COLUMN_DIMENSIONS, colDims); p.Set(KEY.CELLS_PER_COLUMN, 10); p.Set(KEY.MAX_BOOST, maxBoost); p.Set(KEY.DUTY_CYCLE_PERIOD, 50); p.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, minOctOverlapCycles); // Global inhibition // N of 40 (40= 0.02*2048 columns) active cells required to activate the segment. p.Set(KEY.GLOBAL_INHIBITION, true); p.setNumActiveColumnsPerInhArea(0.02 * numColumns); p.Set(KEY.POTENTIAL_RADIUS, (int)(.7 * inputBits)); p.Set(KEY.LOCAL_AREA_DENSITY, -1); // In a case of global inhibition. //p.setInhibitionRadius( Automatically set on the columns pace in a case of global inhibition.); // Activation threshold is 10 active cells of 40 cells in inhibition area. p.setActivationThreshold(10); // Max number of synapses on the segment. p.setMaxNewSynapsesPerSegmentCount((int)(0.02 * numColumns)); double max = 20; Dictionary <string, object> settings = new Dictionary <string, object>() { { "W", 15 }, { "N", inputBits }, { "Radius", -1.0 }, { "MinVal", 0.0 }, { "Periodic", false }, { "Name", "scalar" }, { "ClipInput", false }, { "MaxVal", max } }; var encoder = new ScalarEncoder(settings); bool isInStableState = false; var mem = new Connections(); p.apply(mem); var inputs = new int[] { 0, 1, 2, 3, 4, 5 }; HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, inputs.Length * 150, (isStable, numPatterns, actColAvg, seenInputs) => { // Event should only be fired when entering the stable state. // Ideal SP should never enter unstable state after stable state. Assert.IsTrue(isStable); //Assert.IsTrue(numPatterns == inputs.Length); isInStableState = true; Debug.WriteLine($"Entered STABLE state: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); }); SpatialPooler sp = new SpatialPoolerMT(hpa); sp.Init(mem, UnitTestHelpers.GetMemory()); string outFolder = $"{TestOutputFolder}"; Directory.CreateDirectory(outFolder); string outputHamDistFile = $"{outFolder}\\hamming.txt"; string outputActColFile = $"{outFolder}\\activeCol.txt"; using (StreamWriter swHam = new StreamWriter(outputHamDistFile)) { using (StreamWriter swActCol = new StreamWriter(outputActColFile)) { int cycle = 0; Dictionary <string, int[]> sdrs = new Dictionary <string, int[]>(); while (!isInStableState) { foreach (var digit in inputs) { int[] activeArray = new int[numOfActCols]; int[] oldArray = new int[activeArray.Length]; List <double[, ]> overlapArrays = new List <double[, ]>(); List <double[, ]> bostArrays = new List <double[, ]>(); var inputVector = encoder.Encode(digit); sp.compute(inputVector, activeArray, true); string actColFileName = Path.Combine(outFolder, $"{digit}.actcols.txt"); if (cycle == 0 && File.Exists(actColFileName)) { File.Delete(actColFileName); } var activeCols = ArrayUtils.IndexWhere(activeArray, (el) => el == 1); using (StreamWriter swCols = new StreamWriter(actColFileName, true)) { swCols.WriteLine(Helpers.StringifyVector(activeCols)); } Debug.WriteLine($"'Cycle: {cycle} - {digit}'"); Debug.WriteLine($"IN :{Helpers.StringifyVector(inputVector)}"); Debug.WriteLine($"OUT:{Helpers.StringifyVector(activeCols)}\n"); if (isInStableState) { if (--stableStateCnt <= 0) { return; } } /* * if (isInStableState) * { * swActCol.WriteLine($"\nDigit {digit}"); * * sdrs.Add(digit.ToString(), activeCols); * * // * // To be sure that same input produces the same output after entered the stable state. * for (int i = 0; i < 100; i++) * { * activeArray = new int[numOfActCols]; * * sp.compute(inputVector, activeArray, true); * * var distance = MathHelpers.GetHammingDistance(oldArray, activeArray, true); * * var actColsIndxes = ArrayUtils.IndexWhere(activeArray, i => i == 1); * var oldActColsIndxes = ArrayUtils.IndexWhere(oldArray, i => i == 1); * * var similarity = MathHelpers.CalcArraySimilarity(actColsIndxes, oldActColsIndxes); * * swHam.Write($"Digit {digit}: Dist/Similarity: {distance} | {similarity}\t"); * Debug.Write($"Digit {digit}: Dist/Similarity: {distance} | {similarity}\t"); * Debug.WriteLine($"{Helpers.StringifyVector(actColsIndxes)}"); * * if (i > 5 && similarity < 100) * { * * } * * oldArray = new int[numOfActCols]; * activeArray.CopyTo(oldArray, 0); * } * } * * Debug.WriteLine($"Cycle {cycle++}");*/ } cycle++; } CalculateSimilarity(sdrs, null);//todo } } }
public void LearnCSI(int iteration, int colDimSize, int inputDimSize, int Hammingdim) { FolderInit(); Debug.WriteLine("** running learning SP with Continuous Same Inputs feeding"); /************************************************************************************** * |INITIATION| |SPATIALPOOLER| * Setting the parameters variable * changing the KEY's values */ var parameters = GetDefaultParams(); parameters.Set(KEY.POTENTIAL_RADIUS, inputDimSize * inputDimSize); parameters.Set(KEY.POTENTIAL_PCT, 0.75); parameters.Set(KEY.GLOBAL_INHIBITION, true); parameters.Set(KEY.STIMULUS_THRESHOLD, 5);//5 parameters.Set(KEY.INHIBITION_RADIUS, (int)(0.01 * colDimSize * colDimSize)); parameters.Set(KEY.LOCAL_AREA_DENSITY, -1); parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, (int)(0.02 * colDimSize * colDimSize)); parameters.Set(KEY.DUTY_CYCLE_PERIOD, 1000); //1000 parameters.Set(KEY.MAX_BOOST, 10.0); //0 parameters.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); parameters.Set(KEY.SYN_PERM_ACTIVE_INC, 0.05); parameters.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 0.001); parameters.Set(KEY.SEED, 42); parameters.setInputDimensions(new int[] { inputDimSize, inputDimSize }); parameters.setColumnDimensions(new int[] { colDimSize, colDimSize }); var sp = new SpatialPoolerMT(); var mem = new Connections(); //var rnd = new Random(); parameters.apply(mem); sp.Init(mem); /*************************************************************************************** * |LOGICTEST| |CONTINOUS_PATTERN_LEARNING| * Using input from scalar encoder */ List <int[]> inputVectors; double[] inputDoubleArray = GetInputDoubleArray(-100, 100, Hammingdim * Hammingdim); inputVectors = ScalarEncoderDoubleArray(inputDoubleArray, inputDimSize, CSI); int vectorIndex = 0; Debug.WriteLine($"InputVectors.Count = {inputVectors.Count}"); int[][] activeArray = new int[inputVectors.Count][]; foreach (var inputVector in inputVectors) { activeArray[vectorIndex] = new int[colDimSize * colDimSize]; for (int i = 0; i < iteration; i++) { Debug.WriteLine( $"compute VECTOR {vectorIndex} " + $"iter: {i} " + $"val: {NeoCortexApi.Helpers.StringifyVector(inputVector)} "); sp.compute(inputVector, activeArray[vectorIndex], true); } sp.compute(inputVector, activeArray[vectorIndex], false); vectorIndex++; } vectorIndex = 0; foreach (var inputVector in inputVectors) { int[,] arrayDraw = ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(activeArray[vectorIndex], colDimSize, colDimSize)); NeoCortexUtils.DrawBitmap(arrayDraw, OutImgSize, OutImgSize, $"{outputFolder}\\{CSI}\\{SDROuputFolder_CSI}\\Vector_{vectorIndex}.png", Color.FromArgb(44, 44, 44), Color.FromArgb(250, 100, 100), $"No.{vectorIndex} val {inputDoubleArray[vectorIndex]}"); vectorIndex++; } vectorIndex = 0; //************************drawing similarities******************************************* int[] dummyArray = new int[colDimSize * colDimSize]; int[][] diffArray = new int[inputVectors.Count][]; for (int i = 0; i < inputVectors.Count; i++) { sp.compute(inputVectors[i], dummyArray, false); int[,] drawArray = ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(dummyArray, colDimSize, colDimSize)); NeoCortexUtils.DrawBitmap(drawArray, OutImgSize, OutImgSize, $"{outputFolder}\\{CSI}\\{FreshComputed_CSI}\\Vector_{i}.png", Color.FromArgb(44, 44, 44), Color.FromArgb(100, 250, 100), $"No.{i} newCom, Val_{inputDoubleArray[i]}"); diffArray[i] = AddArray(activeArray[i], dummyArray); } foreach (var inputVector in inputVectors) { int[,] arrayDraw = ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(diffArray[vectorIndex], colDimSize, colDimSize)); Debug.WriteLine($"Drawing SDRdiff index : {vectorIndex} ........."); DrawdiffArray(arrayDraw, OutImgSize / colDimSize, $"{outputFolder}\\{CSI}\\{SDROuputDiff_CSI}\\Vector_{vectorIndex}.png", Color.FromArgb(44, 44, 44), Color.FromArgb(100, 100, 250), Color.FromArgb(250, 100, 100), Color.FromArgb(100, 250, 100), $"No.{vectorIndex} val {inputDoubleArray[vectorIndex]}"); vectorIndex++; } //*********** Checking phase with getHammingDistance ************************************ double[] hammingArray = GetHammingArray(inputVectors, activeArray, sp); LogToCSV(hammingArray, inputVectors, $"{CSI}\\{logOutputFolder}\\HammingOutput.csv"); DrawHammingBitmap( ArrayUtils.Make2DArray <double>(hammingArray, Hammingdim, Hammingdim), 50, $"{outputFolder}\\{CSI}\\{logOutputFolder}\\HammingBitmap.png"); }
/// <summary> /// Implements the experiment. /// </summary> /// <param name="cfg"></param> /// <param name="encoder"></param> /// <param name="inputValues"></param> private static void RunExperiment(HtmConfig cfg, EncoderBase encoder, List <int[]> inputValues) { // Creates the htm memory. var mem = new Connections(cfg); bool isInStableState = false; // // HPC extends the default Spatial Pooler algorithm. // The purpose of HPC is to set the SP in the new-born stage at the begining of the learning process. // In this stage the boosting is very active, but the SP behaves instable. After this stage is over // (defined by the second argument) the HPC is controlling the learning process of the SP. // Once the SDR generated for every input gets stable, the HPC will fire event that notifies your code // that SP is stable now. HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, inputValues.Count * 40, (isStable, numPatterns, actColAvg, seenInputs) => { // Event should only be fired when entering the stable state. // Ideal SP should never enter unstable state after stable state. if (isStable == false) { Debug.WriteLine($"INSTABLE STATE"); // This should usually not happen. isInStableState = false; } else { Debug.WriteLine($"STABLE STATE"); // Here you can perform any action if required. isInStableState = true; } }, requiredSimilarityThreshold: 0.975); // It creates the instance of Spatial Pooler Multithreaded version. SpatialPooler sp = new SpatialPoolerMT(hpa); // Initializes the sp.Init(mem); // Holds the indicies of active columns of the SDR. Dictionary <string, int[]> prevActiveColIndicies = new Dictionary <string, int[]>(); // Holds the active column SDRs. Dictionary <string, int[]> prevActiveCols = new Dictionary <string, int[]>(); // Will hold the similarity of SDKk and SDRk-1 fro every input. Dictionary <string, double> prevSimilarity = new Dictionary <string, double>(); // // Initiaize start similarity to zero. for (int i = 0; i < inputValues.Count; i++) { string inputKey = GetInputGekFromIndex(i); prevSimilarity.Add(inputKey, 0.0); prevActiveColIndicies.Add(inputKey, new int[0]); } // Learning process will take 1000 iterations (cycles) int maxSPLearningCycles = 1000; for (int cycle = 0; cycle < maxSPLearningCycles; cycle++) { //Debug.WriteLine($"Cycle ** {cycle} ** Stability: {isInStableState}"); // // This trains the layer on input pattern. for (int inputIndx = 0; inputIndx < inputValues.Count; inputIndx++) { string inputKey = GetInputGekFromIndex(inputIndx); int[] input = inputValues[inputIndx]; double similarity; int[] activeColumns = new int[(int)cfg.NumColumns]; // Learn the input pattern. // Output lyrOut is the output of the last module in the layer. sp.compute(input, activeColumns, true); // DrawImages(cfg, inputKey, input, activeColumns); var actColsIndicies = ArrayUtils.IndexWhere(activeColumns, c => c == 1); similarity = MathHelpers.CalcArraySimilarity(actColsIndicies, prevActiveColIndicies[inputKey]); Debug.WriteLine($"[i={inputKey}, cols=:{actColsIndicies.Length} s={similarity}] SDR: {Helpers.StringifyVector(actColsIndicies)}"); prevActiveCols[inputKey] = activeColumns; prevActiveColIndicies[inputKey] = actColsIndicies; prevSimilarity[inputKey] = similarity; if (isInStableState) { GenerateResult(cfg, inputValues, prevActiveColIndicies, prevActiveCols); return; } } } }
public void NoiseExperimentTest() { const int colDimSize = 64; const int noiseStepPercent = 5; var parameters = GetDefaultParams(); parameters.Set(KEY.POTENTIAL_RADIUS, 32 * 32); parameters.Set(KEY.POTENTIAL_PCT, 1.0); parameters.Set(KEY.GLOBAL_INHIBITION, true); parameters.Set(KEY.STIMULUS_THRESHOLD, 0.5); parameters.Set(KEY.INHIBITION_RADIUS, (int)0.01 * colDimSize * colDimSize); parameters.Set(KEY.LOCAL_AREA_DENSITY, -1); parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.02 * colDimSize * colDimSize); parameters.Set(KEY.DUTY_CYCLE_PERIOD, 1000); parameters.Set(KEY.MAX_BOOST, 0.0); parameters.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); parameters.Set(KEY.SYN_PERM_ACTIVE_INC, 0.01); parameters.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 0.0); parameters.Set(KEY.SEED, 42); parameters.setInputDimensions(new int[] { 32, 32 }); parameters.setColumnDimensions(new int[] { colDimSize, colDimSize }); var sp = new SpatialPoolerMT(); var mem = new Connections(); parameters.apply(mem); sp.Init(mem); List <int[]> inputVectors = new List <int[]>(); inputVectors.Add(getInputVector1()); inputVectors.Add(getInputVector2()); int vectorIndex = 0; int[][] activeColumnsWithZeroNoise = new int[inputVectors.Count][]; foreach (var inputVector in inputVectors) { var x = getNumBits(inputVector); Debug.WriteLine(""); Debug.WriteLine($"----- VECTOR {vectorIndex} ----------"); // Array of active columns with zero noise. The reference (ideal) output. activeColumnsWithZeroNoise[vectorIndex] = new int[colDimSize * colDimSize]; int[] activeArray = null; for (int j = 0; j < 25; j += noiseStepPercent) { Debug.WriteLine($"--- Vector {0} - Noise Iteration {j} ----------"); int[] noisedInput; if (j > 0) { noisedInput = ArrayUtils.FlipBit(inputVector, (double)((double)j / 100.00)); } else { noisedInput = inputVector; } // TODO: Try CalcArraySimilarity var d = MathHelpers.GetHammingDistance(inputVector, noisedInput, true); Debug.WriteLine($"Input with noise {j} - HamDist: {d}"); Debug.WriteLine($"Original: {Helpers.StringifyVector(inputVector)}"); Debug.WriteLine($"Noised: {Helpers.StringifyVector(noisedInput)}"); for (int i = 0; i < 10; i++) { activeArray = sp.Compute(noisedInput, true, returnActiveColIndiciesOnly: false) as int[]; if (j > 0) { Debug.WriteLine($"{ MathHelpers.GetHammingDistance(activeColumnsWithZeroNoise[vectorIndex], activeArray, true)} -> {Helpers.StringifyVector(ArrayUtils.IndexWhere(activeArray, (el) => el == 1))}"); } } if (j == 0) { Array.Copy(activeArray, activeColumnsWithZeroNoise[vectorIndex], activeColumnsWithZeroNoise[vectorIndex].Length); } var activeCols = ArrayUtils.IndexWhere(activeArray, (el) => el == 1); var d2 = MathHelpers.GetHammingDistance(activeColumnsWithZeroNoise[vectorIndex], activeArray, true); Debug.WriteLine($"Output with noise {j} - Ham Dist: {d2}"); Debug.WriteLine($"Original: {Helpers.StringifyVector(ArrayUtils.IndexWhere(activeColumnsWithZeroNoise[vectorIndex], (el) => el == 1))}"); Debug.WriteLine($"Noised: {Helpers.StringifyVector(ArrayUtils.IndexWhere(activeArray, (el) => el == 1))}"); List <int[, ]> arrays = new List <int[, ]>(); int[,] twoDimenArray = ArrayUtils.Make2DArray <int>(activeArray, 64, 64); twoDimenArray = ArrayUtils.Transpose(twoDimenArray); arrays.Add(ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(noisedInput, 32, 32))); arrays.Add(ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(activeArray, 64, 64))); // NeoCortexUtils.DrawHeatmaps(bostArrays, $"{outputImage}_boost.png", 1024, 1024, 150, 50, 5); NeoCortexUtils.DrawBitmaps(arrays, $"Vector_{vectorIndex}_Noise_{j * 10}.png", Color.Yellow, Color.Gray, OutImgSize, OutImgSize); } vectorIndex++; } vectorIndex = OutputPredictionResult(sp, inputVectors, activeColumnsWithZeroNoise); }
/// <summary> /// /// </summary> private void RunExperiment(int inputBits, HtmConfig cfg, EncoderBase encoder, List <double> inputValues) { Stopwatch sw = new Stopwatch(); sw.Start(); int maxMatchCnt = 0; bool learn = true; var mem = new Connections(cfg); bool isInStableState = false; HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); var numInputs = inputValues.Distinct <double>().ToList().Count; CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); TemporalMemory tm = new TemporalMemory(); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, numInputs * 150, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { // Event should be fired when entering the stable state. Debug.WriteLine($"STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { // Ideal SP should never enter unstable state after stable state. Debug.WriteLine($"INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } // We are not learning in instable state. learn = isInStableState = isStable; //if (isStable && layer1.HtmModules.ContainsKey("tm") == false) // layer1.HtmModules.Add("tm", tm); // Clear all learned patterns in the classifier. cls.ClearState(); // Clear active and predictive cells. //tm.Reset(mem); }, numOfCyclesToWaitOnChange: 50); SpatialPoolerMT sp = new SpatialPoolerMT(hpa); sp.Init(mem); tm.Init(mem); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp); double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; string lastPredictedValue = "0"; //Dictionary<double, List<List<int>>> activeColumnsLst = new Dictionary<double, List<List<int>>>(); //foreach (var input in inputs) //{ // if (activeColumnsLst.ContainsKey(input) == false) // activeColumnsLst.Add(input, new List<List<int>>()); //} int maxCycles = 3500; int maxPrevInputs = inputValues.Count - 1; List <string> previousInputs = new List <string>(); previousInputs.Add("-1.0"); // // Training SP to get stable. New-born stage. // for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Newborn Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($" -- {input} --"); var lyrOut = layer1.Compute(input, learn); if (isInStableState) { break; } } if (isInStableState) { break; } } layer1.HtmModules.Add("tm", tm); // // Now training with SP+TM. SP is pretrained on the given input pattern set. for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layer1.Compute(input, learn) as ComputeCycle; // lyrOut is null when the TM is added to the layer inside of HPC callback by entering of the stable state. //if (isInStableState && lyrOut != null) { var activeColumns = layer1.GetResult("sp") as int[]; //layer2.Compute(lyrOut.WinnerCells, true); //activeColumnsLst[input].Add(activeColumns.ToList()); previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } // In the pretrained SP with HPC, the TM will quickly learn cells for patterns // In that case the starting sequence 4-5-6 might have the sam SDR as 1-2-3-4-5-6, // Which will result in returning of 4-5-6 instead of 1-2-3-4-5-6. // HtmClassifier allways return the first matching sequence. Because 4-5-6 will be as first // memorized, it will match as the first one. if (previousInputs.Count < maxPrevInputs) { continue; } string key = GetKey(previousInputs, input); List <Cell> actCells; if (lyrOut.ActiveCells.Count == lyrOut.WinnerCells.Count) { actCells = lyrOut.ActiveCells; } else { actCells = lyrOut.WinnerCells; } cls.Learn(key, actCells.ToArray()); if (learn == false) { Debug.WriteLine($"Inference mode"); } Debug.WriteLine($"Col SDR: {Helpers.StringifyVector(lyrOut.ActivColumnIndicies)}"); Debug.WriteLine($"Cell SDR: {Helpers.StringifyVector(actCells.Select(c => c.Index).ToArray())}"); if (key == lastPredictedValue) { matches++; Debug.WriteLine($"Match. Actual value: {key} - Predicted value: {lastPredictedValue}"); } else { Debug.WriteLine($"Missmatch! Actual value: {key} - Predicted value: {lastPredictedValue}"); } if (lyrOut.PredictiveCells.Count > 0) { var predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {predictedInputValue}"); lastPredictedValue = predictedInputValue; } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); lastPredictedValue = String.Empty; } } } // The brain does not do that this way, so we don't use it. // tm1.reset(mem); double accuracy = (double)matches / (double)inputs.Length * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {accuracy}%"); if (accuracy == 100.0) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); // // Experiment is completed if we are 30 cycles long at the 100% accuracy. if (maxMatchCnt >= 30) { sw.Stop(); Debug.WriteLine($"Exit experiment in the stable state after 30 repeats with 100% of accuracy. Elapsed time: {sw.ElapsedMilliseconds / 1000 / 60} min."); learn = false; break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } } Debug.WriteLine("------------ END ------------"); }
/// <summary> /// /// </summary> private static void RunExperiment(int inputBits, HtmConfig cfg, EncoderBase encoder, List <double> inputValues) { Stopwatch sw = new Stopwatch(); sw.Start(); int maxMatchCnt = 0; bool learn = true; CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); var mem = new Connections(cfg); bool isInStableState; HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); var numInputs = inputValues.Distinct <double>().ToList().Count; TemporalMemory tm1 = new TemporalMemory(); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, numInputs * 55, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { // Event should be fired when entering the stable state. Debug.WriteLine($"STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { // Ideal SP should never enter unstable state after stable state. Debug.WriteLine($"INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } if (numPatterns != numInputs) { throw new InvalidOperationException("Stable state must observe all input patterns"); } isInStableState = true; cls.ClearState(); tm1.Reset(mem); }, numOfCyclesToWaitOnChange: 25); SpatialPoolerMT sp1 = new SpatialPoolerMT(hpa); sp1.Init(mem, new DistributedMemory() { ColumnDictionary = new InMemoryDistributedDictionary <int, NeoCortexApi.Entities.Column>(1), }); tm1.Init(mem); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); layer1.HtmModules.Add("tm", tm1); double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; string lastPredictedValue = "0"; String prediction = null; Dictionary <double, List <List <int> > > activeColumnsLst = new Dictionary <double, List <List <int> > >(); foreach (var input in inputs) { if (activeColumnsLst.ContainsKey(input) == false) { activeColumnsLst.Add(input, new List <List <int> >()); } } int maxCycles = 3500; int maxPrevInputs = inputValues.Count - 1; List <string> previousInputs = new List <string>(); previousInputs.Add("-1.0"); // // Now training with SP+TM. SP is pretrained on the given input pattern. for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layer1.Compute(input, learn) as ComputeCycle; var activeColumns = layer1.GetResult("sp") as int[]; activeColumnsLst[input].Add(activeColumns.ToList()); previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } string key = GetKey(previousInputs, input); cls.Learn(key, lyrOut.ActiveCells.ToArray()); if (learn == false) { Debug.WriteLine($"Inference mode"); } Debug.WriteLine($"Col SDR: {Helpers.StringifyVector(lyrOut.ActivColumnIndicies)}"); Debug.WriteLine($"Cell SDR: {Helpers.StringifyVector(lyrOut.ActiveCells.Select(c => c.Index).ToArray())}"); if (key == lastPredictedValue) { matches++; Debug.WriteLine($"Match. Actual value: {key} - Predicted value: {lastPredictedValue}"); } else { Debug.WriteLine($"Missmatch! Actual value: {key} - Predicted value: {lastPredictedValue}"); } if (lyrOut.PredictiveCells.Count > 0) { var predictedInputValue = cls.GetPredictedInputValues(lyrOut.PredictiveCells.ToArray(), 3); Debug.WriteLine($"Current Input: {input}"); Debug.WriteLine("The predictions with similarity greater than 50% are"); foreach (var t in predictedInputValue) { if (t.Similarity >= (double)50.00) { Debug.WriteLine($"Predicted Input: {string.Join(", ", t.PredictedInput)},\tSimilarity Percentage: {string.Join(", ", t.Similarity)}, \tNumber of Same Bits: {string.Join(", ", t.NumOfSameBits)}"); } } lastPredictedValue = predictedInputValue.First().PredictedInput; } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); lastPredictedValue = String.Empty; } } double accuracy = (double)matches / (double)inputs.Length * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {accuracy}%"); if (accuracy == 100.0) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); if (maxMatchCnt >= 30) { sw.Stop(); Debug.WriteLine($"Exit experiment in the stable state after 30 repeats with 100% of accuracy. Elapsed time: {sw.ElapsedMilliseconds / 1000 / 60} min."); learn = false; break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } } Debug.WriteLine("---- cell state trace ----"); cls.TraceState($"cellState_MinPctOverlDuty-{cfg.MinPctOverlapDutyCycles}_MaxBoost-{cfg.MaxBoost}.csv"); Debug.WriteLine("---- Spatial Pooler column state ----"); foreach (var input in activeColumnsLst) { using (StreamWriter colSw = new StreamWriter($"ColumState_MinPctOverlDuty-{cfg.MinPctOverlapDutyCycles}_MaxBoost-{cfg.MaxBoost}_input-{input.Key}.csv")) { Debug.WriteLine($"------------ {input.Key} ------------"); foreach (var actCols in input.Value) { Debug.WriteLine(Helpers.StringifyVector(actCols.ToArray())); colSw.WriteLine(Helpers.StringifyVector(actCols.ToArray())); } } } Debug.WriteLine("------------ END ------------"); Console.WriteLine("\n Please enter a number that has been learnt"); int inputNumber = Convert.ToInt16(Console.ReadLine()); Inference(inputNumber, false, layer1, cls); }
/// <summary> /// Implements the experiment. /// </summary> /// <param name="cfg"></param> /// <param name="encoder"></param> /// <param name="inputValues"></param> private static void RunExperiment(HtmConfig cfg, EncoderBase encoder, List <double> inputValues) { // Creates the htm memory. var mem = new Connections(cfg); bool isInStableState = false; // // HPC extends the default Spatial Pooler algorithm. // The purpose of HPC is to set the SP in the new-born stage at the begining of the learning process. // In this stage the boosting is very active, but the SP behaves instable. After this stage is over // (defined by the second argument) the HPC is controlling the learning process of the SP. // Once the SDR generated for every input gets stable, the HPC will fire event that notifies your code // that SP is stable now. HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, inputValues.Count * 15, (isStable, numPatterns, actColAvg, seenInputs) => { // Event should only be fired when entering the stable state. // Ideal SP should never enter unstable state after stable state. if (isStable == false) { Debug.WriteLine($"INSTABLE"); // This should usually not happen. isInStableState = false; } else { Debug.WriteLine($"STABILITY"); // Here you can perform any action if required. isInStableState = true; } }); // It creates the instance of Spatial Pooler Multithreaded version. SpatialPooler sp = new SpatialPoolerMT(hpa); // Initializes the sp.Init(mem, new DistributedMemory() { ColumnDictionary = new InMemoryDistributedDictionary <int, NeoCortexApi.Entities.Column>(1) }); // It creates the instance of the neo-cortex layer. // Algorithm will be performed inside of that layer. CortexLayer <object, object> cortexLayer = new CortexLayer <object, object>("L1"); // Add encoder as the very first module. This model is connected to the sensory input cells // that receive the input. Encoder will receive the input and forward the encoded signal // to the next module. cortexLayer.HtmModules.Add("encoder", encoder); // The next module in the layer is Spatial Pooler. This module will receive the output of the // encoder. cortexLayer.HtmModules.Add("sp", sp); double[] inputs = inputValues.ToArray(); // Will hold the SDR of every inputs. Dictionary <double, int[]> prevActiveCols = new Dictionary <double, int[]>(); // Will hold the similarity of SDKk and SDRk-1 fro every input. Dictionary <double, double> prevSimilarity = new Dictionary <double, double>(); // // Initiaize start similarity to zero. foreach (var input in inputs) { prevSimilarity.Add(input, 0.0); prevActiveCols.Add(input, new int[0]); } // Learning process will take 1000 iterations (cycles) int maxSPLearningCycles = 1000; for (int cycle = 0; cycle < maxSPLearningCycles; cycle++) { Debug.WriteLine($"Cycle ** {cycle} ** Stability: {isInStableState}"); // // This trains the layer on input pattern. foreach (var input in inputs) { double similarity; // Learn the input pattern. // Output lyrOut is the output of the last module in the layer. // var lyrOut = cortexLayer.Compute((object)input, true) as int[]; // This is a general way to get the SpatialPooler result from the layer. var activeColumns = cortexLayer.GetResult("sp") as int[]; var actCols = activeColumns.OrderBy(c => c).ToArray(); similarity = MathHelpers.CalcArraySimilarity(activeColumns, prevActiveCols[input]); Debug.WriteLine($"[cycle={cycle.ToString("D4")}, i={input}, cols=:{actCols.Length} s={similarity}] SDR: {Helpers.StringifyVector(actCols)}"); prevActiveCols[input] = activeColumns; prevSimilarity[input] = similarity; } } }
private void RunExperiment(int inputBits, HtmConfig cfgL4, EncoderBase encoder, List <double> inputValues, HtmConfig cfgL2) { Stopwatch swL2 = new Stopwatch(); //int maxMatchCnt = 0; bool learn = true; bool isSP1Stable = false; bool isSP2STable = false; var memL4 = new Connections(cfgL4); var memL2 = new Connections(cfgL2); var numInputs = inputValues.Distinct <double>().ToList().Count; HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); layerL4 = new CortexLayer <object, object>("L4"); layerL2 = new CortexLayer <object, object>("L2"); tm4 = new TemporalMemoryMT(); tm2 = new TemporalMemoryMT(); // // HPC for Layer 4 SP HomeostaticPlasticityController hpa_sp_L4 = new HomeostaticPlasticityController(memL4, numInputs * 50, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { Debug.WriteLine($"SP L4 STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { Debug.WriteLine($"SP L4 INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } learn = isSP1Stable = isStable; //cls.ClearState(); }, numOfCyclesToWaitOnChange: 50); // // HPC for Layer 2 SP HomeostaticPlasticityController hpa_sp_L2 = new HomeostaticPlasticityController(memL2, numInputs * 50, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { Debug.WriteLine($"SP L2 STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { Debug.WriteLine($"SP L2 INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } learn = isSP2STable = isStable; //cls.ClearState(); }, numOfCyclesToWaitOnChange: 50); SpatialPooler sp4 = new SpatialPoolerMT(hpa_sp_L4); SpatialPooler sp2 = new SpatialPoolerMT(hpa_sp_L2); sp4.Init(memL4); sp2.Init(memL2); // memL2.TraceInputPotential(); tm4.Init(memL4); tm2.Init(memL2); layerL4.HtmModules.Add("encoder", encoder); layerL4.HtmModules.Add("sp", sp4); layerL4.HtmModules.Add("tm", tm4); layerL2.HtmModules.Add("sp", sp2); layerL2.HtmModules.Add("tm", tm2); int[] inpCellsL4ToL2 = new int[cfgL4.CellsPerColumn * cfgL4.NumColumns]; double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; // string lastPredictedValue = "0"; int maxCycles = 3500; int maxPrevInputs = inputValues.Count - 1; List <string> previousInputs = new List <string>(); // // Training SP at Layer 4 to get stable. New-born stage. // using (StreamWriter swL4Sdrs = new StreamWriter($"L4-SDRs-in_{cfgL2.NumInputs}-col_{cfgL2.NumColumns}-r_{cfgL2.PotentialRadius}.txt")) { using (StreamWriter sw = new StreamWriter($"in_{cfgL2.NumInputs}-col_{cfgL2.NumColumns}-r_{cfgL2.PotentialRadius}.txt")) { for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Newborn Cycle {cycle} at L4 SP region ---------------"); foreach (var input in inputs) { Debug.WriteLine($" INPUT: '{input}'\tCycle:{cycle}"); Debug.Write("L4: "); var lyrOut = layerL4.Compute(input, learn); InitArray(inpCellsL4ToL2, 0); if (isSP1Stable) { var cellSdrL4Indexes = memL4.ActiveCells.Select(c => c.Index).ToArray(); // Write SDR as output of L4 and input of L2 swL4Sdrs.WriteLine($"{input} - {Helpers.StringifyVector(cellSdrL4Indexes)}"); // Set the output active cell array ArrayUtils.SetIndexesTo(inpCellsL4ToL2, cellSdrL4Indexes, 1); Debug.Write("L2: "); swL2.Restart(); layerL2.Compute(inpCellsL4ToL2, true); swL2.Stop(); Debug.WriteLine($"{swL2.ElapsedMilliseconds / 1000}"); sw.WriteLine($"{swL2.ElapsedMilliseconds / 1000}"); sw.Flush(); Debug.WriteLine($"L4 out sdr: {Helpers.StringifyVector(cellSdrL4Indexes)}"); var overlaps = ArrayUtils.IndexWhere(memL2.Overlaps, o => o > 0); var strOverlaps = Helpers.StringifyVector(overlaps); Debug.WriteLine($"Potential columns: {overlaps.Length}, overlaps: {strOverlaps}"); } if (isSP1Stable && isSP2STable) { break; } } } } } Debug.WriteLine($"-------------- L4 SP region is {isSP1Stable} ---------------"); //layerL4.HtmModules.Add("tm", tm4); // SP+TM at L4 for (int i = 0; i < maxCycles; i++) { matches -= 0; cycle++; Debug.WriteLine($"-------------- L4 TM Train region Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layerL4.Compute(input, learn) as ComputeCycle; previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } if (previousInputs.Count < maxPrevInputs) { continue; } if (lyrOut.ActiveCells.Count == lyrOut.WinnerCells.Count) { /*var activeColumns = L4.GetResult("sp") as int[]; * foreach (var item in activeColumns) * { * L2.Compute(item, true); * }*/ // Reset tha array InitArray(inpCellsL4ToL2, 0); // Set the output active cell array ArrayUtils.SetIndexesTo(inpCellsL4ToL2, memL4.ActiveCells.Select(c => c.Index).ToArray(), 1); // 4102,25072, 25363, 25539, 25738, 25961, 26009, 26269, 26491, 26585, 26668, 26920, 26934, 27040, 27107, 27262, 27392, 27826, 27948, 28174, 28243, 28270, 28294, 28308, 28429, 28577, 28671, 29139, 29618, 29637, 29809, 29857, 29897, 29900, 29969, 30057, 30727, 31111, 49805, 49972, layerL2.Compute(inpCellsL4ToL2, true); /*foreach (var item in lyrOut.ActiveCells) * { * L2.Compute(item, true); * }*/ //var activeCell = Helpers.StringifyVector(lyrOut.ActiveCells.Select(c => c.Index).ToArray()); //L2.Compute(activeCell, true); } } } }
/// <summary> /// /// </summary> private HtmPredictionEngine RunExperiment(int inputBits, HtmConfig cfg, EncoderBase encoder, Dictionary <string, List <double> > sequences) { Stopwatch sw = new Stopwatch(); sw.Start(); int maxMatchCnt = 0; var mem = new Connections(cfg); bool isInStableState = false; HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); var numUniqueInputs = GetNumberOfInputs(sequences); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); TemporalMemory tm = new TemporalMemory(); // For more information see following paper: https://www.scitepress.org/Papers/2021/103142/103142.pdf HomeostaticPlasticityController hpc = new HomeostaticPlasticityController(mem, numUniqueInputs * 150, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { // Event should be fired when entering the stable state. Debug.WriteLine($"STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { // Ideal SP should never enter unstable state after stable state. Debug.WriteLine($"INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } // We are not learning in instable state. isInStableState = isStable; // Clear active and predictive cells. //tm.Reset(mem); }, numOfCyclesToWaitOnChange: 50); SpatialPoolerMT sp = new SpatialPoolerMT(hpc); sp.Init(mem); tm.Init(mem); // Please note that we do not add here TM in the layer. // This is omitted for practical reasons, because we first eneter the newborn-stage of the algorithm // In this stage we want that SP get boosted and see all elements before we start learning with TM. // All would also work fine with TM in layer, but it would work much slower. // So, to improve the speed of experiment, we first ommit the TM and then after the newborn-stage we add it to the layer. layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp); //double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; var lastPredictedValues = new List <string>(new string[] { "0" }); int maxCycles = 3500; // // Training SP to get stable. New-born stage. // for (int i = 0; i < maxCycles && isInStableState == false; i++) { matches = 0; cycle++; Debug.WriteLine($"-------------- Newborn Cycle {cycle} ---------------"); foreach (var inputs in sequences) { foreach (var input in inputs.Value) { Debug.WriteLine($" -- {inputs.Key} - {input} --"); var lyrOut = layer1.Compute(input, true); if (isInStableState) { break; } } if (isInStableState) { break; } } } // Clear all learned patterns in the classifier. cls.ClearState(); // We activate here the Temporal Memory algorithm. layer1.HtmModules.Add("tm", tm); // // Loop over all sequences. foreach (var sequenceKeyPair in sequences) { Debug.WriteLine($"-------------- Sequences {sequenceKeyPair.Key} ---------------"); int maxPrevInputs = sequenceKeyPair.Value.Count - 1; List <string> previousInputs = new List <string>(); previousInputs.Add("-1.0"); // // Now training with SP+TM. SP is pretrained on the given input pattern set. for (int i = 0; i < maxCycles; i++) { matches = 0; cycle++; Debug.WriteLine(""); Debug.WriteLine($"-------------- Cycle {cycle} ---------------"); Debug.WriteLine(""); foreach (var input in sequenceKeyPair.Value) { Debug.WriteLine($"-------------- {input} ---------------"); var lyrOut = layer1.Compute(input, true) as ComputeCycle; var activeColumns = layer1.GetResult("sp") as int[]; previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } // In the pretrained SP with HPC, the TM will quickly learn cells for patterns // In that case the starting sequence 4-5-6 might have the sam SDR as 1-2-3-4-5-6, // Which will result in returning of 4-5-6 instead of 1-2-3-4-5-6. // HtmClassifier allways return the first matching sequence. Because 4-5-6 will be as first // memorized, it will match as the first one. if (previousInputs.Count < maxPrevInputs) { continue; } string key = GetKey(previousInputs, input, sequenceKeyPair.Key); List <Cell> actCells; if (lyrOut.ActiveCells.Count == lyrOut.WinnerCells.Count) { actCells = lyrOut.ActiveCells; } else { actCells = lyrOut.WinnerCells; } cls.Learn(key, actCells.ToArray()); Debug.WriteLine($"Col SDR: {Helpers.StringifyVector(lyrOut.ActivColumnIndicies)}"); Debug.WriteLine($"Cell SDR: {Helpers.StringifyVector(actCells.Select(c => c.Index).ToArray())}"); // // If the list of predicted values from the previous step contains the currently presenting value, // we have a match. if (lastPredictedValues.Contains(key)) { matches++; Debug.WriteLine($"Match. Actual value: {key} - Predicted value: {lastPredictedValues.FirstOrDefault(key)}."); } else { Debug.WriteLine($"Missmatch! Actual value: {key} - Predicted values: {String.Join(',', lastPredictedValues)}"); } if (lyrOut.PredictiveCells.Count > 0) { //var predictedInputValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); var predictedInputValues = cls.GetPredictedInputValues(lyrOut.PredictiveCells.ToArray(), 3); foreach (var item in predictedInputValues) { Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {item.PredictedInput} - {item.Similarity}"); } lastPredictedValues = predictedInputValues.Select(v => v.PredictedInput).ToList(); } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); lastPredictedValues = new List <string> (); } } // The first element (a single element) in the sequence cannot be predicted double maxPossibleAccuraccy = (double)((double)sequenceKeyPair.Value.Count - 1) / (double)sequenceKeyPair.Value.Count * 100.0; double accuracy = (double)matches / (double)sequenceKeyPair.Value.Count * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {sequenceKeyPair.Value.Count}\t {accuracy}%"); if (accuracy >= maxPossibleAccuraccy) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); // // Experiment is completed if we are 30 cycles long at the 100% accuracy. if (maxMatchCnt >= 30) { sw.Stop(); Debug.WriteLine($"Sequence learned. The algorithm is in the stable state after 30 repeats with with accuracy {accuracy} of maximum possible {maxMatchCnt}. Elapsed sequence {sequenceKeyPair.Key} learning time: {sw.Elapsed}."); break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with accuracy {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } // This resets the learned state, so the first element starts allways from the beginning. tm.Reset(mem); } } Debug.WriteLine("------------ END ------------"); return(new HtmPredictionEngine { Layer = layer1, Classifier = cls, Connections = mem }); }
public void RunPowerPredictionExperiment() { const int inputBits = 300; /* without datetime component */ // 13420; /* with 4096 scalar bits */ // 10404 /* with 1024 bits */; Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.COLUMN_DIMENSIONS, new int[] { 2048 }); p.Set(KEY.INPUT_DIMENSIONS, new int[] { inputBits }); p.Set(KEY.CELLS_PER_COLUMN, 10 /* 50 */); p.Set(KEY.GLOBAL_INHIBITION, true); p.Set(KEY.CONNECTED_PERMANENCE, 0.1); // N of 40 (40= 0.02*2048 columns) active cells required to activate the segment. p.setNumActiveColumnsPerInhArea(0.02 * 2048); // Activation threshold is 10 active cells of 40 cells in inhibition area. p.setActivationThreshold(10 /*15*/); p.setInhibitionRadius(15); p.Set(KEY.MAX_BOOST, 0.0); p.Set(KEY.DUTY_CYCLE_PERIOD, 100000); p.setActivationThreshold(10); p.setMaxNewSynapsesPerSegmentCount((int)(0.02 * 2048)); p.setPermanenceIncrement(0.17); //p.Set(KEY.MAX_SYNAPSES_PER_SEGMENT, 32); //p.Set(KEY.MAX_SEGMENTS_PER_CELL, 128); //p.Set(KEY.MAX_NEW_SYNAPSE_COUNT, 200); //p.Set(KEY.POTENTIAL_RADIUS, 700); //p.Set(KEY.POTENTIAL_PCT, 0.5); //p.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 42); //p.Set(KEY.LOCAL_AREA_DENSITY, -1); CortexRegion region0 = new CortexRegion("1st Region"); SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); Dictionary <string, object> settings = new Dictionary <string, object>(); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); region0.AddLayer(layer1); layer1.HtmModules.Add("sp", sp1); HtmClassifier <double, ComputeCycle> cls = new HtmClassifier <double, ComputeCycle>(); Stopwatch sw = new Stopwatch(); sw.Start(); Train(inputBits, layer1, cls, true); // New born mode. sw.Stop(); Debug.WriteLine($"NewBorn stage duration: {sw.ElapsedMilliseconds / 1000} s"); layer1.AddModule("tm", tm1); sw.Start(); int hunderdAccCnt = 0; for (int i = 0; i < 1000; i++) { float acc = Train(inputBits, layer1, cls, false); Debug.WriteLine($"Accuracy = {acc}, Cycle = {i}"); if (acc == 100.0) { hunderdAccCnt++; } if (hunderdAccCnt >= 10) { break; } //tm1.reset(mem); } if (hunderdAccCnt >= 10) { Debug.WriteLine($"EXPERIMENT SUCCESS. Accurracy 100% reached."); } else { Debug.WriteLine($"Experiment FAILED!. Accurracy 100% was not reached."); } cls.TraceState(); sw.Stop(); Debug.WriteLine($"Training duration: {sw.ElapsedMilliseconds / 1000} s"); }
public void MyTestMethod() { //DIRECTORIES TO STORE INPUT AND OUTPUT FILES OF THE EXPERIMENT //Encoder string E_inFolder = "NoiseExperiments/Input"; //Encoder's raw input file directory //Directory.CreateDirectory(E_inFolder); //----------------INPUT FILE PATH----------------- string E_inFile_train = $"{E_inFolder}\\sinusoidal.csv"; //Encoder's input file in "Training mode" //<Robustness> string E_inFile_robustness = $"{E_inFolder}/Noisy_N-0-2_sinusoidal.csv"; // Encoder's input file in "Testing mode - Robustness" - All the files with name of the form "Noisy_*.csv" //</Robustness> //< Specificity > string E_inFile_specificity = $"{E_inFolder}/sinusoidal-specificity.csv"; // Encoder's input file in "Testing mode - Specificity" //</ Specificity > //------------------------------------------------ string E_outFolder = "NoiseExperiments/MyEncoderOutput"; //Encoder's graphical output (PNG format) during "Testing mode" will be created here Directory.CreateDirectory(E_outFolder); string E_outFolder_train = $"{E_outFolder}/train"; // Encoder's graphical output (PNG format) during "Training mode" will be created here Directory.CreateDirectory(E_outFolder_train); //Spatial Pooler string SP_inFolder = "NoiseExperiments/MySPInput"; //Spatial Pooler's input file (Encoder's output (CSV format)) directory Directory.CreateDirectory(SP_inFolder); string SP_inFile_train = $"{SP_inFolder}/MyEncoderOut_train.csv"; //Spatial Pooler's input file during "Training mode" string SP_inFile_robustness = $"{SP_inFolder}/MyEncoderOut_robustness.csv"; //Spatial Pooler's input file during "Testing mode - robustness" string SP_inFile_specificity = $"{SP_inFolder}/MyEncoderOut_specificity.csv"; //Spatial Pooler's input file during "Testing mode - specificity" string SP_outFolder = "MySPOutput"; //Spatial Pooler's graphical output (PNG format) will be stored here Directory.CreateDirectory(SP_outFolder); string SP_outFolder_compare = $"{SP_outFolder}/compare_445"; //This folder containing CSV files, which show Hamming distance between Spatial Pooler's output in "Training mode" and "Testing Mode" Directory.CreateDirectory(SP_outFolder_compare); //--------------------OUTPUT FILE PATH------------------------- //<Robustness> string SP_outFile_robustness = $"{SP_outFolder_compare}/compare_N-0-2.csv"; //The final output file in "Robustness test" //</Robustness> //<Specificity> string SP_outFile_specificity = $"{SP_outFolder_compare}/compare_specificity.csv"; //The final output file in "Specificity test" //</Specificity> //------------------------------------------------------------- //------------------------------------------------------- //| HTM PARAMETERS | //------------------------------------------------------- const int E_outBits = 445; //Number of Scalar Encoder's output bits const int columnsNumber = 2048; //Number of Spatial Pooler's output columns Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); //------------------SPATIAL POOLER PARAMETERS----------------- p.Set(KEY.INPUT_DIMENSIONS, new int[] { E_outBits }); p.Set(KEY.POTENTIAL_RADIUS, -1); p.Set(KEY.POTENTIAL_PCT, 1); p.Set(KEY.GLOBAL_INHIBITION, true); p.Set(KEY.INHIBITION_RADIUS, 15); //Leave it p.Set(KEY.LOCAL_AREA_DENSITY, -1.0); p.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.02 * columnsNumber); p.Set(KEY.STIMULUS_THRESHOLD, 0.5); p.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); p.Set(KEY.SYN_PERM_ACTIVE_INC, 0.01); p.Set(KEY.SYN_PERM_CONNECTED, 0.10); //Leave it p.Set(KEY.SYN_PERM_BELOW_STIMULUS_INC, 0.01); p.Set(KEY.SYN_PERM_TRIM_THRESHOLD, 0.05); p.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 0.001); p.Set(KEY.MIN_PCT_ACTIVE_DUTY_CYCLES, 0.001); p.Set(KEY.DUTY_CYCLE_PERIOD, 100); p.Set(KEY.MAX_BOOST, 10 /*10.0*/); p.Set(KEY.WRAP_AROUND, true); //p.Set(KEY.LEARN, true); //-------------------TEMPORAL MEMORY PARAMETERS---------------- p.Set(KEY.COLUMN_DIMENSIONS, new int[] { columnsNumber }); p.Set(KEY.CELLS_PER_COLUMN, 32); p.Set(KEY.ACTIVATION_THRESHOLD, 10); p.Set(KEY.LEARNING_RADIUS, 10); p.Set(KEY.MIN_THRESHOLD, 9); p.Set(KEY.MAX_NEW_SYNAPSE_COUNT, 20); p.Set(KEY.MAX_SYNAPSES_PER_SEGMENT, 225); p.Set(KEY.MAX_SEGMENTS_PER_CELL, 225); p.Set(KEY.INITIAL_PERMANENCE, 0.21); p.Set(KEY.CONNECTED_PERMANENCE, 0.5); p.Set(KEY.PERMANENCE_INCREMENT, 0.10); p.Set(KEY.PERMANENCE_DECREMENT, 0.10); p.Set(KEY.PREDICTED_SEGMENT_DECREMENT, 0.1); //p.Set(KEY.LEARN, true); //--------------------------------------------------- //| UNIT TEST | //--------------------------------------------------- //Initiating HTM modules SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); HtmClassifier <double, ComputeCycle> cls = new HtmClassifier <double, ComputeCycle>(); //-------------------ENCODING INPUTS---------------------- Encoding(E_inFile_train, SP_inFile_train, E_outFolder_train, E_outBits); //--------------------TRAINING MODE--------------------- //SP training for (int j = 0; j < 5; j++) { using (StreamReader sr = new StreamReader(SP_inFile_train)) { string line; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(","); int[] SP_input = new int[E_outBits]; for (int i = 0; i < E_outBits; i++) { if (tokens[i + 1] == "0") { SP_input[i] = 0; } else { SP_input[i] = 1; } } for (int i = 0; i < 3; i++) { sp1.Compute(SP_input, true); } } } } Debug.WriteLine("-----------------------------------------------------"); Debug.WriteLine("|-----------------FINISHED TRAINING-----------------|"); Debug.WriteLine("-----------------------------------------------------"); //TM + SP training double lastPredictedValue = 0.0; for (int j = 0; j < 20; j++) { using (StreamReader sr = new StreamReader(SP_inFile_train)) { string line; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(","); int[] SP_input = new int[E_outBits]; for (int i = 0; i < E_outBits; i++) { if (tokens[i + 1] == "0") { SP_input[i] = 0; } else { SP_input[i] = 1; } } var SP_res = sp1.Compute(SP_input, true); var TM_res = tm1.Compute(SP_res, true) as ComputeCycle; double input = Convert.ToDouble(tokens[0], CultureInfo.InvariantCulture); Debug.WriteLine($"Input: {input} - Predicted: {lastPredictedValue}"); //cls.Learn(input, TM_res.ActiveCells.ToArray(), TM_res.PredictiveCells.ToArray()); lastPredictedValue = cls.GetPredictedInputValue(TM_res.PredictiveCells.ToArray()); } } } }
/// <summary> /// Processes the test cases for Noise Test taking the necessary parameters. /// It's the parent method which calls other utility methods to create the input vectors and the outputs. /// </summary> /// <param name="inputSequence">An array of double, consisting the starting indexes for each input vector</param> /// <param name="inputs"> /// A parameter of the class "InputParameters", which contains all the input parameters needed as properties which can be set in a test case /// </param> /// <returns>Returns nothing</returns> public void ProcessTestCase(List <double[]> inputSequences, InputParameters inputs) { string path = Directory.GetCurrentDirectory(); string parentDir = path.Substring(0, path.IndexOf("bin") - 1); string resultDir = parentDir.Substring(0, parentDir.LastIndexOf(@"\")); string timeStamp = DateTime.Now.ToString("yyyyMMddHHmmss"); string outFolder = resultDir + @"\SpatialPooler_Results\" + timeStamp + @"\Output\"; string inFolder = resultDir + @"\SpatialPooler_Results\" + timeStamp + @"\InputVectors"; if (!Directory.Exists(outFolder)) { Directory.CreateDirectory(outFolder); } if (!Directory.Exists(inFolder + @"\")) { Directory.CreateDirectory(inFolder); } //int radius = 0; var parameters = GetDefaultParams(); parameters.Set(KEY.POTENTIAL_RADIUS, 64 * 64); parameters.Set(KEY.POTENTIAL_PCT, 1.0); parameters.Set(KEY.GLOBAL_INHIBITION, false); parameters.Set(KEY.STIMULUS_THRESHOLD, 0.5); parameters.Set(KEY.INHIBITION_RADIUS, (int)0.25 * 64 * 64); parameters.Set(KEY.LOCAL_AREA_DENSITY, -1); parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.1 * 64 * 64); parameters.Set(KEY.DUTY_CYCLE_PERIOD, 1000000); parameters.Set(KEY.MAX_BOOST, 5); Console.WriteLine("Fetched all default parameters\n"); parameters.setInputDimensions(new int[] { 32, 32 }); parameters.setColumnDimensions(new int[] { 64, 64 }); parameters.setNumActiveColumnsPerInhArea(0.02 * 64 * 64); var sp = new SpatialPoolerMT(); var mem = new Connections(); parameters.apply(mem); Console.WriteLine("\nConfiguring the Inputs...\n"); sp.Init(mem, GetInMemoryDictionary()); int outFolderCount = 0; int compareIndex = Convert.ToInt32(inputs.getCompareNumber()); double[][] recordOutput = null; double[] hammingDistance = null; foreach (double[] inputSequence in inputSequences) { outFolderCount++; double minVal = 0.0; for (int i = 0; i < inputSequence.Length; i++) { if (i == 0) { minVal = inputSequence[i]; } else if (inputSequence[i] < minVal) { minVal = inputSequence[i]; } } minVal -= 1.0; Console.WriteLine("\nGetting the Input Vectors...\n"); var inputVectors = GetEncodedSequence(inputSequence, minVal, inputs.getMaxIndex(), inputs, inFolder); int count = 1; //string output = String.Empty; int max = 0; for (int i = 0; i < inputVectors.Count; i++) { hammingDistance = null; //output = String.Empty; Console.WriteLine("Computing the Output for the vector no: " + count.ToString() + "...\n"); var activeArray = sp.Compute(inputVectors[i], true) as int[]; for (int j = 0; j < activeArray.Length; j++) { if (activeArray[j] > max) { max = activeArray[j]; } } //var str = Helpers.StringifyVector(activeArray); int rows = Convert.ToInt32(Math.Ceiling(Math.Sqrt(Convert.ToDouble(max)))); int counter = 0; int index = 0; int[,] outTwoDArray = new int[rows, rows]; for (int j = 0; j < rows; j++) { for (int k = 0; k < rows; k++) { outTwoDArray[j, k] = 0; } } for (int j = 0; j < rows; j++) { for (int k = 0; k < rows; k++) { counter++; if (index < activeArray.Length && activeArray[index] == counter) { index++; outTwoDArray[j, k] = 1; } } } double[][] comparingArray = new double[rows][]; for (int j = 0; j < rows; j++) { comparingArray[j] = new double[rows]; for (int k = 0; k < rows; k++) { comparingArray[j][k] = Convert.ToDouble(outTwoDArray[j, k]); } } int[,] record2Darray = null; if (inputSequence[i] == compareIndex) { if (recordOutput != null) { hammingDistance = MathHelpers.GetHammingDistance(recordOutput, comparingArray, false); record2Darray = new int[recordOutput.Length, recordOutput.Length]; for (int j = 0; j < recordOutput.Length; j++) { for (int k = 0; k < recordOutput.Length; k++) { record2Darray[j, k] = Convert.ToInt32(recordOutput[j][k]); } } } recordOutput = new double[rows][]; for (int j = 0; j < rows; j++) { recordOutput[j] = new double[rows]; for (int k = 0; k < rows; k++) { recordOutput[j][k] = comparingArray[j][k]; } } } if (hammingDistance != null) { int rowHam = Convert.ToInt32(Math.Ceiling(Math.Sqrt(hammingDistance.Length))); int[,] hammingArray = new int[rowHam, rowHam]; int limit = 0; for (int j = 0; j < rowHam; j++) { for (int k = 0; k < rowHam; k++) { if (limit < hammingDistance.Length) { //hj hammingArray[j, k] = Convert.ToInt32(hammingDistance[limit]); limit++; } } } int compare_no = 1; if (!File.Exists($"{outFolder}\\Compare_{compareIndex}.png")) { DrawBitmapHamming(hammingArray, 1024, 1024, $"{outFolder}\\Compare_{compareIndex}.png", $"Compare_{compareIndex}"); DrawBitmapOverlap(record2Darray, outTwoDArray, 1024, 1024, $"{outFolder}\\Overlap_{compareIndex}.png", $"Overlap_{compareIndex}"); } else { while (File.Exists($"{outFolder}\\Compare_{compareIndex}_{compare_no}.png")) { compare_no++; } DrawBitmapHamming(hammingArray, 1024, 1024, $"{outFolder}\\Compare_{compareIndex}_{compare_no}.png", $"Compare_{compareIndex}"); compare_no = 1; while (File.Exists($"{outFolder}\\Overlap_{compareIndex}_{compare_no}.png")) { compare_no++; } DrawBitmapOverlap(record2Darray, outTwoDArray, 1024, 1024, $"{outFolder}\\Overlap_{compareIndex}_{compare_no}.png", $"Overlap_{compareIndex}"); } } if (!Directory.Exists(outFolder + @"\\" + outFolderCount.ToString())) { Directory.CreateDirectory(outFolder + @"\\" + outFolderCount.ToString()); } int[,] out2dimArray = ArrayUtils.Transpose(outTwoDArray); NeoCortexUtils.DrawBitmap(out2dimArray, 1024, 1024, $"{outFolder}\\{outFolderCount}\\{count}.png", Color.Black, Color.Green, text: inputSequence[i].ToString()); //File.WriteAllLines(outFolder + count.ToString() + ".txt", new string[] { str }); Console.WriteLine("Output is recorded in the path: " + outFolder + count.ToString() + ".txt\n"); count++; } } }
public void CreateSdrsTest() { var colDims = new int[] { 64, 64 }; int numOfCols = 64 * 64; string trainingFolder = @"..\..\..\TestFiles\Sdr"; int imgSize = 28; var trainingImages = Directory.GetFiles(trainingFolder, "*.jpeg"); Directory.CreateDirectory($"{nameof(CreateSdrsTest)}"); int counter = 0; bool isInStableState = false; // HTM parameters HtmConfig htmConfig = new HtmConfig(new int[] { imgSize, imgSize }, new int[] { 64, 64 }) { PotentialRadius = 10, PotentialPct = 1, GlobalInhibition = true, LocalAreaDensity = -1.0, NumActiveColumnsPerInhArea = 0.02 * numOfCols, StimulusThreshold = 0.0, SynPermInactiveDec = 0.008, SynPermActiveInc = 0.05, SynPermConnected = 0.10, MinPctOverlapDutyCycles = 1.0, MinPctActiveDutyCycles = 0.001, DutyCyclePeriod = 100, MaxBoost = 10.0, RandomGenSeed = 42, Random = new ThreadSafeRandom(42) }; Connections connections = new Connections(htmConfig); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(connections, trainingImages.Length * 50, (isStable, numPatterns, actColAvg, seenInputs) => { isInStableState = true; Debug.WriteLine($"Entered STABLE state: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); }); SpatialPooler sp = new SpatialPoolerMT(hpa); sp.Init(connections); string outFolder = nameof(CreateSdrsTest); Directory.CreateDirectory(outFolder); while (true) { counter++; Dictionary <string, int[]> sdrs = new Dictionary <string, int[]>(); Dictionary <string, int[]> inputVectors = new Dictionary <string, int[]>(); foreach (var trainingImage in trainingImages) { FileInfo fI = new FileInfo(trainingImage); string outputHamDistFile = $"{outFolder}\\image-{fI.Name}_hamming.txt"; string outputActColFile = $"{outFolder}\\image{fI.Name}_activeCol.txt"; string outputActColFile1 = $"{outFolder}\\image{fI.Name}_activeCol.csv"; using (StreamWriter swActCol = new StreamWriter(outputActColFile)) { using (StreamWriter swActCol1 = new StreamWriter(outputActColFile1)) { int[] activeArray = new int[numOfCols]; string testName = $"{outFolder}\\{fI.Name}"; string inputBinaryImageFile = NeoCortexUtils.BinarizeImage($"{trainingImage}", imgSize, testName); // Read input csv file into array int[] inputVector = NeoCortexUtils.ReadCsvIntegers(inputBinaryImageFile).ToArray(); List <double[, ]> overlapArrays = new List <double[, ]>(); List <double[, ]> bostArrays = new List <double[, ]>(); sp.compute(inputVector, activeArray, true); var activeCols = ArrayUtils.IndexWhere(activeArray, (el) => el == 1); if (isInStableState) { CalculateResult(sdrs, inputVectors, numOfCols, activeCols, outFolder, trainingImage, inputVector); overlapArrays.Add(ArrayUtils.Make2DArray <double>(ArrayUtils.ToDoubleArray(connections.Overlaps), colDims[0], colDims[1])); bostArrays.Add(ArrayUtils.Make2DArray <double>(connections.BoostedOverlaps, colDims[0], colDims[1])); var activeStr = Helpers.StringifyVector(activeArray); swActCol.WriteLine("Active Array: " + activeStr); int[,] twoDimenArray = ArrayUtils.Make2DArray <int>(activeArray, colDims[0], colDims[1]); twoDimenArray = ArrayUtils.Transpose(twoDimenArray); List <int[, ]> arrays = new List <int[, ]>(); arrays.Add(twoDimenArray); arrays.Add(ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(inputVector, (int)Math.Sqrt(inputVector.Length), (int)Math.Sqrt(inputVector.Length)))); //Calculating the max value of the overlap in the OverlapArray int max = SdrRepresentation.TraceColumnsOverlap(overlapArrays, swActCol1, fI.Name); int red = Convert.ToInt32(max * 0.80); // Value above this threshould would be red and below this will be yellow int green = Convert.ToInt32(max * 0.50); // Value above this threshould would be yellow and below this will be green string outputImage = $"{outFolder}\\cycle-{counter}-{fI.Name}"; NeoCortexUtils.DrawBitmaps(arrays, outputImage, Color.Yellow, Color.Gray, OutImgSize, OutImgSize); NeoCortexUtils.DrawHeatmaps(overlapArrays, $"{outputImage}_overlap.png", 1024, 1024, red, red, green); if (sdrs.Count == trainingImages.Length) { return; } } } } } } }
//[DataRow("Box")] //[DataRow("Horizontal")] public void ImageSimilarityExperiment(string inputPrefix) { //int stableStateCnt = 100; double minOctOverlapCycles = 1.0; double maxBoost = 10.0; //int inputBits = 100; var colDims = new int[] { 64, 64 }; int numOfCols = 64 * 64; //int numColumns = colDims[0]; string trainingFolder = "Similarity\\TestFiles"; int imgSize = 28; //var colDims = new int[] { 64, 64 }; //int numOfActCols = colDims[0] * colDims[1]; string TestOutputFolder = $"Output-{nameof(ImageSimilarityExperiment)}"; var trainingImages = Directory.GetFiles(trainingFolder, $"{inputPrefix}*.png"); Directory.CreateDirectory($"{nameof(ImageSimilarityExperiment)}"); int counter = 0; //var parameters = GetDefaultParams(); ////parameters.Set(KEY.DUTY_CYCLE_PERIOD, 20); ////parameters.Set(KEY.MAX_BOOST, 1); ////parameters.setInputDimensions(new int[] { imageSize[imSizeIndx], imageSize[imSizeIndx] }); ////parameters.setColumnDimensions(new int[] { topologies[topologyIndx], topologies[topologyIndx] }); ////parameters.setNumActiveColumnsPerInhArea(0.02 * numOfActCols); //parameters.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.06 * 4096); // TODO. Experiment with different sizes //parameters.Set(KEY.POTENTIAL_RADIUS, imgSize * imgSize); //parameters.Set(KEY.POTENTIAL_PCT, 1.0); //parameters.Set(KEY.GLOBAL_INHIBITION, true); // TODO: Experiment with local inhibition too. Note also the execution time of the experiment. //// Num of active synapces in order to activate the column. //parameters.Set(KEY.STIMULUS_THRESHOLD, 50.0); //parameters.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); //parameters.Set(KEY.SYN_PERM_ACTIVE_INC, 0.05); //parameters.Set(KEY.INHIBITION_RADIUS, (int)0.02 * imgSize * imgSize); // TODO. check if this has influence in a case of the global inhibition. ALso check how this parameter influences the similarity of SDR. //parameters.Set(KEY.SYN_PERM_CONNECTED, 0.2); //parameters.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 0.001); //parameters.Set(KEY.MIN_PCT_ACTIVE_DUTY_CYCLES, 0.001); //parameters.Set(KEY.DUTY_CYCLE_PERIOD, 1000); //parameters.Set(KEY.MAX_BOOST, 100); //parameters.Set(KEY.WRAP_AROUND, true); //parameters.Set(KEY.SEED, 1969); //parameters.setInputDimensions(new int[] { imgSize, imgSize }); //parameters.setColumnDimensions(colDims); Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.INPUT_DIMENSIONS, new int[] { imgSize, imgSize }); p.Set(KEY.COLUMN_DIMENSIONS, colDims); p.Set(KEY.CELLS_PER_COLUMN, 10); p.Set(KEY.MAX_BOOST, maxBoost); p.Set(KEY.DUTY_CYCLE_PERIOD, 50); p.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, minOctOverlapCycles); // Global inhibition // N of 40 (40= 0.02*2048 columns) active cells required to activate the segment. p.Set(KEY.GLOBAL_INHIBITION, true); p.setNumActiveColumnsPerInhArea(0.02 * numOfCols); p.Set(KEY.POTENTIAL_RADIUS, (int)(0.8 * imgSize * imgSize)); p.Set(KEY.LOCAL_AREA_DENSITY, -1); // In a case of global inhibition. //p.setInhibitionRadius( Automatically set on the columns pace in a case of global inhibition.); // Activation threshold is 10 active cells of 40 cells in inhibition area. p.setActivationThreshold(10); // Max number of synapses on the segment. p.setMaxNewSynapsesPerSegmentCount((int)(0.02 * numOfCols)); bool isInStableState = false; var mem = new Connections(); p.apply(mem); HomeostaticPlasticityController hpa = new HomeostaticPlasticityController(mem, trainingImages.Length * 50, (isStable, numPatterns, actColAvg, seenInputs) => { // Event should only be fired when entering the stable state. // Ideal SP should never enter unstable state after stable state. Assert.IsTrue(isStable); Assert.IsTrue(numPatterns == trainingImages.Length); isInStableState = true; Debug.WriteLine($"Entered STABLE state: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); }, requiredSimilarityThreshold: 0.975); SpatialPooler sp = new SpatialPoolerMT(hpa); sp.Init(mem, UnitTestHelpers.GetMemory()); string outFolder = $"{TestOutputFolder}\\{inputPrefix}"; Directory.CreateDirectory(outFolder); string outputHamDistFile = $"{outFolder}\\digit{inputPrefix}_hamming.txt"; string outputActColFile = $"{outFolder}\\digit{inputPrefix}_activeCol.txt"; using (StreamWriter swHam = new StreamWriter(outputHamDistFile)) { using (StreamWriter swActCol = new StreamWriter(outputActColFile)) { int cycle = 0; Dictionary <string, int[]> sdrs = new Dictionary <string, int[]>(); Dictionary <string, int[]> inputVectors = new Dictionary <string, int[]>(); while (true) { foreach (var trainingImage in trainingImages) { int[] activeArray = new int[numOfCols]; FileInfo fI = new FileInfo(trainingImage); string outputImage = $"{outFolder}\\{inputPrefix}_cycle_{counter}_{fI.Name}"; string testName = $"{outFolder}\\{inputPrefix}_{fI.Name}"; string inputBinaryImageFile = NeoCortexUtils.BinarizeImage($"{trainingImage}", imgSize, testName); // Read input csv file into array int[] inputVector = NeoCortexUtils.ReadCsvIntegers(inputBinaryImageFile).ToArray(); int[] oldArray = new int[activeArray.Length]; List <double[, ]> overlapArrays = new List <double[, ]>(); List <double[, ]> bostArrays = new List <double[, ]>(); sp.compute(inputVector, activeArray, true); var activeCols = ArrayUtils.IndexWhere(activeArray, (el) => el == 1); Debug.WriteLine($"Cycle: {cycle++} - Input: {trainingImage}"); Debug.WriteLine($"{Helpers.StringifyVector(activeCols)}\n"); if (isInStableState) { if (sdrs.Count == trainingImages.Length) { CalculateSimilarity(sdrs, inputVectors); return; } var distance = MathHelpers.GetHammingDistance(oldArray, activeArray, true); //var similarity = MathHelpers.CalcArraySimilarity(oldArray, activeArray, true); sdrs.Add(trainingImage, activeCols); inputVectors.Add(trainingImage, inputVector); swHam.WriteLine($"{counter++}|{distance} "); oldArray = new int[numOfCols]; activeArray.CopyTo(oldArray, 0); overlapArrays.Add(ArrayUtils.Make2DArray <double>(ArrayUtils.ToDoubleArray(mem.Overlaps), colDims[0], colDims[1])); bostArrays.Add(ArrayUtils.Make2DArray <double>(mem.BoostedOverlaps, colDims[0], colDims[1])); var activeStr = Helpers.StringifyVector(activeArray); swActCol.WriteLine("Active Array: " + activeStr); int[,] twoDimenArray = ArrayUtils.Make2DArray <int>(activeArray, colDims[0], colDims[1]); twoDimenArray = ArrayUtils.Transpose(twoDimenArray); List <int[, ]> arrays = new List <int[, ]>(); arrays.Add(twoDimenArray); arrays.Add(ArrayUtils.Transpose(ArrayUtils.Make2DArray <int>(inputVector, (int)Math.Sqrt(inputVector.Length), (int)Math.Sqrt(inputVector.Length)))); NeoCortexUtils.DrawBitmaps(arrays, outputImage, Color.Yellow, Color.Gray, OutImgSize, OutImgSize); NeoCortexUtils.DrawHeatmaps(overlapArrays, $"{outputImage}_overlap.png", 1024, 1024, 150, 50, 5); NeoCortexUtils.DrawHeatmaps(bostArrays, $"{outputImage}_boost.png", 1024, 1024, 150, 50, 5); } } } } } }
private void RunExperiment(int inputBits, HtmConfig cfgL4, EncoderBase encoder, List <double> inputValues, HtmConfig cfgL2) { Stopwatch swL2 = new Stopwatch(); int maxMatchCnt = 0; bool learn = true; bool isSP4Stable = false; bool isSP2STable = false; var memL4 = new Connections(cfgL4); var memL2 = new Connections(cfgL2); var numInputs = inputValues.Distinct <double>().ToList().Count; HtmClassifier <string, ComputeCycle> cls = new HtmClassifier <string, ComputeCycle>(); layerL4 = new CortexLayer <object, object>("L4"); layerL2 = new CortexLayer <object, object>("L2"); tm4 = new TemporalMemoryMT(); tm2 = new TemporalMemoryMT(); // HPC for Layer 4 SP HomeostaticPlasticityController hpa_sp_L4 = new HomeostaticPlasticityController(memL4, numInputs * 50, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { Debug.WriteLine($"SP L4 STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { Debug.WriteLine($"SP L4 INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } learn = isSP4Stable = isStable; }, numOfCyclesToWaitOnChange: 50); // HPC for Layer 2 SP HomeostaticPlasticityController hpa_sp_L2 = new HomeostaticPlasticityController(memL2, numInputs * 50, (isStable, numPatterns, actColAvg, seenInputs) => { if (isStable) { Debug.WriteLine($"SP L2 STABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } else { Debug.WriteLine($"SP L2 INSTABLE: Patterns: {numPatterns}, Inputs: {seenInputs}, iteration: {seenInputs / numPatterns}"); } learn = isSP2STable = isStable; cls.ClearState(); }, numOfCyclesToWaitOnChange: 50); SpatialPooler sp4 = new SpatialPoolerMT(hpa_sp_L4); SpatialPooler sp2 = new SpatialPoolerMT(hpa_sp_L2); sp4.Init(memL4); sp2.Init(memL2); // memL2.TraceInputPotential(); tm4.Init(memL4); tm2.Init(memL2); layerL4.HtmModules.Add("encoder", encoder); layerL4.HtmModules.Add("sp", sp4); layerL4.HtmModules.Add("tm", tm4); layerL2.HtmModules.Add("sp", sp2); layerL2.HtmModules.Add("tm", tm2); int[] inpCellsL4ToL2 = new int[cfgL4.CellsPerColumn * cfgL4.NumColumns]; double[] inputs = inputValues.ToArray(); int[] prevActiveCols = new int[0]; int cycle = 0; int matches = 0; string lastPredictedValue = "0"; int maxCycles = 3500; int maxPrevInputs = inputValues.Count - 1; List <string> previousInputs = new List <string>(); // // Training SP at Layer 4 to get stable. New-born stage. // using (StreamWriter swL4Sdrs = new StreamWriter($"L4-SDRs-in_{cfgL2.NumInputs}-col_{cfgL2.NumColumns}-r_{cfgL2.PotentialRadius}.txt")) { using (StreamWriter sw = new StreamWriter($"in_{cfgL2.NumInputs}-col_{cfgL2.NumColumns}-r_{cfgL2.PotentialRadius}.txt")) { for (int i = 0; i < maxCycles; i++) { matches = 0; cycle = i; Debug.WriteLine($"-------------- Newborn Cycle {cycle} at L4 SP region ---------------"); foreach (var input in inputs) { Debug.WriteLine($" INPUT: '{input}'\tCycle:{cycle}"); Debug.Write("L4: "); //L4 SP pre train layerL4.Compute(input, learn); InitArray(inpCellsL4ToL2, 0); if (isSP4Stable) { var cellSdrL4Indexes = memL4.ActiveCells.Select(c => c.Index).ToArray(); // Write SDR as output of L4 and input of L2 swL4Sdrs.WriteLine($"{input} - {Helpers.StringifyVector(cellSdrL4Indexes)}"); // Set the output active cell array ArrayUtils.SetIndexesTo(inpCellsL4ToL2, cellSdrL4Indexes, 1); Debug.WriteLine($"L4 out sdr: {Helpers.StringifyVector(cellSdrL4Indexes)}"); Debug.WriteLine("L2: "); swL2.Restart(); /// <summary> /// This part is for to make SP of Layer2 stable thourgh help /// of HPC Boosting Algo from new born stage. /// </summary> layerL2.Compute(inpCellsL4ToL2, true); swL2.Stop(); Debug.WriteLine($"{swL2.ElapsedMilliseconds / 1000}"); sw.WriteLine($"{swL2.ElapsedMilliseconds / 1000}"); sw.Flush(); var overlaps = ArrayUtils.IndexWhere(memL2.Overlaps, o => o > 0); var strOverlaps = Helpers.StringifyVector(overlaps); Debug.WriteLine($"Potential columns: {overlaps.Length}, overlaps: {strOverlaps}"); } } if (isSP4Stable && isSP2STable) { break; } } } } // SP+TM at L4 for (int i = 0; i < maxCycles; i++) { matches = 0; cycle = i; Debug.WriteLine($"-------------- L4 TM Train region Cycle {cycle} ---------------"); foreach (var input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); var layerL4Out = layerL4.Compute(input, learn) as ComputeCycle; previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } if (previousInputs.Count < maxPrevInputs) { continue; } string key = GetKey(previousInputs, input); List <Cell> actCells; if (layerL4Out.ActiveCells.Count == layerL4Out.WinnerCells.Count) { // SP+TM at L2 Debug.WriteLine($"-------------- L2 TM Train region Cycle {cycle} ---------------"); // Reset tha array InitArray(inpCellsL4ToL2, 0); var cellSdrL4Indexes = memL4.ActiveCells.Select(c => c.Index).ToArray(); // Set the output active cell array ArrayUtils.SetIndexesTo(inpCellsL4ToL2, cellSdrL4Indexes, 1); var layerL2Out = layerL2.Compute(inpCellsL4ToL2, true) as ComputeCycle; int[] overlaps = ArrayUtils.IndexWhere(memL2.Overlaps, o => o > 0); var strOverlaps = Helpers.StringifyVector(overlaps); Debug.WriteLine($"Potential columns: {overlaps.Length}, overlaps: {strOverlaps}"); if (layerL2Out.ActiveCells.Count == layerL2Out.WinnerCells.Count) { actCells = layerL2Out.ActiveCells; } else { actCells = layerL2Out.WinnerCells; } cls.Learn(key, actCells.ToArray()); if (key == lastPredictedValue) { matches++; Debug.WriteLine($"Match. Actual value: {key} - Predicted value: {lastPredictedValue}"); } else { Debug.WriteLine($"Missmatch! Actual value: {key} - Predicted value: {lastPredictedValue}"); } if (layerL2Out.PredictiveCells.Count > 0) { var predictedInputValue = cls.GetPredictedInputValue(layerL2Out.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {predictedInputValue}"); lastPredictedValue = predictedInputValue; } else { Debug.WriteLine($"NO CELLS PREDICTED for next cycle."); lastPredictedValue = String.Empty; } } } double accuracy = (double)matches / (double)inputs.Length * 100.0; Debug.WriteLine($"Cycle: {cycle}\tMatches={matches} of {inputs.Length}\t {accuracy}%"); if (accuracy >= 100.0) { maxMatchCnt++; Debug.WriteLine($"100% accuracy reched {maxMatchCnt} times."); // // Experiment is completed if we are 20 cycles long at the 100% accuracy. if (maxMatchCnt >= 20) { Debug.WriteLine($"Exit experiment in the stable state after 20 repeats with 100% of accuracy."); learn = false; break; } } else if (maxMatchCnt > 0) { Debug.WriteLine($"At 100% accuracy after {maxMatchCnt} repeats we get a drop of accuracy with {accuracy}. This indicates instable state. Learning will be continued."); maxMatchCnt = 0; } } }
public void RunGaussianNoiseExperiment() { const int E_outBits = 423; const int columnsNumber = 2048; int[] SP_Result = null; int[] SP_NoisyResult = null; List <int[]> SP_Result_List = new List <int[]>(); List <int[]> SP_NoisyResult_List = new List <int[]>(); double[] ham_total = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; double[] ham_avg = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; double ham_upper; double ham_lower; int number_training_set = 41; // Integer numbers range from -20 to 20 with step of 1. int number_testing_set = 401; // Decimal numbers range from -20 to 20 with step of 0.1. string experimentFolder = nameof(GaussianNoiseExperiment); // string SP_noisyinFolder = nameof(GoussianNoiseExperiment); Directory.CreateDirectory(experimentFolder); // Directory.CreateDirectory(SP_noisyinFolder); string SP_inFile = $"{experimentFolder}\\MyEncoderOut.csv"; string SP_noisyinFile = $"{experimentFolder}\\MyNoisyEncoderOut.csv"; //string SP_outFolder = "MySPOutput"; //string SP_noisyoutFolder = "MyNoisySPOutput"; //Directory.CreateDirectory(SP_outFolder); //Directory.CreateDirectory(SP_noisyoutFolder); string SP_outFile = $"{experimentFolder}\\MySPOut.csv"; string SP_noisyoutFile = $"{experimentFolder}\\MyNoisySPOut.csv"; //string testFolder = "MyDraftFoler"; //Directory.CreateDirectory(testFolder); //------------------------------------------------------- //| PARAMETERS | //------------------------------------------------------- Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); //------------------SPATIAL POOLER PARAMETERS----------------- p.Set(KEY.INPUT_DIMENSIONS, new int[] { E_outBits }); p.Set(KEY.POTENTIAL_RADIUS, -1); p.Set(KEY.POTENTIAL_PCT, 0.75); p.Set(KEY.GLOBAL_INHIBITION, true); p.Set(KEY.INHIBITION_RADIUS, 15); p.Set(KEY.LOCAL_AREA_DENSITY, -1.0); p.Set(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 0.02 * columnsNumber); p.Set(KEY.STIMULUS_THRESHOLD, 5); p.Set(KEY.SYN_PERM_INACTIVE_DEC, 0.008); p.Set(KEY.SYN_PERM_ACTIVE_INC, 0.05); p.Set(KEY.SYN_PERM_CONNECTED, 0.10); p.Set(KEY.SYN_PERM_BELOW_STIMULUS_INC, 0.01); p.Set(KEY.SYN_PERM_TRIM_THRESHOLD, 0.05); p.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 1); p.Set(KEY.MIN_PCT_ACTIVE_DUTY_CYCLES, 0.001); p.Set(KEY.DUTY_CYCLE_PERIOD, 100); // These values activate powerfull boosting. p.Set(KEY.MAX_BOOST, 5); p.Set(KEY.DUTY_CYCLE_PERIOD, 100); p.Set(KEY.MIN_PCT_OVERLAP_DUTY_CYCLES, 1); p.Set(KEY.MAX_BOOST, 10); p.Set(KEY.WRAP_AROUND, true); p.Set(KEY.LEARN, true); //-------------------TEMPORAL MEMORY PARAMETERS---------------- p.Set(KEY.COLUMN_DIMENSIONS, new int[] { columnsNumber }); p.Set(KEY.CELLS_PER_COLUMN, 32); p.Set(KEY.ACTIVATION_THRESHOLD, 10); p.Set(KEY.LEARNING_RADIUS, 10); p.Set(KEY.MIN_THRESHOLD, 9); p.Set(KEY.MAX_NEW_SYNAPSE_COUNT, 20); p.Set(KEY.MAX_SYNAPSES_PER_SEGMENT, 225); p.Set(KEY.MAX_SEGMENTS_PER_CELL, 225); p.Set(KEY.INITIAL_PERMANENCE, 0.21); p.Set(KEY.CONNECTED_PERMANENCE, 0.1); p.Set(KEY.PERMANENCE_INCREMENT, 0.10); p.Set(KEY.PERMANENCE_DECREMENT, 0.10); p.Set(KEY.PREDICTED_SEGMENT_DECREMENT, 0.1); p.Set(KEY.LEARN, true); //Initiating components of a Cortex Layer SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); HtmClassifier <double, ComputeCycle> cls = new HtmClassifier <double, ComputeCycle>(); Encoding(E_outBits); // Can adjust the number of SP learning cycles below for (int cycle = 0; cycle < 320; cycle++) { if (cycle >= 300) { // These activates ew-born effect which switch offs the boosting. //mem.setMaxBoost(0.0); mem.HtmConfig.MaxBoost = 0.0; //mem.updateMinPctOverlapDutyCycles(0.0); mem.HtmConfig.MinPctOverlapDutyCycles = 0.0; } using (StreamReader sr = new StreamReader(SP_inFile)) { string line; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(","); int[] SP_input = new int[E_outBits]; for (int i = 0; i < E_outBits; i++) { if (tokens[i + 1] == "0") { SP_input[i] = 0; } else { SP_input[i] = 1; } } SP_Result = sp1.Compute(SP_input, true); } } } using (StreamReader sr = new StreamReader(SP_inFile)) { string line; int lineNumber = 0; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(","); int[] SP_input = new int[E_outBits]; for (int i = 0; i < E_outBits; i++) { if (tokens[i + 1] == "0") { SP_input[i] = 0; } else { SP_input[i] = 1; } } SP_Result = sp1.Compute(SP_input, false, false); SP_Result_List.Add(SP_Result); int[,] SP_twoDimenArray = ArrayUtils.Make2DArray(SP_Result, 32, 64); var SP_twoDimArray = ArrayUtils.Transpose(SP_twoDimenArray); NeoCortexUtils.DrawBitmap(SP_twoDimArray, 1024, 1024, $"{experimentFolder}\\{lineNumber}.png", Color.DimGray, Color.LawnGreen, text: tokens[0]); lineNumber++; } } using (StreamReader sr = new StreamReader(SP_noisyinFile)) { string line; int lineNumber = 0; while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(","); int[] SP_input = new int[E_outBits]; for (int i = 0; i < E_outBits; i++) { if (tokens[i + 1] == "0") { SP_input[i] = 0; } else { SP_input[i] = 1; } } SP_NoisyResult = sp1.Compute(SP_input, false, false); SP_NoisyResult_List.Add(SP_NoisyResult); var ham = MathHelpers.GetHammingDistance(SP_Result_List[lineNumber], SP_NoisyResult_List[lineNumber], true); Debug.WriteLine($"Noisy input: {tokens[0]} - Hamming NonZ: {ham}"); ham = MathHelpers.GetHammingDistance(SP_Result_List[lineNumber], SP_NoisyResult_List[lineNumber], false); Debug.WriteLine($"Noisy input: {tokens[0]} - Hamming All: {ham}"); int[,] SP_twoDimenArray = ArrayUtils.Make2DArray(SP_NoisyResult, 32, 64); var SP_twoDimArray = ArrayUtils.Transpose(SP_twoDimenArray); NeoCortexUtils.DrawBitmap(SP_twoDimArray, 1024, 1024, $"{experimentFolder}\\{lineNumber}.png", Color.DimGray, Color.LawnGreen, text: tokens[0]); lineNumber++; } } for (int i = 0; i < number_testing_set - 1; i += 10) { int count = 1; for (int j = i + 1; j < i + 1 + 9; j++) { if (i != 0 && i != number_testing_set - 1) { ham_upper = MathHelpers.GetHammingDistance(SP_NoisyResult_List[i], SP_NoisyResult_List[j], true); ham_lower = MathHelpers.GetHammingDistance(SP_NoisyResult_List[i], SP_NoisyResult_List[i - count], true); ham_total[count - 1] += ham_upper + ham_lower; count++; } else if (i == 0) { ham_upper = MathHelpers.GetHammingDistance(SP_NoisyResult_List[i], SP_NoisyResult_List[j], true); ham_total[count - 1] += ham_upper; count++; } else { ham_lower = MathHelpers.GetHammingDistance(SP_NoisyResult_List[i], SP_NoisyResult_List[i - count], true); ham_total[count - 1] += ham_lower; count++; } } } for (int i = 0; i < 9; i++) { ham_avg[i] = ham_total[i] / (number_training_set * 2 - 2); Debug.WriteLine($"0.{i + 1} step avg hamming distance: {ham_avg[i]}"); } }
public void LongerSequenceExperiment() { int inputBits = 1024; bool learn = true; Parameters p = Parameters.getAllDefaultParameters(); p.Set(KEY.RANDOM, new ThreadSafeRandom(42)); p.Set(KEY.INPUT_DIMENSIONS, new int[] { inputBits }); p.Set(KEY.CELLS_PER_COLUMN, 10); p.Set(KEY.COLUMN_DIMENSIONS, new int[] { 2048 }); CortexNetwork net = new CortexNetwork("my cortex"); List <CortexRegion> regions = new List <CortexRegion>(); CortexRegion region0 = new CortexRegion("1st Region"); regions.Add(region0); SpatialPoolerMT sp1 = new SpatialPoolerMT(); TemporalMemory tm1 = new TemporalMemory(); var mem = new Connections(); p.apply(mem); sp1.Init(mem, UnitTestHelpers.GetMemory()); tm1.Init(mem); Dictionary <string, object> settings = new Dictionary <string, object>() { { "W", 21 }, { "N", inputBits }, { "Radius", -1.0 }, { "MinVal", 0.0 }, // { "MaxVal", 20.0 }, { "Periodic", false }, { "Name", "scalar" }, { "ClipInput", false }, }; double max = 50; List <double> lst = new List <double>(); for (double i = 0; i < max; i++) { lst.Add(i); } settings["MaxVal"] = max; EncoderBase encoder = new ScalarEncoder(settings); CortexLayer <object, object> layer1 = new CortexLayer <object, object>("L1"); // // NewBorn learning stage. region0.AddLayer(layer1); layer1.HtmModules.Add("encoder", encoder); layer1.HtmModules.Add("sp", sp1); HtmClassifier <double, ComputeCycle> cls = new HtmClassifier <double, ComputeCycle>(); double[] inputs = lst.ToArray(); // // This trains SP. foreach (var input in inputs) { Debug.WriteLine($" ** {input} **"); for (int i = 0; i < 3; i++) { var lyrOut = layer1.Compute((object)input, learn) as ComputeCycle; } } // Here we add TM module to the layer. layer1.HtmModules.Add("tm", tm1); // // Now, training with SP+TM. SP is pretrained on pattern. for (int i = 0; i < 200; i++) { foreach (var input in inputs) { var lyrOut = layer1.Compute(input, learn) as ComputeCycle; cls.Learn(input, lyrOut.ActiveCells.ToArray()); Debug.WriteLine($"-------------- {input} ---------------"); if (learn == false) { Debug.WriteLine($"Inference mode"); } Debug.WriteLine($"W: {Helpers.StringifyVector(lyrOut.WinnerCells.Select(c => c.Index).ToArray())}"); Debug.WriteLine($"P: {Helpers.StringifyVector(lyrOut.PredictiveCells.Select(c => c.Index).ToArray())}"); Debug.WriteLine($"Current Input: {input} \t| Predicted Input: {cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray())}"); } if (i == 50) { Debug.WriteLine("Stop Learning From Here. Entering inference mode."); learn = false; } tm1.Reset(mem); } cls.TraceState(); Debug.WriteLine("------------------------------------------------------------------------\n----------------------------------------------------------------------------"); }