The coding of longer sequences in HTM SDRs

Right. I’m imagining we just push the update intervals down below the intervals between the (letter) driving interval, and we can simulate some kind of continuity.

The signal I’m expecting, to review, is something like what we saw in the Brazilian paper I keep referencing:

I expect the words of the input to cluster into (relative) lines in a similar way.

So I’m looking for lines in the raster plot which corresponds to groups of letters forming “words” in the driving prompt.

Our network is sequential, not mutually excitatory like the one they used, so the synchrony might not appear as easily. But I think it must be possible to tune it so that even sequential clustering reinforces itself and results in lines of some kind. If the clusters correspond to words, say because they are a cluster of multiple paths through the columns of the letter representations (different paths, not the same path, learned, as in HTM now) then the lines should correspond to words.

The first thing would be to make the update interval smaller than the input interval to simulate continuity (I still have to check if that’s in the code.)

Then we look at ways clusters could self reinforce. I don’t know how at this point. But if there is a cluster, that cluster should self reinforce if tuned in the right way. It represents a physical property of the network. We just have to tune the network so that it responds to that physical property. Like tuning a radio.

So how to “tune” it?

The “tuning” seems trivial for pulling the spike time of subsequent states back earlier than the external driving interval. Anything a spiking neuron is connected to sequentially, will spike earlier than it would have from the external driving signal (if the update interval is smaller than the external driving interval.)

And what I found was that the network naturally has feedback. If this feedback signal is strong enough, it might exert influence to delay the spike time of a preceding element too. Any feedback signal will take a longer time to arrive, because it has to loop around the whole feedback loop. So it might cause a neuron to spike later than it would have from the external driving signal.

So it seems reasonable we might get a “line” developing for previously observed sequences. Which we can equate with “words”.

For previously unobserved sequences it becomes more interesting. That is where HTM up to now has had nothing to say.

But it may come to the same thing. It may just be more paths through the cluster pulling the spike time of the next state forward. And self-reinforcing through feedback to delay the spike of the preceding state. The “cluster” this time will not be alternate paths through the cells of the letter columns making up a word. This time the cluster can be alternate paths through the cells of paths through different words. It would work the same.

I’m not sure if the driving signal from the “prompt” should be repeating. Perhaps it should not. So the only repeated signal is the feedback signal.

But all this should become clearer in practice than in any attempt at explanation. So I need to look at @complyue’s code to see what’s happening now.

2 Likes

Maybe increase prompt_pace >> 1 will do?

Yes, I hope the code is clear enough for you to understand, and I’ve exposed (almost) all tunable args in Walkthrough.ipynb for you to tinker with and see what happens. (Those args can be omitted when default values are just okay).

Looking forward to improve the code per your findings and directions.

1 Like

OK. I’ve scrolled down to your first example after actually loading Brown Corpus sequences, and the first thing I notice is that while we get some short term “oscillation” it is (almost?) all in letters other than the original driving signal. After connecting up some Brown Corpus sequences, you drive the network with the sequence “q-u-i-c-k”, and I can see columns for q and u and i, c, k spiking, in sequence. But then they are (almost) entirely suppressed.

There does seem to be some very faint colour. What does the intensity of the colour signify?

But other letters have much more activation. “y” and “v” go on-off-on-off… And “w” seems to have some columns(?) activating at each time step. Also “b” and “a”: on-off-on-off.

Any idea why that might be? Why would the originally input letters end up with the least activity? Maybe just randomly those letters have little feedback?

How do I try for another input? I tried copying the “quick” cell and running that replacing “quick” with “brown”, but it didn’t seem to update the plot.

1 Like

I see only prompted letter spikes, and no oscillation at all. Maybe the plotting is a bit confusing, you can zoom in with tools at right side of the plot, until every time-step is ticked on the x-axis, and see the 0.8 span of a unit time-step space, that’s not time-advancing along the time-axis, but the spatial layout of neurons within a single minicolumn. y-axis space is each (mini)column as a whole. I don’t know how to describe it better, hope you can understand it.

It’s a handy feature of Bokeh for better data exploring, each dot indeed renders one spiking neuron, but the dot size is per screen dimension, so they’ll greatly overlap with each others, when the view is zoomed-out largely. Then here is the trick: render each dot with very low fire_dots_alpha=0.01 (alpha specifies opacity), and intensity of colour speaks for intensity of data points.

You can zoom-in enough and see each dot is actually very faint on its own. fire_dots_alpha can be increased per needs.

I guess that’s coz of our connection making algorithm, only consecutive letters are connected, no sequential information encoded anyhow.

The connections/synapses we created so far don’t impose feedback I’d guess.

Once a snapshot plot is drawn, the original plot in the former cell won’t get updated anyway. You can re-run the last cell to draw updated snapshot, or never run it and always scroll back.


P.S. I’ve pushed some minor updates, including the Walkthrough.ipynb, commented about the plotting scenarios, please pull the repository. Note you’ll have to “reset” Walkthrough.ipynb to avoid conflicts detected, which will prevent a successful “git pull”.

image

1 Like

