Performance improvements for Spatial Pooler Topology / Local Inhibition. I mentioned this on the numenta.org forum, and here I'm hoping to flesh out the idea more and communicate it with you all.
The spatial pooler with global inhibition works great as is; however local inhibition does not scale well because of the algorithms used. The differences between local and global inhibition happen at a large scale, but within a small (topological) area local and global inhibition do the same thing. Poor mans topology uses global inhibition to approximate local inhibition by making a spatial pooler with global inhibition for each area of local inhibition. In other words: Macro columns can use global inhibition and still have a large scale topology, by simulating a macro column for each topological area.
Pros:
- Speed, this should run as fast as the underlying spatial poolers with global inhibition
- API, should be similar to the underlying spatial pooler's API
Cons:
- Spatial resolution. The current local-inhibition spreads the mini-columns across the input space, but this proposal would cluster many mini-columns into a point and many clusters are spread across the input space. This can be mitigated by using many clusters of mini-columns which allows for an evenly spread blanket of mini-columns.
Implementation:
A new C++ class which will create and maintain a list of SpatialPooler instances, one for each macro column. Macro columns are arranged in a uniform grid over the input space. Macro columns inputs are rectangular slices of the input space.
Example:
The MNIST dataset would be a good example. Its fast, easy to solve, widely recognized, and its visual data which is pretty.
API: Similar to SpatialPooler class ...
- I thought that I'd replace references to "columns" with either "macroColumns" or "miniColumns" throughout this class.
- initialize() - has the same parameters as the SP class except:
- remove param columnDimensions
- add param macroColumnDimentions of type vector<UInt> This must have the same length as the inputDimensions.
- add param miniColumnsPerMacro of type UInt
- change type of potentialRadius from UInt to vector<Real>
- change type of wrapAround from bool to vector<bool>
- compute() - no change to public facing API. This method will deal with dividing up the inputs, running SP.compute(), and concatenating the results.
- Add method getMacroColumns() -> vector<*SpatialPooler> Use this method to access the underlying SP instances.
- Replace method getColumnDimensions() with:
- getMacroColumnDimensions() -> vector<UInt>
- getMiniColumns() -> UInt
...
Started a separate issue from #3 (comment)
Related #84
Author @ctrl-z-9000-times