def get_phi_spiker(neuron=None): """ returns a somatic spiker that implements an inhomogenuous poisson process, i.e. a spike will be elicited with probability dt*firing_rate """ if neuron is None: neuron = get_default("neuron") return lambda curr, dt, **kwargs: phi(curr['y'][0], neuron) * dt >= np.random.rand()
def get_phi_spiker(neuron=None): """ returns a somatic spiker that implements an inhomogenuous poisson process, i.e. a spike will be elicited with probability dt*firing_rate """ if neuron is None: neuron = get_default("neuron") return lambda curr, dt, **kwargs: phi(curr['y'][0], neuron ) * dt >= np.random.rand()
def run(sim, spiker, spiker_dendr, accumulators, neuron, learn, **kwargs): """ this is the main simulation routine. Arguments: sim -- a dictionary containing the following simulation parameters start: starting time end: ending time dt: time step I_ext: function for evaluating externally applied current pre_spikes: a list of presynaptic spikes spiker -- the somatic spiker spiker_dendr -- the dendritic spiker accumulators -- a list of accumulators for saving model variables during the simulation neuron -- a dictionary containing the neuron parameters, default_neuron is used if none specified learn -- a dictionary contianing the learning parameters, default_learn is used if none specified returns: a list of accumulators containing simulation results """ use_seed = kwargs.get('seed', 0) np.random.seed(use_seed) # restrict to positive weights by default normalizer = lambda weights: np.where(weights > 0, weights, 0.0) # set some default parameters p_backprop = 1.0 syn_cond_soma = sim.get('syn_cond_soma', {sym: lambda t: 0.0 for sym in ['E', 'I']}) # ここはデフォルトのphi()を使っている dendr_predictor = kwargs.get('dendr_predictor', phi) # これはずっと0 I_ext = sim.get('I_ext', step_current(np.array([[sim['start'], 0.0]]))) # ensure numpy arrays, for fancy indexing pre_spikes = sim['pre_spikes'] for i, pre_sp in enumerate(pre_spikes): pre_spikes[i] = np.array(pre_sp) n_syn = len(pre_spikes) for key in ['eps', 'eta', 'tau_delta']: if not isinstance(learn[key], collections.Iterable): learn[key] = np.array([learn[key] for _ in range(n_syn)]) for acc in accumulators: acc.prepare_arrays(n_syn) t_start = sim['start'] t_end = sim['end'] dt = sim['dt'] U0 = neuron['E_L'] curr = { 't': t_start, 'y': np.concatenate((np.array([U0, neuron['E_L'], neuron['E_L']]), np.zeros(2 * n_syn))) # yは203個になる # 最初の3つは[U, V, V_w_star] # それ以降は[dV_dws, dV_w_star_dws]の繰り返し } last_spike = { 't': float('-inf'), 'y': curr['y'] } last_spike_dendr = { 't': float('-inf'), 'y': curr['y'] } weights = np.array(learn['eps']) g_E_Ds = np.zeros(n_syn) syn_pots_sums = np.zeros(n_syn) PIVs = np.zeros(n_syn) deltas = np.zeros(n_syn) weight_updates = np.zeros(n_syn) while curr['t'] < t_end - dt / 2: # currにはtとyが入っている. # curr['y'] = (203,) #print("t={}, t_end={}".format(curr['t'], t_end)) #.. # for each synapse: is there a presynaptic spike at curr['t']? # 各ニューロンのpre synapseニューロンが発火したかどうか curr_pres = np.array([np.sum(np.isclose(pre_sp, curr['t'], rtol=1e-10, atol=1e-10)) for pre_sp in pre_spikes]) # (100,)の 0or1 (2以上の場合もありうる) g_E_Ds = g_E_Ds + curr_pres * weights g_E_Ds = g_E_Ds - dt * g_E_Ds / neuron['tau_s'] # 時定数で減衰 # (100,) # 現在時刻tより前のpre synapse発火タイミングでのexponentialを加算する syn_pots_sums = np.array( [np.sum(np.exp(-(curr['t'] - pre_sp[pre_sp <= curr['t']]) / neuron['tau_s'])) \ for pre_sp in pre_spikes]) # (100,) # is there a postsynaptic spike at curr['t']? if curr['t'] - last_spike['t'] < neuron['tau_ref']: # refractory period中だった場合 does_spike = False else: does_spike = spiker(curr=curr, dt=dt) # sineタスクの場合はdoes_spikeがtrueになることが無い if does_spike: last_spike = {'t': curr['t'], 'y': curr['y']} # does the dendrite detect a spike? dendr_spike = spiker_dendr(curr=curr, last_spike=last_spike, last_spike_dendr=last_spike_dendr) # floatの値, phi(U) * dt if dendr_spike: last_spike_dendr = {'t': curr['t'], 'y': curr['y']} # dendritic prediction # V_w_starから予測 (sigmoidを使ったphi(V_w_star)) dendr_pred = dendr_predictor(curr['y'][2], neuron) # 指定されたh or phi_prime(V_w_star) / phi(V_w_star) h = kwargs.get('h', phi_prime(curr['y'][2], neuron) / phi(curr['y'][2], neuron)) # update weights # 重みの更新 # dV_w_star_dws # (delta_factorは1.0) pos_PIVs = neuron['delta_factor'] * float(dendr_spike) / dt * h * curr['y'][4::2] neg_PIVs = dendr_pred * h * curr['y'][4::2] PIVs = pos_PIVs - neg_PIVs # (phi(U) - phi(V_w_star)) * h * dV_w_star_dws deltas += dt * (PIVs - deltas) / learn['tau_delta'] weight_updates = learn['eta'] * deltas weights = normalizer(weights + weight_updates) # advance state: integrate from curr['t'] to curr['t']+dt curr_I = I_ext(curr['t']) args = (curr['y'], curr['t'], curr['t'] - last_spike['t'], g_E_Ds, syn_pots_sums, curr_I, neuron, syn_cond_soma, p_backprop) curr['y'] += dt * urb_senn_rhs(*args) curr['t'] += dt # save state vals = { 'g_E_Ds' : g_E_Ds, 'syn_pots_sums' : syn_pots_sums, 'y' : curr['y'], 'spike' : float(does_spike), 'dendr_pred' : dendr_pred, 'h' : h, 'PIVs' : PIVs, 'pos_PIVs' : pos_PIVs, 'neg_PIVs' : neg_PIVs, 'dendr_spike' : float(dendr_spike), 'pre_spikes' : curr_pres, 'weights' : weights, 'weight_updates': weight_updates, 'deltas' : deltas, 'I_ext' : curr_I } for acc in accumulators: acc.add(curr['t'], **vals) for acc in accumulators: acc.cleanup() acc.add_variable('seed', use_seed) return accumulators
def phi_U_learner(curr, **kwargs): # phi(U) * dtを返す return factor * phi(curr['y'][0], neuron) * dt
def run(sim, spiker, spiker_dendr, accumulators, neuron=None, learn=None, normalizer=None, **kwargs): """ this is the main simulation routine. Arguments: sim -- a dictionary containing the following simulation parameters start: starting time end: ending time dt: time step I_ext: function for evaluating externally applied current pre_spikes: a list of presynaptic spikes spiker -- the somatic spiker spiker_dendr -- the dendritic spiker accumulators -- a list of accumulators for saving model variables during the simulation neuron -- a dictionary containing the neuron parameters, default_neuron is used if none specified learn -- a dictionary contianing the learning parameters, default_learn is used if none specified normalizer -- a function to normalize synaptic weights, e.g. the default normalizer ensures non-negative weights returns: a list of accumulators containing simulation results """ use_seed = kwargs.get('seed', 0) np.random.seed(use_seed) if neuron is None: neuron = get_default('neuron') if learn is None: learn = get_default('learn') # restrict to positive weights by default if normalizer is None: normalizer = lambda weights: np.where(weights > 0, weights, 0.0) # set some default parameters p_backprop = kwargs.get('p_backprop', 1.0) syn_cond_soma = sim.get('syn_cond_soma', {sym: lambda t: 0.0 for sym in ['E', 'I']}) dendr_predictor = kwargs.get('dendr_predictor', phi) I_ext = sim.get('I_ext', step_current(np.array([[sim['start'], 0.0]]))) # ensure numpy arrays, for fancy indexing pre_spikes = sim['pre_spikes'] for i, pre_sp in enumerate(pre_spikes): pre_spikes[i] = np.array(pre_sp) n_syn = len(pre_spikes) for key in ['eps', 'eta', 'tau_delta']: if not isinstance(learn[key], collections.Iterable): learn[key] = np.array([learn[key] for _ in range(n_syn)]) for acc in accumulators: acc.prepare_arrays(n_syn) t_start = sim['start'] t_end = sim['end'] dt = sim['dt'] U0 = neuron['E_L'] curr = { 't': t_start, 'y': np.concatenate((np.array([U0, neuron['E_L'], neuron['E_L']]), np.zeros(2 * n_syn)))} last_spike = { 't': float('-inf'), 'y': curr['y'] } last_spike_dendr = { 't': float('-inf'), 'y': curr['y'] } weights = np.array(learn['eps']) g_E_Ds = np.zeros(n_syn) syn_pots_sums = np.zeros(n_syn) PIVs = np.zeros(n_syn) deltas = np.zeros(n_syn) weight_updates = np.zeros(n_syn) while curr['t'] < t_end - dt / 2: #print("t={}, t_end={}".format(curr['t'], t_end)) #.. # for each synapse: is there a presynaptic spike at curr['t']? curr_pres = np.array([np.sum(np.isclose(pre_sp, curr['t'], rtol=1e-10, atol=1e-10)) for pre_sp in pre_spikes]) g_E_Ds = g_E_Ds + curr_pres * weights g_E_Ds = g_E_Ds - dt * g_E_Ds / neuron['tau_s'] syn_pots_sums = np.array( [np.sum(np.exp(-(curr['t'] - pre_sp[pre_sp <= curr['t']]) / neuron['tau_s'])) \ for pre_sp in pre_spikes]) # is there a postsynaptic spike at curr['t']? if curr['t'] - last_spike['t'] < neuron['tau_ref']: does_spike = False else: does_spike = spiker(curr=curr, dt=dt) if does_spike: last_spike = {'t': curr['t'], 'y': curr['y']} # does the dendrite detect a spike? dendr_spike = spiker_dendr(curr=curr, last_spike=last_spike, last_spike_dendr=last_spike_dendr) if dendr_spike: last_spike_dendr = {'t': curr['t'], 'y': curr['y']} # dendritic prediction dendr_pred = dendr_predictor(curr['y'][2], neuron) h = kwargs.get('h', phi_prime(curr['y'][2], neuron) / phi(curr['y'][2], neuron)) # update weights pos_PIVs = neuron['delta_factor'] * float(dendr_spike) / dt * h * curr['y'][4::2] neg_PIVs = dendr_pred * h * curr['y'][4::2] PIVs = pos_PIVs - neg_PIVs deltas += dt * (PIVs - deltas) / learn['tau_delta'] weight_updates = learn['eta'] * deltas weights = normalizer(weights + weight_updates) # advance state: integrate from curr['t'] to curr['t']+dt curr_I = I_ext(curr['t']) args = (curr['y'], curr['t'], curr['t'] - last_spike['t'], g_E_Ds, syn_pots_sums, curr_I, neuron, syn_cond_soma, p_backprop) curr['y'] += dt * urb_senn_rhs(*args) curr['t'] += dt # save state vals = { 'g_E_Ds' : g_E_Ds, 'syn_pots_sums' : syn_pots_sums, 'y' : curr['y'], 'spike' : float(does_spike), 'dendr_pred' : dendr_pred, 'h' : h, 'PIVs' : PIVs, 'pos_PIVs' : pos_PIVs, 'neg_PIVs' : neg_PIVs, 'dendr_spike' : float(dendr_spike), 'pre_spikes' : curr_pres, 'weights' : weights, 'weight_updates': weight_updates, 'deltas' : deltas, 'I_ext' : curr_I } for acc in accumulators: acc.add(curr['t'], **vals) for acc in accumulators: acc.cleanup() acc.add_variable('seed', use_seed) return accumulators
def phi_U_learner(curr, **kwargs): return factor * phi(curr['y'][0], neuron) * dt
def dendr_predictor(V, neuron): return np.sum([phi(V,{'phi':{'alpha': al, 'beta':p["beta_wiggle"], 'r_max': r_m}}) for al in alphas])
def task((repetition_i, p)): n_syn = p["n_syn"] learn = get_default("learn") learn["eps"] = 1e-1 / (1.0 * n_syn) learn["eta"] = learn["eps"] * p["eps_factor"] neuron = get_default("neuron") neuron["phi"]["alpha"] = p["alpha"] neuron["phi"]["beta"] = p["beta"] neuron["phi"]["r_max"] = 0.1 neuron["g_S"] = p["g_S"] learn_epochs = 2 test_epochs = 1 epochs = learn_epochs + test_epochs l_c = 4 eval_c = 2 cycles = epochs * l_c + (epochs + 1) * eval_c cycle_dur = p["cycle_dur"] epoch_dur = (l_c + eval_c) * cycle_dur t_end = cycles * cycle_dur g_factor = p["g_factor"] def exc_soma_cond(t): if t % (cycle_dur * (l_c + eval_c)) < cycle_dur * eval_c or t > learn_epochs * epoch_dur: return 0.0 return p["exc_level"] * p["g_factor"] def inh_soma_cond(t): if t % (cycle_dur * (l_c + eval_c)) < cycle_dur * eval_c or t > learn_epochs * epoch_dur: return 0.0 return 1e-1 * p["g_factor"] dt = 0.05 f_r = 1.0 / cycle_dur t_pts = np.arange(0, t_end / cycles, dt) seed = int(int(time.time() * 1e8) % 1e9) reg_spikes = [np.arange(i+1,t_end+1,10) for i in range(n_syn)] poisson_spikes = [t_pts[np.random.rand(t_pts.shape[0]) < f_r * dt] for _ in range(n_syn)] poisson_spikes = [[] if spikes.shape[0] == 0 else np.concatenate( [np.arange(spike, t_end, cycle_dur) for spike in spikes]) for spikes in poisson_spikes] for train in poisson_spikes: train.sort() my_s = { 'start': 0.0, 'end': t_end, 'dt': dt, 'pre_spikes': reg_spikes, 'syn_cond_soma': {'E': exc_soma_cond, 'I': inh_soma_cond}, 'I_ext': lambda t: 0.0 } phi_spiker = get_phi_spiker(neuron) # deprecated def my_spiker(curr, dt, **kwargs): # we want no spikes in eval cycles if curr['t'] % (cycle_dur * (l_c + eval_c)) < cycle_dur * eval_c: return False else: return phi_spiker(curr, dt, **kwargs) if p["wiggle"] is None: dendr_predictor = phi else: us = np.linspace(-100,20,1000) ampl = neuron["phi"]["r_max"] phis = phi(us, neuron) alphas = [] for i in range(p["wiggle"]): alphas.append(us[phis > (i+0.5)*ampl/p["wiggle"]][0]) r_m = neuron['phi']['r_max']/p["wiggle"] def dendr_predictor(V, neuron): return np.sum([phi(V,{'phi':{'alpha': al, 'beta':p["beta_wiggle"], 'r_max': r_m}}) for al in alphas]) accs = [PeriodicAccumulator(get_all_save_keys(), interval=20, y_keep=3), BooleanAccumulator(['spike'])] accums = run(my_s, get_fixed_spiker(np.array([])), get_phi_U_learner(neuron, dt, p["exc_decrease"]), accs, neuron=neuron, seed=seed, learn=learn, dendr_predictor=dendr_predictor) dump((seed, accums), 'wiggle_test/' + p['ident'])
def run(sim, spiker, spiker_dendr, accumulators, neuron=None, learn=None, normalizer=None, **kwargs): """ this is the main simulation routine, can either be called directly, or with the convenience routine do in helper.py arguments: sim -- a dictionary containing the following simulation parameters start: starting time end: ending time dt: time step I_ext: function for evaluating externally applied current pre_spikes: a list of presynaptic spikes spiker -- the somatic spiker spiker_dendr -- the dendritic spiker accumulators -- a list of accumulators for saving model variables during the simulation neuron -- a dictionary containing the neuron parameters, default_neuron is used if none specified learn -- a dictionary contianing the learning parameters, default_learn is used if none specified normalizer -- a function to normalize synaptic weights, e.g. the default normalizer ensures non-negative weights returns: a list of accumulators containing simulation results """ use_seed = kwargs.get('seed', 0) np.random.seed(use_seed) if neuron is None: neuron = get_default('neuron') if learn is None: learn = get_default('learn') # restrict to positive weights by default if normalizer is None: normalizer = lambda weights: np.where(weights > 0, weights, 0.0) # set some default parameters voltage_clamp = kwargs.get('voltage_clamp', False) p_backprop = kwargs.get('p_backprop', 1.0) syn_cond_soma = sim.get('syn_cond_soma', {sym: lambda t: 0.0 for sym in ['E', 'I']}) dendr_predictor = kwargs.get('dendr_predictor', phi) I_ext = sim.get('I_ext', step_current(np.array([[sim['start'], 0.0]]))) # ensure numpy arrays, for fancy indexing pre_spikes = sim['pre_spikes'] for i, pre_sp in enumerate(pre_spikes): pre_spikes[i] = np.array(pre_sp) n_syn = len(pre_spikes) for key in ['eps', 'eta', 'tau_delta']: if not isinstance(learn[key], collections.Iterable): learn[key] = np.array([learn[key] for _ in range(n_syn)]) for acc in accumulators: acc.prepare_arrays(n_syn) t_start, t_end, dt = sim['start'], sim['end'], sim['dt'] if voltage_clamp: U0 = kwargs['U_clamp'] else: U0 = neuron['E_L'] curr = {'t': t_start, 'y': np.concatenate((np.array([U0, neuron['E_L'], neuron['E_L']]), np.zeros(2 * n_syn)))} last_spike = {'t': float('-inf'), 'y': curr['y']} last_spike_dendr = {'t': float('-inf'), 'y': curr['y']} weights = np.array(learn['eps']) g_E_Ds = np.zeros(n_syn) syn_pots_sums = np.zeros(n_syn) PIVs = np.zeros(n_syn) deltas = np.zeros(n_syn) weight_updates = np.zeros(n_syn) while curr['t'] < t_end - dt / 2: # for each synapse: is there a presynaptic spike at curr['t']? curr_pres = np.array( [np.sum(np.isclose(pre_sp, curr['t'], rtol=1e-10, atol=1e-10)) for pre_sp in pre_spikes]) g_E_Ds = g_E_Ds + curr_pres * weights g_E_Ds = g_E_Ds - dt * g_E_Ds / neuron['tau_s'] syn_pots_sums = np.array( [np.sum(np.exp(-(curr['t'] - pre_sp[pre_sp <= curr['t']]) / neuron['tau_s'])) for pre_sp in pre_spikes]) # is there a postsynaptic spike at curr['t']? if curr['t'] - last_spike['t'] < neuron['tau_ref']: does_spike = False else: does_spike = spiker(curr=curr, dt=dt) if does_spike: last_spike = {'t': curr['t'], 'y': curr['y']} # does the dendrite detect a spike? dendr_spike = spiker_dendr(curr=curr, last_spike=last_spike, last_spike_dendr=last_spike_dendr) if dendr_spike: last_spike_dendr = {'t': curr['t'], 'y': curr['y']} # dendritic prediction dendr_pred = dendr_predictor(curr['y'][2], neuron) h = kwargs.get('h', phi_prime(curr['y'][2], neuron) / phi(curr['y'][2], neuron)) # update weights pos_PIVs = neuron['delta_factor'] * float(dendr_spike) / dt * h * curr['y'][4::2] neg_PIVs = dendr_pred * h * curr['y'][4::2] PIVs = pos_PIVs - neg_PIVs deltas += dt * (PIVs - deltas) / learn['tau_delta'] weight_updates = learn['eta'] * deltas weights = normalizer(weights + weight_updates) # advance state: integrate from curr['t'] to curr['t']+dt curr_I = I_ext(curr['t']) args = (curr['y'], curr['t'], curr['t'] - last_spike['t'], g_E_Ds, syn_pots_sums, curr_I, neuron, syn_cond_soma, voltage_clamp, p_backprop) curr['y'] += dt * urb_senn_rhs(*args) curr['t'] += dt # save state vals = {'g_E_Ds': g_E_Ds, 'syn_pots_sums': syn_pots_sums, 'y': curr['y'], 'spike': float(does_spike), 'dendr_pred': dendr_pred, 'h': h, 'PIVs': PIVs, 'pos_PIVs': pos_PIVs, 'neg_PIVs': neg_PIVs, 'dendr_spike': float(dendr_spike), 'pre_spikes': curr_pres, 'weights': weights, 'weight_updates': weight_updates, 'deltas': deltas, 'I_ext': curr_I} for acc in accumulators: acc.add(curr['t'], **vals) for acc in accumulators: acc.cleanup() acc.add_variable('seed', use_seed) return accumulators