NEST main@caf0ae8
 
Loading...
Searching...
No Matches
eprop_archiving_node_recurrent_impl.h
Go to the documentation of this file.
1/*
2 * eprop_archiving_node_recurrent_impl.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// nestkernel
27#include "kernel_manager.h"
28
29namespace nest
30{
31
32template < bool hist_shift_required >
33std::map< std::string, typename EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_function >
35 { "piecewise_linear",
38 { "fast_sigmoid_derivative",
40 { "arctan_derivative",
42 };
43
44template < bool hist_shift_required >
47 , firing_rate_reg_( 0.0 )
48 , f_av_( 0.0 )
49 , n_spikes_( 0 )
50{
51}
52
53template < bool hist_shift_required >
56 , firing_rate_reg_( n.firing_rate_reg_ )
57 , f_av_( n.f_av_ )
58 , n_spikes_( n.n_spikes_ )
59{
60}
61
62template < bool hist_shift_required >
65 const std::string& surrogate_gradient_function_name )
66{
67 const auto found_entry_it = surrogate_gradient_funcs_.find( surrogate_gradient_function_name );
68
69 if ( found_entry_it != surrogate_gradient_funcs_.end() )
70 {
71 return found_entry_it->second;
72 }
73
74 std::string error_message = "Surrogate gradient / pseudo-derivate function surrogate_gradient_function from [";
75 for ( const auto& surrogate_gradient_func : surrogate_gradient_funcs_ )
76 {
77 error_message += " \"" + surrogate_gradient_func.first + "\",";
78 }
79 error_message.pop_back();
80 error_message += " ] required.";
81
82 throw BadProperty( error_message );
83}
84
85template < bool hist_shift_required >
86double
88 const double v_m,
89 const double v_th,
90 const double height,
91 const double width )
92{
93 if ( r > 0.0 )
94 {
95 return 0.0;
96 }
97
98 return height * std::max( 0.0, 1.0 - std::abs( v_m - v_th ) / width );
99}
100
101template < bool hist_shift_required >
102double
104 const double v_m,
105 const double v_th,
106 const double height,
107 const double width )
108{
109 if ( r > 0.0 )
110 {
111 return 0.0;
112 }
113
114 return height * std::exp( -std::abs( v_m - v_th ) / width );
115}
116
117template < bool hist_shift_required >
118double
120 const double v_m,
121 const double v_th,
122 const double height,
123 const double width )
124{
125 if ( r > 0.0 )
126 {
127 return 0.0;
128 }
129
130 return height * std::pow( 1.0 + std::abs( v_m - v_th ) / width, -2.0 );
131}
132
133template < bool hist_shift_required >
134double
136 const double v_m,
137 const double v_th,
138 const double height,
139 const double width )
140{
141 if ( r > 0.0 )
142 {
143 return 0.0;
144 }
146 return height / ( 1.0 + std::pow( ( v_m - v_th ) / width, 2.0 ) );
147}
148
149template < bool hist_shift_required >
150void
152{
153 if ( eprop_indegree_ == 0 )
154 {
155 return;
157
158 eprop_history_.emplace_back( time_step, 0.0, 0.0, 0.0 );
159}
160
161template < bool hist_shift_required >
162void
164 const double surrogate_gradient )
165{
166 if ( eprop_indegree_ == 0 )
167 {
168 return;
169 }
170
171 auto it_hist = get_eprop_history( time_step );
172 it_hist->surrogate_gradient_ = surrogate_gradient;
173}
174
175template < bool hist_shift_required >
176void
178 const double learning_signal )
179{
180 if ( eprop_indegree_ == 0 )
181 {
182 return;
183 }
184
185 long shift = delay_rec_out_ + delay_out_rec_;
187 if constexpr ( hist_shift_required )
188 {
189 shift += delay_out_norm_;
190 }
191
192 auto it_hist = get_eprop_history( time_step - shift );
193 const auto it_hist_end = get_eprop_history( time_step - shift + delay_out_rec_ );
194
195 for ( ; it_hist != it_hist_end; ++it_hist )
196 {
197 it_hist->learning_signal_ += learning_signal;
198 }
199}
200
201template < bool hist_shift_required >
202void
204 const double f_target,
205 const double c_reg )
206{
207 if ( eprop_indegree_ == 0 )
208 {
209 return;
211
212 const double update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps();
213 const double dt = Time::get_resolution().get_ms();
214 const long shift = Time::get_resolution().get_steps();
215
216 const double f_av = n_spikes_ / update_interval;
217 const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step
218 const double firing_rate_reg = c_reg * ( f_av - f_target_ ) / update_interval;
220 firing_rate_reg_history_.emplace_back( t_current_update + shift, firing_rate_reg );
221}
222
223template < bool hist_shift_required >
224void
226 const double z,
227 const double f_target,
228 const double kappa_reg,
229 const double c_reg )
230{
231 if ( eprop_indegree_ == 0 )
232 {
233 return;
234 }
235
236 const double dt = Time::get_resolution().get_ms();
237
238 const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step
239
240 f_av_ = kappa_reg * f_av_ + ( 1.0 - kappa_reg ) * z / dt;
241
242 firing_rate_reg_ = c_reg * ( f_av_ - f_target_ );
243
244 auto it_hist = get_eprop_history( time_step );
245 it_hist->firing_rate_reg_ = firing_rate_reg_;
246}
247
248template < bool hist_shift_required >
249double
251{
252 const auto it_hist = std::lower_bound( firing_rate_reg_history_.begin(), firing_rate_reg_history_.end(), time_step );
253 assert( it_hist != firing_rate_reg_history_.end() );
254
255 return it_hist->firing_rate_reg_;
256}
257
258template < bool hist_shift_required >
259double
261{
262 long shift = delay_rec_out_ + delay_out_rec_;
263
264 if constexpr ( hist_shift_required )
265 {
266 shift += delay_out_norm_;
267 }
268
269 const auto it = get_eprop_history( time_step - shift );
270 if ( it == eprop_history_.end() )
271 {
272 return 0;
273 }
274
275 return it->learning_signal_;
276}
277
278template < bool hist_shift_required >
279void
281{
282 auto it_update_hist = update_history_.begin();
283 auto it_reg_hist = firing_rate_reg_history_.begin();
284
285 while ( it_update_hist != update_history_.end() and it_reg_hist != firing_rate_reg_history_.end() )
286 {
287 if ( it_update_hist->access_counter_ == 0 )
288 {
289 it_reg_hist = firing_rate_reg_history_.erase( it_reg_hist );
290 }
291 else
292 {
293 ++it_reg_hist;
294 }
295 ++it_update_hist;
296 }
297}
298
299} // namespace nest
Class implementing an intermediate archiving node model for recurrent node models supporting e-prop p...
Definition eprop_archiving_node_recurrent.h:43
void write_firing_rate_reg_to_history(const long t_current_update, const double f_target, const double c_reg)
Calculates the firing rate regularization for the current update and writes it to a new entry in the ...
Definition eprop_archiving_node_recurrent_impl.h:203
void write_learning_signal_to_history(const long time_step, const double learning_signal)
Writes the learning signal to the eprop history entry at the specifed time step.
Definition eprop_archiving_node_recurrent_impl.h:177
void append_new_eprop_history_entry(const long time_step)
Creates an entry for the specified time step at the end of the eprop history.
Definition eprop_archiving_node_recurrent_impl.h:151
EpropArchivingNodeRecurrent()
Constructs a new EpropArchivingNodeRecurrent object.
Definition eprop_archiving_node_recurrent_impl.h:45
surrogate_gradient_function find_surrogate_gradient(const std::string &surrogate_gradient_function_name)
Validates and finds surrogate gradient function based on the specified name.
Definition eprop_archiving_node_recurrent_impl.h:64
double compute_exponential_surrogate_gradient(const double r, const double v_m, const double v_th, const double height, const double width)
Computes an exponential function as the surrogate gradient.
Definition eprop_archiving_node_recurrent_impl.h:103
static std::map< std::string, surrogate_gradient_function > surrogate_gradient_funcs_
Maps provided names of surrogate gradients to corresponding pointers to member functions.
Definition eprop_archiving_node_recurrent.h:268
double compute_piecewise_linear_surrogate_gradient(const double r, const double v_m, const double v_th, const double height, const double width)
Computes a piecewise-linear function as the surrogate gradient.
Definition eprop_archiving_node_recurrent_impl.h:87
double compute_arctan_derivative_surrogate_gradient(const double r, const double v_m, const double v_th, const double height, const double width)
Computes the derivative of an arctan surrogate function as the surrogate gradient.
Definition eprop_archiving_node_recurrent_impl.h:135
void erase_used_firing_rate_reg_history()
Erases the history of the used firing rate regularization history.
Definition eprop_archiving_node_recurrent_impl.h:280
double get_learning_signal_from_history(const long time_step)
Retrieves the learning signal from the eprop history at the specified time step.
Definition eprop_archiving_node_recurrent_impl.h:260
void write_surrogate_gradient_to_history(const long time_step, const double surrogate_gradient)
Writes the surrogate gradient to the eprop history entry at the specified time step.
Definition eprop_archiving_node_recurrent_impl.h:163
double get_firing_rate_reg_history(const long time_step)
Retrieves the firing rate regularization at the specified time step from the firing rate regularizati...
Definition eprop_archiving_node_recurrent_impl.h:250
double compute_fast_sigmoid_derivative_surrogate_gradient(const double r, const double v_m, const double v_th, const double height, const double width)
Computes the derivative of a fast-sigmoid surrogate function as the surrogate gradient.
Definition eprop_archiving_node_recurrent_impl.h:119
Base class implementing archiving for node models supporting e-prop plasticity.
Definition eprop_archiving_node.h:53
Time get_eprop_update_interval() const
Definition simulation_manager.h:343
static Time get_resolution()
Definition nest_time.h:325
long get_steps() const
Definition nest_time.h:504
double get_ms() const
Definition nest_time.h:490
SimulationManager simulation_manager
Definition kernel_manager.h:237
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
KernelManager & kernel()
Definition kernel_manager.h:311