From 48cacb144d9ff81506a5c7ca9c9f13fdb8718d0c Mon Sep 17 00:00:00 2001 From: Mazdak Fatahi <mazdak.fatahi@univ-lille.fr> Date: Thu, 17 Nov 2022 13:40:34 +0100 Subject: [PATCH] Upload New File --- SpiNNaker/SpiNNakerHelpers.py | 337 ++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 SpiNNaker/SpiNNakerHelpers.py diff --git a/SpiNNaker/SpiNNakerHelpers.py b/SpiNNaker/SpiNNakerHelpers.py new file mode 100644 index 0000000..0f169b6 --- /dev/null +++ b/SpiNNaker/SpiNNakerHelpers.py @@ -0,0 +1,337 @@ +import numpy as np +import math +from mpl_toolkits.axes_grid1 import ImageGrid +import matplotlib.pyplot as plt +import torch +import snntorch +from snntorch import utils, spikegen +from tqdm import tqdm +#from pyNN.utility.plotting import Figure, Panel +#import spynnaker.pyNN as sim +INPUT_SIZE=784 +# Initialization +#Neurons Parameters +excitatory_neuron_parameters = { + 'v_rest': -70.0,#V_REST, # Resting membrane potential in mV. + 'cm': .3,# 1.0, # Capacity of the membrane in nF + 'tau_m': 10.0, #100.0, # Membrane time constant in ms. + 'tau_refrac': 10,#4.0,#5.0, # Duration of refractory period in ms. + 'tau_syn_E': 1.0, # Decay time of the excitatory synaptic conductance in ms. + 'tau_syn_I': 1.0,#2.0, # Decay time of the inhibitory synaptic conductance in ms. +# 'e_rev_E': 0.0, # Reversal potential for excitatory input in mV +# 'e_rev_I': -100.0, # Reversal potential for inhibitory input in mV + 'v_thresh': -55.4,#-52.0, # Spike threshold in mV. + 'v_reset': -65.0,#V_RESET, # Reset potential after a spike in mV. + 'i_offset': 0.005# 0.0, # Offset current in nA +} + + +def img_grid(input_data, nrows_ncols, file_name=None, figsize=(10, 10), cmap="jet"): + """ + Using ImageGrid from mpl_toolkits.axes_grid1 to show multiple images in grids + Parameters + ---------- + input_data: An array of images. + nrows_ncols: A tuple (number of rows, number of columns) + file_name: A string to save the plot as + cmap: 'flag', 'prism', 'ocean', 'gist_earth', 'terrain', + 'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap', + 'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet', + 'turbo', 'nipy_spectral', 'gist_ncar' + + + Ex_1: + p=np.random.random_integers(0,255,(100,10,10)) + plot_and_save_grid(p, (10, 10), 'test.svg') + + Ex_2: + p=[[[1,2,3],[1,2,3],[1,2,3]] for _ in range(8)] + plots.img_grid(p, (3,2), 'test.svg') + """ + fig = plt.figure(figsize=figsize) + grid = ImageGrid(fig, 111, + nrows_ncols, + axes_pad=0.1, + ) + + for ax, inx in zip(grid, list(range(nrows_ncols[0]*nrows_ncols[1]))): + ax.imshow(input_data[inx],cmap=cmap) + ax.set_axis_off() + + if file_name: + plt.savefig(file_name) + return + +def multi_titled_imgs(input_data, main_title, row_titles, col_titles, file_name=None, axis_off=True, figsize=(10,15), main_title_fontsize=20, rows_fontsize=15, cols_fontsize=10): + """ + Parameters + ---------- + input_data: An array of images. + main_title: A sting as top title + row_titles: An array of n strings for the title of n each row + col_titles: An array of 2 strings for the title of each columns + + Ex_1: + p=np.random.random_integers(0,255,(6,10,10))# 6 random (10, 10) matrixes + main_title='Main Title' + row_titles=["A", "B", "C"] + col_titles=["First Col", "2nd Col"] + plots.multi_titled_imgs(p[:10],main_title,row_titles,col_titles, file_name='a.png', axis_off=False) + """ + + fig = plt.figure(figsize=figsize,constrained_layout=True) + fig.suptitle(main_title, fontsize=main_title_fontsize) + subfigs = fig.subfigures(nrows=len(row_titles), ncols=1) + for row, subfig in enumerate(subfigs): + subfig.suptitle(f'{row_titles[row]}', fontsize=rows_fontsize) + + axs = subfig.subplots(nrows=1, ncols=2) + for col, ax in enumerate(axs): + ax.imshow(input_data[row*2+col]) + ax.set_title(f' {col_titles[col]}', fontsize=cols_fontsize) + if axis_off: + ax.set_axis_off() + if file_name: + plt.savefig(file_name) + return + +def Extract_ConnectionFiles(Input_CSNN_Binary_Files=[], ConnectionFile_Names=[], Input_size=784, Output_size=400, n_samples_to_plot=0, Non_Zero=False, Transpoed=False, Inpute_shape={'x':28, 'y':28},): + """ + To generate connection files from the CSNN binary files. + ---------- + NOTE: For each layer you need to call the function separately. + ---------- + Parameters + ---------- + Authors Note: It is recommended to call the function with Transpoed=False and transpose the input before passing it to the SpikeSourceArray in PyNN. + ----- + Input_CSNN_Binary_Files: Python list of binary file names (different binary files from the same layer) + ConnectionFile_Names: Python list of output file names (as text files compatible with PyNN FromFileConnector) + Input_size: Number of the neurons as the input of the layer + Output_size: Number of the neurons as the output of the layer + n_samples_to_plot: You can plot n_samples_to_plot weights between one input and all the output as plot + Non_Zero: If set to True, the weights with zero values will be removed from the output file. + Transpoed: Since CSNN binary file for the trained weights is transposed, is set Transpoed to True, the function will transpose the weights before generating the output file. + Inpute_shape: Python dictionary of shape of the input samples + + """ + extracted_weights=[[] for _ in Input_CSNN_Binary_Files] + for i, file_name in enumerate(Input_CSNN_Binary_Files): + w = np.fromfile(file_name, dtype=np.dtype(np.float32)) + print(f'Input file shape = {w.shape}') + f=open(ConnectionFile_Names[i], 'w') + f.write('# columns = ["i", "j", "weight", "delay"]\n') + + if Transpoed: + w=w.reshape(Inpute_shape['x'], Inpute_shape['y'], -1)#(28, 28, 400) + w=np.array([w[:, :, j].transpose() for j in range(Output_size) ])#(400, 28, 28) + + w=w.reshape( Output_size, Input_size).transpose()# 400 rows of (28, 28) to 400 rows of 784 then to 784*400 + X,Y=w.shape + print(X,Y) + for x in range(X): + for y in range(Y): + if Non_Zero: + if w[x][y]: + line=f'{x} {y} {w[x][y]} 1\n' + f.write(line) + extracted_weights[i].append(w[x][y]) + else: + line=f'{x} {y} {w[x][y]} 1\n' + f.write(line) + extracted_weights[i].append(w[x][y]) + + f.close() + if n_samples_to_plot: + w_to_plot=[w.reshape(Inpute_shape['x'], Inpute_shape['y'], -1)[ :, :, i] for i in range(n_samples_to_plot)] + + img_grid(w_to_plot,(int(math.sqrt(n_samples_to_plot)),int(math.sqrt(n_samples_to_plot)))) + + else: + w=w.reshape(Input_size, Output_size)# 784*400 + X,Y=w.shape + for x in range(X): + for y in range(Y): + if Non_Zero: + if w[x][y]: + line=f'{x} {y} {w[x][y]} 1\n' + f.write(line) + extracted_weights[i].append(w[x][y]) + else: + line=f'{x} {y} {w[x][y]} 1\n' + f.write(line) + extracted_weights[i].append(w[x][y]) + + f.close() + if n_samples_to_plot: + w_to_plot=[w.reshape(Inpute_shape['x'], Inpute_shape['y'], -1)[ :, :, i] for i in range(n_samples_to_plot)] + + img_grid(w_to_plot,(int(math.sqrt(n_samples_to_plot)),int(math.sqrt(n_samples_to_plot)))) + + return extracted_weights + + +def convert_to_latency_code_V4(input_data, tarnsposed=True, samples_intervel=5, time_step=5, num_steps=10):# for CSNN simulation since exracted weights are transposed + + slice_interval=time_step + input_interval=samples_intervel + + number_of_digits=len(input_data) + coded_digits=[] + if tarnsposed: + for i in range(number_of_digits): + s=spikegen.latency((torch.t(input_data[i][0:28,0:28].T/255)).float(),num_steps=num_steps,normalize=True,linear=True)##spikegen.rate((input_data[i][0:28,0:28]/255).float(), num_steps=num_steps) + #print(s) + coded_digits.append(s[:-1]) + else: + for i in range(number_of_digits): + s=spikegen.latency((torch.t(input_data[i][0:28,0:28]/255)).float(),num_steps=num_steps,normalize=True,linear=True)##spikegen.rate((input_data[i][0:28,0:28]/255).float(), num_steps=num_steps) + #print(s) + coded_digits.append(s[:-1]) + + #print(f'coded_digits ={len(coded_digits)}') + current_time=5# 0 will make the strongest vlaue which will spike first to zero + INPUT_SIZE=784 + spikes_time_source_array=[[] for _ in range(INPUT_SIZE)] + with tqdm(total=number_of_digits) as pbar: + for coded_digit_counter,coded_digit in enumerate(coded_digits): + for time_slice_counter, time_slice in enumerate(coded_digit): + timed_flatten_time_slice=time_slice.view(-1)*current_time + #print(timed_flatten_time_slice.shape) + for spike_time_index in torch.nonzero(timed_flatten_time_slice): + spikes_time_source_array[spike_time_index].append(timed_flatten_time_slice[spike_time_index].item()) + current_time+=slice_interval + current_time+=input_interval + pbar.update(1) + return (current_time, spikes_time_source_array) + +#========================================================================================================== extract_wieghts +def extract_wieghts(projection): + return (projection.get(["weight"],"list", with_address=False)) + +#========================================================================================================== extract_synaptic_parameters +def extract_synaptic_parameters(projection): + stored_kernel_connector=projection.get(['weight', 'delay'],"list") + connection_list=[] + for con in stored_kernel_connector: + connection_list.append((con['source'],con['target'],con['weight'],con['delay'])) + return ( sorted(connection_list, key=lambda x: x[1])) # sort it according to index of neurons in the post population + +#========================================================================================================== plot_and_save_grid +def plot_and_save_grid(input_data,nrows_ncols,save=False,file_name=None): + fig = plt.figure(figsize=(10, 10)) + grid = ImageGrid(fig, 111, # similar to subplot(111) + nrows_ncols, # creates nrow x ncol grid of axes + axes_pad=0.1, # pad between axes in inch. + ) + for ax, inx in zip(grid, list(range(nrows_ncols[0]*nrows_ncols[1]))): + ax.imshow(input_data[inx],cmap="jet") + ax.set_axis_off() + if save: + plt.savefig(file_name) + return + +#========================================================================================================== make_population +def make_populations(inupu_spike_train, EXC_POP_SIZE, INH_POP_SIZE): + INPUT_POP = sim.Population(int(INPUT_SIZE), sim.SpikeSourceArray(inupu_spike_train), label="input") + EXC_POP=[] + INH_POP=[] + for exp_pop_number in range(len(EXC_POP_SIZE)): + print(f'exp_pop_number_{exp_pop_number} has {EXC_POP_SIZE[exp_pop_number]} neurons') + EXC_POP.append(sim.Population(int(EXC_POP_SIZE[exp_pop_number]),sim.IF_curr_exp(**excitatory_neuron_parameters), initial_values={'v': excitatory_neuron_parameters["v_rest"]}, label=f"EXC_POP_{exp_pop_number}")) + for inh_pop_number in range(len(INH_POP_SIZE)): + print(f'inh_pop_number_{inh_pop_number} has {INH_POP_SIZE[inh_pop_number]} neurons') + INH_POP.append(sim.Population(int(INH_POP_SIZE[inh_pop_number]),sim.IF_curr_exp(**inhibitory_neuron_parameters), initial_values={'v': inhibitory_neuron_parameters["v_rest"]}, label=f"INH_POP_{inh_pop_number}")) + return INPUT_POP, EXC_POP, INH_POP + +#========================================================================================================== Make Network +def make_projections_from_file(INPUT_POP, EXC_POPs, INH_POPs, FILES): + EXC_EXC_PRJs=[] + EXC_INH_PRJs=[] + INH_EXC_PRJs=[] + + connections_list_from_file=sim.FromFileConnector(FILES[0]) + INPUT_EXC_PRJ=sim.Projection(INPUT_POP, EXC_POPs[0], connections_list_from_file, receptor_type = 'excitatory') + print(f'Porjection from Input ot Excitatory pop_0 is created') + print('============================================================') + + connections_list_from_file=[] + for exc_pop_number, file in enumerate(FILES[1:]): + connections_list_from_file=sim.FromFileConnector(file) + EXC_EXC_PRJs.append(sim.Projection(EXC_POPs[exc_pop_number], EXC_POPs[exc_pop_number+1], connections_list_from_file, receptor_type = 'excitatory')) + print(f'Porjection from Excitatory pop_{exc_pop_number} ot Excitatory pop_{exc_pop_number+1} is created') + print('============================================================') + for inh_pop_number in range(len(INH_POPs)): + EXC_INH_PRJs.append(sim.Projection(EXC_POPs[inh_pop_number], INH_POPs[inh_pop_number], sim.OneToOneConnector(), synapse_type = sim.StaticSynapse(weight=2, delay=1.0),receptor_type = 'excitatory') ) + print(f'Porjection from Excitatory pop_{inh_pop_number} ot Inhibatory pop_{inh_pop_number} is created') + + inhibitory_excitatory_connection_list = [] + for i in range(INH_POP_SIZE[inh_pop_number]): + for j in range(EXC_POP_SIZE[inh_pop_number]): + if not i==j: + inhibitory_excitatory_connection_list.append((i,j)) + print(f'Connection list from Inhibatory_Pop_{inh_pop_number} to Exctatory_Pop_{inh_pop_number} = {INH_POP_SIZE[inh_pop_number]}*{EXC_POP_SIZE[inh_pop_number]}') + INH_EXC_PRJs.append(sim.Projection(INH_POPs[inh_pop_number], EXC_POPs[inh_pop_number], + sim.FromListConnector(inhibitory_excitatory_connection_list), + synapse_type = sim.StaticSynapse(weight=25,delay=1.0), + receptor_type = 'inhibitory')) + + print('============================================================') + + + return INPUT_EXC_PRJ, EXC_EXC_PRJs + +def make_projections_from_file_with_one_shut_inhibitory(INPUT_POP, EXC_POPs, INH_POPs, FILES): + EXC_EXC_PRJs=[] + EXC_INH_PRJs=[] + INH_EXC_PRJs=[] + + connections_list_from_file=sim.FromFileConnector(FILES[0]) + INPUT_EXC_PRJ=sim.Projection(INPUT_POP, EXC_POPs[0], connections_list_from_file, receptor_type = 'excitatory') + print(f'Porjection from Input ot Excitatory pop_0 is created') + print('============================================================') + + connections_list_from_file=[] + for exc_pop_number, file in enumerate(FILES[1:]): + connections_list_from_file=sim.FromFileConnector(file) + EXC_EXC_PRJs.append(sim.Projection(EXC_POPs[exc_pop_number], EXC_POPs[exc_pop_number+1], connections_list_from_file, receptor_type = 'excitatory')) + print(f'Porjection from Excitatory pop_{exc_pop_number} ot Excitatory pop_{exc_pop_number+1} is created') + print('============================================================') + for inh_pop_number in range(len(INH_POPs)): + EXC_INH_PRJs.append(sim.Projection(EXC_POPs[inh_pop_number], INH_POPs[inh_pop_number], sim.OneToOneConnector(), synapse_type = sim.StaticSynapse(weight=50, delay=1.0),receptor_type = 'excitatory') ) + print(f'Porjection from Excitatory pop_{inh_pop_number} ot Inhibatory pop_{inh_pop_number} is created') + + print(f'Connecting ONE SHUT Inhibatory_Pop_{inh_pop_number} to all Exctatory_Pop_{inh_pop_number} = {INH_POP_SIZE[inh_pop_number]}*{EXC_POP_SIZE[inh_pop_number]}') + INH_EXC_PRJs.append(sim.Projection(INH_POPs[inh_pop_number], EXC_POPs[inh_pop_number], + sim.AllToAllConnector(), + synapse_type = sim.StaticSynapse(weight=100,delay=1.0), + receptor_type = 'inhibitory')) + + print('============================================================') + + + return INPUT_EXC_PRJ, EXC_EXC_PRJs + + +#========================================================================================================== Make Network +# run simulator for 'time' and feed SpikeSourceArray with 'spike_list_flatten' +def init_sim(timestep, time_scale_factor, neuron_tpye, number_of_neurons_per_core): + sim.end() + sim.setup(timestep=timestep,time_scale_factor=time_scale_factor)#sim.setup(timestep=1,time_scale_factor=10) + sim.set_number_of_neurons_per_core(neuron_tpye, number_of_neurons_per_core) + return + +def make_network(spikes_list_flatten, EXC_POP_SIZE, INH_POP_SIZE): + INPUT_POP, EXC_POPs, INH_POPs = make_populations(spikes_list_flatten, EXC_POP_SIZE, INH_POP_SIZE) + INPUT_EXC_PRJ, EXC_EXC_PRJs = make_projections_from_file(INPUT_POP, EXC_POPs, INH_POPs, weights_files)#make_projections_2(INPUT_POP) + return (INPUT_POP, EXC_POPs, INH_POPs, INPUT_EXC_PRJ, EXC_EXC_PRJs) + +def record_activities(activities, INPUT_POP, EXC_POPs, INH_POPs): + if INPUT_POP: + INPUT_POP.record(activities[1]) + for i in range(len(EXC_POPs)): + EXC_POPs[i].record(activities) + for i in range(len(INH_POPs)): + INH_POPs[i].record(activities) + return +#================================================== -- GitLab