From 7394e27e1de1f642d60e55a1c113f08f7a4ce736 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 01:05:55 +0200 Subject: [PATCH 1/6] Connections:destroySynapse fixup, use find instead of lower_bound, caused err in Debug. Seems faster --- src/htm/algorithms/Connections.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index 5bd76a9495..75ec6a1b6f 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -250,18 +250,14 @@ void Connections::destroySynapse(const Synapse synapse) { } } - const auto synapseOnSegment = - std::lower_bound(segmentData.synapses.cbegin(), segmentData.synapses.cend(), - synapse, - [&](const Synapse a, const Synapse b) -> bool { - return dataForSynapse(a).id < dataForSynapse(b).id; - }); - - NTA_ASSERT(synapseOnSegment != segmentData.synapses.end()); + const auto synapseOnSegment = std::find(segmentData.synapses.cbegin(), + segmentData.synapses.cend(), + synapse); + + NTA_ASSERT(synapseOnSegment != segmentData.synapses.cend()); NTA_ASSERT(*synapseOnSegment == synapse); segmentData.synapses.erase(synapseOnSegment); - destroyedSynapses_.push_back(synapse); } @@ -348,7 +344,7 @@ bool Connections::compareSegments(const Segment a, const Segment b) const { // default sort by cell if (aData.cell == bData.cell) //fallback to ordinals: - return aData.id < bData.id; + return aData.id < bData.id; //TODO is segment's id/ordinals needed? else return aData.cell < bData.cell; } From 37a0d9863c7d45392d82c11f0ba3f5c3e747d702 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 01:06:43 +0200 Subject: [PATCH 2/6] SP: allow synapse pruning in adaptSegment already used in TM makes SP 10% faster! (on MNIST 55->50s) --- src/htm/algorithms/SpatialPooler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/htm/algorithms/SpatialPooler.cpp b/src/htm/algorithms/SpatialPooler.cpp index fa22e53eba..cfb68498c5 100644 --- a/src/htm/algorithms/SpatialPooler.cpp +++ b/src/htm/algorithms/SpatialPooler.cpp @@ -702,7 +702,7 @@ Real SpatialPooler::avgConnectedSpanForColumnND_(UInt column) const { void SpatialPooler::adaptSynapses_(const SDR &input, const SDR &active) { for(const auto &column : active.getSparse()) { - connections_.adaptSegment(column, input, synPermActiveInc_, synPermInactiveDec_); + connections_.adaptSegment(column, input, synPermActiveInc_, synPermInactiveDec_, true); connections_.raisePermanencesToThreshold( column, stimulusThreshold_ ); } } From fd58f253e00f5bc303433a08da10437df401ba0e Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 02:15:40 +0200 Subject: [PATCH 3/6] Connections:adaptSegment use synapsesCompetition normally in learning. --- src/htm/algorithms/Connections.cpp | 8 ++++++-- src/htm/algorithms/Connections.hpp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index 75ec6a1b6f..cf36716743 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -475,6 +475,9 @@ void Connections::adaptSegment(const Segment segment, } } + //balance synapses using competition on dendrite + synapseCompetition(segment, 4, 10); //FIXME derive these numbers + //destroy segment if it has too few synapses left -> will never be able to connect again if(pruneZeroSynapses and synapses.size() < connectedThreshold_) { destroySegment(segment); @@ -545,7 +548,8 @@ void Connections::synapseCompetition( const SynapseIdx maximumSynapses) { NTA_ASSERT( minimumSynapses <= maximumSynapses); - NTA_ASSERT( maximumSynapses > 0 ); + NTA_ASSERT( maximumSynapses >= connectedThreshold ); + NTA_ASSERT( minimumSynapses < connectedThreshold ); const auto &segData = dataForSegment( segment ); @@ -570,7 +574,7 @@ void Connections::synapseCompetition( // Can't connect more synapses than there are in the potential pool. desiredConnected = std::min( (SynapseIdx) segData.synapses.size(), desiredConnected); // The N'th synapse is at index N-1 - if( desiredConnected != 0 ) { + if( desiredConnected > 0 ) { desiredConnected--; } // else { diff --git a/src/htm/algorithms/Connections.hpp b/src/htm/algorithms/Connections.hpp index f4b37b13e5..746d0edc5a 100644 --- a/src/htm/algorithms/Connections.hpp +++ b/src/htm/algorithms/Connections.hpp @@ -510,7 +510,7 @@ class Connections : public Serializable */ void synapseCompetition( const Segment segment, const SynapseIdx minimumSynapses, - const SynapseIdx maximumSynapses); + const SynapseIdx maximumSynapses); /** From 9a1bbf99e71fe4f6182845f29563ced462013956 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 02:23:44 +0200 Subject: [PATCH 4/6] Connections: introduce Random rng_ member and use it for synapsesCompetition() --- src/htm/algorithms/Connections.cpp | 5 ++++- src/htm/algorithms/Connections.hpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index cf36716743..0be71f4bf8 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -53,6 +53,8 @@ void Connections::initialize(CellIdx numCells, Permanence connectedThreshold, bo connectedThreshold_ = connectedThreshold - htm::Epsilon; iteration_ = 0; + rng_ = Random(42); //TODO set the seed + nextEventToken_ = 0; timeseries_ = timeseries; @@ -476,7 +478,8 @@ void Connections::adaptSegment(const Segment segment, } //balance synapses using competition on dendrite - synapseCompetition(segment, 4, 10); //FIXME derive these numbers + if(rng_.getReal64() < 0.01f) //1% chance //TODO set the probability? + synapseCompetition(segment, 4, 10); //FIXME derive these numbers //destroy segment if it has too few synapses left -> will never be able to connect again if(pruneZeroSynapses and synapses.size() < connectedThreshold_) { diff --git a/src/htm/algorithms/Connections.hpp b/src/htm/algorithms/Connections.hpp index 746d0edc5a..df9bc1cb67 100644 --- a/src/htm/algorithms/Connections.hpp +++ b/src/htm/algorithms/Connections.hpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace htm { @@ -715,9 +716,9 @@ class Connections : public Serializable std::vector destroyedSynapses_; Permanence connectedThreshold_; //TODO make const UInt32 iteration_ = 0; + Random rng_; // Extra bookkeeping for faster computing of segment activity. - struct identity { constexpr size_t operator()( const CellIdx t ) const noexcept { return t; }; }; //TODO in c++20 use std::identity std::unordered_map, identity> potentialSynapsesForPresynapticCell_; From b2cc6c49efce0dcb5ca3cc2e5f9eee193375a313 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 02:24:17 +0200 Subject: [PATCH 5/6] Revert "Connections: introduce Random rng_ member" This reverts commit 9a1bbf99e71fe4f6182845f29563ced462013956. --- src/htm/algorithms/Connections.cpp | 5 +---- src/htm/algorithms/Connections.hpp | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index 0be71f4bf8..cf36716743 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -53,8 +53,6 @@ void Connections::initialize(CellIdx numCells, Permanence connectedThreshold, bo connectedThreshold_ = connectedThreshold - htm::Epsilon; iteration_ = 0; - rng_ = Random(42); //TODO set the seed - nextEventToken_ = 0; timeseries_ = timeseries; @@ -478,8 +476,7 @@ void Connections::adaptSegment(const Segment segment, } //balance synapses using competition on dendrite - if(rng_.getReal64() < 0.01f) //1% chance //TODO set the probability? - synapseCompetition(segment, 4, 10); //FIXME derive these numbers + synapseCompetition(segment, 4, 10); //FIXME derive these numbers //destroy segment if it has too few synapses left -> will never be able to connect again if(pruneZeroSynapses and synapses.size() < connectedThreshold_) { diff --git a/src/htm/algorithms/Connections.hpp b/src/htm/algorithms/Connections.hpp index df9bc1cb67..746d0edc5a 100644 --- a/src/htm/algorithms/Connections.hpp +++ b/src/htm/algorithms/Connections.hpp @@ -33,7 +33,6 @@ #include #include #include -#include namespace htm { @@ -716,9 +715,9 @@ class Connections : public Serializable std::vector destroyedSynapses_; Permanence connectedThreshold_; //TODO make const UInt32 iteration_ = 0; - Random rng_; // Extra bookkeeping for faster computing of segment activity. + struct identity { constexpr size_t operator()( const CellIdx t ) const noexcept { return t; }; }; //TODO in c++20 use std::identity std::unordered_map, identity> potentialSynapsesForPresynapticCell_; From dad10c0d3068aaa7578994b011cbbae155aaade8 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Wed, 24 Jul 2019 02:54:53 +0200 Subject: [PATCH 6/6] update syn competition bounds --- src/htm/algorithms/Connections.cpp | 2 +- src/htm/algorithms/Connections.hpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index cf36716743..b85ef83bdc 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -476,7 +476,7 @@ void Connections::adaptSegment(const Segment segment, } //balance synapses using competition on dendrite - synapseCompetition(segment, 4, 10); //FIXME derive these numbers + synapseCompetition(segment, 8, 11); //FIXME derive these numbers //destroy segment if it has too few synapses left -> will never be able to connect again if(pruneZeroSynapses and synapses.size() < connectedThreshold_) { diff --git a/src/htm/algorithms/Connections.hpp b/src/htm/algorithms/Connections.hpp index 746d0edc5a..6178995236 100644 --- a/src/htm/algorithms/Connections.hpp +++ b/src/htm/algorithms/Connections.hpp @@ -460,8 +460,9 @@ class Connections : public Serializable * @param increment Change in permanence for synapses with active presynapses. * @param decrement Change in permanence for synapses with inactive presynapses. * @param pruneZeroSynapses (default false) If set, synapses that reach minPermanence(aka. "zero") - * are removed. This is used in TemporalMemory. If the segment becomes empty due to these - * removed synapses, we remove the segment (see @ref `destroySegment`). + * are removed. This is used in TemporalMemory and SpatialPooler. + * If the segment becomes empty due to these removed synapses, we remove the segment + * (see @ref `destroySegment`). */ void adaptSegment(const Segment segment, const SDR &inputs,