I think I get it. y-axis is columns: columns/letter, and columns within a letter. x-axis is time, but in units of column cell representations.

I don’t understand “0.8 span”. But maybe it’s explained in the code.

Sequences in the Brown are coded as different paths between cells within columns though, aren’t they? Like HTM, but not “learned” on the same cells, only randomly transiting different cells from each column, each time? So a sequence will be coded as many paths over the cells for columns of a repeated sequence of letters in a word here, in contrast to HTM, where sequences are coded as specific cells in the columns of repeated sequences?

I think my run of “brown” was just obscured by the original run of “quick”. I tried loading again and running it, and got a plot for “brown”.

I’m basically reloading fresh almost every run at the moment! I have poor Internet here, and it gets confused when the connection drops. Also there’s still some alchemy involved in getting everything to load. Sometimes it seems to hang again without loading the whole environment. But it might resolve when my Internet access is more stable.

1 Like

I suspect this is the part my code by far doesn’t implement your intent, but it’s the best I can think of, per my understanding of the algorithm you described earlier. Hope someone here can give advices to improve it.

2 Likes

Using 0.8 of the time-step span is to just give some gap between dots belonging to different time-steps, to ease the eye. While x-axis is still ticked with integer numbers standing for time-steps.

2 Likes

In this case a local dev env may help a lot, maybe you can install a local copy of Anaconda, then clone my repo and run a local notebook server?

Setup steps after Anaconda installed can take the Gitpod config for reference:

The init: lines are one-time job, and command: lines need to be run every time your computer has been restarted.

The last line should just be jupyter notebook without the rest arg (which workarounds Gitpod’s cloud proxy).

4 Likes

I think you’re getting some “oscillation”, in the sense of spikes traveling around the network and setting the same columns spiking repeatedly. That’s how I interpret the difference in plots for the word “brown” with 1000 inhibitory connections, compared to the default (2m?)

This for 1000 inhibitory connections:

This for the default 2m:

To my understanding, that looks like with 1000 inhibitory connections the “prompt” letters spiked twice. But everything else went hot and stayed hot!

Maybe it’s because letters branch so widely, the only thing they are rarely directly connected to is themself! So everything else is not being inhibited enough, and the driving letters get inhibited too much.

But I don’t understand why the plot suddenly ends at 60 time steps for 2 million inhibitory links, but exactly doubles that for 1000 inhibitory links. That seems like too much of a coincidence.

Maybe I’m misinterpreting that output. It looks on reflection as if the first plot just doubled. Why do the plots stop so suddenly at 60 cycles?

2 Likes

As far as I can see from the code this might be true. Each pairing is added as both to and from a random cell + column for each letter.

e.g. ‘t’ has 10 cols with 100 cells each. ‘h’ has another 10 cols with 100 cells each.
link t->h picks both a random cell/column from ‘t’ and a random from ‘h’
The code doesn’t check for current usage at either end.

Repeating this for n copies of ‘t->h’ means some fraction of repeated synapses.

2 Likes

Yeah, I agree. @complyue fed me the relevant code module, and it looked right to me too:

“def _connect_per_words(

# connect 1 unit synapse for each pair of consecutive letters
# randomly pick 1 column from each letter’s representational columns,
# then randomly pick 1 cell from that column”

1 Like

image

Each run of the NB cell is specified to drive 60 time steps, maybe you run that cell twice?

May also be coz of duplicated internet packets triggering multiple runs, there’s a small chance to be the case when you internet connection is unstable.

Ya, I meant that before the words get “learned” (i.e. when no synapse/connection at all), and later there are sure oscillations seen.

I suspect the same.

My feel about it is that, inhibition has little effect with current setup, the driving letters are just less connected instead of inhibited. It seems that a/b/v/y are most strongly connected, so little chance could trigger them start oscillating.

1 Like

Yes.

And technically those fractions will get merged into a single record, with effis summed up, in a later “compaction” pass, triggered either programmatically, or due to MAX_SYNAPSE reached. Though this is very technical details, not relevant to spiking observation and reasoning.

2 Likes

There is no restriction on self-connection that I can see in the code. Once a node fires, it might keep firing!
Probably need some self-connection stats!

1 Like
self_excit_df = excit_df[ (excit_df.from_column==excit_df.to_column) & (excit_df.from_cell == excit_df.to_cell) ]
self_excit_df

2 Likes

Thanks for mentioning. That’s quite a neat approach for making a path stronger. I wonder if it should be used more generally?

2 Likes

Yeah, I guess double letters are not that rare. Perhaps most might occur as doubles at some point.

The “restriction” in the logic as it stands at this point would be in the path through the cells of a column. The connectivity will not so much be between letters, as between paths through the cells of columns of letters. Each occurrence of a letter should have it’s own unique context and path. Things which don’t happen often will only have a few paths through their cells. Inhibition should deal with those.

Number of paths through the cells in this logic, will be the equivalent of “training” of paths in the existing HTM logic.

1 Like

Not a big concern so long as SNAP_FACTOR is bigger than 1.0

2 Likes

Less rare maybe since we are using learn_words_as_sequence() which runs words together? @complyue

2 Likes

True.

2 Likes