Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Column pooler2 update #293

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d2f061a
SP: strip unlearned columns: return usage
breznak Feb 28, 2019
2a570a9
Merge branch 'master_community' into sp_stripUnlearnedColumns
breznak Mar 1, 2019
d5bcc46
SP: removed stripUnlearnedColumns()
breznak Mar 1, 2019
0c3bc81
Revert "Start ASCII experiment"
breznak Mar 2, 2019
a39117a
Merge branch 'master_community' into columnPooler2-update
breznak Mar 2, 2019
c7e7b9d
merge MNIST example from master
breznak Mar 2, 2019
f499e01
resolve merge conflicts
breznak Mar 2, 2019
01e83b0
ColumnPooler: make in namespace nupic::algorithms::column_pooler
breznak Mar 2, 2019
d132610
ColumnPooler: add initialize() and default empty constructor
breznak Mar 2, 2019
6bffed9
CP: fix typo Inhbition -> Inhibition in names
breznak Mar 2, 2019
1926f0f
MNIST: using CP instead of SP
breznak Mar 2, 2019
3d853b8
Connections: adaptSegment make const input,
breznak Mar 2, 2019
ca27761
CP: tmp check potential segfault
breznak Mar 2, 2019
3b1b11c
Merge pull request #292 from htm-community/connections_segfault
ctrl-z-9000-times Mar 2, 2019
d5a1ec0
API_CHANGELOG formatting
ctrl-z-9000-times Mar 2, 2019
f9032dc
Merge branch 'master' into sp_stripUnlearnedColumns
ctrl-z-9000-times Mar 2, 2019
000f3c8
Merge pull request #286 from htm-community/sp_stripUnlearnedColumns
breznak Mar 2, 2019
3a23166
SDR renamed data formats: "sparse" -> "coordinate", "flatSparse" -> "…
ctrl-z-9000-times Mar 2, 2019
e6d6d4d
Merge branch 'master' into sdr-coordinate
ctrl-z-9000-times Mar 2, 2019
4a4befc
SDR rename to sparse & coordinates: fix python unit tests
ctrl-z-9000-times Mar 2, 2019
9fc710e
Merge pull request #296 from htm-community/sdr-coordinate
breznak Mar 2, 2019
8ff7c51
Merge remote-tracking branch 'community/columnPooler2' into columnPoo…
breznak Mar 2, 2019
5ca87e2
Merge branch 'master_community' into columnPooler2-update
breznak Mar 2, 2019
19bfe50
CP: resolve merge conflicts with FlatSparse renamed
breznak Mar 2, 2019
089aa7a
CP: merge conflict
breznak Mar 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions API_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,5 @@ As a side-effect of this change, the LinkType and LinkParam parameters in the Ne
are ignored. PR #271

* Removed all matrix libraries. Use the `Connections` class instead. PR #169

* Removed `void SpatialPooler::stripUnlearnedColumns()` as unused and not useful (did not effectively remove any columns). PR #286
61 changes: 30 additions & 31 deletions bindings/py/cpp_src/bindings/algorithms/py_SDR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ state of a group of neurons or their associated processes.
SDR's have three commonly used data formats which are:
* dense
* sparse
* flatSparse
* coordinates
The SDR class has three magic properties, one for each of these data formats.
These properties are the primary way of accessing the SDR's data. When these
properties are read from, the data is automatically converted to the requested
Expand All @@ -61,21 +61,21 @@ Example usage:
X.dense = [[0, 1, 0],
[0, 1, 0],
[0, 0, 1]]
X.sparse = [[0, 1, 2], [1, 1, 2]]
X.flatSparse = [ 1, 4, 8 ]
X.sparse = [ 1, 4, 8 ]
X.coordinates = [[0, 1, 2], [1, 1, 2]]

# Access data in any format, SDR will automatically convert data formats,
# even if it was not the format used by the most recent assignment to the
# SDR.
X.dense -> [[ 0, 1, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 1 ]]
X.sparse -> [[ 0, 1, 2 ], [1, 1, 2 ]]
x.flatSparse -> [ 1, 4, 8 ]
X.dense -> [[ 0, 1, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 1 ]]
x.sparse -> [ 1, 4, 8 ]
X.coordinates -> [[ 0, 1, 2 ], [1, 1, 2 ]]

# Data format conversions are cached, and when an SDR value changes the
# cache is cleared.
X.flatSparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache.
X.sparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache.
X.dense # This line will convert formats.
X.dense # This line will resuse the result of the previous line

