Input signal for neural network

Hello, everybody!

How can the following case be implemented in the simulator. An image is taken (a number on a white background), for example, 25 * 25 pixels in size. Further, each pixel is binarized from 0 to 1, where 0 is a white background. The resulting array is fed to a neural network (25 by 25 neurons or more) the size of a picture for 1 second. That is, each pixel in the form of a current is supplied to its neuron for 1 second (the time can be any, since the image is not supplied as a time base as in the documentation). I did not find a similar case in the documentation.

Hi serge, these previous discussions may be relevant to you


as well as the following repos
sdpenguin/ Brian2STDPMNIST
MNIST spiking neural network

from the documentation, you may be interested in the example at the end of this page:
although notably it replays “1D slices” of one image out over time i believe

@adam , thanks for your reply. I’ve seen these examples, but so far they haven’t led me to a solution to my problem. Since I need to get an image as in the example in the documentation, but not in time, but in space, that is, the growth of the activity of the neural network will not be the number of the neuron from time, but the number of the neuron by the number of the neuron. Those. for example, an image of 25 by 25 pixels is reproduced on a network raster of 25 neurons by 25 neurons. I saw the rest of the examples, and there the input signal is encoded differently - either through time and is used (TimesArray), or through the Poisson process (PoissonInput) and the spike sequence.

ah I think I misunderstood your question the first time…
This seems relatively straightforward if you want to represent the image with 625 (25x25) neurons, you can simply flatten the image out into a vector and pass this 625x1 vector into your 625 neurons…
but if instead you want to represent the image as the correlations between two sets of 25 neurons (50 neurons total). This seems more complicated.

making up a solution from scratch you could do something like generate input currents with the desired correlation properties (perhaps out of some orthogonal signal basis set) then feed these into your 25 + 25 neurons. Then the image might be “read out” of the neuron from the observed cross-correlation matrix of the network, is that what you’re looking for?

@adam , thank you for your answer. I’m thinking in this way about representation of signal (like a vector) to neuron network. But one question for me is difficult - how extract and visualized rastr of spiking activity (25*25 neurons without time) using SpikeMonitor.

Hi @serge25 and @adam, apologies for jumping into the discussion :blush:
If you want to present spikes in 2D, then you need some additional dimension for the time. If the total number of spikes is enough, you could simply use colour. If you are interested in the dynamics over time, then I think the best solution is to use time itself as the 3rd dimension, i.e. do an animation. You can copy the approach used in this example: Example: opencv_movie — Brian 2 documentation
The example sets a column and row attribute for each neuron (could of course also be x and y), which then allows you to do something like group.colum[i] and group.row[i] to get columns/rows for the indices that are returned by the SpikeMonitor. Hope that gives you some ideas.

@mstimberg , thank you for your answer. I’am found more easy way for activity representation after stimulation (some transformation and slicing of array SpikeMonitor). But I ran into another problem. How to apply stimulus vector value to each neuron.

I’m trying to add array stimulus as vector to neurons like this

stimul = np.concatenate(img)

def update_input(t):
        N.Istim = 'Amp_stimul * stimul[int(i)]'

But this is not working (error - ‘SympyNodeRenderer’ object has no attribute ‘render_Subscript’). How to input value of stimulus in vector form for different neurons?

Hi @serge25 . You don’t need a network_operation to give different input to individual neurons. I assume your input changes over time? In that case you can use the 2D form of a TimedArray: Input stimuli — Brian 2 documentation If you provide a 2D array as the values for TimedArray, then you can call it as a function with two arguments, time and neuron index.

@mstimberg , not quite so, the input does not change over time. The idea is that a stimulus in the form of a picture (it does not change for neurons) can be exposed to neurons regardless of time. That is, the stimulus would not appear in time (as in the example in the documentation), but in the space of the neural network without changing in time.

But if it is not a function of time, then you can assign the value in the beginning and don’t need to reassign it every ms as with your network_operation.
I.e. something along the lines of:

N = NeuronGroup(25*25, '''...
            Istim = Amp_stimul * stimul : amp
            stimul : 1 (constant)''')
N.stimul = ... # flat representation of stimulus

But this is also what @adam proposed earlier – does that not work for you?

1 Like

@mstimberg , As far as I understand, TimedArray does a time sweep of the stimulus (or a 2D array), in my example, I want to feed the same vector or array to the neural network without changing the stimulus over time (at each point in time, the stimulus remains unchanged).

How to feed the values of a vector (equal to the dimension of the network) to N.stimul ?

@mstimberg This is what i want to do.

If you have your stimulus in a 25x25 matrix A, you can use A.flatten() to get it as a 625-element vector. You can then use this to assign values to the parameter of a 625-element NeuronGroup. In the same way, you can get back a matrix from flat vectors like the total spike count per neuron recorded by a SpikeMonitor: count_matrix = spike_mon.count[:].reshape(25, 25). 1.4.2. Numerical operations on arrays — Scipy lecture notes

@mstimberg , thank you, but I don’t understand how to pass a vector of values, because (N.stimul from your example) expects a constant, not a vector.

If you define a parameter as part of the equations (as stimul above), it becomes a neuron-specific parameter, i.e. a vector for the whole group. The (constant) behind the definition means that it is a constant vector (in contrast to a value that will be changed from another object during the simulation, e.g. by a Synapses object) – this will only be used for certain optimizations.

>>> N = NeuronGroup(10, 'stimul : 1 (constant)')
>>> N.stimul
<neurongroup_1.stimul: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])>

@mstimberg thank you.

1 Like

Could you suggest how to record neuron activity events only in a certain period of time (simulation time is 500 ms, and record only from 200 to 300 ms). Or may be it is possible slicing of recording values from 200 to 300 ms.

Sure. You can switch off a monitor when you don’t need it, e.g.:

mon = StateMonitor(...) = False
run(200*ms) = True

But of course you can also slice it. The recorded values are a 2D array neurons × time steps, so you’ll have to slice your 2nd dimension. E.g. to get the values between 200ms and 300ms for the default time step of 0.1ms:

values = mon.v[:, 2000:3000]

if you want to make this robust against changes of the simulation time step, you can also use:

from brian2.core.functions import timestep
values = mon.v[:, timestep(200*ms, defaultclock.dt):timestep(300*ms, defaultclock.dt)

Finally, a bit less efficient but also quite readable would be to use

values = mon.v[:, (mon.t >=200*ms) & (mon.t < 300*ms)]

Thank you @mstimberg for the detailed answer!

@mstimberg this also works for SpikeMonitor?