예제 #1
0
        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}");
        }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
        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----------------------------------------------------------------------------");
        }
예제 #5
0
        /// <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 ------------");
        }
예제 #6
0
        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);
             *  }
             * }
             */
        }
예제 #7
0
        /// <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 ------------");
        }
예제 #8
0
        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
                }
            }
        }
예제 #9
0
        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;
                    }
                }
            }
        }
예제 #11
0
        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);
        }
예제 #12
0
        /// <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 ------------");
        }
예제 #13
0
        /// <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);
        }
예제 #14
0
        /// <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;
                }
            }
        }
예제 #15
0
        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);
                    }
                }
            }
        }
예제 #16
0
        /// <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());
                    }
                }
            }
        }
예제 #19
0
        /// <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++;
                }
            }
        }
예제 #20
0
        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;
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #21
0
        //[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);
                            }
                        }
                    }
                }
            }
        }
예제 #22
0
        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]}");
            }
        }
예제 #24
0
        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----------------------------------------------------------------------------");
        }