예제 #1
0
    def test_getMultiplicityMap(self):
        """Test generating a multiplicity map from a coreIdMap."""

        inputShape = (10, 10, 2)
        inputLayer = NxInputLayer(inputShape)
        layer = NxConv2D(2, 3)
        layer(inputLayer.input)

        coreShape = np.array([4, 3, 2])
        layerShape = layer.output_shape[1:]
        numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int)
        coreIdMap = getCoreIdMapFromCoreShape(coreShape, layerShape,
                                              numCoresPerAxis)
        multiplicityMap = layer.getMultiplicityMap(coreIdMap)

        if self.verbose:
            plotMat(multiplicityMap, title='MultiplicityMap')

        target = [[1, 1, 1, 2, 2, 1, 2, 2, 1,
                   1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1],
                  [1, 1, 1, 2, 2, 1, 2, 2, 1,
                   1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1],
                  [2, 2, 2, 4, 4, 2, 4, 4, 2,
                   2], [2, 2, 2, 4, 4, 2, 4, 4, 2, 2],
                  [1, 1, 1, 2, 2, 1, 2, 2, 1,
                   1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1],
                  [1, 1, 1, 2, 2, 1, 2, 2, 1, 1],
                  [1, 1, 1, 2, 2, 1, 2, 2, 1, 1]]

        self.assertTrue(np.array_equal(multiplicityMap, target))
예제 #2
0
    def test_partitionModel3(self):
        """Test partitioning of a NxModel.

        After completion of the algorithm, the partitioner reconstructs the
        kernelIdMap from the synapses and axons generated during partitioning.
        An exception is thrown if the reconstructed map does not equal the
        original map.
        """

        inputShape = (73, 81, 3)
        inputLayer = NxInputLayer(inputShape)
        hiddenLayer = NxConv2D(11,
                               3,
                               strides=(2, 2),
                               padding='same',
                               validatePartitions=True)(inputLayer.input)
        hiddenLayer = NxAveragePooling2D(4,
                                         validatePartitions=True)(hiddenLayer)
        hiddenLayer = NxFlatten()(hiddenLayer)
        outputLayer = NxDense(50, validatePartitions=True)(hiddenLayer)

        model = NxModel(inputLayer.input, outputLayer)

        model.partition()

        model.clearTemp()
예제 #3
0
    def test_synMem2(self):
        """Test issue where nxcompiler runs out of synMem.

        The problem is that whenever the number of syn bits is an exact
        multiple of 64, nxcompiler requires an extra mem word. E.g. 128 bits
        would count as 3 words.

        We have implemented a check in the NxTF compiler that allocates an
        extra mem word when it detects that the numBits are an exact multiple
        of 64. So this test should pass.
        """

        inputLayer = NxInputLayer((1, 1, 1))
        x = NxConv2D(6, (1, 1),
                     name='conv1',
                     kernel_initializer='ones',
                     synapseEncoding='dense1',
                     useSharedSign=False)(inputLayer.input)
        model = NxModel(inputLayer.input, x, saveOutput=False)
        model.compileModel()
        model.run(1)
        model.disconnect()

        layers = model.partitionOptimizer.getLayers()
        assert layers[1].numSynMemWords == 2
예제 #4
0
    def test_synMem(self):
        """Test issue where nxcompiler runs out of synMem.

        The problem is that whenever the number of syn bits is an exact
        multiple of 64, nxcompiler requires an extra mem word. E.g. 128 bits
        would count as 3 words.

        Normally, this test would fail due to an assertion in the nxcompiler
        that checks for number of syn mem words to be smaller than 2**14.

        We have implemented a check in the NxTF compiler that allocates an
        extra mem word when it detects that the numBits are an exact multiple
        of 64. So this test should pass.
        """

        np.random.seed(123)
        inputLayer = NxInputLayer((1, 1, 256))

        x = NxConv2D(256, (1, 1), name='conv1')(inputLayer.input)

        model = NxModel(inputLayer.input, x)

        model.compileModel()
        model.run(1)
        model.disconnect()
