def build_genn_neuron(self, native_params, init_vals): # Create model using unmodified defs genn_model = create_custom_neuron_class(self.genn_neuron_name, **self.neuron_defs.definitions) # Get spike times spk_times = native_params["spikeTimes"] # Create empty numpy arrays to hold start and end spikes indices start_spike = np.empty(shape=native_params.shape, dtype=np.uint32) end_spike = np.empty(shape=native_params.shape, dtype=np.uint32) # Calculate indices for each sequence cum_size = 0 for i, seq in enumerate(spk_times): start_spike[i] = cum_size cum_size += len(seq.value) end_spike[i] = cum_size # Build initialisation dictionary neuron_ini = {"startSpike": start_spike, "endSpike": end_spike} # Return with model return genn_model, {}, neuron_ini
import numpy as np import matplotlib.pyplot as plt from pygenn.genn_model import GeNNModel from pygenn.genn_wrapper import NO_DELAY from pygenn.genn_model import create_custom_weight_update_class from pygenn.genn_model import create_custom_neuron_class if_model = create_custom_neuron_class( "if_model", param_names=["Vtheta", "lambda", "Vrest", "Vreset"], var_name_types=[("V", "scalar")], sim_code=""" if ($(V) >= $(Vtheta)) { $(V) = $(Vreset); } $(V) += (-$(lambda) + $(Isyn)) * DT; $(V) = fmax($(V), $(Vrest)); """, reset_code=""" """, threshold_condition_code="$(V) >= $(Vtheta)") fusi_model = create_custom_weight_update_class( "fusi_model", param_names=["tauC", "a", "b", "thetaV", "thetaLUp", "thetaLDown", "thetaHUp", "thetaHDown", "thetaX", "alpha", "beta", "Xmax", "Xmin", "JC", "Jplus", "Jminus"], var_name_types=[("X", "scalar")], post_var_name_types=[("C", "scalar")], sim_code=""" $(addToInSyn, (($(X) > $(thetaX)) ? $(Jplus) : $(Jminus)));
fs_relu_input_model = create_custom_neuron_class( 'fs_relu_input', param_names=['K', 'alpha'], derived_params=[ ("scale", create_dpf_class(lambda pars, dt: pars[1] * 2**(-pars[0]))()) ], var_name_types=[('input', 'scalar', VarAccess_READ_ONLY_DUPLICATE), ('Vmem', 'scalar')], sim_code=''' // Convert K to integer const int kInt = (int)$(K); // Get timestep within presentation const int pipeTimestep = (int)($(t) / DT); // If this is the first timestep, apply input if(pipeTimestep == 0) { $(Vmem) = $(input); } const scalar hT = $(scale) * (1 << (kInt - (1 + pipeTimestep))); ''', threshold_condition_code=''' $(Vmem) >= hT ''', reset_code=''' $(Vmem) -= hT; ''', is_auto_refractory_required=False)
#---------------------------------------------------------------------------- recurrent_alif_model = genn_model.create_custom_neuron_class( "recurrent_alif", param_names=["TauM", "TauAdap", "Vthresh", "TauRefrac", "Beta"], var_name_types=[("V", "scalar"), ("A", "scalar"), ("RefracTime", "scalar"), ("E", "scalar")], additional_input_vars=[("ISynFeedback", "scalar", 0.0)], derived_params=[ ("Alpha", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[0]))() ), ("Rho", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[1]))()) ], sim_code=""" $(E) = $(ISynFeedback); $(V) = ($(Alpha) * $(V)) + $(Isyn); $(A) *= $(Rho); if ($(RefracTime) > 0.0) { $(RefracTime) -= DT; } """, reset_code=""" $(RefracTime) = $(TauRefrac); $(V) -= $(Vthresh); $(A) += 1.0; """, threshold_condition_code=""" $(RefracTime) <= 0.0 && $(V) >= ($(Vthresh) + ($(Beta) * $(A))) """, is_auto_refractory_required=False)
lif_e_model = genn_model.create_custom_neuron_class( "lif_e_model", param_names=[ "Tau", "Erest", "Vreset", "Vthres", "RefracPeriod", "tauTheta" ], var_name_types=[("V", "scalar"), ("RefracTime", "scalar"), ("theta", "scalar"), ("SpikeNumber", "unsigned int")], sim_code=""" if ($(RefracTime) <= 0.0) { scalar alpha = $(Erest) + $(Isyn); $(V) = ($(V) - alpha) * $(ExpTC); } else { $(RefracTime) -= DT; $(theta) = $(theta) * $(ExpTtheta); } """, reset_code=""" $(V) = $(Vreset); $(RefracTime) = $(RefracPeriod); $(SpikeNumber) += 1; $(theta) += 1.0; """, threshold_condition_code= "$(RefracTime) <= 0.0 && $(V) >= $(Vthres) + $(theta)", derived_params=[ ("ExpTC", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[0]))() ), ("ExpTtheta", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[5]))()) ])
def accuracy(predictions, y_list): return np.sum(np.array(predictions) == np.array(y_list)) / float( len(y_list)) * 100 # ******************************************************************************** # Model Definitions # ******************************************************************************** # Poisson model poisson_model = genn_model.create_custom_neuron_class( "poisson_model", var_name_types=[("timeStepToSpike", "scalar"), ("frequency", "scalar")], sim_code=""" if($(timeStepToSpike) <= 0.0f) { $(timeStepToSpike) += 1.0 / $(frequency); } $(timeStepToSpike) -= 1.0; """, threshold_condition_code="$(timeStepToSpike) <= 0.0") # LIF neuron model # excitatory neurons lif_e_model = genn_model.create_custom_neuron_class( "lif_e_model", param_names=[ "Tau", "Vrest", "Vreset", "Vthres", "RefracPeriod", "tauTheta", "thetaPlus" ], var_name_types=[("V", "scalar"), ("RefracTime", "scalar"), ("theta", "scalar"), ("SpikeNumber", "unsigned int")],
if_params = {"Vthr": 5.0} rm_params = {"Vspike": 60, "alpha": 3, "y": -2.468, "beta": 0.0165} ex_params = {"Vsyn": 0, "tau_syn": 10, "g": G_MAX} inh_params = {"Vsyn": -92, "tau_syn": 10, "g": G_MAX} PROBABILITY_CONNECTION = 0.75 fixed_prob = {"prob": PROBABILITY_CONNECTION} # ---------------------------------------------------------------------------- # Custom GeNN models # ---------------------------------------------------------------------------- # Very simple integrate-and-fire neuron model if_model = create_custom_neuron_class( "if_model", param_names=["Vthr"], var_name_types=[("V", "scalar"), ("SpikeCount", "unsigned int")], sim_code="$(V) += $(Isyn) * DT;", reset_code=""" $(V) = 0.0; $(SpikeCount)++; """, threshold_condition_code="$(V) >= $(Vthr)") # Current source model which injects current with a magnitude specified by a state variable cs_model = create_custom_current_source_class( "cs_model", var_name_types=[("magnitude", "scalar")], injection_code="$(injectCurrent, $(magnitude));") lateral_inhibition = create_custom_init_var_snippet_class( "lateral_inhibition", param_names=["g"], var_init_code="$(value)=($(id_pre)==$(id_post)) ? 0.0 : $(g);")
""" Finally, we are ready to specify a custom input neuron model and the model. """ ssa_input_model = genn_model.create_custom_neuron_class( "ssa_input_model", param_names=["t_rise", "t_decay"], var_name_types=[("startSpike", "unsigned int"), ("endSpike", "unsigned int"), ("z", "scalar"), ("z_tilda", "scalar")], sim_code=""" // filtered presynaptic trace // $(z) *= exp(- DT / $(t_rise)); $(z) += (- $(z) / $(t_rise)) * DT; $(z_tilda) += ((- $(z_tilda) + $(z)) / $(t_decay)) * DT; if ($(z_tilda) < 0.0000001) { $(z_tilda) = 0.0; } """, reset_code=""" $(startSpike)++; $(z) += 1.0; """, threshold_condition_code= "$(startSpike) != $(endSpike) && $(t)>= $(spikeTimes)[$(startSpike)]", extra_global_params=[("spikeTimes", "scalar*")], is_auto_refractory_required=False) SSA_INPUT_PARAMS = {"t_rise": 5, "t_decay": 10} ssa_input_init = {
fs_relu_model = create_custom_neuron_class( 'fs_relu', param_names=['K', 'alpha', 'upstreamAlpha'], derived_params=[ ("scale", create_dpf_class(lambda pars, dt: pars[1] * 2**(-pars[0]))()), ("upstreamScale", create_dpf_class(lambda pars, dt: pars[2] * 2**(-pars[0]))()) ], var_name_types=[('Fx', 'scalar'), ('Vmem', 'scalar')], sim_code=''' // Convert K to integer const int kInt = (int)$(K); // Get timestep within presentation const int pipeTimestep = (int)($(t) / DT); // Calculate magic constants. For RelU hT=h=T // **NOTE** d uses last timestep as that was when spike was SENT const scalar hT = $(scale) * (1 << (kInt - (1 + pipeTimestep))); const scalar d = $(upstreamScale) * (1 << ((kInt - pipeTimestep) % kInt)); // Accumulate input // **NOTE** needs to be before applying input as spikes from LAST timestep must be processed $(Fx) += ($(Isyn) * d); // If this is the first timestep, apply input if(pipeTimestep == 0) { $(Vmem) = $(Fx); $(Fx) = 0.0; } ''', threshold_condition_code=''' $(Vmem) >= hT ''', reset_code=''' $(Vmem) -= hT; ''', is_auto_refractory_required=False)
###### Sample script to test implementation of Poisson neuron with changeable spiking frequency ####### from pygenn.genn_model import create_custom_neuron_class, GeNNModel poisson_model = create_custom_neuron_class( "poisson_model", var_name_types=[("rate", "scalar"), ("spikeCount", "scalar")], sim_code=""" """, reset_code=""" $(spikeCount) += 1; """, threshold_condition_code="$(gennrand_uniform) >= exp(-$(rate) * 0.001 * DT)" ) TIMESTEP = 1.0 PRESENT_TIMESTEPS = 1000 model = GeNNModel("float", "tutorial_1") model.dT = TIMESTEP poisson_init = {"rate": 30.0, "spikeCount": 0.0} p = model.add_neuron_population("p", 1, poisson_model, {}, poisson_init) model.build() model.load() while model.timestep < PRESENT_TIMESTEPS: model.step_time()
output_model = create_custom_neuron_class( "lif_superspike", param_names=[ "C", "Tau_mem", "Vrest", "Vthresh", "Ioffset", "TauRefrac", "t_rise", "t_decay", "beta", "t_peak", "tau_avg_err" ], var_name_types=[("V", "scalar"), ("RefracTime", "scalar"), ("sigma_prime", "scalar"), ("err_rise", "scalar"), ("err_tilda", "scalar"), ("err_decay", "scalar"), ("startSpike", "unsigned int"), ("endSpike", "unsigned int"), ("avg_sq_err", "scalar")], sim_code=""" // membrane potential dynamics if ($(RefracTime) == $(TauRefrac)) { $(V) = $(Vrest); } if ($(RefracTime) <= 0.0) { scalar alpha = (($(Isyn) + $(Ioffset)) * $(Rmembrane)) + $(Vrest); $(V) = alpha - ($(ExpTC) * (alpha - $(V))); } else { $(RefracTime) -= DT; } // filtered partial derivative const scalar one_plus_hi = 1.0 + fabs($(beta) * 0.001 * ($(V) - $(Vthresh))); $(sigma_prime) = 1.0 / (one_plus_hi * one_plus_hi); // error scalar S_pred = 0.0; if ($(startSpike) != $(endSpike) && $(t) >= $(spikeTimes)[$(startSpike)]) { $(startSpike)++; S_pred = 1.0; } const scalar S_real = $(RefracTime) <= 0.0 && $(V) >= $(Vthresh) ? 1.0 : 0.0; const scalar mismatch = S_pred - S_real; $(err_rise) = ($(err_rise) * $(t_rise_mult)) + mismatch; $(err_decay) = ($(err_decay) * $(t_decay_mult)) + mismatch; $(err_tilda) = ($(err_decay) - $(err_rise)) * $(norm_factor); // calculate average error trace const scalar temp = $(err_tilda) * $(err_tilda) * DT * 0.001; $(avg_sq_err) *= $(mul_avgerr); $(avg_sq_err) += temp; """, reset_code=""" $(RefracTime) = $(TauRefrac); """, threshold_condition_code="$(RefracTime) <= 0.0 && $(V) >= $(Vthresh)", derived_params=[ ("ExpTC", create_dpf_class(lambda pars, dt: exp(-dt / pars[1]))()), ("Rmembrane", create_dpf_class(lambda pars, dt: pars[1] / pars[0])()), ("norm_factor", create_dpf_class(lambda pars, dt: 1.0 / (-exp(-pars[9] / pars[6]) + exp(-pars[9] / pars[7])))()), ("t_rise_mult", create_dpf_class(lambda pars, dt: exp(-dt / pars[6]))()), ("t_decay_mult", create_dpf_class(lambda pars, dt: exp(-dt / pars[7]))()), ("mul_avgerr", create_dpf_class(lambda pars, dt: exp(-dt / pars[10]))()) ], extra_global_params=[("spikeTimes", "scalar*")])
images = get_image_data("http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz", "testing_images.npy", 2051, max) labels = get_label_data("http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz", "testing_labels.npy", 2049) assert images.shape[0] == labels.shape[0] return images, labels def accuracy(predictions, y_list): return np.sum(np.array(predictions) == np.array(y_list)) / float(len(y_list)) * 100 # ******************************************************************************** # Model Definitions # ******************************************************************************** # Neurons for input layer input_model = genn_model.create_custom_neuron_class( "input", extra_global_params=[("ImageData", "float*"), ("ImageOffset", "unsigned int*")], threshold_condition_code="$(gennrand_uniform) < $(ImageData)[$(ImageOffset)[0] + $(id)]", is_auto_refractory_required=False ) # Neurons for hidden layers hidden_layer_model = genn_model.create_custom_neuron_class( "hidden_layer", param_names=["Tau"], var_name_types=[("V", "scalar"), ("U", "scalar"), ("PhiF", "scalar"), ("PsiH", "scalar")], additional_input_vars=[("IsynBack", "scalar", 0.0)], derived_params=[ ("OneMinusTau", genn_model.create_dpf_class(lambda pars, dt: 1.0 - pars[0])()) ], sim_code=""" // Update voltage $(V) = ($(OneMinusTau) * $(V)) + ($(Tau) * $(Isyn));
def convert(self, tf_model, scaled_tf_weights=None): supported_layers = (tf.keras.layers.Dense, tf.keras.layers.Flatten, tf.keras.layers.Conv2D, tf.keras.layers.AveragePooling2D, tf.keras.layers.Dropout) # Check model compatibility if not isinstance(tf_model, tf.keras.models.Sequential): raise NotImplementedError( 'Implementation for type {} models not found'.format( type(tf_model))) for layer in tf_model.layers[:-1]: if not isinstance(layer, supported_layers): raise NotImplementedError( '{} layers are not supported'.format(layer)) elif isinstance(layer, tf.keras.layers.Dense): if layer.activation != tf.keras.activations.relu: print(layer.activation) raise NotImplementedError( 'Only ReLU activation function is supported') if layer.use_bias == True: raise NotImplementedError( 'TensorFlow model should be trained without bias tensors' ) # create custom classes if_model = genn_model.create_custom_neuron_class( "if_model", param_names=["Vres", "Vthr", "Cm"], var_name_types=[("Vmem", "scalar"), ("SpikeNumber", "unsigned int")], sim_code=""" $(Vmem) += $(Isyn)*(DT / $(Cm)); """, reset_code=""" $(Vmem) = $(Vres); $(SpikeNumber) += 1; """, threshold_condition_code="$(Vmem) >= $(Vthr)") cs_model = genn_model.create_custom_current_source_class( "cs_model", var_name_types=[("magnitude", "scalar")], injection_code=""" $(injectCurrent, $(magnitude)); """) # Params and init dense_if_params = { "Vres": self.Vres, "Vthr": self.Vthr, "Cm": self.dCm } sparse_if_params = { "Vres": self.Vres, "Vthr": self.Vthr, "Cm": self.sCm } if_init = { "Vmem": genn_model.init_var("Uniform", { "min": self.Vres, "max": self.Vthr }), "SpikeNumber": 0 } cs_init = {"magnitude": 10.0} # Fetch augmented weight matrices gw_inds, gw_vals, n_units = self.create_weight_matrices( tf_model, scaled_tf_weights) # Define model and populations self.g_model = genn_model.GeNNModel("float", "g_model") self.neuron_pops = [] self.syn_pops = [] for i, (inds, vals, n) in enumerate(zip(gw_inds, gw_vals, n_units), start=1): if i == 1: # Presynaptic neuron self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i - 1), n_units[i - 1], if_model, sparse_if_params, if_init)) if inds is None: # Postsynaptic neuron self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i), n_units[i], if_model, dense_if_params, if_init)) # Synapse self.syn_pops.append( self.g_model.add_synapse_population( "syn" + str(i - 1) + str(i), "DENSE_INDIVIDUALG", genn_wrapper.NO_DELAY, self.neuron_pops[-2], self.neuron_pops[-1], "StaticPulse", {}, {'g': vals}, {}, {}, "DeltaCurr", {}, {})) else: self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i), n_units[i], if_model, sparse_if_params, if_init)) self.syn_pops.append( self.g_model.add_synapse_population( "syn" + str(i - 1) + str(i), "SPARSE_INDIVIDUALG", genn_wrapper.NO_DELAY, self.neuron_pops[-2], self.neuron_pops[-1], "StaticPulse", {}, {'g': vals}, {}, {}, "DeltaCurr", {}, {})) self.syn_pops[-1].set_sparse_connections(inds[0], inds[1]) self.current_source = self.g_model.add_current_source( "cs", cs_model, "if0", {}, cs_init) self.g_model.dT = self.timestep self.g_model.build() self.g_model.load() return self.g_model, self.neuron_pops, self.current_source
from pygenn.genn_model import create_custom_neuron_class from pygenn.genn_wrapper.Models import VarAccess_READ_ONLY_DUPLICATE from ml_genn.layers.input_neurons import InputNeurons spike_input_model = create_custom_neuron_class( 'spike_input', var_name_types=[('input', 'scalar', VarAccess_READ_ONLY_DUPLICATE)], sim_code=''' const bool spike = $(input) != 0.0; ''', threshold_condition_code=''' $(input) > 0.0 && spike ''', is_auto_refractory_required=False, ) class SpikeInputNeurons(InputNeurons): def __init__(self, signed_spikes=False): super(SpikeInputNeurons, self).__init__() self.signed_spikes = signed_spikes def compile(self, mlg_model, layer): model = spike_input_model vars = {'input': 0.0} super(SpikeInputNeurons, self).compile(mlg_model, layer, model, {}, vars, {})
# ---------------------------------------------------------------------------- IF_PARAMS = {"Vtheta": 1.0, "lambda": 0.01, "Vrest": 0.0, "Vreset": 0.0} TIMESTEP = 1.0 PRESENT_TIMESTEPS = 100 # ---------------------------------------------------------------------------- # Custom GeNN models # ---------------------------------------------------------------------------- if_model = create_custom_neuron_class( "if_model", param_names=["Vtheta", "lambda", "Vrest", "Vreset"], var_name_types=[("V", "scalar"), ("SpikeCount", "scalar")], sim_code=""" if ($(V) >= $(Vtheta)) { $(V) = $(Vreset); $(SpikeCount) += 1; } $(V) += (-$(lambda) + $(Isyn)) * DT; $(V) = fmax($(V), $(Vrest)); """, reset_code=""" """, threshold_condition_code="$(V) >= $(Vtheta)") poisson_model = create_custom_neuron_class( "poisson_model", var_name_types=[("rate", "scalar")], sim_code=""" """, reset_code=""" """,
import numpy as np from pygenn.genn_model import create_custom_neuron_class from ml_genn.layers.neurons import Neurons if_model = create_custom_neuron_class( 'if', var_name_types=[('Vmem', 'scalar'), ('nSpk', 'unsigned int')], extra_global_params=[('Vthr', 'scalar')], sim_code=''' if ($(t) == 0.0) { // Reset state at t = 0 $(Vmem) = 0.0; $(nSpk) = 0; } $(Vmem) += $(Isyn) * DT; ''', threshold_condition_code=''' $(Vmem) >= $(Vthr) ''', reset_code=''' $(Vmem) = 0.0; $(nSpk) += 1; ''', is_auto_refractory_required=False, ) class IFNeurons(Neurons): def __init__(self, threshold=1.0): super(IFNeurons, self).__init__() self.threshold = threshold
# ---------------------------------------------------------------------------- # Custom models # ---------------------------------------------------------------------------- izhikevich_dopamine_model = genn_model.create_custom_neuron_class( "izhikevich_dopamine", param_names=["a", "b", "c", "d", "tauD", "dStrength"], var_name_types=[("V", "scalar"), ("U", "scalar"), ("D", "scalar")], extra_global_params=[("rewardTimesteps", "uint32_t*")], sim_code= """ $(V)+=0.5*(0.04*$(V)*$(V)+5.0*$(V)+140.0-$(U)+$(Isyn))*DT; //at two times for numerical stability $(V)+=0.5*(0.04*$(V)*$(V)+5.0*$(V)+140.0-$(U)+$(Isyn))*DT; $(U)+=$(a)*($(b)*$(V)-$(U))*DT; const unsigned int timestep = (unsigned int)($(t) / DT); const bool injectDopamine = (($(rewardTimesteps)[timestep / 32] & (1 << (timestep % 32))) != 0); if(injectDopamine) { const scalar dopamineDT = $(t) - $(prev_seT); const scalar dopamineDecay = exp(-dopamineDT / $(tauD)); $(D) = ($(D) * dopamineDecay) + $(dStrength); } """, threshold_condition_code="$(V) >= 30.0", reset_code= """ $(V)=$(c); $(U)+=$(d); """) izhikevich_stdp_tag_update_code=""" // Calculate how much tag has decayed since last update
from pygenn.genn_model import create_custom_neuron_class from pygenn.genn_wrapper.Models import VarAccess_READ_ONLY_DUPLICATE from ml_genn.layers.input_neurons import InputNeurons poisson_input_model = create_custom_neuron_class( 'poisson_input', var_name_types=[('input', 'scalar', VarAccess_READ_ONLY_DUPLICATE)], sim_code=''' const bool spike = $(gennrand_uniform) >= exp(-fabs($(input)) * DT); ''', threshold_condition_code=''' $(input) > 0.0 && spike ''', is_auto_refractory_required=False, ) class PoissonInputNeurons(InputNeurons): def __init__(self, signed_spikes=False): super(PoissonInputNeurons, self).__init__() self.signed_spikes = signed_spikes def compile(self, mlg_model, layer): model = poisson_input_model vars = {'input': 0.0} super(PoissonInputNeurons, self).compile(mlg_model, layer, model, {}, vars, {})
#---------------------------------------------------------------------------- # Neuron models #---------------------------------------------------------------------------- recurrent_lif_model = genn_model.create_custom_neuron_class( "recurrent_lif", param_names=["TauM", "Vthresh", "TauRefrac"], var_name_types=[("V", "scalar"), ("RefracTime", "scalar")], derived_params=[ ("Alpha", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[0]))()) ], sim_code=""" $(V) = ($(Alpha) * $(V)) + $(Isyn); if ($(RefracTime) > 0.0) { $(RefracTime) -= DT; } """, reset_code=""" $(RefracTime) = $(TauRefrac); $(V) -= $(Vthresh); """, threshold_condition_code=""" $(RefracTime) <= 0.0 && $(V) >= $(Vthresh) """, is_auto_refractory_required=False) recurrent_alif_model = genn_model.create_custom_neuron_class( "recurrent_alif", param_names=["TauM", "TauAdap", "Vthresh", "TauRefrac", "Beta"], var_name_types=[("V", "scalar"), ("A", "scalar"),
hidden_neuron_model = genn_model.create_custom_neuron_class( "hidden", param_names=["C", "tauMem", "Vrest", "Vthresh", "tauRefrac"], var_name_types=[("V", "scalar"), ("refracTime", "scalar"), ("errTilda", "scalar")], additional_input_vars=[("ISynFeedback", "scalar", 0.0)], derived_params=[("ExpTC", genn_model.create_dpf_class(lambda pars, dt: np.exp(-dt / pars[1]))()), ("Rmembrane", genn_model.create_dpf_class(lambda pars, dt: pars[1] / pars[0])())], sim_code=""" // membrane potential dynamics if ($(refracTime) == $(tauRefrac)) { $(V) = $(Vrest); } if ($(refracTime) <= 0.0) { scalar alpha = ($(Isyn) * $(Rmembrane)) + $(Vrest); $(V) = alpha - ($(ExpTC) * (alpha - $(V))); } else { $(refracTime) -= DT; } // error $(errTilda) = $(ISynFeedback); """, reset_code=""" $(refracTime) = $(tauRefrac); """, threshold_condition_code=""" $(refracTime) <= 0.0 && $(V) >= $(Vthresh) """, is_auto_refractory_required=False)
default=1, help= "Number of samples in the dataset for which the network should be simulated. (default=1)", ) args = parser.parse_args() # Define custom Izhikevich neuron class izk_neuron = create_custom_neuron_class( "izk_neuron", param_names=["a", "b", "c", "d", "C", "k"], var_name_types=[("V", "scalar"), ("U", "scalar")], sim_code=""" $(V)+= (0.5/$(C))*($(k)*($(V) + 60.0)*($(V) + 40.0)-$(U)+$(Isyn)); //at two times for numerical stability $(V)+= (0.5/$(C))*($(k)*($(V) + 60.0)*($(V) + 40.0)-$(U)+$(Isyn)); $(U)+=$(a)*($(b)*($(V) + 60.0)-$(U))*DT; """, reset_code=""" $(V)=$(c); $(U)+=$(d); """, threshold_condition_code="$(V) > 30", ) # Set the parameters and initial values of variables for the IZK neuron (whose class has been defined above) izk_params = { "a": 0.03, "b": -2.0, "c": -50.0, "d": 100.0,
from pygenn.genn_model import create_custom_neuron_class from pygenn.genn_wrapper.Models import VarAccess_READ_ONLY_DUPLICATE from ml_genn.layers.input_neurons import InputNeurons if_input_model = create_custom_neuron_class( 'if_input', var_name_types=[('input', 'scalar', VarAccess_READ_ONLY_DUPLICATE), ('Vmem', 'scalar')], sim_code=''' if ($(t) == 0.0) { // Reset state at t = 0 $(Vmem) = 0.0; } $(Vmem) += $(input) * DT; ''', threshold_condition_code=''' $(Vmem) >= 1.0 ''', reset_code=''' $(Vmem) = 0.0; ''', is_auto_refractory_required=False, ) class IFInputNeurons(InputNeurons): def compile(self, mlg_model, layer): model = if_input_model vars = {'input': 0.0, 'Vmem': 0.0} super(IFInputNeurons, self).compile(mlg_model, layer, model, {}, vars,