/** * Uses the specified {@link Connections} object to Build the structural * anatomy needed by this {@code TemporalMemory} to implement its algorithms. * * The connections object holds the {@link Column} and {@link Cell} infrastructure, * and is used by both the {@link SpatialPooler} and {@link TemporalMemory}. Either of * these can be used separately, and therefore this Connections object may have its * Columns and Cells initialized by either the init method of the SpatialPooler or the * init method of the TemporalMemory. We check for this so that complete initialization * of both Columns and Cells occurs, without either being redundant (initialized more than * once). However, {@link Cell}s only get created when initializing a TemporalMemory, because * they are not used by the SpatialPooler. * * @param c {@link Connections} object */ public static void Init(Connections c) { SparseObjectMatrix <Column> matrix = c.GetMemory() ?? new SparseObjectMatrix <Column>(c.GetColumnDimensions()); c.SetMemory(matrix); int numColumns = matrix.GetMaxIndex() + 1; c.SetNumColumns(numColumns); int cellsPerColumn = c.GetCellsPerColumn(); Cell[] cells = new Cell[numColumns * cellsPerColumn]; //Used as flag to determine if Column objects have been created. Column colZero = matrix.GetObject(0); for (int i = 0; i < numColumns; i++) { Column column = colZero == null ? new Column(cellsPerColumn, i) : matrix.GetObject(i); for (int j = 0; j < cellsPerColumn; j++) { cells[i * cellsPerColumn + j] = column.GetCell(j); } //If columns have not been previously configured if (colZero == null) { matrix.Set(i, column); } } //Only the TemporalMemory initializes cells so no need to test for redundancy c.SetCells(cells); }
/** * {@inheritDoc} */ public override List <EncoderResult> GetBucketInfo(int[] buckets) { SparseObjectMatrix <int[]> topDownMapping = GetTopDownMapping(); //The "category" is simply the bucket index int category = buckets[0]; int[] encoding = topDownMapping.GetObject(category); //Which input value does this correspond to? double inputVal; if (IsPeriodic()) { inputVal = GetMinVal() + GetResolution() / 2 + category * GetResolution(); } else { inputVal = GetMinVal() + category * GetResolution(); } return(new List <EncoderResult> { new EncoderResult(inputVal, inputVal, encoding) }); }
private List <EncoderResult> GetEncoderResultsByIndex(SparseObjectMatrix <int[]> topDownMapping, int categoryIndex) { List <EncoderResult> result = new List <EncoderResult>(); string category = _sdrByCategory.GetCategory(categoryIndex); int[] encoding = topDownMapping.GetObject(categoryIndex); result.Add(new EncoderResult(category, categoryIndex, encoding)); return(result); }
/** * {@inheritDoc} */ public override List <EncoderResult> TopDownCompute(int[] encoded) { //Get/generate the topDown mapping table SparseObjectMatrix <int[]> topDownMapping = scalarEncoder.GetTopDownMapping(); // See which "category" we match the closest. int category = ArrayUtils.Argmax(RightVecProd(topDownMapping, encoded)); return(GetBucketInfo(new int[] { category })); }
/** * Returns a list of items, one for each bucket defined by this encoder. * Each item is the value assigned to that bucket, this is the same as the * EncoderResult.value that would be returned by GetBucketInfo() for that * bucket and is in the same format as the input that would be passed to * encode(). * * This call is faster than calling GetBucketInfo() on each bucket individually * if all you need are the bucket values. * * @param returnType class type parameter so that this method can return encoder * specific value types * * @return list of items, each item representing the bucket value for that * bucket. */ public override List <S> GetBucketValues <S>(Type t) { if (bucketValues == null) { SparseObjectMatrix <int[]> topDownMapping = GetTopDownMapping(); int numBuckets = topDownMapping.GetMaxIndex() + 1; bucketValues = new List <double>(); for (int i = 0; i < numBuckets; i++) { ((List <double>)bucketValues).Add((double)GetBucketInfo(new[] { i })[0].Get(1)); } } return((List <S>)bucketValues); }
/** * Returns a list of items, one for each bucket defined by this encoder. * Each item is the value assigned to that bucket, this is the same as the * EncoderResult.value that would be returned by getBucketInfo() for that * bucket and is in the same format as the input that would be passed to * encode(). * * This call is faster than calling getBucketInfo() on each bucket individually * if all you need are the bucket values. * * @param returnType class type parameter so that this method can return encoder * specific value types * * @return list of items, each item representing the bucket value for that * bucket. */ public override List <T> GetBucketValues <T>(Type t) { if (bucketValues == null) { SparseObjectMatrix <int[]> topDownMapping = scalarEncoder.GetTopDownMapping(); int numBuckets = topDownMapping.GetMaxIndex() + 1; bucketValues = new List <string>(); for (int i = 0; i < numBuckets; i++) { ((List <string>)bucketValues).Add((string)GetBucketInfo(new int[] { i })[0].GetValue()); } } return((List <T>)bucketValues); }
/** * Return the internal topDownMapping matrix used for handling the * {@link #getBucketInfo(int[])} and {@link #topDownCompute(int[])} methods. This is a matrix, one row per * category (bucket) where each row contains the encoded output for that * category. * * @return {@link SparseObjectMatrix} */ public SparseObjectMatrix <int[]> GetTopDownMapping() { if (topDownMapping == null) { topDownMapping = new SparseObjectMatrix <int[]>(new int[] { _sdrByCategory.Count }); int[] outputSpace = new int[GetN()]; List <string> categories = _sdrByCategory.Keys.ToList(); int inx = 0; foreach (string category in categories) { EncodeIntoArray(category, outputSpace); topDownMapping.Set(inx, Arrays.CopyOf(outputSpace, outputSpace.Length)); inx++; } } return(topDownMapping); }
/** * Return the internal topDownMapping matrix used for handling the * bucketInfo() and topDownCompute() methods. This is a matrix, one row per * category (bucket) where each row contains the encoded output for that * category. * * @param c the connections memory * @return the internal topDownMapping */ public SparseObjectMatrix <int[]> GetTopDownMapping() { if (base.topDownMapping == null) { //The input scalar value corresponding to each possible output encoding if (IsPeriodic()) { SetTopDownValues( ArrayUtils.Arrange(GetMinVal() + GetResolution() / 2.0, GetMaxVal(), GetResolution())); } else { //Number of values is (max-min)/resolutions SetTopDownValues( ArrayUtils.Arrange(GetMinVal(), GetMaxVal() + GetResolution() / 2.0, GetResolution())); } } //Each row represents an encoded output pattern int numCategories = GetTopDownValues().Length; SparseObjectMatrix <int[]> topDownMapping; SetTopDownMapping( topDownMapping = new SparseObjectMatrix <int[]>( new int[] { numCategories })); double[] topDownValues = GetTopDownValues(); int[] outputSpace = new int[GetN()]; double minVal = GetMinVal(); double maxVal = GetMaxVal(); for (int i = 0; i < numCategories; i++) { double value = topDownValues[i]; value = Math.Max(value, minVal); value = Math.Min(value, maxVal); EncodeIntoArray(value, outputSpace); topDownMapping.Set(i, Arrays.CopyOf(outputSpace, outputSpace.Length)); } return(topDownMapping); }
/** * Uses the specified {@link Connections} object to Build the structural * anatomy needed by this {@code TemporalMemory} to implement its algorithms. * * The connections object holds the {@link Column} and {@link Cell} infrastructure, * and is used by both the {@link SpatialPooler} and {@link TemporalMemory}. Either of * these can be used separately, and therefore this Connections object may have its * Columns and Cells initialized by either the init method of the SpatialPooler or the * init method of the TemporalMemory. We check for this so that complete initialization * of both Columns and Cells occurs, without either being redundant (initialized more than * once). However, {@link Cell}s only get created when initializing a TemporalMemory, because * they are not used by the SpatialPooler. * * @param c {@link Connections} object */ public void init(Connections conn) { this.connections = conn; SparseObjectMatrix <Column> matrix = this.connections.getMemory() == null ? new SparseObjectMatrix <Column>(this.connections.getColumnDimensions()) : (SparseObjectMatrix <Column>) this.connections.getMemory(); this.connections.setMemory(matrix); int numColumns = matrix.getMaxIndex() + 1; this.connections.setNumColumns(numColumns); int cellsPerColumn = this.connections.getCellsPerColumn(); Cell[] cells = new Cell[numColumns * cellsPerColumn]; //Used as flag to determine if Column objects have been created. Column colZero = matrix.getObject(0); for (int i = 0; i < numColumns; i++) { Column column = colZero == null ? new Column(cellsPerColumn, i, this.connections.getSynPermConnected(), this.connections.NumInputs) : matrix.getObject(i); for (int j = 0; j < cellsPerColumn; j++) { cells[i * cellsPerColumn + j] = column.Cells[j]; } //If columns have not been previously configured if (colZero == null) { matrix.set(i, column); } } //Only the TemporalMemory initializes cells so no need to test for redundancy this.connections.setCells(cells); }
/// <summary> /// Performs the remote initialization ot the SP on actor nodes. /// </summary> /// <param name="c"></param> /// <param name="distMem"></param> public override void InitMatrices(Connections c, DistributedMemory distMem) { IHtmDistCalculus remoteHtm = distMem?.ColumnDictionary as IHtmDistCalculus; if (remoteHtm == null) { throw new ArgumentException("Must implement IHtmDistCalculus!"); } this.distMemConfig = distMem; SparseObjectMatrix <Column> mem = (SparseObjectMatrix <Column>)c.HtmConfig.Memory; c.HtmConfig.Memory = mem == null ? mem = new SparseObjectMatrix <Column>(c.HtmConfig.ColumnDimensions, dict: distMem.ColumnDictionary) : mem; c.HtmConfig.InputMatrix = new SparseBinaryMatrix(c.HtmConfig.InputDimensions); // Initiate the topologies c.HtmConfig.ColumnTopology = new Topology(c.HtmConfig.ColumnDimensions); c.HtmConfig.InputTopology = new Topology(c.HtmConfig.InputDimensions); //Calculate numInputs and numColumns int numInputs = c.HtmConfig.InputMatrix.GetMaxIndex() + 1; int numColumns = c.HtmConfig.Memory.GetMaxIndex() + 1; if (numColumns <= 0) { throw new ArgumentException("Invalid number of columns: " + numColumns); } if (numInputs <= 0) { throw new ArgumentException("Invalid number of inputs: " + numInputs); } c.HtmConfig.NumInputs = numInputs; c.HtmConfig.NumColumns = numColumns; if (distMem != null) { //var distHtmCla = distMem.ColumnDictionary as HtmSparseIntDictionary<Column>; var distHtmCla = distMem.ColumnDictionary;// as ActorSbDistributedDictionaryBase<Column>; distHtmCla.HtmConfig = c.HtmConfig; } // // Fill the sparse matrix with column objects //var numCells = c.getCellsPerColumn(); // var partitions = mem.GetPartitions(); List <KeyPair> colList = new List <KeyPair>(); for (int i = 0; i < numColumns; i++) { //colList.Add(new KeyPair() { Key = i, Value = new Column(numCells, i, c.getSynPermConnected(), c.NumInputs) }); colList.Add(new KeyPair() { Key = i, Value = c.HtmConfig }); } Stopwatch sw = new Stopwatch(); sw.Start(); remoteHtm.InitializeColumnPartitionsDist(colList); //mem.set(colList); sw.Stop(); //c.setPotentialPools(new SparseObjectMatrix<Pool>(c.getMemory().getDimensions(), dict: distMem == null ? null : distMem.PoolDictionary)); Debug.WriteLine($" Upload time: {sw.ElapsedMilliseconds}"); // Already initialized by creating of columns. //c.setConnectedMatrix(new SparseBinaryMatrix(new int[] { numColumns, numInputs })); //Initialize state meta-management statistics c.HtmConfig.OverlapDutyCycles = new double[numColumns]; c.HtmConfig.ActiveDutyCycles = new double[numColumns]; c.HtmConfig.MinOverlapDutyCycles = new double[numColumns]; c.HtmConfig.MinActiveDutyCycles = new double[numColumns]; c.BoostFactors = (new double[numColumns]); ArrayUtils.FillArray(c.BoostFactors, 1); }
/// <summary> /// Implements muticore initialization of pooler. /// </summary> /// <param name="c"></param> protected override void ConnectAndConfigureInputs(Connections c) { IHtmDistCalculus remoteHtm = this.distMemConfig.ColumnDictionary as IHtmDistCalculus; if (remoteHtm == null) { throw new ArgumentException(""); } List <double> avgSynapsesConnected = remoteHtm.ConnectAndConfigureInputsDist(c.HtmConfig); //List<KeyPair> colList = new List<KeyPair>(); //ConcurrentDictionary<int, KeyPair> colList2 = new ConcurrentDictionary<int, KeyPair>(); //int numColumns = c.NumColumns; //// Parallel implementation of initialization //ParallelOptions opts = new ParallelOptions(); ////int synapseCounter = 0; //Parallel.For(0, numColumns, opts, (indx) => //{ // //Random rnd = new Random(42); // //int i = (int)indx; // //var data = new ProcessingDataParallel(); // //// Gets RF // //data.Potential = HtmCompute.MapPotential(c.HtmConfig, i, rnd); // //data.Column = c.getColumn(i); // //// This line initializes all synases in the potential pool of synapses. // //// It creates the pool on proximal dendrite segment of the column. // //// After initialization permancences are set to zero. // ////connectColumnToInputRF(c.HtmConfig, data.Potential, data.Column); // //data.Column.CreatePotentialPool(c.HtmConfig, data.Potential, -1); // ////Interlocked.Add(ref synapseCounter, data.Column.ProximalDendrite.Synapses.Count); // ////colList.Add(new KeyPair() { Key = i, Value = column }); // //data.Perm = HtmCompute.InitSynapsePermanences(c.HtmConfig, data.Potential, rnd); // //data.AvgConnected = GetAvgSpanOfConnectedSynapses(c, i); // //HtmCompute.UpdatePermanencesForColumn(c.HtmConfig, data.Perm, data.Column, data.Potential, true); // if (!colList2.TryAdd(i, new KeyPair() { Key = i, Value = data })) // { // } //}); ////c.setProximalSynapseCount(synapseCounter); //List<double> avgSynapsesConnected = new List<double>(); //foreach (var item in colList2.Values) ////for (int i = 0; i < numColumns; i++) //{ // int i = (int)item.Key; // ProcessingDataParallel data = (ProcessingDataParallel)item.Value; // //ProcessingData data = new ProcessingData(); // // Debug.WriteLine(i); // //data.Potential = mapPotential(c, i, c.isWrapAround()); // //var st = string.Join(",", data.Potential); // //Debug.WriteLine($"{i} - [{st}]"); // //var counts = c.getConnectedCounts(); // //for (int h = 0; h < counts.getDimensions()[0]; h++) // //{ // // // Gets the synapse mapping between column-i with input vector. // // int[] slice = (int[])counts.getSlice(h); // // Debug.Write($"{slice.Count(y => y == 1)} - "); // //} // //Debug.WriteLine(" --- "); // // Console.WriteLine($"{i} - [{String.Join(",", ((ProcessingData)item.Value).Potential)}]"); // // This line initializes all synases in the potential pool of synapses. // // It creates the pool on proximal dendrite segment of the column. // // After initialization permancences are set to zero. // //var potPool = data.Column.createPotentialPool(c, data.Potential); // //connectColumnToInputRF(c, data.Potential, data.Column); // //data.Perm = initPermanence(c.getSynPermConnected(), c.getSynPermMax(), // // c.getRandom(), c.getSynPermTrimThreshold(), c, data.Potential, data.Column, c.getInitConnectedPct()); // //updatePermanencesForColumn(c, data.Perm, data.Column, data.Potential, true); // avgSynapsesConnected.Add(data.AvgConnected); // colList.Add(new KeyPair() { Key = i, Value = data.Column }); //} SparseObjectMatrix <Column> mem = (SparseObjectMatrix <Column>)c.HtmConfig.Memory; //if (mem.IsRemotelyDistributed) //{ // // Pool is created and attached to the local instance of Column. // // Here we need to update the pool on remote Column instance. // mem.set(colList); //} // The inhibition radius determines the size of a column's local // neighborhood. A cortical column must overcome the overlap score of // columns in its neighborhood in order to become active. This radius is // updated every learning round. It grows and shrinks with the average // number of connected synapses per column. UpdateInhibitionRadius(c, avgSynapsesConnected); }