Expand All @@ -85,12 +85,12 @@ This class will detect that it's being given it's own data and will omit the
copy operation.

Example Usage of In-Place Assignment:
X = SDR((1000, 1000))
X = SDR((1000, 1000)) # Initial value is all zeros
data = X.dense
data[ 0, 4] = 1
data[444, 444] = 1
X.dense = data
X.flatSparse -> [ 4, 444444 ]
X.sparse -> [ 4, 444444 ]

Data Validity Warning: The SDR allocates and frees its data when it is
constructed and deconstructed, respectively. If you have a numpy array which
Expand All @@ -102,15 +102,14 @@ Examples of Invalid Data Accesses:
del A
# The variable "use_after_free" now references data which has been deallocated.
# Another way this can happen is:
use_after_free = SDR( dimensions ).sparse
use_after_free = SDR( dimensions ).flatSparse
use_after_free = SDR( dimensions ).dense

Data Validity Warning: After assigning a new value to the SDR, all existing
numpy arrays of data are invalid. In order to get the latest copy of the data,
re-access the data from the SDR. Examples:
A = SDR( dimensions )
out_of_date = A.dense
A.flatSparse = []
A.sparse = []
# The variable "out_of_date" is now liable to be overwritten.
A.dense = out_of_date # This does not work, since the data is invalid.
)");
Expand Down Expand Up @@ -183,34 +182,34 @@ After modifying this array you MUST assign the array back into the SDR, in order
to notify the SDR that its dense array has changed and its cached data is out of
date. If you did't copy this data, then SDR won't copy either.)");

py_SDR.def_property("flatSparse",
py_SDR.def_property("sparse",
[](SDR &self) {
auto capsule = py::capsule(&self, [](void *self) {});
return py::array(self.getSum(), self.getFlatSparse().data(), capsule);
return py::array(self.getSum(), self.getSparse().data(), capsule);
},
[](SDR &self, SDR_flatSparse_t data) {
[](SDR &self, SDR_sparse_t data) {
NTA_CHECK( data.size() <= self.size );
self.setFlatSparse( data ); },
self.setSparse( data ); },
R"(A numpy array containing the indices of only the true values in the SDR.
These are indices into the flattened SDR. This format allows for quickly
accessing all of the true bits in the SDR.)");

py_SDR.def_property("sparse",
py_SDR.def_property("coordinates",
[](SDR &self) {
auto capsule = py::capsule(&self, [](void *self) {});
auto outer = py::list();
auto sparse = self.getSparse().data();
for(auto dim = 0u; dim < self.dimensions.size(); dim++) {
auto vec = py::array(sparse[dim].size(), sparse[dim].data(), capsule);
auto coords = self.getCoordinates().data();
for(auto dim = 0u; dim < self.dimensions.size(); ++dim) {
auto vec = py::array(coords[dim].size(), coords[dim].data(), capsule);
outer.append(vec);
}
return outer;
},
[](SDR &self, SDR_sparse_t data) {
[](SDR &self, SDR_coordinate_t data) {
NTA_CHECK( data.size() == self.dimensions.size() );
self.setSparse( data ); },
R"(List of numpy arrays, containing the indices of only the true values in the
SDR. This is a list of lists: the outter list contains an entry for each
self.setCoordinates( data ); },
R"(List of numpy arrays, containing the coordinates of only the true values in
the SDR. This is a list of lists: the outter list contains an entry for each
dimension in the SDR. The inner lists contain the coordinates of each true bit.
The inner lists run in parallel. This format is useful because it contains the
location of each true bit inside of the SDR's dimensional space.)");
Expand Down Expand Up @@ -301,8 +300,8 @@ Example Usage:
# Convert SDR dimensions from (4 x 4) to (8 x 2)
A = SDR([ 4, 4 ])
B = SDR_Proxy( A, [8, 2])
A.sparse = ([1, 1, 2], [0, 1, 2])
B.sparse -> ([2, 2, 5], [0, 1, 0])
A.coordinates = ([1, 1, 2], [0, 1, 2])
B.coordinates -> ([2, 2, 5], [0, 1, 0])

SDR_Proxy supports pickle, however loading a pickled SDR proxy will return an
SDR, not an SDR_Proxy.)");
Expand All @@ -326,12 +325,12 @@ Example Usage:
# Setup 2 SDRs to hold the inputs.
A = SDR( 10 )
B = SDR( 10 )
A.flatSparse = [2, 3, 4, 5]
B.flatSparse = [0, 1, 2, 3]
A.sparse = [2, 3, 4, 5]
B.sparse = [0, 1, 2, 3]

# Calculate the logical intersection
X = SDR_Intersection(A, B)
X.flatSparse -> [2, 3]
X.sparse -> [2, 3]

# Assignments to the input SDRs are propigated to the SDR_Intersection
B.zero()
Expand Down
6 changes: 0 additions & 6 deletions bindings/py/cpp_src/bindings/algorithms/py_SpatialPooler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,6 @@ namespace nupic_ext
self.compute(get_it<UInt>(x), learn, get_it<UInt>(y));
});

// stripUnlearnedColumns
py_SpatialPooler.def("stripUnlearnedColumns", [](SpatialPooler& self, py::array_t<UInt>& x)
{
self.stripUnlearnedColumns(get_it(x));
});

// setBoostFactors
py_SpatialPooler.def("setBoostFactors", [](SpatialPooler& self, py::array_t<Real>& x)
{
Expand Down
64 changes: 32 additions & 32 deletions bindings/py/tests/SDR_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,24 @@ def testExampleUsage(self):
[0, 1, 0],
[0, 0, 1]]
assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] )
assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.flatSparse) == [ 1, 4, 8 ] )
X.sparse = [[0, 1, 2], [1, 1, 2]]
assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.sparse) == [ 1, 4, 8 ] )
X.coordinates = [[0, 1, 2], [1, 1, 2]]
assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] )
assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.flatSparse) == [ 1, 4, 8 ] )
X.flatSparse = [ 1, 4, 8 ]
assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.sparse) == [ 1, 4, 8 ] )
X.sparse = [ 1, 4, 8 ]

