This repository has been archived by the owner on Sep 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Python column segment walk #3197
Merged
scottpurdy
merged 32 commits into
numenta:master
from
andrewmalta13:python-columnSegmentWalk
Jul 18, 2016
Merged
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
3908315
initial implementation
andrewmalta13 2e99d31
skip serialization test
andrewmalta13 af063d3
change to column generator
andrewmalta13 3b8bda5
passes unit tests, tutorial_temporal_memory, and extensive tests
andrewmalta13 c2fc03d
removes debugging prints and skips serialization test
andrewmalta13 ca9d304
removes debugging comments
andrewmalta13 44b6906
removes debug comments from connections
andrewmalta13 384b870
cleans up sloppy computeActivity
andrewmalta13 2efc991
Merge branch 'master' of https://github.com/numenta/nupic into python…
andrewmalta13 a9dff1b
addresses some implementation bugs
andrewmalta13 f3faf02
incorporates binary search into the algorithm where applicable
andrewmalta13 d7f631a
misc changes to connections
andrewmalta13 88d26e8
removes some unneccesary validation checks
andrewmalta13 29fcbb4
updates documentation and style
andrewmalta13 25d4e73
removes pylint warnings I introduced
andrewmalta13 283180b
fixes pylint warnings in temporal memory unit tests
andrewmalta13 87fa098
updates connections tests
andrewmalta13 7e9faf1
updated docstrings
andrewmalta13 d02c6fb
removes testing file
andrewmalta13 2696941
addresses some comments
andrewmalta13 b140f5e
addresses more comments
andrewmalta13 42e09fc
reverts generating cell in else change
andrewmalta13 4e80a26
addresses some more feedback
andrewmalta13 c89e2db
fixes spacing style
andrewmalta13 68d376b
uses arrays instead of dicts in computeActivity
andrewmalta13 7a443a6
updates docstrings
andrewmalta13 9aa84d5
addresses comments and updates style to pass pylint
andrewmalta13 b5cd93f
replaces segmentCMP with lambda and updates docstrings
andrewmalta13 6ebafaa
Merge branch 'master' of https://github.com/numenta/nupic into python…
andrewmalta13 010cd7a
fixes some pylint warnings
andrewmalta13 92cbaaa
adds pseudocode to core functions
andrewmalta13 f3a1a54
Merge branch 'master' of https://github.com/numenta/nupic into python…
andrewmalta13 File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
# http://numenta.org/licenses/ | ||
# ---------------------------------------------------------------------- | ||
|
||
from collections import defaultdict, namedtuple | ||
from collections import defaultdict | ||
|
||
|
||
|
||
|
@@ -74,6 +74,19 @@ def __init__(self, | |
self._nextSynapseIdx = 0 | ||
|
||
|
||
def segmentCmp(self, a, b): | ||
""" | ||
A simple comparison function for segments to sort them | ||
by the cell they are on. | ||
|
||
@param a (int) segment 1 | ||
@param b (int) segment 2 | ||
|
||
@return (int) comparison integer between the two cells | ||
""" | ||
return self._segments[a] - self._segments[b] | ||
|
||
|
||
def cellForSegment(self, segment): | ||
""" | ||
Returns the cell that a segment belongs to. | ||
|
@@ -85,6 +98,18 @@ def cellForSegment(self, segment): | |
return self._segments[segment] | ||
|
||
|
||
def columnForSegment(self, segment, cellsPerColumn): | ||
""" | ||
Returns the column that a segment's presynapticCell belongs to | ||
|
||
@param segment (int) Segment index | ||
@param cellsPerColumn (int) Number of cells in a column in the tm | ||
|
||
@return (int) | ||
""" | ||
return self._segments[segment] / cellsPerColumn | ||
|
||
|
||
def segmentsForCell(self, cell): | ||
""" | ||
Returns the segments that belong to a cell. | ||
|
@@ -109,7 +134,6 @@ def dataForSynapse(self, synapse): | |
|
||
@return (SynapseData) Synapse data | ||
""" | ||
self._validateSynapse(synapse) | ||
|
||
return self._synapses[synapse] | ||
|
||
|
@@ -192,7 +216,6 @@ def createSynapse(self, segment, presynapticCell, permanence): | |
@return (int) Synapse index | ||
""" | ||
self._validateSegment(segment) | ||
self._validatePermanence(permanence) | ||
|
||
# Add data | ||
synapse = self._nextSynapseIdx | ||
|
@@ -231,7 +254,6 @@ def updateSynapsePermanence(self, synapse, permanence): | |
@param synapse (int) Synapse index | ||
@param permanence (float) New permanence | ||
""" | ||
self._validatePermanence(permanence) | ||
|
||
data = self._synapses[synapse] | ||
newData = SynapseData(data.segment, | ||
|
@@ -243,6 +265,52 @@ def updateSynapsePermanence(self, synapse, permanence): | |
self._synapsesForPresynapticCell[newData.presynapticCell][synapse] = newData | ||
|
||
|
||
def computeActivity(self, activeInput, activePermanenceThreshold, | ||
activeSynapseThreshold, matchingPermananceThreshold, | ||
matchingSynapseThreshold): | ||
""" | ||
Computes active and matching segments given the current active input. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can start doc strings on the first line: |
||
|
||
@param activeInput (set) currently active cells | ||
@param activePermanenceThreshold (float) permanence threshold for a synapse to be considered active | ||
@param activeSynapseThreshold (int) number of synapses needed for a segment to be considered active | ||
@param matchingPermananceThreshold (float) permanence threshold for a synapse to be considered matching | ||
@param matchingSynapseThreshold (int) number of synapses needed for a segment to be considered matching | ||
|
||
@return (tuple) Contains: | ||
`activeSegments` (list), | ||
`matchingSegments` (list), | ||
|
||
Notes: | ||
activeSegments and matchingSegments are sorted by the cell they are on. | ||
""" | ||
|
||
numActiveSynapsesForSegment = [0] * self._nextSegmentIdx | ||
numMatchingSynapsesForSegment = [0] * self._nextSegmentIdx | ||
|
||
for cell in activeInput: | ||
for synapseData in self.synapsesForPresynapticCell(cell).values(): | ||
segment = synapseData.segment | ||
permanence = synapseData.permanence | ||
if permanence >= matchingPermananceThreshold: | ||
numMatchingSynapsesForSegment[segment] += 1 | ||
if synapseData.permanence >= activePermanenceThreshold: | ||
numActiveSynapsesForSegment[segment] += 1 | ||
|
||
activeSegments = [] | ||
matchingSegments = [] | ||
for i in xrange(self._nextSegmentIdx): | ||
if numActiveSynapsesForSegment[i] >= activeSynapseThreshold: | ||
activeSegments.append(i) | ||
|
||
for i in xrange(self._nextSegmentIdx): | ||
if numMatchingSynapsesForSegment[i] >= matchingSynapseThreshold: | ||
matchingSegments.append(i) | ||
|
||
return (sorted(activeSegments, cmp=self.segmentCmp), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using lambda functions is probably easier here since it's such a simple comparison and used only in these two places:
|
||
sorted(matchingSegments, cmp=self.segmentCmp)) | ||
|
||
|
||
def numSegments(self): | ||
""" | ||
Returns the number of segments. | ||
|
@@ -281,6 +349,7 @@ def write(self, proto): | |
protoSynapse.permanence = synapseData.permanence | ||
|
||
|
||
|
||
@classmethod | ||
def read(cls, proto): | ||
""" | ||
|
@@ -304,9 +373,9 @@ def read(cls, proto): | |
|
||
for k in xrange(len(protoSynapses)): | ||
protoSynapse = protoSynapses[k] | ||
synapse = connections.createSynapse(segment, | ||
int(protoSynapse.presynapticCell), | ||
protoSynapse.permanence) | ||
connections.createSynapse(segment, | ||
int(protoSynapse.presynapticCell), | ||
protoSynapse.permanence) | ||
|
||
return connections | ||
|
||
|
@@ -331,16 +400,16 @@ def __eq__(self, other): | |
otherSegmentSet = set() | ||
for segment in other.segmentsForCell(cell): | ||
otherSynapseSet = other._synapseSetForSynapses( | ||
other.synapsesForSegment(segment)) | ||
other.synapsesForSegment(segment)) | ||
otherSegmentSet.add(frozenset(otherSynapseSet)) | ||
|
||
if segmentSet != otherSegmentSet: return False | ||
|
||
synapseSet = self._synapseSetForSynapses( | ||
self.synapsesForPresynapticCell(cell)) | ||
self.synapsesForPresynapticCell(cell)) | ||
|
||
otherSynapseSet = other._synapseSetForSynapses( | ||
other.synapsesForPresynapticCell(cell)) | ||
other.synapsesForPresynapticCell(cell)) | ||
|
||
if synapseSet != otherSynapseSet: return False | ||
|
||
|
@@ -373,7 +442,7 @@ def _synapseSetForSynapses(self, synapses): | |
for synapse in synapses: | ||
synapseData = self.dataForSynapse(synapse) | ||
synapseSet.add((synapseData.presynapticCell, | ||
round(synapseData.permanence, 7))) | ||
round(synapseData.permanence, 7))) | ||
|
||
return synapseSet | ||
|
||
|
@@ -396,24 +465,3 @@ def _validateSegment(self, segment): | |
""" | ||
if not segment in self._segments: | ||
raise IndexError("Invalid segment") | ||
|
||
|
||
def _validateSynapse(self, synapse): | ||
""" | ||
Raises an error if synapse index is invalid. | ||
|
||
@param synapse (int) Synapse index | ||
""" | ||
if not synapse in self._synapses: | ||
raise IndexError("Invalid synapse") | ||
|
||
|
||
@staticmethod | ||
def _validatePermanence(permanence): | ||
""" | ||
Raises an error if permanence is invalid. | ||
|
||
@param permanence (float) Permanence | ||
""" | ||
if permanence < 0 or permanence > 1: | ||
raise ValueError("Invalid permanence") |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the style guide: "Separate methods inside classes by two blank lines."