NEST main@caf0ae8
 
Loading...
Searching...
No Matches
eprop_readout.h
Go to the documentation of this file.
1/*
2 * eprop_readout.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef EPROP_READOUT_H
24#define EPROP_READOUT_H
25
26// nestkernel
27#include "connection.h"
30#include "eprop_synapse.h"
31#include "event.h"
32#include "nest_types.h"
33#include "ring_buffer.h"
35
36namespace nest
37{
38
39/* BeginUserDocs: neuron, e-prop plasticity, current-based, Bellec
40
41Short description
42+++++++++++++++++
43
44Current-based leaky integrate readout neuron model with delta-shaped
45postsynaptic currents for e-prop plasticity
46
47Description
48+++++++++++
49
50``eprop_readout`` is an implementation of an integrate-and-fire neuron model
51with delta-shaped postsynaptic currents used as readout neuron for eligibility propagation (e-prop) plasticity.
52
53E-prop plasticity was originally introduced and implemented in TensorFlow in :footcite:p:`Bellec2020`.
54
55The membrane voltage time course :math:`v_j^t` of the neuron :math:`j` is given by:
56
57.. math::
58 v_j^t &= \kappa v_j^{t-1}+ \zeta \sum_{i \neq j} W_{ji}^\text{out} z_i^{t-1} \,, \\
59 \kappa &= e^{ -\frac{ \Delta t }{ \tau_\text{m} } } \,, \\
60 \zeta &=
61 \begin{cases}
62 1 \\
63 1 - \kappa
64 \end{cases} \,, \\
65
66where :math:`W_{ji}^\text{out}` is the output synaptic weight matrix and
67:math:`z_i^{t-1}` is the recurrent presynaptic spike state variable.
68
69Descriptions of further parameters and variables can be found in the table below.
70
71The spike state variable of a presynaptic neuron is expressed by a Heaviside function:
72
73.. math::
74 z_i^t = H \left( v_i^t - v_\text{th} \right) \,. \\
75
76An additional state variable and the corresponding differential equation
77represents a piecewise constant external current.
78
79See the documentation on the :doc:`iaf_psc_delta<../models/iaf_psc_delta/>` neuron model
80for more information on the integration of the subthreshold dynamics.
81
82The change of the synaptic weight is calculated from the gradient :math:`g^t` of
83the loss :math:`E^t` with respect to the synaptic weight :math:`W_{ji}`:
84:math:`\frac{ \text{d} E^t }{ \text{d} W_{ij} }`
85which depends on the presynaptic
86spikes :math:`z_i^{t-1}` and the learning signal :math:`L_j^t` emitted by the readout
87neurons.
88
89In the interval between two presynaptic spikes, the gradient is calculated
90at each time step until the cutoff time point. This computation occurs over
91the time range:
92
93:math:`t \in \left[ t_\text{spk,prev}, \min \left( t_\text{spk,prev} + \Delta t_\text{c}, t_\text{spk,curr} \right)
94\right]`.
95
96Here, :math:`t_\text{spk,prev}` represents the time of the previous spike that
97passed the synapse, while :math:`t_\text{spk,curr}` is the time of the
98current spike, which triggers the application of the learning rule and the
99subsequent synaptic weight update. The cutoff :math:`\Delta t_\text{c}`
100defines the maximum allowable interval for integration between spikes.
101The expression for the gradient is given by:
102
103.. math::
104 \frac{ \text{d} E^t }{ \text{d} W_{ji} } = L_j^t \bar{z}_i^{t-1} \,. \\
105
106The presynaptic spike trains are low-pass filtered with the following exponential kernel:
107
108.. math::
109 \bar{z}_i^t = \mathcal{F}_\kappa \left( z_{i}^t \right)
110 = \kappa \bar{z}_i^{t-1} + \zeta z_i^t \,. \\
111
112Since readout neurons are leaky integrators without a spiking mechanism, the
113formula for computing the gradient lacks the surrogate gradient /
114pseudo-derivative and a firing regularization term.
115
116As a last step for every round in the loop over the time steps :math:`t`, the new weight is retrieved by feeding the
117current gradient :math:`g^t` to the optimizer (see :doc:`weight_optimizer<../models/weight_optimizer/>`
118for more information on the available optimizers):
119
120.. math::
121 w^t = \text{optimizer} \left( t, g^t, w^{t-1} \right) \,. \\
122
123After the loop has terminated, the filtered dynamic variables of e-prop are propagated from the end of the cutoff until
124the next spike:
125
126.. math::
127 p &= \text{max} \left( 0, t_\text{s}^{t} - \left( t_\text{s}^{t-1} + {\Delta t}_\text{c} \right) \right) \,, \\
128 \bar{z}_i^{t+p} &= \bar{z}_i^t \alpha^p \,. \\
129
130The learning signal :math:`L_j^t` is given by the non-plastic feedback weight
131matrix :math:`B_{jk}` and the continuous error signal :math:`e_k^t` emitted by
132readout neuron :math:`k` and :math:`e_k^t` defined via a mean-squared error
133loss:
134
135.. math::
136 L_j^t = B_{jk} e_k^t = B_{jk} \left( y_k^t - y_k^{*,t} \right) \,. \\
137
138where the readout signal :math:`y_k^t` corresponds to the membrane voltage of
139readout neuron :math:`k` and :math:`y_k^{*,t}` is the real-valued target signal.
140
141Furthermore, the readout and target signal are multiplied by a learning window
142signal, which has a value of 1.0 within the learning window and 0.0 outside.
143
144For more information on e-prop plasticity, see the documentation on the other e-prop models:
145
146 * :doc:`eprop_iaf<../models/eprop_iaf/>`
147 * :doc:`eprop_iaf_adapt<../models/eprop_iaf_adapt/>`
148 * :doc:`eprop_synapse<../models/eprop_synapse/>`
149 * :doc:`eprop_learning_signal_connection<../models/eprop_learning_signal_connection/>`
150
151Details on the event-based NEST implementation of e-prop can be found in :footcite:p:`KorcsakGorzo2025`.
152
153Parameters
154++++++++++
155
156The following parameters can be set in the status dictionary.
157
158========================= ======= ===================== ================== =====================================
159**Neuron parameters**
160----------------------------------------------------------------------------------------------------------------
161Parameter Unit Math equivalent Default Description
162========================= ======= ===================== ================== =====================================
163``C_m`` pF :math:`C_\text{m}` 250.0 Capacitance of the membrane
164``E_L`` mV :math:`E_\text{L}` 0.0 Leak / resting membrane potential
165``I_e`` pA :math:`I_\text{e}` 0.0 Constant external input current
166``tau_m`` ms :math:`\tau_\text{m}` 10.0 Time constant of the membrane
167``V_min`` mV :math:`v_\text{min}` negative maximum Absolute lower bound of the membrane
168 value voltage
169 representable by
170 ``double`` type in
171 C++
172========================= ======= ===================== ================== =====================================
173
174=========================== ======= =========================== ================ ===============================
175**E-prop parameters**
176----------------------------------------------------------------------------------------------------------------
177Parameter Unit Math equivalent Default Description
178=========================== ======= =========================== ================ ===============================
179``eprop_isi_trace_cutoff`` ms :math:`{\Delta t}_\text{c}` maximum value Cutoff for integration of
180 representable e-prop update between two
181 by ``double`` spikes
182 type in C++
183=========================== ======= =========================== ================ ===============================
184
185Recordables
186+++++++++++
187
188The following state variables evolve during simulation and can be recorded.
189
190=============== ==== =============== ============= ================
191**Neuron state variables and recordables**
192-------------------------------------------------------------------
193State variable Unit Math equivalent Initial value Description
194=============== ==== =============== ============= ================
195``V_m`` mV :math:`v_j` 0.0 Membrane voltage
196=============== ==== =============== ============= ================
197
198========================= ==== =============== ============= ==============
199**E-prop state variables and recordables**
200---------------------------------------------------------------------------
201State variable Unit Math equivalent Initial value Description
202========================= ==== =============== ============= ==============
203``error_signal`` mV :math:`L_j` 0.0 Error signal
204``readout_signal`` mV :math:`y_j` 0.0 Readout signal
205``target_signal`` mV :math:`y^*_j` 0.0 Target signal
206========================= ==== =============== ============= ==============
207
208Usage
209+++++
210
211This model can only be used in combination with the other e-prop models
212and the network architecture requires specific wiring, input, and output.
213The usage is demonstrated in several
214:doc:`supervised regression and classification tasks <../auto_examples/eprop_plasticity/index>`
215reproducing among others the original proof-of-concept tasks in :footcite:p:`Bellec2020`.
216
217References
218++++++++++
219
220.. footbibliography::
221
222Sends
223+++++
224
225LearningSignalConnectionEvent, DelayedRateConnectionEvent
226
227Receives
228++++++++
229
230SpikeEvent, CurrentEvent, DelayedRateConnectionEvent, DataLoggingRequest
231
232See also
233++++++++
234
235Examples using this model
236+++++++++++++++++++++++++
237
238.. listexamples:: eprop_readout
239
240EndUserDocs */
241
242void register_eprop_readout( const std::string& name );
243
252{
253
254public:
257
260
261 using Node::handle;
263
265
266 void
270
271 void
275
276 void handle( SpikeEvent& ) override;
277 void handle( CurrentEvent& ) override;
278 void handle( DelayedRateConnectionEvent& ) override;
279 void handle( DataLoggingRequest& ) override;
280
281 size_t handles_test_event( SpikeEvent&, size_t ) override;
282 size_t handles_test_event( CurrentEvent&, size_t ) override;
283 size_t handles_test_event( DelayedRateConnectionEvent&, size_t ) override;
284 size_t handles_test_event( DataLoggingRequest&, size_t ) override;
285
286 void get_status( Dictionary& ) const override;
287 void set_status( const Dictionary& ) override;
288
289private:
290 void init_buffers_() override;
291 void pre_run_hook() override;
292
293 void update( Time const&, const long, const long ) override;
294
295 void compute_gradient( const long,
296 const long,
297 double&,
298 double&,
299 double&,
300 double&,
301 double&,
302 double&,
305 const bool,
306 const bool,
307 double&,
308 long&,
309 long& ) override;
310
311 long get_shift() const override;
312 bool is_eprop_recurrent_node() const override;
313
315 friend class RecordablesMap< eprop_readout >;
316
318 friend class UniversalDataLogger< eprop_readout >;
319
322 {
324 double C_m_;
325
327 double E_L_;
328
330 double I_e_;
331
333 double tau_m_;
334
336 double V_min_;
337
339 Parameters_();
340
342 void get( Dictionary& ) const;
343
345 double set( const Dictionary&, Node* );
346 };
347
349 struct State_
350 {
353
356
359
362
364 double i_in_;
365
367 double v_m_;
368
370 double z_in_;
371
373 State_();
374
376 void get( Dictionary&, const Parameters_& ) const;
377
379 void set( const Dictionary&, const Parameters_&, double, Node* );
380 };
381
400
403 {
405 double P_v_m_;
406
408 double P_i_in_;
409 };
410
413 static const size_t MIN_RATE_RECEPTOR = 1;
414
422
424 double
425 get_v_m_() const
426 {
427 return S_.v_m_ + P_.E_L_;
428 }
429
431 double
433 {
434 return S_.readout_signal_;
435 }
436
438 double
440 {
441 return S_.target_signal_;
442 }
443
445 double
447 {
448 return S_.error_signal_;
449 }
450
451 // the order in which the structure instances are defined is important for speed
452
455
458
461
464
467};
468
469inline long
471{
472 return offset_gen_ + delay_in_rec_;
473}
474
475inline bool
477{
478 return false;
479}
480
481inline size_t
483{
484 if ( receptor_type != 0 )
485 {
486 throw UnknownReceptorType( receptor_type, get_name() );
487 }
488
489 return 0;
490}
491
492inline size_t
494{
495 if ( receptor_type != 0 )
496 {
497 throw UnknownReceptorType( receptor_type, get_name() );
498 }
499
500 return 0;
501}
502
503inline size_t
505{
506 size_t step_rate_model_id = kernel().model_manager.get_node_model_id( "step_rate_generator" );
507 size_t model_id = e.get_sender().get_model_id();
508
509 if ( step_rate_model_id == model_id and receptor_type != TARGET_SIG and receptor_type != LEARNING_WINDOW_SIG )
510 {
511 throw IllegalConnection(
512 "eprop_readout neurons expect a connection with a step_rate_generator node through receptor_type "
513 "1 or 2." );
514 }
515
516 if ( receptor_type < MIN_RATE_RECEPTOR or receptor_type >= SUP_RATE_RECEPTOR )
517 {
518 throw UnknownReceptorType( receptor_type, get_name() );
519 }
520
521 return receptor_type;
522}
523
524inline size_t
526{
527 if ( receptor_type != 0 )
528 {
529 throw UnknownReceptorType( receptor_type, get_name() );
530 }
531
532 return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
533}
534
535inline void
537{
539 P_.get( d );
540 S_.get( d, P_ );
541 d[ names::recordables ] = recordablesMap_.get_list();
542
543 Dictionary receptor_dict;
544 receptor_dict[ names::eprop_learning_window ] = static_cast< long >( LEARNING_WINDOW_SIG );
545 receptor_dict[ names::target_signal ] = static_cast< long >( TARGET_SIG );
546
547 d[ names::receptor_types ] = receptor_dict;
548}
549
550inline void
552{
554 // temporary copies in case of errors
555 Parameters_ ptmp = P_;
556 State_ stmp = S_;
557
558 // make sure that ptmp and stmp consistent - throw BadProperty if not
559 const double delta_EL = ptmp.set( d, this );
560 stmp.set( d, ptmp, delta_EL, this );
561
562 P_ = ptmp;
563 S_ = stmp;
564}
565
566} // namespace nest
567
568#endif // EPROP_READOUT_H
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
Class containing the common properties for all connections of a certain type.
Definition common_synapse_properties.h:50
Event for electrical currents.
Definition event.h:569
Request data to be logged/logged data to be sent.
Definition event.h:636
Event for rate model connections with delay.
Definition secondary_event.h:331
Class implementing an intermediate archiving node model for readout node models supporting e-prop pla...
Definition eprop_archiving_node_readout.h:43
void get_status(Dictionary &d) const override
Export properties of the node by setting entries in the status dictionary.
Definition eprop_archiving_node_readout.h:87
void set_status(const Dictionary &d) override
Change properties of the node according to the entries in the dictionary.
Definition eprop_archiving_node_readout.h:97
const long delay_in_rec_
Transmission delay from input to recurrent neurons.
Definition eprop_archiving_node.h:171
const long offset_gen_
Offset since generator signals start from time step 1.
Definition eprop_archiving_node.h:168
To be thrown if a connection is not possible.
Definition exceptions.h:490
Event for learning signal connections.
Definition secondary_event.h:384
size_t get_node_model_id(const std::string) const
Definition model_manager.cpp:310
Base class for all NEST network objects.
Definition node.h:99
std::string get_name() const
Return class name.
Definition node.cpp:105
Map names of recordables to data access functions.
Definition recordables_map.h:61
Buffer Layout.
Definition ring_buffer.h:83
Event for spike information.
Definition event.h:418
Definition nest_time.h:135
Exception to be thrown if the specified receptor type does not exist in the node.
Definition exceptions.h:417
Base class implementing a weight optimizer model.
Definition weight_optimizer.h:238
Class implementing a readout neuron model for e-prop plasticity with additional biological features.
Definition eprop_readout.h:252
double get_v_m_() const
Get the current value of the membrane voltage.
Definition eprop_readout.h:425
State_ S_
Structure of state variables.
Definition eprop_readout.h:457
void sends_secondary_event(DelayedRateConnectionEvent &) override
Required to check, if source neuron may send a SecondaryEvent.
Definition eprop_readout.h:272
static const size_t MIN_RATE_RECEPTOR
Minimal spike receptor type.
Definition eprop_readout.h:413
void set_status(const Dictionary &) override
Change properties of the node according to the entries in the dictionary.
Definition eprop_readout.h:551
void update(Time const &, const long, const long) override
Advance the state of the node in time through the given interval.
Definition eprop_readout.cpp:203
double get_readout_signal_() const
Get the current value of the normalized readout signal.
Definition eprop_readout.h:432
void pre_run_hook() override
Re-calculate dependent parameters of the node.
Definition eprop_readout.cpp:188
eprop_readout()
Default constructor.
Definition eprop_readout.cpp:158
void init_buffers_() override
Configure persistent internal data structures.
Definition eprop_readout.cpp:180
Variables_ V_
Structure of internal variables.
Definition eprop_readout.h:460
size_t handles_test_event(SpikeEvent &, size_t) override
Check if the node can handle a particular event and receptor type.
Definition eprop_readout.h:482
RateSynapseTypes
Enumeration of spike receptor types.
Definition eprop_readout.h:417
@ LEARNING_WINDOW_SIG
Definition eprop_readout.h:418
@ TARGET_SIG
Definition eprop_readout.h:419
@ SUP_RATE_RECEPTOR
Definition eprop_readout.h:420
void sends_secondary_event(LearningSignalConnectionEvent &) override
Required to check if source node may send a LearningSignalConnectionEvent.
Definition eprop_readout.h:267
Buffers_ B_
Structure of buffers.
Definition eprop_readout.h:463
static RecordablesMap< eprop_readout > recordablesMap_
Map storing a static set of recordables.
Definition eprop_readout.h:466
long get_shift() const override
Retrieves the temporal shift of the signal.
Definition eprop_readout.h:470
void compute_gradient(const long, const long, double &, double &, double &, double &, double &, double &, const CommonSynapseProperties &, WeightOptimizer *, const bool, const bool, double &, long &, long &) override
Compute gradient change for eprop synapses.
Definition eprop_readout.cpp:293
friend class UniversalDataLogger< eprop_readout >
Logger for universal data supporting the data logging request / reply mechanism. Populated with a rec...
Definition eprop_readout.h:318
void get_status(Dictionary &) const override
Export properties of the node by setting entries in the status dictionary.
Definition eprop_readout.h:536
bool is_eprop_recurrent_node() const override
Checks if the node is part of the recurrent network and thus not a readout neuron.
Definition eprop_readout.h:476
void handle(SpikeEvent &) override
Handle incoming spike events.
Definition eprop_readout.cpp:269
Parameters_ P_
Structure of parameters.
Definition eprop_readout.h:454
double get_error_signal_() const
Get the current value of the error signal.
Definition eprop_readout.h:446
double get_target_signal_() const
Get the current value of the target signal.
Definition eprop_readout.h:439
ModelManager model_manager
Definition kernel_manager.h:243
virtual size_t handles_test_event(SpikeEvent &, size_t receptor_type)
Check if the node can handle a particular event and receptor type.
Definition node.cpp:271
virtual void sends_secondary_event(GapJunctionEvent &ge)
Required to check, if source neuron may send a SecondaryEvent.
Definition node.cpp:381
virtual void handle(SpikeEvent &e)
Handle incoming spike events.
Definition node.cpp:265
const std::string recordables("recordables")
const std::string receptor_types("receptor_types")
const std::string eprop_learning_window("eprop_learning_window")
const std::string target_signal("target_signal")
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
KernelManager & kernel()
Definition kernel_manager.h:311
void register_eprop_readout(const std::string &name)
Definition eprop_readout.cpp:43
Structure of buffers.
Definition eprop_readout.h:384
RingBuffer currents_
Buffer for incoming currents.
Definition eprop_readout.h:395
RingBuffer spikes_
Buffer for incoming spikes.
Definition eprop_readout.h:392
UniversalDataLogger< eprop_readout > logger_
Logger for universal data.
Definition eprop_readout.h:398
Structure of parameters.
Definition eprop_readout.h:322
void get(Dictionary &) const
Get the parameters and their values.
Definition eprop_readout.cpp:104
double set(const Dictionary &, Node *)
Set the parameters and throw errors in case of invalid values.
Definition eprop_readout.cpp:114
double I_e_
Constant external input current (pA).
Definition eprop_readout.h:330
double C_m_
Capacitance of the membrane (pF).
Definition eprop_readout.h:324
double V_min_
Absolute lower bound of the membrane voltage relative to the leak membrane potential (mV).
Definition eprop_readout.h:336
Parameters_()
Default constructor.
Definition eprop_readout.cpp:69
double tau_m_
Time constant of the membrane (ms).
Definition eprop_readout.h:333
double E_L_
Leak / resting membrane potential (mV).
Definition eprop_readout.h:327
Structure of state variables.
Definition eprop_readout.h:350
State_()
Default constructor.
Definition eprop_readout.cpp:78
double learning_window_signal_
Signal indicating whether the readout neurons are in a learning phase.
Definition eprop_readout.h:361
double readout_signal_
Readout signal. Leaky integrated spikes emitted by the recurrent network.
Definition eprop_readout.h:355
double error_signal_
Error signal. Deviation between the readout and the target signal.
Definition eprop_readout.h:352
double z_in_
Binary input spike state variable - 1.0 if the neuron has spiked in the previous time step and 0....
Definition eprop_readout.h:370
double target_signal_
Target / teacher signal that the network is supposed to learn.
Definition eprop_readout.h:358
void get(Dictionary &, const Parameters_ &) const
Get the state variables and their values.
Definition eprop_readout.cpp:140
double i_in_
Input current (pA).
Definition eprop_readout.h:364
double v_m_
Membrane voltage relative to the leak membrane potential (mV).
Definition eprop_readout.h:367
void set(const Dictionary &, const Parameters_ &, double, Node *)
Set the state variables.
Definition eprop_readout.cpp:149
Structure of internal variables.
Definition eprop_readout.h:403
double P_v_m_
Propagator matrix entry for evolving the membrane voltage (mathematical symbol "kappa" in user docume...
Definition eprop_readout.h:405
double P_i_in_
Propagator matrix entry for evolving the incoming currents.
Definition eprop_readout.h:408