# Access data in any format, SDR will automatically convert data formats,
# even if it was not the format used by the most recent assignment to the
# SDR.
assert( X.dense.tolist() == [[ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]] )
assert( [list(v) for v in X.sparse] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.flatSparse) == [ 1, 4, 8 ] )
assert( [list(v) for v in X.coordinates] == [[ 0, 1, 2 ], [1, 1, 2 ]] )
assert( list(X.sparse) == [ 1, 4, 8 ] )

# Data format conversions are cached, and when an SDR value changes the
# cache is cleared.
X.flatSparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache.
X.sparse = [1, 2, 3] # Assign new data to the SDR, clearing the cache.
X.dense # This line will convert formats.
X.dense # This line will resuse the result of the previous line

Expand All @@ -64,7 +64,7 @@ def testExampleUsage(self):
data[ 0, 4] = 1
data[444, 444] = 1
X.dense = data
assert(list(X.flatSparse) == [ 4, 444444 ])
assert(list(X.sparse) == [ 4, 444444 ])

def testConstructor(self):
A = SDR((103,))
Expand All @@ -87,7 +87,7 @@ def testConstructor(self):

def testZero(self):
A = SDR((103,))
A.flatSparse = list(range(20))
A.sparse = list(range(20))
A.zero()
assert( np.sum( A.dense ) == 0 )

Expand All @@ -102,7 +102,7 @@ def testDense(self):
assert(A.dense[0] + A.dense[99] == 2)
# Test modify in-place
A.dense = A.dense
assert(set(A.flatSparse) == set((0, 99)))
assert(set(A.sparse) == set((0, 99)))
# Test dense dimensions
assert(B.dense.shape == (100, 100, 1))
# No crash with dimensions
Expand Down Expand Up @@ -153,45 +153,45 @@ def testDenseInplace(self):

assert( inplace_time < copy_time / 3 )

def testFlatSparse(self):
def testSparse(self):
A = SDR((103,))
B = SDR((100, 100, 1))

A.flatSparse
B.flatSparse = [1,2,3,4]
assert(all(B.flatSparse == np.array([1,2,3,4])))
A.sparse
B.sparse = [1,2,3,4]
assert(all(B.sparse == np.array([1,2,3,4])))

B.flatSparse = []
B.sparse = []
assert( not B.dense.any() )

# Test wrong dimensions assigned
C = SDR( 1000 )
C.randomize( .98 )
try:
A.flatSparse = C.flatSparse
A.sparse = C.sparse
except RuntimeError:
pass
else:
self.fail()

def testSparse(self):
def testCoordinates(self):
A = SDR((103,))
B = SDR((100, 100, 1))
C = SDR((2, 4, 5, 1,1,1,1, 3))

