Пример #1
0
    def run_sim(self):
        """
        Sets up and runs the simulation
        """
        num_neurons = 1471  # total neurons in network
        num_inputs = 14     # number of neurons considered inputs
        num_runs = 1        # number of times to loop the learning
        num_samples = 1     # number of samples to learn`
        sim_time = 1000.0    # time to run sim for`
        inhibitory_split = 0.2
        connection_probability_factor = 0.02
        plot_spikes = True
        save_figures = True
        show_figures = True
        sim_start_time = strftime("%Y-%m-%d_%H:%M")

        cell_params_lif = {'cm': 0.25, 'i_offset': 0.0, 'tau_m': 10.0, 'tau_refrac': 2.0, 'tau_syn_E': 3.0,
                           'tau_syn_I': 3.0, 'v_reset': -65.0, 'v_rest': -65.0, 'v_thresh': -50.0}

        # Create the 3d structure of the NeuCube based on the user's given structure file
        network_structure = NetworkStructure()
        network_structure.load_structure_file()
        network_structure.load_input_location_file()
        # Calculate the inter-neuron distance to be used in the small world connections
        network_structure.calculate_distances()
        # Generate two connection matrices for excitatory and inhibitory neurons based on your defined split
        network_structure.calculate_connection_matrix(inhibitory_split, connection_probability_factor)
        # Get these lists to be used when connecting the neurons later
        excitatory_connection_list = network_structure.get_excitatory_connection_list()
        inhibitory_connection_list = network_structure.get_inhibitory_connection_list()
        # Choose the correct neurons to connect them to, based on your a-priori knowledge of the data source -- eg, EEG
        # to 10-20 locations, fMRI to voxel locations, etc.
        input_neuron_indexes = network_structure.find_input_neurons()
        # Make the input connections based on this new list
        input_weight = 4.0
        input_connection_list = []
        for index, input_neuron_index in enumerate(input_neuron_indexes):
            input_connection_list.append((index, input_neuron_index, input_weight, 0))

        for run_number in xrange(num_runs):
            excitatory_weights = []
            inhibitory_weights = []
            for sample_number in xrange(num_samples):
                # At the moment with the limitations of the SpiNNaker hardware we have to reinstantiate EVERYTHING
                # each run. In future there will be some form of repetition added, where the structure stays in memory
                # on the SpiNNaker and only the input spikes need to be updated.

                data_prefix = sim_start_time + "_r" + str(run_number + 1) + "-s" + str(sample_number + 1)

                # Set up the hardware - min_delay should never be less than the timestep.
                # Timestep should = 1.0 (ms) for normal realtime applications
                p.setup(timestep=1.0, min_delay=1.0)
                p.set_number_of_neurons_per_core("IF_curr_exp", 100)

                # Create a population of neurons for the reservoir
                neurons = p.Population(num_neurons, p.IF_curr_exp, cell_params_lif, label="Reservoir")

                # Setup excitatory STDP
                timing_rule_ex = p.SpikePairRule(tau_plus=20.0, tau_minus=20.0)
                weight_rule_ex = p.AdditiveWeightDependence(w_min=0.1, w_max=1.0, A_plus=0.02, A_minus=0.02)
                stdp_model_ex  = p.STDPMechanism(timing_dependence=timing_rule_ex, weight_dependence=weight_rule_ex)
                # Setup inhibitory STDP
                timing_rule_inh = p.SpikePairRule(tau_plus=20.0, tau_minus=20.0)
                weight_rule_inh = p.AdditiveWeightDependence(w_min=0.0, w_max=0.6, A_plus=0.02, A_minus=0.02)
                stdp_model_inh  = p.STDPMechanism(timing_dependence=timing_rule_inh, weight_dependence=weight_rule_inh)

                # record the spikes from that population
                neurons.record('spikes')

                # Generate a population of SpikeSourceArrays containing the encoded input spike data
                # eg. spike_sources = p.Population(14, p.SpikeSourceArray, {'spike_times': [[]]})
                # for the moment I'm going to cheat and just use poisson trains as I don't have data with me
                spike_sources = p.Population(num_inputs, p.SpikeSourcePoisson, {'rate': rand.randint(20, 80)},
                                             label="Poisson_pop_E")

                # Connect the input spike sources with the "input" neurons
                connected_inputs = p.Projection(spike_sources, neurons, p.FromListConnector(input_connection_list))

                # If we have weights saved/recorded from a previous run of this network, load them into the structure
                # population.set(weights=weights_list) and population.setWeights(weight_list) are not supported in
                # SpiNNaker at the moment so we have to do this manually.
                if excitatory_weights and inhibitory_weights:
                    for index, ex_connection in enumerate(excitatory_connection_list):
                        ex_connection[2] = excitatory_weights[index]
                    for index, in_connection in enumerate(inhibitory_connection_list):
                        in_connection[2] = inhibitory_weights[index]

                # Setup the connectors
                excitatory_connector = p.FromListConnector(excitatory_connection_list)
                inhibitory_connector = p.FromListConnector(inhibitory_connection_list)

                # Connect the excitatory and inhibitory neuron populations
                connected_excitatory_neurons = p.Projection(neurons, neurons, excitatory_connector,
                                                            synapse_dynamics=p.SynapseDynamics(slow=stdp_model_ex),
                                                            target="excitatory")
                connected_inhibitory_neurons = p.Projection(neurons, neurons, inhibitory_connector,
                                                            synapse_dynamics=p.SynapseDynamics(slow=stdp_model_inh),
                                                            target="inhibitory")

                # Set up recording the spike trains of all the neurons
                neurons.record()
                spike_sources.record()

                # Run the actual simulation
                p.run(sim_time)

                # Save the output spikes
                spikes_out = neurons.getSpikes(compatible_output=True)
                input_spikes_out = spike_sources.getSpikes(compatible_output=True)
                # Get the synaptic weights of all the neurons
                excitatory_weights = connected_excitatory_neurons.getWeights()
                inhibitory_weights = connected_inhibitory_neurons.getWeights()

                # when we're all done, clean up
                p.end()

                # Make some plots, save them if required. Check if you need to either save or show them, because if not,
                # there's no point wasting time plotting things nobody will ever see.
                if plot_spikes and (save_figures or show_figures):
                    plot = Plot(save_figures, data_prefix)
                    # Plot the 3D structure of the network
                    plot.plot_structure(network_structure.get_positions(), figure_number=0)
                    # Plot the spikes
                    plot.plot_spike_raster(spikes_out, sim_time, num_neurons, figure_number=1)
                    # Plot the weights
                    plot.plot_both_weights(excitatory_weights, inhibitory_weights, figure_number=2)
                    # If we want to show the figures, show them now, otherwise ignore and move on
                    if show_figures:
                        # Show them all at once
                        plot.show_plots()
                    plot.clear_figures()
                    plot = None