# Yet another "Yet Another HTM Implementation"

**URL:** <https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831>\
**Category:** Implementations\
**Tags:** htm-implementations\
**Created:** [October 28, 2018, 1:39am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831 "2018-10-28T01:39:24Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Balladeer](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/balladeer/32/3094_2.png) [@Balladeer](https://discourse.numenta.org/u/Balladeer)\
**Post date:** [October 28, 2018, 1:39am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/1 "2018-10-28T01:39:24Z")

</div>

Hey folks!

Jeff’s talk at the APL last month reinvigorated my interest in HTM, so I’ve spent the last month or so catching up on the current state of things. To help me with that goal, I ended up tinkering on [ZHTM](https://bitbucket.org/zhtm/zhtm/src/develop/) after work.

ZHTM is a Python 3 implementation of both a Spatial Pooler and the Temporal Memory algorithm (as defined largely by [BAMI](https://numenta.com/resources/biological-and-machine-intelligence/)). The current implementation uses just base Python; the only dependencies (thus far) are `pytest` and `pytest-mock` for testing purposes.

As of earlier today, it is at least _possible_ to feed inputs into the Temporal Memory algorithm repeatedly without obvious errors, so I’m celebrating that milestone by posting here.

I’ve also got some super-hacky Vue.js visualizations in progress, but they are a significantly less demo-worthy at the moment:

![zhtm_viewer_screenshot](https://canada1.discourse-cdn.com/flex030/uploads/numenta/original/2X/0/0245d3455403d0e4cc5878ff3793173ed5b8240e.png)

Over the next month, I am hoping to move the system from “doesn’t throw exceptions” into “might be useful” territory:

- Add integration tests to assert that Spatial Pooler and Temporal Memory operate as expected at a higher level than the unit tests currently provide
- Create example systems with known data sets (e.g. the gym or traffic data sets)
- Add 5+ of the basic encoders
- Create demos of at least 3 major components of the system via the web viewer (unpublished)

Anyway, thanks to everyone for your helpful posts and articles. I haven’t said much in the last month, but I appreciate all the knowledge you’ve been sharing.

P.S. Here’s part of the call graph from calling the Temporal Memory algorithm 20 times. I just thought it looked neat.

 ![zhtm_silly_call_graph](https://canada1.discourse-cdn.com/flex030/uploads/numenta/original/2X/8/84d86b8cd4079b4c795d30ab787e6d733e3a223f.png)

---

<div class="post-metadata">

**Author:** ![Jose\_Cueto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/jose_cueto/32/4052_2.png) [@Jose\_Cueto](https://discourse.numenta.org/u/Jose_Cueto)\
**Post date:** [October 28, 2018, 2:49am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/2 "2018-10-28T02:49:58Z")

</div>

Thanks for sharing - yet another concrete interpretation of BAMI. Although I try to avoid repeating myself, I’m also slowly writing an HTM framework primarily for learning HTM theory. I tend to learn algorithms better by reading/writing code than text docs or videos.

I thought of using plain objects as well as it would ease the learning process, but I think I will be using a different approach to future proof it. Just to inform you, I have also loosely asked around about how much matrix/linear algebra is used in nupic py and c++. I didnt get much responses, however at this stage, I think that HTM algorithms doesn’t have to use linear algebra libs as much as those existing ML fwks today.

---

<div class="post-metadata">

**Author:** ![Balladeer](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/balladeer/32/3094_2.png) [@Balladeer](https://discourse.numenta.org/u/Balladeer)\
**Post date:** [October 28, 2018, 10:31am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/3 "2018-10-28T10:31:45Z")

</div>

> [@Jose\_Cueto](#):
>
> I tend to learn algorithms better by reading/writing code than text docs or videos.

I hear you there! It’s really easy to just skim some code and _think_ that you understand something. Nothing forces you to prove it like making working code.

---

<div class="post-metadata">

**Author:** ![Balladeer](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/balladeer/32/3094_2.png) [@Balladeer](https://discourse.numenta.org/u/Balladeer)\
**Post date:** [November 20, 2018, 3:54pm UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/4 "2018-11-20T15:54:19Z")

</div>

Quick status update!

I’ve been plugging away at this implementation. Yesterday I managed to run a `zhtm` system through the anomaly benchmark. This is using raw prediction-error scoring, as I haven’t implemented the ‘anomaly likelihood’ stuff quite yet.

I did discover a pretty big conceptual misunderstanding to work through: I totally misinterpreted how data was passed from the spatial pooler into the temporal memory. Rather than send the spatial pooler’s active columns directly into the temporal memory system, I was re-sampling the spatial pooler’s output, in the same way that the spatial pooler samples the input space. Once I fixed that mistake, the system started behaving itself more like I expected.

### Anomaly benchmark

Here are some super preliminary results from the `final_results.json` file that NAB generates:

```auto
{
    "null": {
        "reward_low_FN_rate": 0.0,
        "reward_low_FP_rate": 0.0,
        "standard": 0.0
    },
    "numenta": {
        "reward_low_FN_rate": 74.32064726862069,
        "reward_low_FP_rate": 61.70812096732759,
        "standard": 69.67062607534481
    },
    "zhtm": {
        "reward_low_FN_rate": 73.01327530933908,
        "reward_low_FP_rate": 56.10583427353449,
        "standard": 66.84749917090518
    }
}

```

Despite not having the likelihood stuff implemented, my system appears to be within the same ballpark as the Numenta detector, which is exciting for me! (You can see the ‘official’ scores for other detectors [here](https://github.com/numenta/NAB), in the section labeled ‘Scoreboard’).

Part of me is worried I’ve done something wrong that is artificially inflating the score, so I’ll be on the lookout for that as I improve and refine the code base.

* * *

### Brief system config I used:

```auto
input SDR
* basic ScalarEncoder
* num_buckets clamped to [150, 1000]
* num_active_bits: 41

spatial pooler
* num_columns: 2048
* stimulus_threshold: 0
* winning_column_count: 41
* min_overlap_duty_cycle_percent = 0.001
* boost_strength = 0.01
* percent_potential = 0.8

temporal memory
* num_columns = 2048
* TMColumn.cell_count = 32

* Cell.new_synapse_count = 15
* Cell.desired_synapses_per_segment = 32
* Cell.distal_segment_activation_threshold = 0
* Cell.distal_segment_matching_threshold = 0

* DendriteSegment.permanence_increment = 0.1
* DendriteSegment.permanence_decrement = 0.05

```

---

<div class="post-metadata">

**Author:** ![rhyolight](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/rhyolight/32/3922_2.png) [@rhyolight](https://discourse.numenta.org/u/rhyolight)\
**Post date:** [November 20, 2018, 4:15pm UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/5 "2018-11-20T16:15:13Z")

</div>

Outstanding!

---

<div class="post-metadata">

**Author:** ![Jose\_Cueto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/jose_cueto/32/4052_2.png) [@Jose\_Cueto](https://discourse.numenta.org/u/Jose_Cueto)\
**Post date:** [January 15, 2019, 4:18am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/6 "2019-01-15T04:18:30Z")

</div>

Hi @Balladeer,

Have you implemented an SDR encoder as well or are you reusing the existing ones in nupic? Asking to get an idea of your implementation. Cheers.

---

<div class="post-metadata">

**Author:** ![Balladeer](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/balladeer/32/3094_2.png) [@Balladeer](https://discourse.numenta.org/u/Balladeer)\
**Post date:** [January 15, 2019, 12:20pm UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/7 "2019-01-15T12:20:59Z")

</div>

My base [SDR](https://bitbucket.org/zhtm/zhtm/src/develop/zhtm/sdr.py) is just a wrapper around python set objects. As for encoders, I’ve implemented:

1. [scalar encoder](https://bitbucket.org/zhtm/zhtm/src/develop/zhtm/encoders/scalar_encoder.py), which gets you basic number encoding
2. [cycle encoder](https://bitbucket.org/zhtm/zhtm/src/develop/zhtm/encoders/cycle_encoder.py), which lets you encode categories, with or without neighboring overlap
  - the cycle encoder is then used behind the scenes to create a pile of [date / time encoders](https://bitbucket.org/zhtm/zhtm/src/develop/zhtm/encoders/datetime_encoders.py).

3. [multi encoder](https://bitbucket.org/zhtm/zhtm/src/develop/zhtm/encoders/multi_encoder.py), which lets you combine a list of encoders into a single output SDR

With those three, I’ve been able to experiment with quite a bit. My plan is to work on other encoders as I have a need for them.

---

<div class="post-metadata">

**Author:** ![Jose\_Cueto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/jose_cueto/32/4052_2.png) [@Jose\_Cueto](https://discourse.numenta.org/u/Jose_Cueto)\
**Post date:** [January 15, 2019, 8:08pm UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/8 "2019-01-15T20:08:26Z")

</div>

Awesome! Thanks.

---

<div class="post-metadata">

**Author:** ![Jose\_Cueto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/jose_cueto/32/4052_2.png) [@Jose\_Cueto](https://discourse.numenta.org/u/Jose_Cueto)\
**Post date:** [January 16, 2019, 5:32am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/9 "2019-01-16T05:32:10Z")

</div>

In your scalar encoder, what does a `bucket` mean by the way?

---

<div class="post-metadata">

**Author:** ![Balladeer](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/balladeer/32/3094_2.png) [@Balladeer](https://discourse.numenta.org/u/Balladeer)\
**Post date:** [January 16, 2019, 12:21pm UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/10 "2019-01-16T12:21:52Z")

</div>

A `bucket` basically represents a range of numbers all at once. Short example:

Say we are encoding the values 1-100, and decide the use 10 buckets. If we use `num_active_bits = 1`, then our scalar encoder outputs an SDR with ten bits: `0000000000`

Each bit represents 1/10 of the input space, so bucket 1 would be on for all values 1-10, bucket 2 would be on for all values 11-20, bucket 3 for 21-30, etc:

- input `01` --\> output `1000000000`
- input `05` --\> output `1000000000`
- input `10` --\> output `1000000000`
- input `11` --\> output `0100000000`
- input `55` --\> output `0000010000`
- input `99` --\> output `0000000001`

This is very similar to how a histogram works, or any other “range banding” generalization: convert a large number of inputs into a smaller number of outputs.

You might look at [this test](https://bitbucket.org/zhtm/zhtm/src/0ac572b5759406ab57f8b32fe7b52056b6e67d34/tests/encoders/test_scalar_encoder.py#lines-8) for some more on how the scalar encoder is expected to behave.

You can also check out the section called “A Simple Encoder for Numbers” from the [encoder chapter (pdf!)](https://numenta.com/assets/pdf/biological-and-machine-intelligence/BaMI-Encoders.pdf) of BAMI, as my encoder basically just implements the one described in that section.

---

<div class="post-metadata">

**Author:** ![Jose\_Cueto](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.numenta.org/jose_cueto/32/4052_2.png) [@Jose\_Cueto](https://discourse.numenta.org/u/Jose_Cueto)\
**Post date:** [January 17, 2019, 12:56am UTC](https://discourse.numenta.org/t/yet-another-yet-another-htm-implementation/4831/11 "2019-01-17T00:56:51Z")

</div>

Thanks for taking the time to provide an explanation and for the links. I understand now that bucket is just like a bin in a histogram.
