In the last post, I sketched how you might bolt a boolean circuit on top of a trained network. But that alone leaves a lot on the table: the inputs to that circuit will flip on and off as tokens fly through the neural net. That will render the boolean circuit you prepared unstable.
If you actually want to attach circuits that reason about — and respond to — the content of the network’s thoughts, you’re going to need some kind of memory inside these boolean circuits. Like registers in a CPU.
That way, we can remember something like: “We thought about lattes” or “We thought about pumpkins” to produce a stable answer to the question, “did we thought about pumpkin spice lattes?”.
So in this post I’m going to try to sketch out how we might build a latch neuron inside a neural network: a single bit of memory.
Here’s how we’ll define our latch neuron. For simplicity, I’m going to do this experiment in our boolean circuit world where the only values are 0 and 1. It’s easier to think about, and it has a wonderful parallel to the entry level microprocessor design classes I distantly remember..
A latch neuron:
- Has the output
0by default - Supports a
set(neuron)operation that pins its value to1 - Supports a
reset(neuron)operation that pins its value to0
Both the set and reset operations must be brief pulses to the neuron that have permanent effects — until anther such pulse comes.
To implement this, we need to think recurrently, feeding the latch neuron’s output back into itself like a loop.
That means we’re going to need some notation that lets us talk about both both prior and future values of the neuron.
So let’s call the current/prior output of the latch neuron q and the updated output of the latch neuron q'
Given that, we’ve got a neuron with three inputs: set, reset, and q and one output q'
And we want the following behavior:
| set | reset | q’ |
|---|---|---|
| 0 | 0 | q |
| 1 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 1 | 0 |
Remember, set and reset are pulses that override q', but otherwise q' should be q
We can implement this with by having the same hard threshold function we did in the boolean circuit post:
H(x) = x > 0
And then setting the weights on the inputs such that they’re combined like this before being passed into that threshold
q + set - 2 * reset - 0.5
An agent helped me figure that out and it’s hard (for me) to picture how that works, but let’s add it to the table above so that you can see:
| q | set | reset | q + set − 2×reset − 0.5 | q′ |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 + 0 − 2×0 − 0.5 = −0.5 | 0 |
| 0 | 0 | 1 | 0 + 0 − 2×1 − 0.5 = −2.5 | 0 |
| 0 | 1 | 0 | 0 + 1 − 2×0 − 0.5 = 0.5 | 1 |
| 0 | 1 | 1 | 0 + 1 − 2×1 − 0.5 = −1.5 | 0 |
| 1 | 0 | 0 | 1 + 0 − 2×0 − 0.5 = 0.5 | 1 |
| 1 | 0 | 1 | 1 + 0 − 2×1 − 0.5 = −1.5 | 0 |
| 1 | 1 | 0 | 1 + 1 − 2×0 − 0.5 = 1.5 | 1 |
| 1 | 1 | 1 | 1 + 1 − 2×1 − 0.5 = −0.5 | 0 |
So this combination of weights plus bias on the input side, and threshold on the output side, results in exactly the boolean function we want.
Because we’re hard quantizing the output to a 0 or a 1, there isn’t going to be any decay over time.
Once set, the output remains a pure 1 until reset.
The timing issue… I have to admit I’m not completely sure how to think about because I don’t fully understand how this recurrence, from a practical standpoint, is implemented down at the GPU layer.
Because this latch construction is recurrent, there is a clock frequency that has to be associated with the updates, and I’m not sure, from a practical standpoint, what that clock frequency is with respect to other things going on.
In any event though, this seems like a viable construction to start with.
I’m going to try adding it to my boolean expressions as a way to pin the notion of a concept having being mentioned so that once mentioned, we can better retain the fact that it was mentioned.
In the initial Manchurian Candidate experiment I did, the effect of Manchurian mode would quickly decay as the chat progressed. I’m hoping this provides a basis for us to keep it active until another passphrase deactivates it.