예제 #5
0
    def test_Conv2D(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 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.
        """

        kernelShape = (3, 3, 1)
        kernelScale = 10
        # No need to divide by thrGain because spike input receives equal gain.
        vThMant = int(np.asscalar(np.prod(kernelShape))) * kernelScale

        kernel_init = partial(kernel_initializer, kernelScale=kernelScale)

        layer = NxConv2D(
            filters=kernelShape[-1], kernel_size=kernelShape[:-1],
            vThMant=vThMant, kernel_initializer=kernel_init,
            bias_initializer='zeros', validatePartitions=True,
            probeSpikes=True, activation='relu')

        corr = runCorrelationRandom(layer, vThMant)

        self.assertAlmostEqual(corr, 1, 2,
                               msg="Correlation between ANN activations "
                                   "and SNN spikerates is too low.")
예제 #6
0
    def test_compileNxModel(self):
        """Check that NxModel can be compiled with Keras."""

        inputShape = (7, 7, 1)
        inputLayer = NxInputLayer(inputShape)
        outputLayer = NxConv2D(2, 3)(inputLayer.input)
        model = NxModel(inputLayer.input, outputLayer)
        model.clearTemp()
예제 #7
0
    def _setup_2layer_stimulus_net(inputImage,
                                   vTh,
                                   padding='same',
                                   verbose=False):
        """Helper method to set up a 2-layer CNN.

        The output layer has a single kernel with all weights equal to 1.
        """

        assert isinstance(inputImage, np.ndarray)

        inputShape = inputImage.shape

        inputLayer = NxInputLayer(inputShape,
                                  vThMant=vTh,
                                  biasExp=0,
                                  visualizePartitions=False)
        outputLayer = NxConv2D(filters=1,
                               kernel_size=3,
                               padding=padding,
                               vThMant=1000,
                               weightExponent=0,
                               synapseEncoding='sparse',
                               kernel_initializer='ones',
                               bias_initializer='zeros',
                               visualizePartitions=False)

        model = NxModel(inputLayer.input,
                        outputLayer(inputLayer.input),
                        numCandidatesToCompute=1)

        mapper = model.compileModel()

        if verbose:
            hiddenCore = model.board.n2Chips[0].n2CoresAsList[1]
            outputCore = model.board.n2Chips[0].n2CoresAsList[0]

            mapper.printCore(hiddenCore, compartments=True)
            mapper.printCore(outputCore, compartments=True)

        outputShape = model.output_shape[1:]

        # Define probes to read out current and voltages
        vProbes1 = []
        uProbes2 = []
        for i in range(int(np.asscalar(np.prod(inputShape)))):
            vProbes1.append(inputLayer[i].probe(state=ProbableStates.VOLTAGE))
        for i in range(int(np.asscalar(np.prod(outputShape)))):
            uProbes2.append(outputLayer[i].probe(state=ProbableStates.CURRENT))

        # Set bias currents
        for i, b in enumerate(np.ravel(inputImage, 'F')):
            inputLayer[i].biasMant = b
            inputLayer[i].phase = 2

        return model, vProbes1, uProbes2
def create_snn_model():
    """
    Create a Spiking Model of the MNIST dnn
    :return: Spiking Model
    """
    vth_mant = 2**9
    bias_exp = 6
    weight_exponent = 0
    synapse_encoding = 'sparse'

    inputLayer = NxInputLayer(input_shape, vThMant=vth_mant, biasExp=bias_exp)

    layer = NxConv2D(filters=16,
                     kernel_size=(5, 5),
                     strides=(2, 2),
                     input_shape=input_shape,
                     vThMant=vth_mant,
                     weightExponent=weight_exponent,
                     synapseEncoding=synapse_encoding)(inputLayer.input)
    layer = NxConv2D(filters=32,
                     kernel_size=(3, 3),
                     vThMant=vth_mant,
                     weightExponent=weight_exponent,
                     synapseEncoding=synapse_encoding)(layer)
    layer = NxConv2D(filters=64,
                     kernel_size=(3, 3),
                     strides=(2, 2),
                     vThMant=vth_mant,
                     weightExponent=weight_exponent,
                     synapseEncoding=synapse_encoding)(layer)
    layer = NxConv2D(filters=10,
                     kernel_size=(4, 4),
                     activation='softmax',
                     vThMant=vth_mant,
                     weightExponent=weight_exponent,
                     synapseEncoding=synapse_encoding)(layer)

    spiking_model = NxModel(inputLayer.input, layer, numCandidatesToCompute=1)

    spiking_model.summary()
    return spiking_model
예제 #9
0
    def test_compile(self):
        """Check compilation of NxModel and retrieval of cxResourceMap."""

        # Create an arbitrary model
        inputShape = (31, 35, 2)
        inputLayer = NxInputLayer(inputShape)
        hiddenLayer = NxConv2D(4, 3)
        outputLayer = NxConv2D(7, 3)
        model = NxModel(inputLayer.input,
                        outputLayer(hiddenLayer(inputLayer.input)),
                        numCandidatesToCompute=1)

        model.compileModel()

        if self.verbose:
            hiddenLayer.exclusionCriteria.print()
            outputLayer.exclusionCriteria.print()

            for l in model.layers:
                if isinstance(l, NxConv2D):
                    print(l._cxResourceMap)
예제 #10
0
    def test_evaluateNxModel(self):
        """Check that NxModel can be evaluated like a Keras Model."""

        batchSize = 10
        batchInputShape = (batchSize, 7, 7, 1)
        inputLayer = NxInputLayer(batch_input_shape=batchInputShape)
        layer = NxConv2D(2, 3)(inputLayer.input)
        model = NxModel(inputLayer.input, layer)

        model.compile('sgd', 'mse')
        model.evaluate(np.random.random_sample(model.input_shape),
                       np.random.random_sample(model.output_shape))
        model.clearTemp()
예제 #11
0
    def test_partitionModel2(self):
        """Test partitioning of a NxModel.

        After completion of the algorithm, the partitioner reconstructs the
        kernelIdMap from the synapses and axons generated during partitioning.
        An exception is thrown if the reconstructed map does not equal the
        original map.
        """

        inputShape = (2, 2, 128)
        inputLayer = NxInputLayer(inputShape)
        hiddenLayer = NxConv2D(128, 2, padding='same', validatePartitions=True)
        hiddenLayer.exclusionCriteria.maxNumCompartments /= 4
        outputLayer = NxConv2D(256, 3, padding='same', validatePartitions=True)
        outputLayer.exclusionCriteria.maxNumCompartments /= 4

        model = NxModel(inputLayer.input,
                        outputLayer(hiddenLayer(inputLayer.input)))

        model.partition()

        model.clearTemp()
예제 #12
0
    def test_getCoreIdMapFromCoreShape2(self):
        """Test generating the coreIdMap given a coreShape."""

        inputShape = (4, 4, 2)
        inputLayer = NxInputLayer(inputShape)
        layer = NxConv2D(2, 3)
        layer(inputLayer.input)

        coreShape = np.array([2, 1, 2])
        layerShape = layer.output_shape[1:]
        numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int)
        coreIds = getCoreIdMapFromCoreShape(coreShape, layerShape,
                                            numCoresPerAxis)
        target = np.array([[[0, 0], [1, 1]], [[0, 0], [1, 1]]])
        self.assertTrue(np.array_equal(coreIds, target))

        if self.verbose:
            plotMat(coreIds[:, :, 0], title='coreIds[:, :, 0]')
            plotMat(coreIds[:, :, 1], title='coreIds[:, :, 1]')
예제 #13
0
    def setUpDNN(self) -> ComposableDNN:
        """Sets up a DNN"""
        # Specify input shape of network.
        inputShape = (16, 16, 3)

        #################
        # BUILD NETWORK #
        #################

        inputLayer = NxInputLayer(inputShape)

        x = NxConv2D(4, (3, 3))(inputLayer.input)
        x = NxAveragePooling2D()(x)
        x = NxFlatten()(x)
        x = NxDense(10)(x)

        DNNModel = NxModel(inputLayer.input, x)

        composableDNNModel = ComposableDNN(model=DNNModel, num_steps_per_img=100)
        return composableDNNModel
예제 #14
0
    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))
예제 #15
0
    def test_CompartmentInterface_probe(self):
        """Check probe generation."""

        # Create an arbitrary model
        inputShape = (16, 16, 1)
        inputLayer = NxInputLayer(inputShape)
        outputLayer = NxConv2D(1, 3, padding='same', validatePartitions=True)
        model = NxModel(inputLayer.input,
                        outputLayer(inputLayer.input),
                        numCandidatesToCompute=3)

        model.compileModel()

        uProbe = outputLayer[0].probe(ProbableStates.CURRENT)
        sProbe = outputLayer[0].probe(ProbableStates.SPIKE)
        aProbe = outputLayer[0].probe(ProbableStates.ACTIVITY)
        pProbe = outputLayer[2].probe(ProbableStates.PHASE)

        self.assertTrue(isinstance(uProbe, N2Probe))
        self.assertTrue(isinstance(sProbe, N2SpikeProbe))
        self.assertTrue(isinstance(aProbe, N2Probe))
        self.assertTrue(isinstance(pProbe, N2Probe))

        self.assertEqual(uProbe.chipId, outputLayer._cxResourceMap[0, 0])
        self.assertEqual(uProbe.coreId, outputLayer._cxResourceMap[0, 1])
        self.assertEqual(uProbe.nodeId, outputLayer._cxResourceMap[0, 2])

        self.assertEqual(sProbe.chipId, outputLayer._cxResourceMap[0, 0])
        self.assertEqual(sProbe.coreId, outputLayer._cxResourceMap[0, 1])
        self.assertEqual(sProbe.cxId, outputLayer._cxResourceMap[0, 2])

        self.assertEqual(aProbe.chipId, outputLayer._cxResourceMap[0, 0])
        self.assertEqual(aProbe.coreId, outputLayer._cxResourceMap[0, 1])
        self.assertEqual(aProbe.nodeId, outputLayer._cxResourceMap[0, 2])

        self.assertEqual(pProbe.chipId, outputLayer._cxResourceMap[2, 0])
        self.assertEqual(pProbe.coreId, outputLayer._cxResourceMap[2, 1])
        self.assertEqual(pProbe.nodeId, outputLayer._cxResourceMap[2, 2] // 4)
예제 #16
0
    def test_setter_getter(self):
        """Check setter and getter methods of CompartmentInterface."""

        # Create an arbitrary model
        inputShape = (16, 16, 1)
        inputLayer = NxInputLayer(inputShape)
        outputLayer = NxConv2D(1, 3, padding='same', validatePartitions=True)
        model = NxModel(inputLayer.input,
                        outputLayer(inputLayer.input),
                        numCandidatesToCompute=3)

        model.compileModel()

        # Set ome arbitrary values
        outputLayer[0].current = 1
        outputLayer[0].voltage = 2
        outputLayer[0].activity = 3
        outputLayer[0].biasMant = 4
        outputLayer[0].biasExp = 5
        outputLayer[0].phase = 1
        outputLayer[1].phase = 2
        outputLayer[2].phase = 3
        outputLayer[3].phase = 4
        outputLayer[4].phase = 5

        # Check values
        self.assertEqual(outputLayer[0].current, 1)
        self.assertEqual(outputLayer[0].voltage, 2)
        self.assertEqual(outputLayer[0].activity, 3)
        self.assertEqual(outputLayer[0].biasMant, 4)
        self.assertEqual(outputLayer[0].biasExp, 5)
        self.assertEqual(outputLayer[0].phase, 1)
        self.assertEqual(outputLayer[1].phase, 2)
        self.assertEqual(outputLayer[2].phase, 3)
        self.assertEqual(outputLayer[3].phase, 4)
        self.assertEqual(outputLayer[4].phase, 5)
예제 #17
0
    def test_partitionModel4(self):
        """Test partitioning of a NxModel.

        After completion of the algorithm, the partitioner reconstructs the
        kernelIdMap from the synapses and axons generated during partitioning.
        An exception is thrown if the reconstructed map does not equal the
        original map.
        """

        inputShape = (15, 15, 3)
        inputLayer = NxInputLayer(inputShape)
        outputLayer = NxConv2D(3,
                               3,
                               strides=(2, 2),
                               padding='same',
                               validatePartitions=True)(inputLayer.input)

        model = NxModel(inputLayer.input,
                        outputLayer,
                        numCandidatesToCompute=10)

        model.partition()

        model.clearTemp()
예제 #18
0
    def test_compressConnections(self):
        """Check axon compression."""

        inputShapes = np.array([[7, 7, 2], [32, 32, 3],
                                [32, 32, 3], [27, 26, 2], [32, 30, 2],
                                [30, 35, 2], [7, 7, 2], [20, 25, 2], [7, 7, 2],
                                [30, 35, 2], [7, 7, 2], [30, 35, 2]])

        layerArgs = np.array([[2, 3], [2, 3], [2, 3], [2, 1], [2, 2], [2, 3],
                              [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3]])

        layerKwargs = np.array([
            {
                'synapseEncoding': 'sparse'
            },
            {
                'synapseEncoding': 'sparse'
            },
            {
                'synapseEncoding': 'sparse',
                'strides': 2
            },
            {
                'synapseEncoding': 'sparse',
                'strides': 2
            },
            {
                'synapseEncoding': 'sparse',
                'strides': 2
            },
            {
                'synapseEncoding': 'sparse',
                'strides': 2,
                'padding': 'same'
            },
            {
                'synapseEncoding': 'runlength'
            },
            {
                'synapseEncoding': 'runlength',
                'strides': 2,
                'padding': 'same'
            },
            {
                'synapseEncoding': 'dense1'
            },
            {
                'synapseEncoding': 'dense1',
                'strides': 2,
                'padding': 'same'
            },
            {
                'synapseEncoding': 'dense2'
            },
            {
                'synapseEncoding': 'dense2',
                'strides': 2,
                'padding': 'same'
            },
        ])

        coreShapes = np.array([[5, 5, 2], [30, 10, 2], [10, 5, 2], [7, 13, 2],
                               [16, 5, 2], [8, 9, 2], [5, 5, 2], [6, 9, 2],
                               [5, 5, 2], [15, 10, 2], [5, 5, 2], [6, 9, 2]])

        # numOutputAxons (second column) is expected to be zero because we are
        # looking at the output layer.
        expectedResults = np.array([[14, 0, 900, 281, 378],
                                    [108, 0, 29160, 6873, 10080],
                                    [198, 0, 4050, 2430, 2592],
                                    [52, 0, 56, 42, 28],
                                    [60, 0, 768, 528, 384],
                                    [144, 0, 1408, 808, 868],
                                    [14, 0, 900, 288, 371],
                                    [104, 0, 928, 524, 580],
                                    [14, 0, 900, 660, 427],
                                    [72, 0, 1408, 1226, 840],
                                    [14, 0, 3587, 290, 700],
                                    [216, 0, 2920, 874, 1052]])

        doTest = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], bool)

        np.random.seed(0)
        for inputShape, args, kwargs, coreShape, expectedResult in \
                zip(inputShapes[doTest],
                    layerArgs[doTest],
                    layerKwargs[doTest],
                    coreShapes[doTest],
                    expectedResults[doTest]):

            with self.subTest(inputShape=inputShape,
                              args=args,
                              kwargs=kwargs,
                              coreShape=coreShape,
                              expectedResult=expectedResult):

                # The Keras layer initializer does not know how to handle
                # np.int types. Convert to builtin int manually.
                args = list(args)
                args[1] = int(args[1])

                inputLayer = NxInputLayer(tuple(inputShape))
                layer = NxConv2D(*args, **kwargs)
                layer(inputLayer.input)

                # Assumes that this layer will never go beyond one chip.
                layer.coreCounter = 0

                layerShape = layer.output_shape[1:]
                numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int)
                coreIdMap = getCoreIdMapFromCoreShape(coreShape, layerShape,
                                                      numCoresPerAxis)

                multiplicityMapPre = np.ones(layer.input_shape[1:-1], int)
                postLayerPartition = getDummyLayer(layer.output_shape[1:])

                partitionCandidate = Layer(layer.name, '',
                                           layer.compartmentKwargs,
                                           layer.connectionKwargs, coreIdMap,
                                           multiplicityMapPre,
                                           postLayerPartition)

                partitionCandidate = layer.compile(partitionCandidate)

                try:
                    layer.validatePartition(partitionCandidate)
                finally:
                    layer.deleteKernelIdMap()

                layer.deleteKernelIdMap()

                result = [
                    partitionCandidate.numInputAxons,
                    partitionCandidate.numOutputAxons,
                    partitionCandidate.numSyn,
                    partitionCandidate.numSynEntries,
                    partitionCandidate.numSynMemWords
                ]
                self.verbose = True
                if self.verbose:
                    print(result)

                for er, r in zip(expectedResult, result):
                    self.assertEqual(er, r)
예제 #19
0
    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.")
예제 #20
0
    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)
예제 #21
0
conn_kwargs['signMode'] = sign_mode

# Weight matrix needs to be transposed when going from SLAYER (Pytorch) to
# NxTF (Keras)
weights = weights.transpose((3, 2, 1, 0))  # (out, in, h, w) -> (w, h, in, out)

filters = 16

# SLAYER does not use biases.
biases = np.zeros(filters)

layer = NxConv2D(filters=filters,
                 kernel_size=(5, 5),
                 padding='same',
                 weights=[weights, biases],
                 compartmentKwargs=compartment_kwargs,
                 connectionKwargs=conn_kwargs,
                 activation='relu',
                 resetMode=reset_mode,
                 name=name)(input_layer.input)

name = 'pool2'
weights = np.load(os.path.join(path_weights, name + '.npy'))
shape = weights.shape + (filters, filters)
weights = np.broadcast_to(np.expand_dims(weights, (-2, -1)), shape)
layer = NxAveragePooling2D(2,
                           2,
                           compartmentKwargs=compartment_kwargs,
                           connectionKwargs=connection_kwargs,
                           resetMode=reset_mode,
                           name=name)(layer)
예제 #22
0
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)