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> /// /// </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 ------------"); }
private float Train(int inpBits, IHtmModule <object, object> network, HtmClassifier <double, ComputeCycle> cls, bool isNewBornMode = true) { float accurracy; string outFolder = nameof(RunPowerPredictionExperiment); Directory.CreateDirectory(outFolder); CortexNetworkContext ctx = new CortexNetworkContext(); Dictionary <string, object> scalarEncoderSettings = getScalarEncoderDefaultSettings(inpBits); //var dateTimeEncoderSettings = getFullDateTimeEncoderSettings(); ScalarEncoder scalarEncoder = new ScalarEncoder(scalarEncoderSettings); //DateTimeEncoder dtEncoder = new DateTimeEncoder(dateTimeEncoderSettings, DateTimeEncoder.Precision.Hours); string fileName = "TestFiles\\rec-center-hourly-short.csv"; using (StreamReader sr = new StreamReader(fileName)) { string line; int cnt = 0; int matches = 0; using (StreamWriter sw = new StreamWriter("out.csv")) { while ((line = sr.ReadLine()) != null) { cnt++; //if (isNewBornMode && cnt > 100) break; bool x = false; if (x) { break; } List <int> output = new List <int>(); string[] tokens = line.Split(","); // Encode scalar value var result = scalarEncoder.Encode(tokens[1]); output.AddRange(result); // This part adds datetime components to the input vector. //output.AddRange(new int[scalarEncoder.Offset]); //DateTime dt = DateTime.Parse(tokens[0], CultureInfo.InvariantCulture); // Encode date/time/hour. //result = dtEncoder.Encode(new DateTimeOffset(dt, TimeSpan.FromMilliseconds(0))); //output.AddRange(result); // This performs a padding to the inputBits = 10404 = 102*102. output.AddRange(new int[inpBits - output.Count]); var outArr = output.ToArray(); Debug.WriteLine($"-------------- {tokens[1]} --------------"); if (isNewBornMode) { for (int j = 0; j < 10; j++) { // Output here are active cells. var res = network.Compute(output.ToArray(), true); Debug.WriteLine(Helpers.StringifyVector(((int[])res))); } } else { var lyrOut = network.Compute(output.ToArray(), true) as ComputeCycle;; double input = Convert.ToDouble(tokens[1], CultureInfo.InvariantCulture); if (input == lastPredictedValue) { matches++; Debug.WriteLine($"Match {input}"); } else { Debug.WriteLine($"Missmatch Actual value: {input} - Predicted value: {lastPredictedValue}"); } cls.Learn(input, lyrOut.ActiveCells.ToArray()); lastPredictedValue = cls.GetPredictedInputValue(lyrOut.PredictiveCells.ToArray()); sw.WriteLine($"{tokens[0]};{input.ToString(CultureInfo.InvariantCulture)};{lastPredictedValue.ToString(CultureInfo.InvariantCulture)}"); 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} Predicted Input: {lastPredictedValue}"); int[,] twoDimenArray = ArrayUtils.Make2DArray <int>(outArr, (int)Math.Sqrt(outArr.Length), (int)Math.Sqrt(output.Count)); var twoDimArray = ArrayUtils.Transpose(twoDimenArray); NeoCortexUtils.DrawBitmap(twoDimArray, 1024, 1024, $"{outFolder}\\{tokens[0].Replace("/", "-").Replace(":", "-")}.png", Color.Yellow, Color.Black, text: input.ToString()); } Debug.WriteLine($"NewBorn stage: {isNewBornMode} - record: {cnt}"); } } accurracy = (float)matches / (float)cnt * (float)100.0; } return(accurracy); }
/// <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 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----------------------------------------------------------------------------"); }
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); * } * } */ }
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----------------------------------------------------------------------------"); }
/// <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 ------------"); }
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; Connections memL4 = new Connections(cfgL4); Connections memL2 = new Connections(cfgL2); int 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(); tm4 = new TemporalMemory(); tm2 = new TemporalMemory(); // // 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; 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 SpatialPooler(hpa_sp_L4); SpatialPooler sp2 = new SpatialPooler(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 (double input in inputs) { Debug.WriteLine($" INPUT: '{input}'\t Cycle:{cycle}"); Debug.Write("L4: "); object lyrOut = layerL4.Compute(input, learn); int[] activeColumns = layerL4.GetResult("sp") as int[]; int[] cellSdrL4Indexes = memL4.ActiveCells.Select(c => c.Index).ToArray(); Debug.WriteLine($"L4out Active Coloumn for input: {input}: {Helpers.StringifyVector(activeColumns)}"); Debug.WriteLine($"L4out SDR for input: {input}: {Helpers.StringifyVector(cellSdrL4Indexes)}"); if (isSP4Stable) { /// <summary> /// Checking Layer4 SP is giving similar or different /// Active Cell Sdr Indexes After it reaches to stable state. /// This portion is actuallly to hold all acive cell sdr /// indexes after Layer 4 SP reaches at stable state via HPC. /// /// But why we have done this? /// /// Actually, In Necortex api we have obeserved during severel /// experiments that whenvever Layer4 SP reaches to STABLE sate /// it doesnt give us smilar pattern of Active Cell SDR Indexes /// for each particular input data. /// /// Instead active cell sdr patern of L4 varried though it has reached /// to stable sate! /// /// So we want to obeserve whether Layer 4 SP is giving similar active cell sdr indexes /// or different acrive cell sdr indexes after it reaches to stable state. /// /// If we receive similar acrive cell sdr indexes from Layer 4 sp after it reaches /// to stable state then do train Layer 2 sp by as usual process in NeocortexApi by /// calling Layer4.Compute(). /// /// But if we receive different active cell sdr indexes then we will train Layer 2 sp /// from L4_ActiveCell_sdr_log so that during training /// Layer 2 SP gets similar stable active cell sdr indexes of layer4 /// from that dictionary. As a result, L2 SP will get similar sequence /// of active cell sdr indexes during SP Tarining and reach to STABLE state /// </summary> Array.Sort(cellSdrL4Indexes); if (!L4_ActiveCell_sdr_log.ContainsKey(input)) { L4_ActiveCell_sdr_log.Add(input, cellSdrL4Indexes); } else { if (L4_ActiveCell_sdr_log[input].SequenceEqual(cellSdrL4Indexes)) { Debug.WriteLine($"Layer4.Compute() is giving similar cell sdr indexes for input : {input} after reaching to stable state"); isSimilar_L4_active_cell_sdr = true; } else { isSimilar_L4_active_cell_sdr = false; Debug.WriteLine($"Layer4.Compute() is giving different cell sdr indexes for input : {input} after reaching to stable state"); Debug.WriteLine($"Sdr Mismatch with L4_ActiveCell_sdr_log after reaching to stable state"); Debug.WriteLine($" L4_ActiveCell_sdr_log output for input {input}: { Helpers.StringifyVector(L4_ActiveCell_sdr_log[input])}"); Debug.WriteLine($"L4 out sdr input:{input} {Helpers.StringifyVector(cellSdrL4Indexes)}"); //Debug.WriteLine($"L4 out ac input: {input}: {Helpers.StringifyVector(activeColumns)}"); } } if (!isSimilar_L4_active_cell_sdr) { cellSdrL4Indexes = L4_ActiveCell_sdr_log[input]; } // // Training SP at Layer 2 to get stable. New-born stage. // // Write SDR as output of L4 and input of L2 // swL4Sdrs.WriteLine($"{input} - {Helpers.StringifyVector(cellSdrL4Indexes)}"); // Set the output active cell array InitArray(inpCellsL4ToL2, 0); ArrayUtils.SetIndexesTo(inpCellsL4ToL2, cellSdrL4Indexes, 1); Debug.WriteLine($"L4 cell sdr to L2 SP Train for Input {input}: "); layerL2.Compute(inpCellsL4ToL2, true); int[] overlaps = ArrayUtils.IndexWhere(memL2.Overlaps, o => o > 0); string strOverlaps = Helpers.StringifyVector(overlaps); Debug.WriteLine($"Potential columns: {overlaps.Length}, overlaps: {strOverlaps}"); } } if (isSP4Stable && isSP2STable) { break; } } } } // // SP+TM at L2 for (int i = 0; i < maxCycles; i++) { matches = 0; cycle = i; Debug.WriteLine($"-------------- L2 TM Train region Cycle {cycle} ---------------"); foreach (double input in inputs) { Debug.WriteLine($"-------------- {input} ---------------"); // Reset tha array //var cellSdrL4Indexes = L4_ActiveCell_sdr_log[input]; object layerL4Out = layerL4.Compute(input, learn); previousInputs.Add(input.ToString()); if (previousInputs.Count > (maxPrevInputs + 1)) { previousInputs.RemoveAt(0); } if (previousInputs.Count < maxPrevInputs) { continue; } key = GetKey(previousInputs, input); List <Cell> actCells; InitArray(inpCellsL4ToL2, 0); int[] cellSdrL4Indexes; if (!isSimilar_L4_active_cell_sdr) { cellSdrL4Indexes = L4_ActiveCell_sdr_log[input]; } else { cellSdrL4Indexes = memL4.ActiveCells.Select(c => c.Index).ToArray(); } // Set the output active cell array ArrayUtils.SetIndexesTo(inpCellsL4ToL2, cellSdrL4Indexes, 1); ComputeCycle layerL2Out = layerL2.Compute(inpCellsL4ToL2, true) as ComputeCycle; if (layerL2Out.ActiveCells.Count == layerL2Out.WinnerCells.Count) { actCells = layerL2Out.ActiveCells; } else { actCells = layerL2Out.WinnerCells; } /// <summary> /// HTM Classifier has added for Layer 2 /// </summary> cls.Learn(key, actCells.ToArray()); if (key == lastPredictedValue) { matches++; Debug.WriteLine($"Match. Actual Sequence: {key} - Last Predicted Sequence: {lastPredictedValue}"); } else { Debug.WriteLine($"Missmatch! Actual Sequence: {key} - Last Predicted Sequence: {lastPredictedValue}"); } /// <summary> /// Classifier is taking Predictive Cells from Layer 2 /// </summary> if (layerL2Out.PredictiveCells.Count > 0) { string predictedInputValue = cls.GetPredictedInputValue(layerL2Out.PredictiveCells.ToArray()); Debug.WriteLine($"Current Input: {input} \t| New Predicted Input Sequence: {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."); } } }
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; } } }