// Return a segmentUpdate data structure containing a list of proposed changes to segment. // Let activeSynapses be the list of active synapses where the originating cells have // their activeState output = 1 at time step t. // (This list is empty if s = -1 since the segment doesn't exist.) newSynapses is an optional argument // that defaults to false. If newSynapses is true, then newSynapseCount - count(activeSynapses) synapses // are added to activeSynapses. These synapses are randomly chosen from the set of cells that have // learnState output = 1 at time step t. public SegmentUpdate GetSegmentActiveSynapses(int t, HTMSegment segment = null, bool newSynapses = false) { SegmentUpdate segmentUpdate = new SegmentUpdate(); segmentUpdate.ActiveSynapses = new List <HTMSynapse>(); segmentUpdate.NewSynapses = new List <HTMCell>(); segmentUpdate.AddNewSynapses = newSynapses; segmentUpdate.Segment = segment; if (segmentUpdate.Segment != null) { segmentUpdate.ActiveSynapses = segment.GetActiveSynapses(t, false, false); } if (!newSynapses) { return(segmentUpdate); } int newSynapseCount = Math.Max(0, _newSynapseCount - segmentUpdate.ActiveSynapses.Count); //List<HTMCell> learningCells = GetRandomActiveCells(t); List <HTMCell> learningCells = GetRandomLearningCells(t); newSynapseCount = Math.Min(newSynapseCount, learningCells.Count); // Truncate the array of learning cells. To do : get a random sample of the array. for (int i = 0; i < newSynapseCount; i++) { segmentUpdate.NewSynapses.Add(learningCells[i]); } return(segmentUpdate); }
// Return a segment that is/was active at time t. // If multiple segments are active, sequence segments are given preference. // Otherwise, segments with most activity are given preference. public HTMSegment GetActiveSegment(int t) { List <HTMSegment> activeSegs = new List <HTMSegment>(); foreach (HTMSegment seg in _distalSegments) { if (seg.GetActive(-1, false, false)) { activeSegs.Add(seg); } } if (activeSegs.Count == 0) { return(null); } else if (activeSegs.Count == 1) { return(activeSegs[0]); } // There're more the one active segments so sequence segments given priority. List <HTMSegment> sequenceSegs = new List <HTMSegment>(); foreach (HTMSegment seg in activeSegs) { if (seg.IsSequence) { sequenceSegs.Add(seg); } } if (sequenceSegs.Count == 1) { return(sequenceSegs[0]); } else if (sequenceSegs.Count > 1) { activeSegs = sequenceSegs; } // Search the segment that had, in the previous step, the highest activity measured by the number of active synapses. HTMSegment mostActiveSegment = null; int maxActivity = int.MinValue; int activity; foreach (HTMSegment seg in activeSegs) { activity = seg.GetActivity(-1); if (activity > maxActivity) { maxActivity = activity; mostActiveSegment = seg; } } return(mostActiveSegment); }
// For the given column, return the cell with the best matching segment. // If no cell has a matching segment, then return the cell with the fewest number of segments. public CellSegmentInfo GetBestMatchingCell(bool sequence, int t) { HTMCell bestCell = null; HTMSegment bestSeg = null; int bestCount = 0; HTMSegment seg; int synapseCount; foreach (HTMCell cell in _cells) { seg = cell.GetBestMatchingSegment(t, sequence); // TO DO . to study in depth. the previsous function is aggressive in finding the segment but // nevertheless exclude segment with activation under minThreshold, this could bring // to add step by step similar segments? if (seg != null) { synapseCount = seg.GetActiveSynapses(t, false, false).Count; if (synapseCount > bestCount) { bestCell = cell; bestSeg = seg; bestCount = synapseCount; } } } if (bestCell == null) { int fewestSegmentCount = int.MaxValue; foreach (HTMCell cell in _cells) { if (cell.DistalSegments.Count < fewestSegmentCount) { fewestSegmentCount = cell.DistalSegments.Count; bestCell = cell; //if (cell.DistalSegments.Count > 0) // bestSeg = cell.DistalSegments[0]; // choose the first segment } } } CellSegmentInfo cellSegmentInfo = new CellSegmentInfo(); cellSegmentInfo.Cell = bestCell; cellSegmentInfo.Segment = bestSeg; return(cellSegmentInfo); }
// Find the segment with the largest number of active synapses. // This routine is aggressive in finding the best match. // The permanence value of synapses is allowed to be below connectedPerm. // The number of active synapses is allowed to be below activationThreshold, // but must be above minThreshold. public HTMSegment GetBestMatchingSegment(int t, bool sequence) { HTMSegment bestSegment = null; int bestSynapseCount = _column.Region.MinSegmentActivityForLearning; int synCount; foreach (HTMSegment seg in _distalSegments) { synCount = seg.GetActiveSynapses(t, false, false).Count; if (synCount > bestSynapseCount) { bestSynapseCount = synCount; bestSegment = seg; } } return(bestSegment); }
double _y; // The x-position of the column inside the matrix. Range from 0 to 1. #endregion Fields #region Constructors public HTMColumn(HTMRegionAgent region, int posX, int posY, double x, double y) { _region = region; _posX = posX; _posY = posY; _x = x; _y = y; _cells = new List<HTMCell>(); for (int i = 0; i < region.CellsPerColumn; i++) _cells.Add(new HTMCell(this, i)); _proximalSegment = new HTMSegment(null, _region.SegmentActivationThreshold); _isActive = false; _overlap = 0; _boost = 1.0; _activeDutyCycle = 1.0; _overlapDutyCycle = 1.0; }
public HTMColumn(HTMRegionAgent region, int posX, int posY, double x, double y) { _region = region; _posX = posX; _posY = posY; _x = x; _y = y; _cells = new List <HTMCell>(); for (int i = 0; i < region.CellsPerColumn; i++) { _cells.Add(new HTMCell(this, i)); } _proximalSegment = new HTMSegment(null, _region.SegmentActivationThreshold); _isActive = false; _overlap = 0; _boost = 1.0; _activeDutyCycle = 1.0; _overlapDutyCycle = 1.0; }
public void StepTemporalPooling() { // Phase 1 // From the Numenta Docs: // The first phase calculates the active state for each cell. // For each winning column we determine which cells should become active. // If the bottom-up input was predicted by any cell (i.e. its predictiveState was 1 due to // a sequence segment in the previous time step), then those cells become active (lines 4-9). // If the bottom-up input was unexpected (i.e. no cells had predictiveState output on), // then each cell in the column becomes active (lines 11-13). foreach (HTMColumn col in _activeColumns) { bool buPredicted = false; bool lcChosen = false; foreach (HTMCell cell in col.Cells) { if (cell.GetPredicting(-1)) { // _correctPrediction++; HTMSegment segment = cell.GetActiveSegment(-1); if (segment != null && segment.IsSequence) { buPredicted = true; cell.SetActive(true); if (_doTemporalLearning) { if (segment.GetActive(-1, true, false)) { lcChosen = true; cell.SetLearning(true); } } } } } if (!buPredicted) { foreach (HTMCell cell in col.Cells) { cell.SetActive(true); } } // If the bottom-up input was not predicted, the best matching cell is chosen as the learning cell and a new segment is added to that cell. if (_doTemporalLearning) { if (!lcChosen) { CellSegmentInfo bestCellSegmentInfo = col.GetBestMatchingCell(true, -1); bestCellSegmentInfo.Cell.SetLearning(true); SegmentUpdate segmentToUpdate = bestCellSegmentInfo.Cell.GetSegmentActiveSynapses(-1, bestCellSegmentInfo.Segment, true); segmentToUpdate.IsSequence = true; if (segmentToUpdate.Segment != null || (segmentToUpdate.AddNewSynapses && segmentToUpdate.NewSynapses.Count > 0)) // queue the update only if necessary { bestCellSegmentInfo.Cell.SegmentUpdateList.Add(segmentToUpdate); } } } } // Phase 2 // The second phase calculates the predictive state for each cell. // A cell will turn on its predictive state output if one of its segments becomes active, // i.e. if enough of its lateral inputs are currently active due to feed-forward input. // In this case, the cell queues up the following changes: // a) reinforcement of the currently active segment (lines 47-48), // and b) reinforcement of a segment that could have predicted this activation, // i.e. a segment that has a (potentially weak) match to activity during the previous time step (lines 50-53). foreach (HTMColumn col in _columns) { foreach (HTMCell cell in col.Cells) { //if (cell.GetActive(0)) // Cells with active dendrite segments are put in the predictive state UNLESS they are already active due to feed-forward input. // continue; foreach (HTMSegment seg in cell.DistalSegments) { if (!seg.GetActive(0, false, false)) { continue; } cell.SetPredicting(true); // TO DO : check. Active and predictive state are mutual exclusive? // if so, the changing from active to predicting must be done // through a temporary array to avoid cell asymmetrical behavior. //cell.SetActive(false); if (_doTemporalLearning) { // a) reinforcement of the currently active segment SegmentUpdate activeSegUpdate = cell.GetSegmentActiveSynapses(0, seg); cell.SegmentUpdateList.Add(activeSegUpdate); // b) reinforcement of a segment that could have predicted this activation, HTMSegment predSegment = cell.GetBestMatchingSegment(-1, true); if (predSegment == null) { continue; } SegmentUpdate predSegUpdate = cell.GetSegmentActiveSynapses(-1, predSegment, true); cell.SegmentUpdateList.Add(predSegUpdate); } } } } // Phase 3 // The third and last phase actually carries out learning. // In this phase segment updates that have been queued up are actually // implemented once we get feed-forward input and the cell is chosen // as a learning cell (lines 56-57). Otherwise, // if the cell ever stops predicting for any reason, // we negatively reinforce the segments (lines 58-60). if (_doTemporalLearning) { foreach (HTMColumn col in _columns) { foreach (HTMCell cell in col.Cells) { if (cell.SegmentUpdateList.Count == 0) // if there isn't segment to adapt then continue. { continue; } if (cell.GetLearning(0)) { // once we get feed-forward input and the cell is chosen as a learning cell cell.AdaptSegments(true); } else // if (!cell.GetPredicting(0) && cell.GetPredicting(-1)) { // if the cell ever stops predicting for any reason, // we negatively reinforce the segments cell.AdaptSegments(false); } } } } }
// Return a segmentUpdate data structure containing a list of proposed changes to segment. // Let activeSynapses be the list of active synapses where the originating cells have // their activeState output = 1 at time step t. // (This list is empty if s = -1 since the segment doesn't exist.) newSynapses is an optional argument // that defaults to false. If newSynapses is true, then newSynapseCount - count(activeSynapses) synapses // are added to activeSynapses. These synapses are randomly chosen from the set of cells that have // learnState output = 1 at time step t. public SegmentUpdate GetSegmentActiveSynapses(int t, HTMSegment segment = null, bool newSynapses = false) { SegmentUpdate segmentUpdate = new SegmentUpdate(); segmentUpdate.ActiveSynapses = new List<HTMSynapse>(); segmentUpdate.NewSynapses = new List<HTMCell>(); segmentUpdate.AddNewSynapses = newSynapses; segmentUpdate.Segment = segment; if (segmentUpdate.Segment != null) segmentUpdate.ActiveSynapses = segment.GetActiveSynapses(t, false, false); if (!newSynapses) return segmentUpdate; int newSynapseCount = Math.Max(0, _newSynapseCount - segmentUpdate.ActiveSynapses.Count); //List<HTMCell> learningCells = GetRandomActiveCells(t); List<HTMCell> learningCells = GetRandomLearningCells(t); newSynapseCount = Math.Min(newSynapseCount, learningCells.Count); // Truncate the array of learning cells. To do : get a random sample of the array. for (int i = 0 ; i < newSynapseCount; i++) segmentUpdate.NewSynapses.Add(learningCells[i]); return segmentUpdate; }
// This function iterates through a list of segmentUpdate's and reinforces each segment. // For each segmentUpdate element, the following changes are performed. If positiveReinforcement is true // then synapses on the active list get their permanence counts incremented by permanenceInc. // All other synapses get their permanence counts decremented by permanenceDec. // If positiveReinforcement is false, then synapses on the active list get their permanence counts // decremented by permanenceDec. After this step, any synapses in segmentUpdate that do yet exist // get added with a permanence count of initialPerm. public void AdaptSegments(bool positiveReinforcement) { foreach (SegmentUpdate segInfo in _segmentUpdateList) { if (segInfo.Segment != null) { if (positiveReinforcement) { foreach (HTMSynapse syn in segInfo.Segment.Synapses) if (segInfo.ActiveSynapses.Contains(syn)) syn.IncreasePermanence(); else syn.DecreasePermanence(); } else foreach (HTMSynapse syn in segInfo.ActiveSynapses) syn.DecreasePermanence(); // TO DO : the series of negative reinforcements should bring to eliminate the entire segment. } if (segInfo.AddNewSynapses && segInfo.NewSynapses.Count > 0) { // check wheter exist a similar segment bool isFound = false; foreach (HTMSegment seg in _distalSegments) { int foundCount = 0; foreach (HTMSynapse syn in seg.Synapses) if (segInfo.NewSynapses.Contains(syn.InputCell)) foundCount++; if (foundCount == segInfo.NewSynapses.Count) { isFound = true; break; } } if (isFound) continue; // update or create a segment HTMSegment segment; if (segInfo.Segment != null) segment = segInfo.Segment; else { segment = new HTMSegment(this, _column.Region.SegmentActivationThreshold); _distalSegments.Add(segment); _column.Region.Director.Log("Created new distal segment on a cell on column " + segment.Cell.Column.PosX.ToString() + "," + segment.Cell.Column.PosY.ToString()); } segment.IsSequence = segInfo.IsSequence; foreach (HTMCell cell in segInfo.NewSynapses) { // bool find = false; foreach (HTMSynapse syn in segment.Synapses) { if (syn.InputCell == cell) { find = true; break; } } // if (!find) segment.Synapses.Add(new HTMSynapse(cell)); } } } _segmentUpdateList.Clear(); }
// This function iterates through a list of segmentUpdate's and reinforces each segment. // For each segmentUpdate element, the following changes are performed. If positiveReinforcement is true // then synapses on the active list get their permanence counts incremented by permanenceInc. // All other synapses get their permanence counts decremented by permanenceDec. // If positiveReinforcement is false, then synapses on the active list get their permanence counts // decremented by permanenceDec. After this step, any synapses in segmentUpdate that do yet exist // get added with a permanence count of initialPerm. public void AdaptSegments(bool positiveReinforcement) { foreach (SegmentUpdate segInfo in _segmentUpdateList) { if (segInfo.Segment != null) { if (positiveReinforcement) { foreach (HTMSynapse syn in segInfo.Segment.Synapses) { if (segInfo.ActiveSynapses.Contains(syn)) { syn.IncreasePermanence(); } else { syn.DecreasePermanence(); } } } else { foreach (HTMSynapse syn in segInfo.ActiveSynapses) { syn.DecreasePermanence(); } } // TO DO : the series of negative reinforcements should bring to eliminate the entire segment. } if (segInfo.AddNewSynapses && segInfo.NewSynapses.Count > 0) { // check wheter exist a similar segment bool isFound = false; foreach (HTMSegment seg in _distalSegments) { int foundCount = 0; foreach (HTMSynapse syn in seg.Synapses) { if (segInfo.NewSynapses.Contains(syn.InputCell)) { foundCount++; } } if (foundCount == segInfo.NewSynapses.Count) { isFound = true; break; } } if (isFound) { continue; } // update or create a segment HTMSegment segment; if (segInfo.Segment != null) { segment = segInfo.Segment; } else { segment = new HTMSegment(this, _column.Region.SegmentActivationThreshold); _distalSegments.Add(segment); _column.Region.Director.Log("Created new distal segment on a cell on column " + segment.Cell.Column.PosX.ToString() + "," + segment.Cell.Column.PosY.ToString()); } segment.IsSequence = segInfo.IsSequence; foreach (HTMCell cell in segInfo.NewSynapses) { // bool find = false; foreach (HTMSynapse syn in segment.Synapses) { if (syn.InputCell == cell) { find = true; break; } } // if (!find) { segment.Synapses.Add(new HTMSynapse(cell)); } } } } _segmentUpdateList.Clear(); }