Jeffress Model¶
In this article we want to show that it is possible to model the Jeffress Model [JEF1948] [SP2011] using an extended SRM model.
Adapting the SRM model¶
In the SRM model, we can add a delay on the dendrites, by shifting the epsilon function:
# IMAGE of shifted epsilon function.
Using this we can model the following network:
Neurons 0 and 4 (green) are the input neurons. The blue neurons 1 – 3 and 5 – 7 are neurons with a delay on their dendrites. The output neurons 8 – 10 are the coincidence detectors. They spike only if their according two input neurons spike together.
Note
If we shift the epsilon function, it’s not anymore the original SRM model. Any properties of the original models might not be preserved.
Thus, we call the adapted model SRM_X model from now on.
Our Example¶
Neuron 0 spikes at time 0ms, and neuron 4 spikes at time 20ms.
The spikes arrive at the intermediate neurons at the following times:
Neuron | 1 | 2 | 3 | 5 | 6 | 7 |
---|---|---|---|---|---|---|
Arrival | 5ms | 15ms | 25ms | 45ms | 35ms | 25ms |
As you can see, only neurons 3 and 7 receive a spike at the same time (25ms). This means that they are excited at the same time, and their output will arrive at neuron 10 at the same time. Thus, neuron 10 will also spike.
In source code¶
Let’s write our example in Python :)
First, we import all required modules.
import numpy as np
import matplotlib.pyplot as plt
from neurons import spiking, plotting
Now we define how many neurons we have and how many timesteps we want to simulate:
neurons = 11
timesteps = 100
In the ax_delays variable we define the delays in the epsilon function (First neuron 0ms, second neuron 5ms and so on):
ax_delays = np.array([0, 5, 15, 25, 0, 25, 15, 5, 0, 0, 0])
The other variables (threshold, \(\tau_c, \tau_m, \eta_r\)) are the same for all neurons. Now we have everything to define the SRM_X model.
threshold = np.array([1]*neurons)
t_current = np.array([5]*neurons)
t_membrane = np.array([10]*neurons)
eta_reset = np.array([2]*neurons)
model = spiking.SRM_X(neurons=neurons, threshold=threshold, t_current=t_current,
t_membrane=t_membrane, eta_reset=eta_reset, ax_delay=ax_delays)
Let’s connect the neurons together.
weights = np.zeros((neurons, neurons))
# Connect input layer
weights[0, (1, 2, 3)] = 1
weights[4, (5, 6, 7)] = 1
# Connect to output layer
weights[(1, 5), 8] = 1.1
weights[(2, 6), 9] = 1.1
weights[(3, 7), 10] = 1.1
And set up a simple spiketrain. The spikes at neuron 4 are shifted by 20ms in comparison to neuron 1:
spiketrain = np.zeros((neurons, timesteps), dtype=bool)
spiketrain[0, (0, 5, 10)] = 1
spiketrain[4, (20, 25, 30)] = 1
It’s time to simulate our model:
for t in range(timesteps):
model.simulate(spiketrain, weights, t)
As always, we want to see our result, and we use a PSTH diagram for this reason:
psth = plotting.PSTH(spiketrain, binsize=5)
psth.show_plot(neuron_indices=[8, 9, 10])
plt.show()
Which gives us following plot:
We see that only the output neuron 10 spikes, while the other output neurons 8 and 9 remain silent.
Note
Playing around with the neuron_indices parameter of psth.show_plot, one can discover the spike trains of the other neurons as well.
Extending the Network¶
Of course this was only a toy example with 3 output neurons. In a future article we want to show a more complex network.
The distribution of the delays and the correct mechanism of generating a delay is still a topic of active discussions. [SP2011]
References¶
[JEF1948] | Jeffress L A, 1948, A place theory of sound localization,” J Comp Physiol Psychol 41, 35-39. |
[SP2011] | (1, 2) Scholarpedia Jeffress Model |
Source Code¶
Here you can see the whole source code for our Jeffress example:
import numpy as np
import matplotlib.pyplot as plt
from neurons import spiking, plotting
neurons = 11
timesteps = 100
ax_delays = np.array([0, 5, 15, 25, 0, 25, 15, 5, 0, 0, 0])
threshold = np.array([1]*neurons)
t_current = np.array([5]*neurons)
t_membrane = np.array([10]*neurons)
eta_reset = np.array([2]*neurons)
model = spiking.SRM_X(neurons=neurons, threshold=threshold, t_current=t_current,
t_membrane=t_membrane, eta_reset=eta_reset, ax_delay=ax_delays)
weights = np.zeros((neurons, neurons))
# Connect input layer
weights[0, (1, 2, 3)] = 1
weights[4, (5, 6, 7)] = 1
# Connect to output layer
weights[(1, 5), 8] = 1.1
weights[(2, 6), 9] = 1.1
weights[(3, 7), 10] = 1.1
spiketrain = np.zeros((neurons, timesteps), dtype=bool)
spiketrain[0, (0, 5, 10)] = 1
spiketrain[4, (20, 25, 30)] = 1
for t in range(timesteps):
model.simulate(spiketrain, weights, t)
psth = plotting.PSTH(spiketrain, binsize=5)
psth.show_plot(neuron_indices=[8, 9, 10])
plt.show()