diff --git a/scripts/Read_Activity.ipynb b/scripts/Read_Activity.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..4d0b648f3ad20c7cf53cc770cf68704273173092 --- /dev/null +++ b/scripts/Read_Activity.ipynb @@ -0,0 +1,494 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Classification using SpiNNaker activity and SVM\n", + "In this document, we load and preprocess the spikes activity received in the output layer of SpiNNaker, and use an SVM for the classification. Using MNIST dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from torchvision import transforms,datasets\n", + "from sklearn.svm import LinearSVC\n", + "from neo.io import PickleIO" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load MNIST dataset with the preprocessing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transform=transforms.Compose([\n", + " transforms.Resize((28,28)),\n", + " transforms.Grayscale(),\n", + " transforms.ToTensor(),\n", + " transforms.Normalize((0,),(1,))])\n", + "\n", + "dataPath='~/datasets'\n", + "mnistTrain=datasets.MNIST(dataPath,train=True,download=True,transform=transform)\n", + "mnistTest=datasets.MNIST(dataPath,train=False,download=True,transform=transform)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load SpiNNaker activity data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k = PickleIO(filename=\"[Trainset_Activity]\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k = PickleIO(filename=\"[Testset_Activity]\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the blocks from the neo file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_block = Train60k.read_block()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k_block = Test10k.read_block()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define network information" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "input_nbr = 60000\n", + "input_nbr_testset = 10000\n", + "neuron_nbr = len(Train60k_block.segments[0].spiketrains)\n", + "presentation_time = 29" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def neoToNpArray(block, input_nbr, neuron_nbr, presentation_time):\n", + " \"\"\"Convert Neo object to Numpy array\n", + "\n", + " Args:\n", + " block (neo): neo object\n", + " input_nbr (int): number of inputs\n", + " neuron_nbr (int): number of neurons\n", + " presentation_time (int): presentation time for each input (silence period included)\n", + "\n", + " Returns:\n", + " activityArray (numpy array): numpy array of the network activity\n", + " \"\"\"\n", + " activityArray = np.zeros((input_nbr, presentation_time, neuron_nbr))\n", + " for neuron_id, spikesPerNeuron in enumerate(block.segments[0].spiketrains):\n", + " for spike in spikesPerNeuron:\n", + " spike_timestamp = float(spike)\n", + " in_nbr = int(spike_timestamp / presentation_time)\n", + " pre_time = int(spike_timestamp % presentation_time)\n", + " activityArray[in_nbr][pre_time][neuron_id] = 1\n", + " \n", + " return activityArray" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show the time of the latest spike" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "max = - np.Infinity\n", + "for spikes in Train60k_block.segments[0].spiketrains:\n", + " if len(np.array(spikes)) > 0:\n", + " s = np.max(np.array(spikes))\n", + " if max < s:\n", + " max = s\n", + "\n", + "print(\"last spike time: \",max)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Convert Neo object to Numpy array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array= neoToNpArray(Train60k_block,input_nbr,neuron_nbr,presentation_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the shape to confirm the content" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def optimizeNpy(npyArray, presentation_time):\n", + " \"\"\"Optimize the Numpy array by keeping only the first spike\n", + "\n", + " Args:\n", + " npyArray (numpy array): numpy array of the network activity\n", + " presentation_time (int): presentation time for each input (silence period included)\n", + "\n", + " Returns:\n", + " npyArray_reduced (numpy array): reduced numpy array\n", + " \"\"\"\n", + " npyArray_reduced = np.zeros((npyArray.shape[0],presentation_time,npyArray.shape[2]))\n", + " activityArray = np.zeros((presentation_time,npyArray.shape[2]))\n", + " # for each input\n", + " for i,inp in enumerate(npyArray):\n", + " # for each timestamp before 19\n", + " for j,s in enumerate(inp[0:presentation_time]):\n", + " # for each neuron\n", + " for k,n in enumerate(s):\n", + " if(activityArray[k] == 0 and n == 1):\n", + " npyArray_reduced[i,j,k] = 1\n", + " activityArray[k] = 1\n", + " activityArray = np.zeros((presentation_time,npyArray.shape[2]))\n", + "\n", + " return npyArray_reduced" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reduce the content of numpy array by reducing the spikes activity and keeping only first spikes per neuron" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array_reduced = optimizeNpy(Train60k_array,19)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check the shape of the new created numpy array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array_reduced.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def optimizeSteps(npyArray, input_nbr, neuron_nbr, presentation_time):\n", + " \"\"\"Code the spikes in a numerical format suitable for SVM training\n", + "\n", + " Args:\n", + " npyArray (numpy array): numpy array of the network activity\n", + " input_nbr (int): number of inputs\n", + " neuron_nbr (int): number of neurons\n", + " presentation_time (int): time of presentation (ms)\n", + "\n", + " Returns:\n", + " activityArray (numpy array): numpy array with the proper spikes coding\n", + " \"\"\"\n", + " activityArray = np.zeros((input_nbr,neuron_nbr))\n", + " totalStep = presentation_time\n", + " for i,inp in enumerate(npyArray):\n", + " # for each timestamp\n", + " for j,s in enumerate(inp):\n", + " # for each neuron\n", + " for k,n in enumerate(s):\n", + " if(activityArray[i,k] == 0 and n == 1):\n", + " activityArray[i,k] = ((totalStep - j) / totalStep)\n", + "\n", + " return activityArray" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Apply the spike encoding for numerical representation before using SVM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array_reduced_encoded = optimizeSteps(Train60k_array_reduced, 60000, 1600, presentation_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check the shape of the new created array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Train60k_array_reduced_encoded.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Convert Neo object to Numpy array for testset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k_array = neoToNpArray(Test10k_block,input_nbr_testset,neuron_nbr,presentation_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check the shape of the new created array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k_array.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### SVM" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Prepare the data for SVM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "labelsArray = np.array(mnistTrain.targets)\n", + "activityArraySVM = Train60k_array_reduced_encoded.reshape((60000,-1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Train the SVM and show the score" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "clf_spike = LinearSVC(max_iter=10000)\n", + "\n", + "clf_spike.fit(activityArraySVM, labelsArray)\n", + "score = clf_spike.score(activityArraySVM, labelsArray)\n", + "print(\"score: \",round(score * 100,2), \"%\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test the network accuracy using testset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k_array_reduced = optimizeNpy(Test10k_array,19)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Test10k_array_reduced_encoded = optimizeSteps(Test10k_array_reduced, 10000, 1600, presentation_time)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "labelsArray_test = np.array(mnistTest.targets)\n", + "activityArraySVM_test = Test10k_array_reduced_encoded.reshape((10000,-1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "activityArraySVM_test.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predict_spike = clf_spike.predict(activityArraySVM_test)\n", + "error_spike = labelsArray_test[labelsArray_test != predict_spike]\n", + "error_spike[:] = 1 \n", + "\n", + "print(\"Acc:\", (1 - error_spike.sum()/len(predict_spike))*100,\"%\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.10 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}