def test_stimulus_4(self): """Check correct propagation of spikes one layer to the next. Sets up a two layer network with one channel each, and sweeps across various input sizes. """ doPlot = False padding = 'same' bias = 10 vTh = 1 numSteps = (vTh << 6) // bias + 1 + 1 + 1 stepSize = 20 minSize = 60 maxSize = 101 numSizes = (maxSize - minSize) // stepSize sizeY = int(np.sqrt(numSizes)) sizeX = int(np.ceil(numSizes / sizeY)) sizes = range(minSize, maxSize, stepSize) for i, s in enumerate(sizes): inputImage = np.ones((s, s, 2), int) * bias model, vProbes1, uProbes2 = self._setup_2layer_stimulus_net( inputImage, vTh, padding, self.verbose) model.run(numSteps) model.disconnect() outputShape = model.output_shape[1:] data = extract(uProbes2) imgData = _data_to_img(data // 2**6, outputShape) # In center region, 2*9 kernels overlap each pixel self.assertTrue(np.all(imgData[1:-1, 1:-1] == 18)) # Along edges, 2*6 kernels overlap each pixel self.assertTrue(np.all(imgData[1:-1, 0] == 12)) self.assertTrue(np.all(imgData[1:-1, -1] == 12)) self.assertTrue(np.all(imgData[0, 1:-1] == 12)) self.assertTrue(np.all(imgData[-1, 1:-1] == 12)) # In corners, 2*4 kernels overlap each pixel self.assertTrue(np.all(imgData[0, 0] == 8)) self.assertTrue(np.all(imgData[0, -1] == 8)) self.assertTrue(np.all(imgData[-1, 0] == 8)) self.assertTrue(np.all(imgData[-1, -1] == 8)) if doPlot: plt.subplot(sizeY, sizeX, i + 1) plt.title("Size={}".format(s)) plt.imshow(imgData[:, :, 0]) if doPlot: plt.show()
def test_stimulus_1_padding_same(self): """Check correct propagation of spikes one layer to the next. Sets up a two layer network with one channel each. Here we stimulate a single node in input layer and validate excitation of current in feature layer. """ doPlot = False # Configures input layer to produce a single spike that's detected in # output layer padding = 'same' bias = 10 vTh = 1 numSteps = (vTh << 6) // bias + 1 + 1 + 1 # Define size and an arbitrary single pixel stimulus of input layer inputImage = np.zeros((3, 3, 1), int) inputImage[0, 1, 0] = bias # Set up network and run model, vProbes1, uProbes2 = self._setup_2layer_stimulus_net( inputImage, vTh, padding, self.verbose) model.run(numSteps) model.disconnect() # Extract probe data outputShape = model.output_shape[1:] data = extract(uProbes2) imgData = _data_to_img(data // 2**6, outputShape) target = np.asarray([[1, 1, 1], [1, 1, 1], [0, 0, 0]], int) target = np.expand_dims(target, -1) self.assertTrue(np.array_equal(imgData, target)) if doPlot: plt.figure(1) plt.imshow(imgData) plt.figure(2) _plot_stimulus_response(vProbes1, uProbes2) plt.show() print("Hidden layer resourceMap:") print(model.layers[0]._cxResourceMap) print("Output layer resourceMap:") print(model.layers[1]._cxResourceMap)
def test_stimulus_2_padding_valid(self): """Same as test_stimulus_1 but using padding='valid'.""" doPlot = False # Configures input layer to produce a single spike that's detected in # output layer padding = 'valid' bias = 10 vTh = 1 numSteps = (vTh << 6) // bias + 1 + 1 + 1 # Define size and an arbitrary single pixel stimulus of input layer inputImage = np.zeros((8, 8, 1), int) inputImage[1, 3, 0] = bias # Set up network and run model, vProbes1, uProbes2 = self._setup_2layer_stimulus_net( inputImage, vTh, padding, self.verbose) model.run(numSteps) model.disconnect() # Extract probe data outputShape = model.output_shape[1:] data = extract(uProbes2) imgData = _data_to_img(data // 2 ** 6, outputShape) target = np.asarray([[0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], int) target = np.expand_dims(target, -1) self.assertTrue(np.array_equal(imgData, target)) if doPlot: plt.figure(1) plt.imshow(imgData) plt.figure(2) _plot_stimulus_response(vProbes1, uProbes2) plt.show() print("Hidden layer resourceMap:") print(model.layers[0]._cxResourceMap) print("Output layer resourceMap:") print(model.layers[1]._cxResourceMap)
def test_stimulus_3(self): """Check correct propagation of spikes one layer to the next. Sets up a two layer network with one channel each. Here we stimulate a single node in input layer and validate excitation of current in feature layer, by sweeping across a certain patch of the input. """ doPlot = False padding = 'same' bias = 10 vTh = 1 numSteps = (vTh << 6) // bias + 1 + 1 + 1 nY = 45 nX = 5 i = 0 for x in range(nX): for y in range(36, 38): inputImage = np.zeros((nY, nX, 1), int) inputImage[y, x, 0] = bias model, vProbes1, uProbes2 = self._setup_2layer_stimulus_net( inputImage, vTh, padding, self.verbose) model.run(numSteps) model.disconnect() outputShape = model.output_shape[1:] data = extract(uProbes2) imgData = _data_to_img(data // 2**6, outputShape) assert np.max(imgData) == 1, \ "x = {}, y = {}, max = {}".format(x, y, np.max(imgData)) if np.max(imgData) > 1: print("--------------------------------------------------") print("Error for x = {}, y = {}, max = {}".format( x, y, np.max(imgData))) print("--------------------------------------------------") if doPlot: plt.title("x = {}, y = {}".format(x, y)) plt.imshow(imgData[:, :, 0]) plt.show() i += 1
def runModel(model, input_generator, x_test, y_test, spike_probes): """ Runs the model and gets the accuracy :param model: MNIST composable model :param input_generator: Input Generator :param x_test: The test vector :param y_test: The test data labels :param spike_probes: List of Spike Probes created :return: Accuracy """ # Define batch size and number of batches batch_size = 16 num_batches = 8 # Initialize arrays for results num_samples = num_batches * batch_size classifications = np.zeros(num_samples, int) labels = np.zeros(num_samples, int) dts = np.zeros(num_samples) # Classify images x_test_int = (x_test * 255).astype(int) model.board.sync = False t_start_eff = time.time() for b in range(num_batches): print("Batch: {}".format(b)) batch_x_test = x_test_int[b * batch_size:(b + 1) * batch_size] batch_y_test = y_test[b * batch_size:(b + 1) * batch_size] input_generator.batchEncode(batch_x_test) # Run model model.run(num_steps_per_img * batch_size) spike_trains = extract(spike_probes)[-num_steps_per_img * batch_size:] for i, (input_image, target) in enumerate(zip(batch_x_test, batch_y_test)): it = b * batch_size + i # Extract output spike_train = spike_trains[i * \ num_steps_per_img:(i + 1) * num_steps_per_img] spike_count = np.sum(spike_train, 0) classifications[it] = np.argmax(spike_count) labels[it] = np.argmax(target) t_end_eff = time.time() model.disconnect() errors = classifications != labels num_errors = np.sum(errors) return (num_samples - num_errors) / num_samples
def test_NxInputLayer(self): """ Test input layer in soft-reset mode. """ plot = False verbose = False resetMode = 'soft' neuronSize = 2 if resetMode == 'soft' else 1 input_shape = (32, 32, 3) inputSize = np.prod(input_shape) inputLayer = NxInputLayer(input_shape, probeSpikes=True, vThMant=255, resetMode=resetMode) out = inputLayer.input model = NxModel(out, out) model.compile('adam', 'categorical_crossentropy', ['accuracy']) model.summary() layers = [inputLayer] input_image = np.linspace( 0, 256, endpoint=False, num=inputSize).reshape(input_shape).astype(int) x_test = [input_image] y_test = [0] mapper = model.compileModel() if verbose: printLayerMappings(layers, mapper, synapses=True, inputAxons=True) printLayers(layers) layerProbes = [] numProbes = 32 for i, layer in enumerate(layers): shape = layer.output_shape[1:] # Define probes to read out currents. vProbes = [] sProbes = [] uProbes = [] toProbe = numProbes if i == (len(layers) - 1) else numProbes * neuronSize toProbe = min(toProbe, int(np.asscalar(np.prod(shape))) * neuronSize) for j in range(toProbe): vProbes.append(layer[j].probe(ProbableStates.VOLTAGE)) sProbes.append(layer[j].probe(ProbableStates.ACTIVITY)) uProbes.append(layer[j].probe(ProbableStates.CURRENT)) layerProbes.append([uProbes, vProbes, sProbes]) # How many time steps to run each sample. num_steps = 1000 # How many samples to test. num_samples_to_test = 1 # Iterate over samples in testset. for i, (input_image, target) in enumerate(zip(x_test, y_test)): if i == num_samples_to_test: break if plot: plt.hist(input_image.ravel()) plt.show() # Set input bias currents. for j, b in enumerate(np.ravel(input_image, 'F')): inputLayer[j * neuronSize].biasMant = b inputLayer[j * neuronSize].biasExp = 6 inputLayer[j * neuronSize].phase = 2 # Run model. model.run(num_steps) # Clean up. data = [[extract(probe) for probe in lp] for lp in layerProbes] spikesRates = [] for i, (layer, d) in enumerate(zip(layers, data)): sData = d[2][:, (neuronSize - 1)::neuronSize] spikecount = (sData // 127).sum(0) spikesRates.append(spikecount / num_steps) model.disconnect() layer_activations = [x_test[0]] if plot: for activations, spikerate in zip(layer_activations, spikesRates): plt.figure() scale = np.max(activations) spikesFlat = spikerate #spikerate.flatten() plt.plot( activations.flatten('F')[:len(spikesFlat)] / scale, spikesFlat, '.') plotLayerProbes(layers, data, neuronSize) cor = np.corrcoef(np.ravel(spikesRates[-1]), np.ravel(layer_activations[0], 'F')[:numProbes // 2])[0, 1] self.assertGreater(cor, 0.99)
def test_random_cor(self): """ Tests the soft reset mode by comparing activations from an ANN to spike-rate from the converted SNN. The input and weights are randomly initialized. """ seed = 123 np.random.seed(seed) plot = False verbose = False visualizePartitions = False logger = None resetMode = 'soft' neuronSize = 2 if resetMode == 'soft' else 1 inputShape = (4, 4, 1) inputScale = 255 inputImage = np.random.randint(int(inputScale * 0.25), int(inputScale), inputShape) maxNumSpikes = 100 numSteps = int(np.max(inputImage / 255) * maxNumSpikes) inputLayer = NxInputLayer(batch_input_shape=(1, ) + inputShape, vThMant=255, visualizePartitions=visualizePartitions, resetMode=resetMode, probeSpikes=True) out = inputLayer.input layers = [inputLayer] # Conv2D kernelShape = (3, 3, 1) kernelScale = 4 # No need to divide by thrGain because spike input receives equal gain. vThMant = 2**9 - 1 kernel_init = partial(kernel_initializer, kernelScale=kernelScale) numLayers = 1 for i in range(numLayers): layer = NxConv2D(filters=kernelShape[-1], kernel_size=kernelShape[:-1], vThMant=vThMant, kernel_initializer=kernel_init, bias_initializer='ones', validatePartitions=False, probeSpikes=True, activation='relu', resetMode=resetMode) layers.append(layer) out = layer(out) model = NxModel(inputLayer.input, out, logger=logger) for layer in layers[1:]: weights, biases = layer.get_weights() weights, biases = to_integer(weights, biases, 8, np.max(weights) // 2) layer.set_weights([weights, biases]) mapper = model.compileModel() if verbose: printLayerMappings(layers, mapper, synapses=True, inputAxons=True) printLayers(layers) print(model.summary()) layerProbes = [] for layer in layers: shape = layer.output_shape[1:] # Define probes to read out currents. vProbes = [] sProbes = [] uProbes = [] for i in range(int(np.asscalar(np.prod(shape))) * neuronSize): vProbes.append(layer[i].probe(ProbableStates.VOLTAGE)) sProbes.append(layer[i].probe(ProbableStates.ACTIVITY)) uProbes.append(layer[i].probe(ProbableStates.CURRENT)) layerProbes.append([uProbes, vProbes, sProbes]) # Set bias currents for i, b in enumerate(np.ravel(inputImage, 'F')): inputLayer[i * neuronSize].biasMant = b inputLayer[i * neuronSize].phase = 2 if verbose: for layer in layers: print(getCompartmentStates(layer, neuronSize)) model.run(numSteps) if verbose: for layer in layers: print(getCompartmentStates(layer, neuronSize)) model.disconnect() data = [[extract(probe) for probe in lp] for lp in layerProbes] if plot: plotLayerProbes(layers, data, neuronSize) spikesRates = [] for i, (layer, d) in enumerate(zip(layers, data)): sData = d[2][:, (neuronSize - 1)::neuronSize] shape = layer.output_shape[1:] spikecount = _data_to_img(sData // 127, shape) spikesRates.append(spikecount / numSteps) batchInputImage = np.expand_dims(inputImage, 0) activations = model.predict(batchInputImage)[0] if plot: plt.figure() plt.plot(inputImage.flatten(), spikesRates[0].flatten(), '.') plt.show() plt.figure() plt.plot(activations.flatten(), spikesRates[-1].flatten(), '.') plt.show() plt.figure() plt.imshow(normalize_image_dims(activations)) plt.show() plt.figure() plt.imshow(normalize_image_dims(spikesRates[-1])) plt.show() cor = np.corrcoef(np.ravel(spikesRates[-1]), np.ravel(activations))[0, 1] self.assertGreater(cor, 0.99) if verbose: print(cor)
def test_Flatten(self): """Test correlation between ANN activations and SNN spikerates. The network consists of a 3D input layer, followed by a flatten layer, which has 1-to-1 connections to the output layer. The input pixel values are set to ascending integers in Fortran style. This test asserts that the spikerates in the output layer are close to the ANN activations, by computing the Pearson correlation coefficient. A perfect correlation cannot be expected due to quantization errors when approximating ANN activations with discrete spikes. However, correlations should be higher than 0.99. """ visualizePartitions = False doPlot = False # Height, width, depth inputShape = (3, 4, 5) numInputNeurons = int(np.asscalar(np.prod(inputShape))) numOutputNeurons = numInputNeurons - 1 inputScale = 255 thrToInputRatio = 2**7 thrGain = 2**6 # No need to divide by thrGain because spike input receives equal gain. vThMant = 1 vThMantInput = thrToInputRatio * inputScale // thrGain maxNumSpikes = 100 numSteps = thrToInputRatio * maxNumSpikes weights = np.eye(numInputNeurons, numOutputNeurons, dtype=int) biases = np.zeros(numOutputNeurons, int) nxInput = NxInputLayer(inputShape, vThMant=vThMantInput, visualizePartitions=visualizePartitions) nxLayer = NxDense(numOutputNeurons, weights=[weights, biases], vThMant=vThMant, validatePartitions=True, probeSpikes=True) nxModel = NxModel(nxInput.input, nxLayer(NxFlatten()(nxInput.input))) nxModel.compileModel() kerasInput = Input(inputShape) kerasLayer = Dense(numOutputNeurons, weights=[weights, biases])(Flatten()(kerasInput)) kerasModel = Model(kerasInput, kerasLayer) # Define probes to read out currents. sProbes = [] for i in range(numOutputNeurons): sProbes.append(nxLayer[i].probe(ProbableStates.ACTIVITY)) # Set bias currents inputImage = np.reshape(np.arange(numInputNeurons), inputShape, 'F') inputImage = inputImage % 255 for i, b in enumerate(np.ravel(inputImage, 'F')): nxInput[i].biasMant = b nxInput[i].phase = 2 nxModel.run(numSteps) nxModel.disconnect() data = extract(sProbes) spikecount = _data_to_img(data // 127, nxLayer.output_shape[1:]) spikerates = spikecount / numSteps * thrToInputRatio batchInputImage = np.expand_dims(inputImage, 0) activations = \ kerasModel.predict(batchInputImage)[0] / (vThMant * thrGain) if doPlot: plt.figure(3) plt.imshow(normalize_image_dims(inputImage)) plt.show() plt.figure(6) plt.plot(activations.flatten(), spikerates.flatten(), '.') plt.show() plt.figure(7) plt.imshow(normalize_image_dims(activations)) plt.show() plt.figure(8) plt.imshow(normalize_image_dims(spikerates)) plt.show() corr = np.corrcoef(np.ravel(spikerates), np.ravel(activations))[0, 1] self.assertAlmostEqual(corr, 1, 2, msg="Correlation between ANN activations " "and SNN spikerates is too low.")
def test_Conv2DBiases(self): """Test correlation between ANN activations and SNN spikerates. The network consists of an input layer connected to a convolution layer. The input to the network is a square gray-scale image of random integers. The weights are also random integers. Biases are non-zero. This test asserts that the spikerates in the output layer are close to the ANN activations, by computing the Pearson correlation coefficient. A perfect correlation cannot be expected due to quantization errors when approximating ANN activations with discrete spikes. However, correlations should be higher than 0.99. """ def bias_initializer(shape, dtype=None, biasScale=1): """Increasing integer bias initializer for Keras layer. :param list | tuple | np.ndarray shape: Shape of biases. :param str | type | None dtype: Data type of biases. :param int biasScale: Scale factor applied to the biases. :return: Bias tensor. """ return k.constant(np.arange(biasScale), dtype, shape) numFilters = 16 kernelShape = (3, 3) inputShape = (28, 28, 3) vThMant = numFilters * 2**4 thrGain = 2**6 visualizePartitions = False plotUV = False numSteps = 500 bias_init = partial(bias_initializer, biasScale=numFilters) layer = NxConv2D(filters=numFilters, kernel_size=kernelShape, vThMant=vThMant, kernel_initializer='zeros', bias_initializer=bias_init, validatePartitions=True, probeSpikes=True, activation='relu', strides=(2, 2)) inputLayer = NxInputLayer(batch_input_shape=(1, ) + inputShape, vThMant=vThMant, visualizePartitions=visualizePartitions) model = NxModel(inputLayer.input, layer(inputLayer.input)) model.compileModel() outputShape = layer.output_shape[1:] # Define probes to read out currents. vProbes = [] sProbes = [] for i in range(int(np.asscalar(np.prod(outputShape)))): vProbes.append(layer[i].probe(ProbableStates.VOLTAGE)) sProbes.append(layer[i].probe(ProbableStates.ACTIVITY)) model.run(numSteps) model.disconnect() data = extract(sProbes) spikecount = _data_to_img(data // 127, outputShape) spikerates = spikecount / numSteps batchInputImage = np.expand_dims(np.zeros(inputShape), 0) activations = model.predict(batchInputImage)[0] / (vThMant * thrGain) if plotUV: plt.figure(1) _plot_stimulus_response(vProbes, sProbes) plt.show() plt.figure(2) plt.plot(activations.flatten(), spikerates.flatten(), '.') plt.show() plt.figure(3) plt.imshow(normalize_image_dims(activations)) plt.show() plt.figure(4) plt.imshow(normalize_image_dims(spikerates)) plt.show() corr = np.corrcoef(np.ravel(spikerates), np.ravel(activations))[0, 1] self.assertAlmostEqual(corr, 1, 2, msg="Correlation between ANN activations " "and SNN spikerates is too low.")
def runCorrelationRandom(layer, vThMant, insertFlatten=False, inputShape=None, logger=None): """Run network to test correlation between ANN and SNN. :param NxLayer | Layer layer: NxLayer to test. :param int vThMant: Threshold of ``layer``; used to scale activations. :param bool insertFlatten: Whether to flatten input before applying it to ``layer``. :param np.ndarray | tuple | list inputShape: Shape of input to the network. :param logging.Logger logger: Logger. :return: Pearson correlation coefficient of ANN activations and SNN rates. :rtype: float """ seed = 123 np.random.seed(seed) visualizePartitions = False plotUV = False if inputShape is None: inputShape = (7, 7, 1) numInputNeurons = int(np.asscalar(np.prod(inputShape))) inputScale = numInputNeurons - 1 thrToInputRatio = 2**7 thrGain = 2**0 vThMantInput = thrToInputRatio * inputScale // thrGain maxNumSpikes = 100 numSteps = thrToInputRatio * maxNumSpikes inputImage = np.random.randint(0, inputScale, inputShape) inputLayer = NxInputLayer(batch_input_shape=(1, ) + inputShape, vThMant=vThMantInput, visualizePartitions=visualizePartitions) out = layer(NxFlatten()(inputLayer.input)) \ if insertFlatten else layer(inputLayer.input) model = NxModel(inputLayer.input, out, logger=logger) model.compileModel() outputShape = layer.output_shape[1:] # Define probes to read out currents. vProbes0 = [] for i in range(numInputNeurons): vProbes0.append(inputLayer[i].probe(ProbableStates.VOLTAGE)) vProbes = [] sProbes = [] for i in range(int(np.asscalar(np.prod(outputShape)))): vProbes.append(layer[i].probe(ProbableStates.VOLTAGE)) sProbes.append(layer[i].probe(ProbableStates.ACTIVITY)) # Set bias currents for i, b in enumerate(np.ravel(inputImage, 'F')): inputLayer[i].biasMant = b inputLayer[i].phase = 2 model.run(numSteps) model.disconnect() data = extract(sProbes) spikecount = _data_to_img(data // 127, outputShape) spikerates = spikecount / numSteps * thrToInputRatio batchInputImage = np.expand_dims(inputImage, 0) activations = model.predict(batchInputImage)[0] / (vThMant * thrGain) if plotUV: plt.figure(1) _plot_stimulus_response(vProbes0, []) plt.show() plt.figure(2) _plot_stimulus_response(vProbes, sProbes) plt.show() plt.figure(3) plt.imshow(normalize_image_dims(inputImage)) plt.show() plt.figure(6) plt.plot(activations.flatten(), spikerates.flatten(), '.') plt.show() plt.figure(7) plt.imshow(normalize_image_dims(activations)) plt.show() plt.figure(8) plt.imshow(normalize_image_dims(spikerates)) plt.show() return np.corrcoef(np.ravel(spikerates), np.ravel(activations))[0, 1]
def runModelFromConfig(argsInput, argsHidden, argsOutput, n=None): """A helper function used by test_correlationUniform. Given a model configuration, this function creates a NxModel, checks that the model architecture is valid, then partitions, maps and runs the network with a constant white input image. The function probes voltage and current states, which can be plotted. Spikecountss are derived from the current trace.and are used to assert that the SNN activity equals the ANN activations. :param InputParams argsInput: Parameters for input layer. :param LayerParams argsHidden: Parameters for hidden layer. :param LayerParams argsOutput: Parameters for output layer. :param int n: The id of the current config. Only used for printing. """ # Define stimulus and runtime settings. # ##################################### inputScale = 1 vThMantInput = 1 vThMant = 1 numSteps = (vThMantInput << 6) // inputScale + 1 + 1 + 1 + 1 biasExp = 0 visualizePartitions = False plotUV = False # Build model. # ############ inputShape = (argsInput.imgHeight, argsInput.imgWidth, argsInput.imgDepth) batchInputShape = (1, ) + inputShape inputLayer = NxInputLayer(batch_input_shape=batchInputShape, biasExp=biasExp, vThMant=vThMantInput, visualizePartitions=visualizePartitions) inputLayer._maxNumCompartments = argsInput.maxNumCxPerCore hiddenLayer = NxConv2D(argsHidden.kernelDepth, (argsHidden.kernelHeight, argsHidden.kernelWidth), strides=(argsHidden.strideY, argsHidden.strideX), padding=argsHidden.padding, vThMant=vThMant, synapseEncoding=argsHidden.encoding, kernel_initializer='ones', visualizePartitions=visualizePartitions, validatePartitions=True) hiddenLayer._maxNumCompartments = argsHidden.maxNumCxPerCore outputLayer = NxConv2D(argsOutput.kernelDepth, (argsOutput.kernelHeight, argsOutput.kernelWidth), strides=(argsOutput.strideY, argsOutput.strideX), padding=argsOutput.padding, vThMant=vThMant, synapseEncoding=argsOutput.encoding, kernel_initializer='ones', validatePartitions=True) outputLayer._maxNumCompartments = argsOutput.maxNumCxPerCore hiddenShape = hiddenLayer.compute_output_shape(batchInputShape) outputShape = outputLayer.compute_output_shape(hiddenShape) hiddenShape = hiddenShape[1:] outputShape = outputShape[1:] if np.any(np.array(hiddenShape) <= 0) or \ np.any(np.array(outputShape) <= 0): print("Configuration resulted in negative layer shape; skip.") print("Input layer shape: {}".format(inputShape)) print("Hidden layer shape: {}".format(hiddenShape)) print("Output layer shape: {}".format(outputShape)) return # Create NxModel from input to output layer. snn = NxModel(inputLayer.input, outputLayer(hiddenLayer(inputLayer.input)), numCandidatesToCompute=1) snn.compileModel() # Create plain Keras model from input to hidden layer so we # can read out hidden layer activations. model1 = Model(inputLayer.input, hiddenLayer(inputLayer.input)) hiddenInput = Input(hiddenShape) model2 = Model(hiddenInput, outputLayer(hiddenInput)) # Define probes to read out currents. # ################################### u = ProbableStates.CURRENT v = ProbableStates.VOLTAGE uProbes1 = [] vProbes1 = [] for i in range(int(np.asscalar(np.prod(hiddenShape)))): uProbes1.append(hiddenLayer[i].probe(u)) if plotUV: vProbes1.append(hiddenLayer[i].probe(v)) uProbes2 = [] vProbes2 = [] for i in range(int(np.asscalar(np.prod(outputShape)))): uProbes2.append(outputLayer[i].probe(u)) if plotUV: vProbes2.append(outputLayer[i].probe(v)) # Apply input image via bias currents. # #################################### inputImage = inputScale * np.ones(inputShape, int) for i, biasMant in enumerate(np.ravel(inputImage, 'F')): inputLayer[i].biasMant = biasMant inputLayer[i].phase = 2 # Run model. # ########## snn.run(numSteps) snn.disconnect() # Get SNN spike counts. data1 = extract(uProbes1) spikecount1 = _data_to_img(data1 // (vThMant * 2**6), hiddenShape) data2 = extract(uProbes2) spikecount2 = _data_to_img(data2 // (vThMant * 2**6), outputShape) # Get ANN activations as target reference. batchInputImage = np.expand_dims(inputImage, 0) activations1 = model1.predict(batchInputImage) activations2 = model2.predict(activations1 > 0) # Remove batch dim. activations1 = activations1[0].astype(int) activations2 = activations2[0].astype(int) # Plotting. # ######### if plotUV: plt.figure() _plot_stimulus_response(vProbes1, uProbes1) plt.show() plt.figure() _plot_stimulus_response(vProbes2, uProbes2) plt.show() # Validation. # ########### def getErrorMessage(spikecounts, activations): """Generate an error message for failed test. The error message contains a code snippet to reproduce failure. :param np.ndarray spikecounts: SNN spike counts of layer. :param np.ndarray activations: ANN activations of layer. :return: Error message. :rtype: str """ return ("SNN spikecounts not equal to ANN activations.\n" + "Spikecounts: \n{}\n\n".format(spikecounts) + "Activations: \n{}\n\n".format(activations) + "Use the following code to reproduce the error.\n\n" + "def test_correlation{}():\n".format('' if n is None else n) + "\targsInput = {}\n".format(argsInput) + "\targsHidden = {}\n".format(argsHidden) + "\targsOutput = {}\n".format(argsOutput) + "\trunModelFromConfig(argsInput, argsHidden, argsOutput)\n\n") assert np.array_equal(spikecount1, activations1), \ getErrorMessage(spikecount1, activations1) assert np.array_equal(spikecount2, activations2), \ getErrorMessage(spikecount2, activations2)