A.sparse
B.sparse = [[0, 55, 99], [0, 11, 99], [0, 0, 0]]
A.coordinates
B.coordinates = [[0, 55, 99], [0, 11, 99], [0, 0, 0]]
assert(B.dense[0, 0, 0] == 1)
assert(B.dense[55, 11, 0] == 1)
assert(B.dense[99, 99, 0] == 1)
C.randomize( .5 )
assert( len(C.sparse) == len(C.dimensions) )
assert( len(C.coordinates) == len(C.dimensions) )

# Test wrong dimensions assigned
C = SDR((2, 4, 5, 1,1,1,1, 3))
C.randomize( .5 )
try:
A.sparse = C.sparse
A.coordinates = C.coordinates
except RuntimeError:
pass
else:
Expand All @@ -200,14 +200,14 @@ def testSparse(self):
def testSetSDR(self):
A = SDR((103,))
B = SDR((103,))
A.flatSparse = [66]
A.sparse = [66]
B.setSDR( A )
assert( B.dense[66] == 1 )
assert( B.getSum() == 1 )
B.dense[77] = 1
B.dense = B.dense
A.setSDR( B )
assert( set(A.flatSparse) == set((66, 77)) )
assert( set(A.sparse) == set((66, 77)) )

# Test wrong dimensions assigned
C = SDR((2, 4, 5, 1,1,1,1, 3))
Expand Down Expand Up @@ -326,8 +326,8 @@ def testExampleUsage(self):
# Convert SDR dimensions from (4 x 4) to (8 x 2)
A = SDR([ 4, 4 ])
B = SDR_Proxy( A, [8, 2])
A.sparse = ([1, 1, 2], [0, 1, 2])
assert( (np.array(B.sparse) == ([2, 2, 5], [0, 1, 0]) ).all() )
A.coordinates = ([1, 1, 2], [0, 1, 2])
assert( (np.array(B.coordinates) == ([2, 2, 5], [0, 1, 0]) ).all() )

def testLostSDR(self):
# You need to keep a reference to the SDR, since SDR class does not use smart pointers.
Expand All @@ -343,8 +343,8 @@ def testChaining(self):

A.dense.fill( 1 )
A.dense = A.dense
assert( len(C.flatSparse) == A.size )
assert( len(D.flatSparse) == A.size )
assert( len(C.sparse) == A.size )
assert( len(D.sparse) == A.size )
del B

@pytest.mark.skip(reason="Known issue: https://github.com/htm-community/nupic.cpp/issues/160")
Expand All @@ -356,10 +356,10 @@ class SdrIntersectionTest(unittest.TestCase):
def testExampleUsage(self):
A = SDR( 10 )
B = SDR( 10 )
A.flatSparse = [2, 3, 4, 5]
B.flatSparse = [0, 1, 2, 3]
A.sparse = [2, 3, 4, 5]
B.sparse = [0, 1, 2, 3]
X = SDR_Intersection(A, B)
assert((X.flatSparse == [2, 3]).all())
assert((X.sparse == [2, 3]).all())
B.zero()
assert(X.getSparsity() == 0)

Expand Down
18 changes: 0 additions & 18 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -400,23 +400,6 @@ add_custom_target(mnist
COMMENT "Executing ${src_executable_mnistsp}"
VERBATIM)

#########################################################
## ASCII Example
#
set(src_executable_ascii ascii)
add_executable(${src_executable_ascii} "examples/ascii.cpp")
target_link_libraries(${src_executable_ascii} ${core_library})
target_compile_options(${src_executable_ascii} PUBLIC ${INTERNAL_CXX_FLAGS})
target_compile_definitions(${src_executable_ascii} PRIVATE ${COMMON_COMPILER_DEFINITIONS})
target_include_directories(${src_executable_ascii} PRIVATE
${CORE_LIB_INCLUDES}
${EXTERNAL_INCLUDES}
)
# add_custom_target(ascii
# COMMAND ${src_executable_ascii}
# DEPENDS ${src_executable_ascii}
# COMMENT "Executing ${src_executable_ascii}"
# VERBATIM)

##################################################
#
Expand All @@ -426,7 +409,6 @@ install(TARGETS
${core_library}
${src_executable_hotgym}
${src_executable_mnistsp}
${src_executable_ascii}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
Expand Down
26 changes: 0 additions & 26 deletions src/examples/ascii.cpp

This file was deleted.

Loading