def test_saveLoadNxModel(self): """Check that NxModel can be saved and loaded like a Keras Model.""" inputLayer = NxInputLayer(batch_input_shape=(1, 10, 10, 3)) layer = NxConv2D(2, 3)(inputLayer.input) model1 = NxModel(inputLayer.input, layer) model1.compile('sgd', 'mse') model1.compileModel() model1.clearTemp() filename = os.path.abspath( os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../..', 'temp', str(hash(model1)))) model1.save(filename) model2 = loadNxModel(filename) os.remove(filename) x = np.random.random_sample(model1.input_shape) y1 = model1.predict(x) y2 = model2.predict(x) self.assertTrue(np.array_equal(y1, y2))
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 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 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]