-
Notifications
You must be signed in to change notification settings - Fork 277
/
Copy pathTemporalMemory.hpp
482 lines (424 loc) · 13.1 KB
/
TemporalMemory.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
/*
* Copyright 2013-2016 Numenta Inc.
*
* Copyright may exist in Contributors' modifications
* and/or contributions to the work.
*
* Use of this source code is governed by the MIT
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
/** @file
* Definitions for the Temporal Memory in C++
*/
#ifndef NTA_TEMPORAL_MEMORY_HPP
#define NTA_TEMPORAL_MEMORY_HPP
#include <nupic/algorithms/Connections.hpp>
#include <nupic/types/Serializable.hpp>
#include <nupic/types/Types.hpp>
#include <nupic/utils/Random.hpp>
#include <vector>
#include <nupic/proto/TemporalMemoryProto.capnp.h>
using namespace std;
using namespace nupic;
using namespace nupic::algorithms::connections;
namespace nupic {
namespace algorithms {
namespace temporal_memory {
/**
* Temporal Memory implementation in C++.
*
* Example usage:
*
* SpatialPooler sp(inputDimensions, columnDimensions, <parameters>);
* TemporalMemory tm(columnDimensions, <parameters>);
*
* while (true) {
* <get input vector, streaming spatiotemporal information>
* sp.compute(inputVector, learn, activeColumns)
* tm.compute(number of activeColumns, activeColumns, learn)
* <do something with the tm, e.g. classify tm.getActiveCells()>
* }
*
* The public API uses C arrays, not std::vectors, as inputs. C arrays are
* a good lowest common denominator. You can get a C array from a vector,
* but you can't get a vector from a C array without copying it. This is
* important, for example, when using numpy arrays. The only way to
* convert a numpy array into a std::vector is to copy it, but you can
* access a numpy array's internal C array directly.
*/
class TemporalMemory : public Serializable<TemporalMemoryProto> {
public:
TemporalMemory();
/**
* Initialize the temporal memory (TM) using the given parameters.
*
* @param columnDimensions
* Dimensions of the column space
*
* @param cellsPerColumn
* Number of cells per column
*
* @param activationThreshold
* If the number of active connected synapses on a segment is at least
* this threshold, the segment is said to be active.
*
* @param initialPermanence
* Initial permanence of a new synapse.
*
* @param connectedPermanence
* If the permanence value for a synapse is greater than this value, it
* is said to be connected.
*
* @param minThreshold
* If the number of potential synapses active on a segment is at least
* this threshold, it is said to be "matching" and is eligible for
* learning.
*
* @param maxNewSynapseCount
* The maximum number of synapses added to a segment during learning.
*
* @param permanenceIncrement
* Amount by which permanences of synapses are incremented during
* learning.
*
* @param permanenceDecrement
* Amount by which permanences of synapses are decremented during
* learning.
*
* @param predictedSegmentDecrement
* Amount by which segments are punished for incorrect predictions.
*
* @param seed
* Seed for the random number generator.
*
* @param maxSegmentsPerCell
* The maximum number of segments per cell.
*
* @param maxSynapsesPerSegment
* The maximum number of synapses per segment.
*
* @param checkInputs
* Whether to check that the activeColumns are sorted without
* duplicates. Disable this for a small speed boost.
*
* Notes:
*
* predictedSegmentDecrement: A good value is just a bit larger than
* (the column-level sparsity * permanenceIncrement). So, if column-level
* sparsity is 2% and permanenceIncrement is 0.01, this parameter should be
* something like 4% * 0.01 = 0.0004).
*/
TemporalMemory(vector<UInt> columnDimensions, UInt cellsPerColumn = 32,
UInt activationThreshold = 13,
Permanence initialPermanence = 0.21,
Permanence connectedPermanence = 0.50, UInt minThreshold = 10,
UInt maxNewSynapseCount = 20,
Permanence permanenceIncrement = 0.10,
Permanence permanenceDecrement = 0.10,
Permanence predictedSegmentDecrement = 0.0, Int seed = 42,
UInt maxSegmentsPerCell = 255,
UInt maxSynapsesPerSegment = 255, bool checkInputs = true);
virtual void
initialize(vector<UInt> columnDimensions = {2048}, UInt cellsPerColumn = 32,
UInt activationThreshold = 13, Permanence initialPermanence = 0.21,
Permanence connectedPermanence = 0.50, UInt minThreshold = 10,
UInt maxNewSynapseCount = 20,
Permanence permanenceIncrement = 0.10,
Permanence permanenceDecrement = 0.10,
Permanence predictedSegmentDecrement = 0.0, Int seed = 42,
UInt maxSegmentsPerCell = 255, UInt maxSynapsesPerSegment = 255,
bool checkInputs = true);
virtual ~TemporalMemory();
//----------------------------------------------------------------------
// Main functions
//----------------------------------------------------------------------
/**
* Get the version number of for the TM implementation.
*
* @returns Integer version number.
*/
virtual UInt version() const;
/**
* This *only* updates _rng to a new Random using seed.
*
* @returns Integer version number.
*/
void seed_(UInt64 seed);
/**
* Indicates the start of a new sequence.
* Resets sequence state of the TM.
*/
virtual void reset();
/**
* Calculate the active cells, using the current active columns and
* dendrite segments. Grow and reinforce synapses.
*
* @param activeColumnsSize
* Size of activeColumns.
*
* @param activeColumns
* A sorted list of active column indices.
*
* @param learn
* If true, reinforce / punish / grow synapses.
*/
void activateCells(size_t activeColumnsSize, const UInt activeColumns[],
bool learn = true);
/**
* Calculate dendrite segment activity, using the current active cells.
*
* @param learn
* If true, segment activations will be recorded. This information is
* used during segment cleanup.
*/
void activateDendrites(bool learn = true);
/**
* Perform one time step of the Temporal Memory algorithm.
*
* This method calls activateCells, then calls activateDendrites. Using
* the TemporalMemory via its compute method ensures that you'll always
* be able to call getPredictiveCells to get predictions for the next
* time step.
*
* @param activeColumnsSize
* Number of active columns.
*
* @param activeColumns
* Sorted list of indices of active columns.
*
* @param learn
* Whether or not learning is enabled.
*/
virtual void compute(size_t activeColumnsSize, const UInt activeColumns[],
bool learn = true);
// ==============================
// Helper functions
// ==============================
/**
* Create a segment on the specified cell. This method calls
* createSegment on the underlying connections, and it does some extra
* bookkeeping. Unit tests should call this method, and not
* connections.createSegment().
*
* @param cell
* Cell to add a segment to.
*
* @return Segment
* The created segment.
*/
Segment createSegment(CellIdx cell);
/**
* Returns the indices of cells that belong to a column.
*
* @param column Column index
*
* @return (vector<CellIdx>) Cell indices
*/
vector<CellIdx> cellsForColumn(Int column);
/**
* Returns the number of cells in this layer.
*
* @return (int) Number of cells
*/
UInt numberOfCells(void);
/**
* Returns the indices of the active cells.
*
* @returns (std::vector<CellIdx>) Vector of indices of active cells.
*/
vector<CellIdx> getActiveCells() const;
/**
* Returns the indices of the predictive cells.
*
* @returns (std::vector<CellIdx>) Vector of indices of predictive cells.
*/
vector<CellIdx> getPredictiveCells() const;
/**
* Returns the indices of the winner cells.
*
* @returns (std::vector<CellIdx>) Vector of indices of winner cells.
*/
vector<CellIdx> getWinnerCells() const;
vector<Segment> getActiveSegments() const;
vector<Segment> getMatchingSegments() const;
/**
* Returns the dimensions of the columns in the region.
*
* @returns Integer number of column dimension
*/
vector<UInt> getColumnDimensions() const;
/**
* Returns the total number of columns.
*
* @returns Integer number of column numbers
*/
UInt numberOfColumns() const;
/**
* Returns the number of cells per column.
*
* @returns Integer number of cells per column
*/
UInt getCellsPerColumn() const;
/**
* Returns the activation threshold.
*
* @returns Integer number of the activation threshold
*/
UInt getActivationThreshold() const;
void setActivationThreshold(UInt);
/**
* Returns the initial permanence.
*
* @returns Initial permanence
*/
Permanence getInitialPermanence() const;
void setInitialPermanence(Permanence);
/**
* Returns the connected permanance.
*
* @returns Returns the connected permanance
*/
Permanence getConnectedPermanence() const;
void setConnectedPermanence(Permanence);
/**
* Returns the minimum threshold.
*
* @returns Integer number of minimum threshold
*/
UInt getMinThreshold() const;
void setMinThreshold(UInt);
/**
* Returns the maximum number of synapses that can be added to a segment
* in a single time step.
*
* @returns Integer number of maximum new synapse count
*/
UInt getMaxNewSynapseCount() const;
void setMaxNewSynapseCount(UInt);
/**
* Get and set the checkInputs parameter.
*/
bool getCheckInputs() const;
void setCheckInputs(bool);
/**
* Returns the permanence increment.
*
* @returns Returns the Permanence increment
*/
Permanence getPermanenceIncrement() const;
void setPermanenceIncrement(Permanence);
/**
* Returns the permanence decrement.
*
* @returns Returns the Permanence decrement
*/
Permanence getPermanenceDecrement() const;
void setPermanenceDecrement(Permanence);
/**
* Returns the predicted Segment decrement.
*
* @returns Returns the segment decrement
*/
Permanence getPredictedSegmentDecrement() const;
void setPredictedSegmentDecrement(Permanence);
/**
* Returns the maxSegmentsPerCell.
*
* @returns Max segments per cell
*/
UInt getMaxSegmentsPerCell() const;
/**
* Returns the maxSynapsesPerSegment.
*
* @returns Max synapses per segment
*/
UInt getMaxSynapsesPerSegment() const;
/**
* Raises an error if cell index is invalid.
*
* @param cell Cell index
*/
bool _validateCell(CellIdx cell);
/**
* Save (serialize) the current state of the spatial pooler to the
* specified file.
*
* @param fd A valid file descriptor.
*/
virtual void save(ostream &outStream) const;
using Serializable::write;
virtual void write(TemporalMemoryProto::Builder &proto) const override;
/**
* Load (deserialize) and initialize the spatial pooler from the
* specified input stream.
*
* @param inStream A valid istream.
*/
virtual void load(istream &inStream);
using Serializable::read;
virtual void read(TemporalMemoryProto::Reader &proto) override;
/**
* Returns the number of bytes that a save operation would result in.
* Note: this method is currently somewhat inefficient as it just does
* a full save into an ostream and counts the resulting size.
*
* @returns Integer number of bytes
*/
virtual UInt persistentSize() const;
bool operator==(const TemporalMemory &other);
bool operator!=(const TemporalMemory &other);
//----------------------------------------------------------------------
// Debugging helpers
//----------------------------------------------------------------------
/**
* Print the main TM creation parameters
*/
void printParameters();
/**
* Returns the index of the column that a cell belongs to.
*
* @param cell Cell index
*
* @return (int) Column index
*/
Int columnForCell(CellIdx cell);
/**
* Print the given UInt array in a nice format
*/
void printState(vector<UInt> &state);
/**
* Print the given Real array in a nice format
*/
void printState(vector<Real> &state);
protected:
UInt numColumns_;
vector<UInt> columnDimensions_;
UInt cellsPerColumn_;
UInt activationThreshold_;
UInt minThreshold_;
UInt maxNewSynapseCount_;
bool checkInputs_;
Permanence initialPermanence_;
Permanence connectedPermanence_;
Permanence permanenceIncrement_;
Permanence permanenceDecrement_;
Permanence predictedSegmentDecrement_;
vector<CellIdx> activeCells_;
vector<CellIdx> winnerCells_;
vector<Segment> activeSegments_;
vector<Segment> matchingSegments_;
vector<UInt32> numActiveConnectedSynapsesForSegment_;
vector<UInt32> numActivePotentialSynapsesForSegment_;
UInt maxSegmentsPerCell_;
UInt maxSynapsesPerSegment_;
UInt64 iteration_;
vector<UInt64> lastUsedIterationForSegment_;
Random rng_;
public:
Connections connections;
};
} // end namespace temporal_memory
} // end namespace algorithms
} // namespace nupic
#endif // NTA_TEMPORAL_MEMORY_HPP