def setup_layers(self, batch_shape): '''Iterates over all layers to instantiate them in the simulator.''' self.add_input_layer(batch_shape) for layer in self.parsed_model.layers[1:]: print("Instantiating layer: {}".format(layer.name)) self.add_layer(layer) layer_type = get_type(layer) print("Building layer: {}".format(layer.name)) if layer_type == 'Flatten': self.flatten_shapes.append( (layer.name, get_shape_from_label(self.layers[-1].label))) self.build_flatten(layer) continue if layer_type in {'Dense', 'Sparse'}: self.build_dense(layer) elif layer_type in { 'Conv1D', 'Conv2D', 'DepthwiseConv2D', 'SparseConv2D', 'SparseDepthwiseConv2D' }: self.build_convolution(layer) self.data_format = layer.data_format elif layer_type in {'MaxPooling2D', 'AveragePooling2D'}: self.build_pooling(layer) elif layer_type == 'ZeroPadding': padding = layer.padding if set(padding).issubset((1, (1, 1))): self.change_padding = True return else: raise NotImplementedError( "Border_mode {} not supported.".format(padding))
def add_layer(self, layer): from snntoolbox.parsing.utils import get_type spike_layer_name = getattr(self.sim, 'Spike' + get_type(layer)) # noinspection PyProtectedMember inbound = [self._spiking_layers[inb.name] for inb in layer._inbound_nodes[0].inbound_layers] if len(inbound) == 1: inbound = inbound[0] layer_kwargs = layer.get_config() layer_kwargs['config'] = self.config # Check if layer uses binary activations. In that case, we will want to # tell the following to MaxPool layer because then we can use a # cheaper operation. if 'Conv' in layer.name and 'binary' in layer.activation.__name__: self._binary_activation = layer.activation.__name__ if 'MaxPool' in layer.name and self._binary_activation is not None: layer_kwargs['activation'] = self._binary_activation self._binary_activation = None # Replace activation from kwargs by 'linear' before initializing # superclass, because the relu activation is applied by the spike- # generation mechanism automatically. In some cases (quantized # activation), we need to apply the activation manually. This # information is taken from the 'activation' key during conversion. activation_str = str(layer_kwargs.pop(str('activation'), None)) spike_layer = spike_layer_name(**layer_kwargs) spike_layer.activation_str = activation_str self._spiking_layers[layer.name] = spike_layer(inbound)
def load(self, path, filename): dirpath = os.path.join(path, filename, 'brian2-model') npz_files = [f for f in sorted(os.listdir(dirpath)) if os.path.isfile(os.path.join(dirpath, f))] print("Loading spiking model...") self.parsed_model = load_model( os.path.join(self.config.get('paths', 'path_wd'), self.config.get('paths', 'filename_parsed_model') + '.h5')) self.num_classes = int(self.parsed_model.layers[-1].output_shape[-1]) self.top_k = min(self.num_classes, self.config.getint('simulation', 'top_k')) # Get batch input shape batch_shape = list(self.parsed_model.layers[0].batch_input_shape) batch_shape[0] = self.batch_size if self.config.get('conversion', 'spike_code') == 'ttfs_dyn_thresh': batch_shape[0] *= 2 self.add_input_layer(batch_shape) # Iterate over layers to create spiking neurons and connections. for layer, f in zip(self.parsed_model.layers[1:], npz_files): print("Building layer: {}".format(layer.name)) self.add_layer(layer) layer_type = get_type(layer) filepath = os.path.join(dirpath, f) print("Using layer-weights stored in: {}".format(filepath)) print("Loading stored weights...") input_file = np.load(filepath) weights = input_file['arr_0'] if layer_type == 'Dense': self.build_dense(layer, weights=weights) elif layer_type == 'Conv2D': self.build_convolution(layer, weights=weights) if layer.data_format == 'channels_last': self.data_format = layer.data_format elif layer_type in {'MaxPooling2D', 'AveragePooling2D'}: self.build_pooling(layer, weights=weights) elif layer_type == 'Flatten': self.build_flatten(layer) print("Compiling spiking model...\n") self.compile() # Compute number of operations of ANN. if self.fanout is None: self.set_connectivity() self.operations_ann = get_ann_ops(self.num_neurons, self.num_neurons_with_bias, self.fanin) print("Number of operations of ANN: {}".format( self.operations_ann)) print("Number of neurons: {}".format(sum(self.num_neurons[1:]))) print("Number of synapses: {}\n".format(self.num_synapses)) self.is_built = True
def get_type(self, layer): from snntoolbox.parsing.utils import get_type return get_type(layer)
def build_convolution(self, layer): # If the parsed model contains a ZeroPadding layer, we need to tell the # Conv layer about it here, because ZeroPadding layers are removed when # building the pyNN model. if self.change_padding: if layer.padding == 'valid': self.change_padding = False layer.padding = 'ZeroPadding' else: raise NotImplementedError( "Border_mode {} in combination with ZeroPadding is not " "supported.".format(layer.padding)) delay = self.config.getfloat('cell', 'delay') transpose_kernel = \ self.config.get('simulation', 'keras_backend') == 'tensorflow' if get_type(layer) in ['Conv2D', 'SparseConv2D']: weights, biases = build_convolution(layer, delay, transpose_kernel) elif get_type(layer) in ['DepthwiseConv2D', 'SparseDepthwiseConv2D']: weights, biases = build_depthwise_convolution( layer, delay, transpose_kernel) elif get_type(layer) == 'Conv1D': weights, biases = build_1d_convolution(layer, delay) else: ValueError("Layer {} of type {} unrecognised here. " "How did you get into this function?".format( layer.name, get_type(layer))) self.set_biases(biases) weights = self.scale_weights(weights) exc_connections = [c for c in weights if c[2] > 0] inh_connections = [c for c in weights if c[2] < 0] if self.config.getboolean('tools', 'simulate'): self.connections.append( self.sim.Projection( self.layers[-2], self.layers[-1], (self.sim.FromListConnector( exc_connections, ['weight', 'delay'])), receptor_type='excitatory', label=self.layers[-1].label + '_excitatory')) self.connections.append( self.sim.Projection( self.layers[-2], self.layers[-1], (self.sim.FromListConnector( inh_connections, ['weight', 'delay'])), receptor_type='inhibitory', label=self.layers[-1].label + '_inhibitory')) else: # The spinnaker implementation of Projection.save() is not working # yet, so we do save the connections manually here. filepath = os.path.join(self.config.get('paths', 'path_wd'), self.layers[-1].label) # noinspection PyTypeChecker np.savetxt(filepath + '_excitatory', np.array(exc_connections), ['%d', '%d', '%.18f', '%.3f'], header="columns = ['i', 'j', 'weight', 'delay']") # noinspection PyTypeChecker np.savetxt(filepath + '_inhibitory', np.array(inh_connections), ['%d', '%d', '%.18f', '%.3f'], header="columns = ['i', 'j', 'weight', 'delay']")
def get_type(self, layer): return get_type(layer)