From 4b9db2959f7cce94a39b650f6e9f3f17552897a4 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 00:40:27 -0800 Subject: [PATCH 01/13] Add files via upload --- docs/_static/img/visuals.ipynb | 3338 ++++++++++++++++++++++++++++++++ 1 file changed, 3338 insertions(+) create mode 100644 docs/_static/img/visuals.ipynb diff --git a/docs/_static/img/visuals.ipynb b/docs/_static/img/visuals.ipynb new file mode 100644 index 00000000..65f6867c --- /dev/null +++ b/docs/_static/img/visuals.ipynb @@ -0,0 +1,3338 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "W-v36rDBv41L", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "e90ecaba-4b80-4664-8c80-fe5fbc9cc8ff" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m109.7/109.7 kB\u001b[0m \u001b[31m4.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m107.5/107.5 kB\u001b[0m \u001b[31m13.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.4/50.4 kB\u001b[0m \u001b[31m5.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m109.0/109.0 kB\u001b[0m \u001b[31m4.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h" + ] + } + ], + "source": [ + "!pip install tonic --quiet\n", + "!pip install snntorch --quiet" + ] + }, + { + "cell_type": "code", + "source": [ + "import tonic\n", + "import tonic.transforms as transforms\n", + "# from torchvision import datasets, transforms\n", + "import torch\n", + "import torchvision\n", + "import snntorch as snn\n", + "import snntorch.spikeplot as splt\n", + "import matplotlib.pyplot as plt\n", + "from IPython.display import HTML\n", + "import numpy as np" + ], + "metadata": { + "id": "6WWIF2I1v7sA" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# Load the Drive helper and mount\n", + "from google.colab import drive\n", + "\n", + "# This will prompt for authorization.\n", + "drive.mount('/content/drive')" + ], + "metadata": { + "id": "c2PcG-B3v9K8", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "219be2c5-2926-4124-af1a-c54b57c46044" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Mounted at /content/drive\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# After executing the cell above, Drive\n", + "# files will be present in \"/content/drive/My Drive\".\n", + "!ls \"/content/drive/My Drive/SNN_Class/STMNIST_Project\"" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "00hHZOeuv-8k", + "outputId": "b925df35-2975-4aef-8b10-2dcd765b7227" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "'Copy of Spiking Tactile MNIST.ipynb' STMNIST\n", + " dylans_visuals.ipynb\t\t STMNIST_FinalProj.ipynb\n", + "'Link to my shit.gdoc'\t\t STMNISTProjectShato.ipynb\n", + "'Spiking Tactile MNIST.ipynb'\t WrapperClass_STMNIST_FinalProj.ipynb\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "dataset = tonic.prototype.datasets.STMNIST(root=\"/content/drive/My Drive/SNN_Class/STMNIST_Project\",\n", + " keep_compressed = False, shuffle = False)" + ], + "metadata": { + "id": "4r9zaUjHwAcM" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "events, target = next(iter(dataset))\n", + "print(target)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "lWxj31O41EYj", + "outputId": "46510d2f-bc31-4d45-fec5-f213828f5937" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "2\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "print(len(dataset)) # 23 participants writing 30 times each for 9 digits 23*30*9 = 6210" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_v1auSbyepQr", + "outputId": "ca258977-3f3d-4a04-f868-f68b9fbd8df0" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "6953\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# events, target = next(iter(dataset))" + ], + "metadata": { + "id": "N4gdZjZZwCXS" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "data_list = []\n", + "counter = 0\n", + "for sample in dataset:\n", + " data_list.append(sample)\n", + " counter += 1\n", + " if counter % 10 == 0:\n", + " print(f\"{counter} samples moved over\")\n", + " if counter == 100:\n", + " break" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "M9H_99UTSgQS", + "outputId": "609a23a0-d72f-41ea-eb07-1c1a90bcbd7f" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "10 samples moved over\n", + "20 samples moved over\n", + "30 samples moved over\n", + "40 samples moved over\n", + "50 samples moved over\n", + "60 samples moved over\n", + "70 samples moved over\n", + "80 samples moved over\n", + "90 samples moved over\n", + "100 samples moved over\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "events, target = data_list[0]" + ], + "metadata": { + "id": "k9r1BnUJHZt9" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# If you're feeling sentimental, you can save the animation: .gif, .mp4 etc.\n", + "animation.save(\"spike_tile_mnist_test.mp4\")" + ], + "metadata": { + "id": "W-BXlVOu9nHk" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "tonic.utils.plot_event_grid(events, axis_array=(1, 8), plot_frame_number=True)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 122 + }, + "id": "D3q8Qb5wBO-k", + "outputId": "500c29a0-e88c-40f2-c04f-fd085c5fe160" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "frame_transform = transforms.Compose([transforms.Denoise(filter_time=100000),\n", + " transforms.ToFrame(sensor_size=(10,10,2),\n", + " time_window=10000)\n", + " ])\n", + "\n", + "transform = tonic.transforms.ToFrame(\n", + " sensor_size=(10, 10, 2),\n", + " time_window=100000,\n", + ")\n", + "\n", + "frames = transform(events)\n", + "\n", + "frames = frames / np.max(frames)\n", + "\n", + "print(frames.shape)\n", + "\n", + "frames = np.rot90(frames, k=-1, axes=(2, 3))\n", + "frames = np.flip(frames, axis=3)\n", + "\n", + "# frames_rotated = torchvision.transforms.functional.rotate(frames, angle=90)\n", + "\n", + "# frames = frames.astype(np.uint8)\n", + "\n", + "print(np.max(frames))\n", + "print(np.min(frames))\n", + "\n", + "# print(frames[0])\n", + "print(target)\n", + "animation = tonic.utils.plot_animation(frames)\n", + "\n", + "# Display the animation inline in a Jupyter notebook\n", + "from IPython.display import HTML\n", + "HTML(animation.to_jshtml())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "0RoMMuzkwEIq", + "outputId": "ac6d264a-46e9-4e29-d59a-6bc4cd336a59" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "(15, 2, 10, 10)\n", + "1.0\n", + "0.0\n", + "5\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGNUlEQVR4nO3csU0DQRRFUQaZ0NUQQEnkdEKhJC7g04CNVnCXBXROPMHLrn4ya2bmDgC+6f7oAQD8D4ICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASp60P1+Pbnju+7uXp6AW3vT4fveC6h/PRC257vxy9ALhiy6cqLhQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASCxZmY2PVxr7y38lPPRAz5xOXoAcM2WVLhQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkFgzM5serrX3FgB+qS2pcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJA4rT14czsuQOAP86FAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQOIDjk4gHbZn1rYAAAAASUVORK5CYII=\n" + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + " \n", + "
\n", + " \n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 10 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "sensor_size is (10,10,2) for STMNIST" + ], + "metadata": { + "id": "mRon4thv-5vv" + } + }, + { + "cell_type": "code", + "source": [ + "transform = frame_transform(events)\n", + "transform = np.rot90(transform, k=-1, axes=(2, 3))\n", + "transform = np.flip(transform, axis=3)\n", + "transform = torch.from_numpy(transform)\n", + "# print(transform)" + ], + "metadata": { + "id": "yL0D2kGCHCbi" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "print(transform.shape)\n", + "print(transform.size())\n", + "print(transform.size(0))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OqvuXLxIH-eP", + "outputId": "b8050147-9bc2-4584-a148-8179c2f1ed1b" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([159, 2, 10, 10])\n", + "torch.Size([159, 2, 10, 10])\n", + "159\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "num_steps = transform.size(0)\n", + "# Reshape\n", + "transform_plot = transform.reshape((num_steps, -1))\n", + "print(transform_plot.size())\n", + "# raster plot\n", + "fig = plt.figure(facecolor=\"w\", figsize=(10, 5))\n", + "ax = fig.add_subplot(111)\n", + "splt.raster(transform_plot, ax, s=1.5, c=\"black\")\n", + "\n", + "plt.title(\"Input Layer\")\n", + "plt.xlabel(\"Time step\")\n", + "plt.ylabel(\"Neuron Number/Taxel Address\")\n", + "plt.show()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 504 + }, + "id": "u_mo-3tf-Qka", + "outputId": "6e1d25b7-ec12-484c-fd99-d9ab1187af6e" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([159, 200])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAHWCAYAAAB9mLjgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABp1UlEQVR4nO3deXgUVfr//U8DCZAAYZEtyhIlIMgioiCigoog46gogwsKaKICAgq4IPNVAR1lcVRwg3FMREdwQQEVBUVkcQEUMCwKiMgqmw4kkWRIGlLPHz70L93pTldVqrfk/bquvrSrT506dUi6+859FpdhGIYAAAAAAKZVinQDAAAAACDWEEgBAAAAgEUEUgAAAABgEYEUAAAAAFhEIAUAAAAAFhFIAQAAAIBFBFIAAAAAYBGBFAAAAABYRCAFAAAAABYRSAEAAACARQRSAADHzZo1Sy6XS2vXro10UyRJ+fn5mjBhgpYvX26q/PLly+VyufTee++FtmEAgJhFIAUAKPfy8/M1ceJE04EUAADBEEgBABDjDMPQ//73v0g3AwAqFAIpAEBY3H777apRo4Z+/fVX9e3bVzVq1FD9+vX1wAMP6OTJk55yu3btksvl0j//+U8999xzatasmapXr67u3btr8+bNXnX26NFDPXr08Hut5s2be+qrX7++JGnixIlyuVxyuVyaMGFCme/pn//8py666CLVq1dP1atXV6dOnUoMB+zevbs6dOjg9/xWrVqpd+/enudFRUWaNm2azjnnHFWrVk0NGzbUkCFDdPToUa/zmjdvrr/+9a/69NNPdf7556t69er617/+Veb7AQCYRyAFAAibkydPqnfv3qpXr57++c9/qnv37nrmmWf0yiuvlCj7xhtv6Pnnn9fw4cM1btw4bd68WZdffrkOHTpk6Zr169fXjBkzJEnXX3+9/vOf/+g///mPbrjhhjLfz/Tp09WxY0c9/vjjeuqpp1SlShX1799fH3/8safMwIEDtXHjxhJB4HfffaeffvpJt912m+fYkCFD9OCDD6pbt26aPn267rjjDs2ePVu9e/eW2+32On/btm265ZZbdOWVV2r69Ok699xzy3w/AAALDAAAHPbaa68ZkozvvvvOc2zw4MGGJOPxxx/3KtuxY0ejU6dOnuc7d+40JBnVq1c39u3b5zm+Zs0aQ5IxevRoz7Hu3bsb3bt3L3H9wYMHG82aNfM8/+233wxJxvjx4021f9myZYYkY+7cuaWWy8/P93peWFhotG3b1rj88ss9x7Kzs41q1aoZY8eO9Sp77733GomJicaxY8cMwzCML7/80pBkzJ4926vc4sWLSxxv1qyZIclYvHixqfsBADiPjBQAIKyGDh3q9fySSy7RL7/8UqJc3759dfrpp3ued+7cWV26dNEnn3wS8jaaVb16dc//Hz16VDk5Obrkkku0fv16z/GkpCRdd911euutt2QYhqQ/M3PvvPOO+vbtq8TEREnS3LlzlZSUpCuvvFK///6759GpUyfVqFFDy5Yt87p2SkqK17BAAEB4EUgBAMKmWrVqnvlKp9SpU6fEHCBJSk1NLXGsZcuW2rVrV6iaZ9nChQt14YUXqlq1aqpbt65nGGFOTo5XuUGDBmnPnj368ssvJUmff/65Dh06pIEDB3rKbN++XTk5OWrQoIHq16/v9Th27JgOHz7sVWdKSkrobxAAEFCVSDcAAFBxVK5c2dH6XC6XJ8tTXPHFK0Llyy+/1LXXXqtLL71UL7/8sho3bqy4uDi99tprmjNnjlfZ3r17q2HDhnrzzTd16aWX6s0331SjRo3Us2dPT5mioiI1aNBAs2fP9ns93wC0eDYMABB+BFIAgKi0ffv2Esd++uknz2p80p/ZLH/DAnfv3u313OVyOd6+999/X9WqVdOnn36qqlWreo6/9tprJcpWrlxZAwYM0KxZszRlyhQtWLBAd911l1dgedZZZ+nzzz9Xt27dCJIAIAYwtA8AEJUWLFigX3/91fP822+/1Zo1a9SnTx/PsbPOOktbt27Vb7/95jm2YcMGff311151JSQkSJKys7Mda1/lypXlcrlKLN2+YMECv+UHDhyoo0ePasiQITp27JjXan2SdOONN+rkyZN64oknSpx74sQJR9sOACg7MlIAgKjUokULXXzxxRo2bJgKCgo0bdo01atXTw899JCnTFpamp599ln17t1b6enpOnz4sGbOnKlzzjlHubm5nnLVq1dXmzZt9M4776hly5aqW7eu2rZtq7Zt25bahvfff19bt24tcXzw4MG6+uqr9eyzz+qqq67SgAEDdPjwYb300ktq0aKFNm7cWOKcjh07qm3btpo7d65at26t8847z+v17t27a8iQIZo0aZKysrLUq1cvxcXFafv27Zo7d66mT5+uv/3tb1a7EQAQIgRSAICoNGjQIFWqVEnTpk3T4cOH1blzZ7344otq3Lixp0zr1q31xhtv6LHHHtOYMWPUpk0b/ec//9GcOXO0fPlyr/peffVVjRw5UqNHj1ZhYaHGjx8fNJB6++23/R7v0aOHLr/8cmVkZGjy5MkaNWqUUlJSNGXKFO3atctvIHXqnh566CGvRSaKmzlzpjp16qR//etf+vvf/64qVaqoefPmuu2229StW7dS2woACC+X4W+WLgAAEbJr1y6lpKTo6aef1gMPPBDp5jhq+vTpGj16tHbt2qWmTZtGujkAgDJgjhQAAGFgGIYyMjLUvXt3gigAKAcY2gcAQAjl5eXpww8/1LJly7Rp0yZ98MEHkW4SAMABBFIAAITQb7/9pgEDBqh27dr6+9//rmuvvTbSTQIAOIA5UgAAAABgEXOkAAAAAMAiAikAAAAAsIg5UpKKioq0f/9+1axZUy6XK9LNAQAAABAhhmHojz/+UHJysipVCpx3IpCStH//fjVp0iTSzQAAAAAQJfbu3aszzjgj4OsEUpJq1qwp6c/OqlWrVoRbAwAAACBScnNz1aRJE0+MEAiBlOQZzlerVi0CKQAAAABBp/xEdLGJSZMm6YILLlDNmjXVoEED9e3bV9u2bfMqc/z4cQ0fPlz16tVTjRo11K9fPx06dMirzJ49e3T11VcrISFBDRo00IMPPqgTJ06E81YAAAAAVCARDaRWrFih4cOHa/Xq1VqyZIncbrd69eqlvLw8T5nRo0fro48+0ty5c7VixQrt379fN9xwg+f1kydP6uqrr1ZhYaG++eYbvf7665o1a5Yee+yxSNwSAAAAgAogqjbk/e2339SgQQOtWLFCl156qXJyclS/fn3NmTNHf/vb3yRJW7duVevWrbVq1SpdeOGFWrRokf76179q//79atiwoSRp5syZGjt2rH777TfFx8eXuE5BQYEKCgo8z0+Ng8zJyWFoHwAAAFCB5ebmKikpKWhsEFX7SOXk5EiS6tatK0lat26d3G63evbs6Slz9tlnq2nTplq1apUkadWqVWrXrp0niJKk3r17Kzc3Vz/88IPf60yaNElJSUmeByv2AQAAALAiagKpoqIijRo1St26dVPbtm0lSQcPHlR8fLxq167tVbZhw4Y6ePCgp0zxIOrU66de82fcuHHKycnxPPbu3evw3QAAAAAoz6Jm1b7hw4dr8+bN+uqrr0J+rapVq6pq1aohvw4AAACA8ikqMlIjRozQwoULtWzZMq9Nrxo1aqTCwkJlZ2d7lT906JAaNWrkKeO7it+p56fKAAAAAICTIhpIGYahESNGaP78+friiy+UkpLi9XqnTp0UFxenpUuXeo5t27ZNe/bsUdeuXSVJXbt21aZNm3T48GFPmSVLlqhWrVpq06ZNeG4EAAAAQIUS0aF9w4cP15w5c/TBBx+oZs2anjlNSUlJql69upKSkpSenq4xY8aobt26qlWrlkaOHKmuXbvqwgsvlCT16tVLbdq00cCBAzV16lQdPHhQjzzyiIYPH87wPQAAAAAhEdHlzwPtFvzaa6/p9ttvl/Tnhrz333+/3nrrLRUUFKh37956+eWXvYbt7d69W8OGDdPy5cuVmJiowYMHa/LkyapSxVycaHaJQwAAAADlm9nYIKr2kYoUAikAAAAAUozuIwUAAAAAsYBACgAQMW6329QxAACiDYEUACAi0tPTFR8fr/T09FKPAQAQjZgjJeZIAUC4ud1uxcfHe54XFhZKUoljcXFxcrvdiouLK3G+7zF/1yhexsw5AAAwRwoAELXi4uKUlpYmSUpLS1NcXJzfY3azVr5lyHQBAJxGRkpkpAAgUkrLNlnJWvmeX7xMXl6eEhMT/Z5jJmtFJgsAKhYyUgCAqOcvQDl1zGzWyt/5qampkqTU1FQlJCR4PT91jpmsFZksAEAgZKRERgoAopnVLJGZjJQky2XKMmfLzDnhLAMACIyMFACgXCgtaxWofPGslb+MlL+sVajmbJk5J5xlAADOICMlMlIAUB7ZmWvl9JwtM+c4lTGzklUDAARGRgoAUKHZmWtV1uyXnSDFbh1OXBsAYB+BFACg3MvIyFBhYaEyMjJKPVaaQIFLafWYDeJ86/A3PDHYte0uzgEAsIehfWJoHwDAPDsLN4RzU2EWmwCAsmFoHwAAIWB3+J6denzL2DnH7HkAAGsIpAAAAADAIgIpAAAAALCIQAoAAAAALCKQAgAE5Xa7gx6zWwYAgFhEIAUAKFV6erri4+OVnp4e8JjdMgAAxCqWPxfLnwNAIG63W/Hx8Z7nhYWFkuR1LC8vT4mJiZbLxMXFsSw3ACDqsPw5AKDMzGzy6m+zWH9lUlNTJUmpqamKi4sjQwUAiGlkpERGCgCCMbPJa2llfDNbgTJUAABEGhkpAIBjzGzyWloZM1ksAABiCRkpkZECgHAxk8WKpLJm3pw8J5RlAACBkZECAEQdM1msSAnV6oShXPXQThkAgDPISImMFABUdKFandDuioahKsNqiQAQHBkpAABMKsvqhMVXI/Qt42+1Qn/nOFUmWPtYLREAnENGSmSkAAB/sjoHyV8mq3jGJ5T7cPmW8ZdtYrVEALCOjBQAABZZXZ3QXyareBkn9+EKViZQ21ktEQBCg4yUyEgBAMom2JwjJ1bbS09PV2ZmptLS0pSRkWG6jL9jzJECgMDMxgYEUiKQAgBEt0BDCIOVkfwP/wMABMbQPgAAygk7w/jMDv8DANhDRkpkpAAAscHMkDw25AWAsiEjBQBAOWMmGDKzYAYAoOwiGkitXLlS11xzjZKTk+VyubRgwQKv110ul9/H008/7SnTvHnzEq9Pnjw5zHcCANHB7XaX+txsGQAAULqIBlJ5eXnq0KGDXnrpJb+vHzhwwOuRmZkpl8ulfv36eZV7/PHHvcqNHDkyHM0HgKjiu9Gqv41XzZQBAADBRc0cKZfLpfnz56tv374By/Tt21d//PGHli5d6jnWvHlzjRo1SqNGjbJ9beZIAYh1ZjZelYJv8lp8I1crS3MHKhNrnJqDFKr+c6oMACCwcjdH6tChQ/r444/9/tV08uTJqlevnjp27Kinn35aJ06cKLWugoIC5ebmej0AIJbZ3eQ1NTVVkpSamuq1F1FFzGyZuQc7feFU/zlVBgDgjJjJSE2dOlWTJ0/W/v37Va1aNc/xZ599Vuedd57q1q2rb775RuPGjdMdd9yhZ599NuC1JkyYoIkTJ5Y4TkYKQKyzkgkxs+9QWTNbscKpfZp8+8Kp/rPbvlj7dwCAaFDuMlKZmZm69dZbvYIoSRozZox69Oih9u3ba+jQoXrmmWf0wgsvqKCgIGBd48aNU05Ojuexd+/eUDcfAMLC94tzaSu4mdl3yGxmK9b3KnJqnybfvnCq/+y2DwAQOjGRkfryyy916aWXKisrSx06dCi1nh9++EFt27bV1q1b1apVK1PXZo4UgIrM7vwd5kgFPsYcKQCIXeUqI5WRkaFOnToFDaIkKSsrS5UqVVKDBg3C0DIAiH1m9h2yWybWRNs+TWaWpneqDADAmogGUseOHVNWVpaysrIkSTt37lRWVpb27NnjKZObm6u5c+fqzjvvLHH+qlWrNG3aNG3YsEG//PKLZs+erdGjR+u2225TnTp1wnUbAAB4OLXYRKjKAACcEdGhfcuXL9dll11W4vjgwYM1a9YsSdIrr7yiUaNG6cCBA0pKSvIqt379et1zzz3aunWrCgoKlJKSooEDB2rMmDGqWrWq6XYwtA8A4ASnlqEPVRkWoACA4GJiaF+PHj1kGEaJx6kgSpLuvvtu5efnlwiiJOm8887T6tWrlZ2drf/973/68ccfNW7cOEtBFAAATnFqsY5QlSGIAgDnRM1iE5FERgoA4CSnFpsIVRkAQGAxkZECAKAiiLYghsUnAKDsCKQAAHCQmcUdom1BCgCAdQztE0P7AADO8F1swt/iDtG2IEW0ZcsAINIY2gcAQJiZWdwh2hakAADYQ0ZKZKQAAM4ys7hDtC1IAQD4ExkpAAAixEyQ4lsmUPYqXGUAANYQSAFABPiumuZvFbVgZcycAwAAQoNACgDCzImV1sycAwAAQoc5UmKOFIDwcWLFNjPnnFqNLdrn1NiZS2S2fWxmCwCwgzlSABCF7K60lpqaKklKTU01dU5cXFzU7ztkZ78lJ++BLB8AoCzISImMFIDws5IJCbQ3kdVzpOjZd8jOfkvh3l/Jtwx7LgFAxUBGCgCimJWV1gLtTWT1nGjad8jOfkvh3l/JTBvLwszCICweAgDRi4yUyEgBiA125uowRyo650ilp6crMzNTaWlpysjIsF0GAOA8s7EBgZQIpAAA4WN3WCPDCgEgPBjaBwBAFLI7rBEAEF3ISImMFAAg/OwOawQAhBYZKQAAopiZAIkgCgCiF4EUAAAAAFhEIAUAgMN8ly33t4x5tJUBAFhDIAUAgIPS09MVHx+v9PR0v8+jsQwAwDoWmxCLTQAAnOG7bHleXp4SExM9zwsLCyUpqsowDwsAvLHYBAAAYea7bHlCQkKJZcyjrQwAwB4yUiIjBQBwlu+y5f6WMY+2MgCAP5GRAgAgQnyDlECb7kZTGQCANQRSAOAwOyuksYoaAACxhUAKABxkZ4U0VlEDACD2MEdKzJEC8Ccz80ZKm2tiZsU2f3NXip/DKmoAAEQWc6QAwAI7mSPf53ZWSPM9hyAKAIDYQEZKZKSAis5MVshKtsnOCmmsogYAQHQIa0bq5MmTysrK0tGjR52oDgDCykxWyEq2yc4KaQRRAADEFlsZqVGjRqldu3ZKT0/XyZMn1b17d33zzTdKSEjQwoUL1aNHjxA0NXTISAGQyj5HCgAAxL6QZqTee+89dejQQZL00UcfaefOndq6datGjx6t//u//7PXYiDKmFnC2s4y13avhdCzkzkiiIIZofyd5v0CACLDViD1+++/q1GjRpKkTz75RP3791fLli2VlpamTZs2OdpAIBLMLGFtZ5lru9cCELtC+TvN+wUARI6toX3NmjXTv//9b11xxRVKSUnRjBkzdPXVV+uHH37QxRdfbHqu1MqVK/X0009r3bp1OnDggObPn6++fft6Xr/99tv1+uuve53Tu3dvLV682PP8yJEjGjlypD766CNVqlRJ/fr10/Tp01WjRg3T98PQvorH33CsU8fMLCogyfIy14Ha4eQCBgw7A6KLleXtrQ4tDVQ3v/cAUDYhHdp3xx136MYbb1Tbtm3lcrnUs2dPSdKaNWt09tlnm64nLy9PHTp00EsvvRSwzFVXXaUDBw54Hm+99ZbX67feeqt++OEHLVmyRAsXLtTKlSt1991327ktVBDBsktxcXFKTU2VJKWmpvpdVMBfmeLPzX6JMbuAQTgzZACc4/teEei9wc7y+/7q5vceAMLH9vLn7733nvbu3av+/fvrjDPOkCS9/vrrql27tq677jrrDXG5/GaksrOztWDBAr/nbNmyRW3atNF3332n888/X5K0ePFi/eUvf9G+ffuUnJxs6tpkpCoOf3/Blcxll8q68WqwdpVlk1ez9wAgvOwsrW+2jMTvPQCEQsiXP//b3/6m0aNHe4Ko7OxsDR482FYQVZrly5erQYMGatWqlYYNG6b//ve/ntdWrVql2rVre4IoSerZs6cqVaqkNWvWBKyzoKBAubm5Xg9UDP6WuTabFfJd3trqxqvB2hXouZlrOd0eAM6ws7S+7x9VApXh9x4AIsywYfLkycbbb7/ted6/f3+jUqVKxumnn25s2LDBTpWGJGP+/Plex9566y3jgw8+MDZu3GjMnz/faN26tXHBBRcYJ06cMAzDMJ588kmjZcuWJeqqX7++8fLLLwe81vjx4w1JJR45OTm22o7YU1hYGPSYvzJOnGOXmWuFsz0AzLPzfpKWlmZIMtLS0kyX8XcOAMCanJwcU7GBraF9KSkpmj17ti666CItWbJEN954o9555x29++672rNnjz777DPLAZ2/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Fizwet1Mfx45ckS33nqratWqpdq1ays9PV3Hjh0L411Et9L62O12a+zYsWrXrp0SExOVnJysQYMGaf/+/V510MfBBftZLm7o0KFyuVyaNm2a13H6uXRm+njLli269tprlZSUpMTERF1wwQXas2eP5/VIfd8gkIoS77zzjsaMGaPx48dr/fr16tChg3r37q3Dhw9HumkxacWKFRo+fLhWr16tJUuWyO12q1evXsrLy/OUGT16tD766CPNnTtXK1as0P79+3XDDTdEsNWx67vvvtO//vUvtW/f3us4fVx2R48eVbdu3RQXF6dFixbpxx9/1DPPPKM6dep4ykydOlXPP/+8Zs6cqTVr1igxMVG9e/fW8ePHI9jy2DFlyhTNmDFDL774orZs2aIpU6Zo6tSpeuGFFzxl6GNr8vLy1KFDB7300kt+XzfTn7feeqt++OEHLVmyRAsXLtTKlSt19913h+sWol5pfZyfn6/169fr0Ucf1fr16zVv3jxt27ZN1157rVc5+ji4YD/Lp8yfP1+rV69WcnJyidfo59IF6+MdO3bo4osv1tlnn63ly5dr48aNevTRR1WtWjVPmYh93zAQFTp37mwMHz7c8/zkyZNGcnKyMWnSpAi2qvw4fPiwIclYsWKFYRiGkZ2dbcTFxRlz5871lNmyZYshyVi1alWkmhmT/vjjDyM1NdVYsmSJ0b17d+O+++4zDIM+dsrYsWONiy++OODrRUVFRqNGjYynn37acyw7O9uoWrWq8dZbb4WjiTHv6quvNtLS0ryO3XDDDcatt95qGAZ9XFaSjPnz53uem+nPH3/80ZBkfPfdd54yixYtMlwul/Hrr7+Gre2xwreP/fn2228NScbu3bsNw6CP7QjUz/v27TNOP/10Y/PmzUazZs2M5557zvMa/WyNvz6+6aabjNtuuy3gOZH8vkFGKgoUFhZq3bp16tmzp+dYpUqV1LNnT61atSqCLSs/cnJyJEl169aVJK1bt05ut9urz88++2w1bdqUPrdo+PDhuvrqq736UqKPnfLhhx/q/PPPV//+/dWgQQN17NhR//73vz2v79y5UwcPHvTq56SkJHXp0oV+Numiiy7S0qVL9dNPP0mSNmzYoK+++kp9+vSRRB87zUx/rlq1SrVr19b555/vKdOzZ09VqlRJa9asCXuby4OcnBy5XC7Vrl1bEn3slKKi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\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Split the tensor into two tensors of size [124, 1, 10, 10]\n", + "# Split the tensor using array indexing\n", + "tensor1 = transform[:, 0:1, :, :]\n", + "tensor2 = transform[:, 1:2, :, :]\n", + "\n", + "print(\"Original Tensor Size:\", transform.shape)\n", + "print(\"Tensor 1 Size:\", tensor1.shape)\n", + "print(\"Tensor 2 Size:\", tensor2.shape)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Nqh9gtwQNFM7", + "outputId": "bd37310e-2959-4418-ed96-f6b948992849" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Original Tensor Size: torch.Size([159, 2, 10, 10])\n", + "Tensor 1 Size: torch.Size([159, 1, 10, 10])\n", + "Tensor 2 Size: torch.Size([159, 1, 10, 10])\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "print('tensor1 max', tensor1.max())\n", + "print('tensor1 min', tensor1.min())\n", + "print('tensor2 max', tensor2.max())\n", + "print('tensor2 min',tensor2.min())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "O8wS4ML6OGQs", + "outputId": "aadd27f0-629b-4cb9-89b7-c24672d307cc" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "tensor1 max tensor(9, dtype=torch.int16)\n", + "tensor1 min tensor(0, dtype=torch.int16)\n", + "tensor2 max tensor(11, dtype=torch.int16)\n", + "tensor2 min tensor(0, dtype=torch.int16)\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "num_steps = tensor1.size(0)\n", + "# Reshape\n", + "tensor1_plot = tensor1.reshape((num_steps, -1))\n", + "print(tensor1_plot.size())\n", + "# raster plot\n", + "fig = plt.figure(facecolor=\"w\", figsize=(10, 5))\n", + "ax = fig.add_subplot(111)\n", + "splt.raster(tensor1_plot, ax, s=1.5, c=\"black\")\n", + "\n", + "plt.title(\"Input Layer (Polarity 1)\")\n", + "plt.xlabel(\"Time step\")\n", + "plt.ylabel(\"Neuron Number/Taxel Address\")\n", + "plt.show()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 504 + }, + "id": "xWyg_TSgNxJ0", + "outputId": "daa241e1-6862-4aff-c6fa-ac57b1c67633" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([159, 100])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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qkKFCvm+npSUpCpVqqhGjRrq0qWL0tPTNWvWLLVp00YrV65UZmamhgwZooiI//eR+vjjj6tcuXJeZ4T8HaPLOnTooGuuucbUNXljdqztcnlMf//9d1v7BYBgCHylJwDAlNKlS7vrgy6rUKFCnpobSWrQoEGefQ0bNtTHH38csPj8tXjxYv3rX//Sjh07dPHiRff+3EtHP/roo5o3b57Wrl2rm2++WStXrtSJEyf0yCOPuNscOHBAaWlpqlq1qtdznTx50mO7Xr16fsV6OWnw5vnnn9dNN92kUqVKqXLlymrcuLF7oYQjR45I+rOmJ6fo6GhdeeWV7tfzY3aMJP+vyRszY22Xy2Oa31LhABDOSJIAIEyUKlXK1v4cDofXL/85F4IIlLVr16pr1666+eab9fbbb6t69eqKiorSjBkzNGfOHI+2nTt3VmJioj788EPdfPPN+vDDD1WtWjWPhRSys7NVtWpVzZ492+v5cieXZhcYkP6sLfKWiF7WrFkz04s6+MOfMZL8u6b8mBlru1we08qVK9veNwAEGkkSABRBBw4cyLPvp59+8ijmr1Chgtdb9XLPbgTi//R/9tlnKl26tJYvX66YmBj3/hkzZuRpW6pUKT300EOaOXOmxo8frwULFujxxx/3SBqvuuoqrVy5Uu3bt7clWcipUaNG+uyzzywde3mxh/3793s8OygzM1OHDx8uMPnwZ4z8UdC/p5mxtsvhw4cVERGhhg0b2t43AAQaNUkAUAQtWLBAv/32m3t706ZN2rhxo+688073vquuukr79u3TqVOn3Pt++OEHrVu3zqOvuLg4SbL14aOlSpWSw+HIs3z5ggULvLZ/5JFHdObMGT3xxBM6f/58npXWevTooaysLI0ePTrPsZcuXSpU7O3atdOZM2e8JpS+dOzYUdHR0XrjjTc8Zu2Sk5OVlpamLl265Husv2Nk1uXaovzGxNdY22Xr1q1q0qSJEhISAtI/AAQSM0kAUATVr19fN954o/r376+LFy9q0qRJqlSpkp599ll3m6SkJL3++uvq3LmznE6nTp48qalTp6pJkyYeyzLHxsbqmmuu0bx589SwYUNVrFhRTZs2VdOmTQuM4bPPPtO+ffvy7O/du7e6dOmi119/XXfccYceeughnTx5Um+99Zbq16+vnTt35jmmVatWatq0qT755BM1btxY1157rcfr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5MmTuvbaaxUZGanIyEitWbNGb7zxhiIjI5WYmMj42qB69eq65pprPPY1btzYvarP5bHkb4d1zzzzjHs2qVmzZnrkkUc0dOhQ9wwpY2wvM+NZrVq1PIsWXbp0SadPn2bM/XQ5QTpy5IhWrFjhnkWSGOfCWrt2rU6ePKk6deq4PwePHDmiv//977riiiskMcaFVblyZUVGRvr8HAzV9w2SpCCIjo5W69attWrVKve+7OxsrVq1Su3atQthZEWXYRh66qmnNH/+fH399deqV6+ex+utW7dWVFSUx5jv379fv/zyC2Nuwm233aZdu3Zpx44d7p82bdqoV69e7v9mfAuvffv2eZau/+mnn1S3bl1JUr169VStWjWPcT579qw2btzIOJuUkZGhiAjPj7pSpUq5/w8mY2wvM+PZrl07paamauvWre42X3/9tbKzs3X99dcHPeai6nKCdODAAa1cuVKVKlXyeJ1xLpxHHnlEO3fu9PgcrFGjhp555hktX75cEmNcWNHR0Wrbtm2Bn4Mh/T4X0GUh4DZ37lwjJibGmDlzprFnzx6jb9++Rvny5Y2UlJRQh1Yk9e/f30hISDC++eYb4/jx4+6fjIwMd5t+/foZderUMb7++mtjy5YtRrt27Yx27dqFMOqiLefqdobB+Nph06ZNRmRkpPHyyy8bBw4cMGbPnm3ExcUZH374obvNuHHjjPLlyxsLFy40du7caXTr1s2oV6+e8ccff4Qw8qKjd+/eRs2aNY3Fixcbhw8fNj7//HOjcuXKxrPPPutuwxj759y5c8b27duN7du3G5KM119/3di+fbt7VTUz43nHHXcYrVq1MjZu3Gh89913RoMGDYyePXuG6pLCUkHjnJmZaXTt2tWoVauWsWPHDo/PwYsXL7r7YJwL5uu9nFvu1e0MgzH2xdcYf/7550ZUVJQxbdo048CBA8aUKVOMUqVKGWvXrnX3EarvGyRJQTRlyhSjTp06RnR0tHHdddcZ33//fahDKrIkef2ZMWOGu80ff/xhPPnkk0aFChWMuLg445577jGOHz8euqCLuNxJEuNrj0WLFhlNmzY1YmJijEaNGhnTpk3zeD07O9t47rnnjMTERCMmJsa47bbbjP3794co2qLn7NmzxuDBg406deoYpUuXNq688krjH//4h8cXScbYP6tXr/b697d3796GYZgbz//+979G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\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Reshape\n", + "tensor2_plot = tensor2.reshape((num_steps, -1))\n", + "print(tensor2_plot.size())\n", + "# raster plot\n", + "fig = plt.figure(facecolor=\"w\", figsize=(10, 5))\n", + "ax = fig.add_subplot(111)\n", + "splt.raster(tensor2_plot, ax, s=1.5, c=\"black\")\n", + "\n", + "plt.title(\"Input Layer (Polarity 2)\")\n", + "plt.xlabel(\"Time step\")\n", + "plt.ylabel(\"Neuron Number/Taxel Address\")\n", + "plt.show()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 504 + }, + "id": "dyXcO2-HN8Ae", + "outputId": "2b904fe5-30d3-4a5a-cb0e-d109d78b4250" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([159, 100])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0kAAAHWCAYAAACi1sL/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABYsklEQVR4nO3de5xNZf//8fces/cwg3GIcT7kEDlEqKTSXaJu31Q6SqX2vhPJsYRvdwe5c6iEdJC+EypKZyGEJCFyCpHcqBRD3c4zMdvM+v3Rz7733rNnZu01ax9mvJ6PxzwerWtf61qffY2Z2Z+u9bmWwzAMQwAAAAAASVJCrAMAAAAAgHhCkgQAAAAAfkiSAAAAAMAPSRIAAAAA+CFJAgAAAAA/JEkAAAAA4IckCQAAAAD8kCQBAAAAgB+SJAAAAADwQ5IEAICkv//977r//vsjNv69996revXq2T6uw+HQU089Zfu4Vm3btk2JiYnaunVrrEMBAMtIkgAgyqZPny6Hw6F169bFOhRJUlZWlp566il9+eWXpvp/+eWXcjgc+uCDDyIbWBStXLlSn3/+uYYNG+ZrO/M+z3w5nU6de+65uueee7R79+4YRluwVatW6amnntKRI0dsGzM3N1fTp09Xt27dVLt2baWkpKh58+b617/+pZMnTwb0Pf/889W1a1c98cQTtl0fAKItMdYBAABiKysrSyNHjpQkXXnllbENJkaee+45XX311WrYsGGe1wYMGKB27drJ6/Vqw4YNmjp1qubPn68tW7aoRo0aMYg20J9//qnExP/+OV+1apVGjhype++9VxUqVLDlGllZWbrvvvt0ySWXqE+fPqpatapWr16tJ598UkuXLtUXX3whh8Ph69+nTx/9/e9/165du9SgQQNbYgCAaCJJAgCUaIZh6OTJkypTpkzI1w8ePKj58+drypQpIV+//PLLdcstt0iS7rvvPjVu3FgDBgzQjBkzNGLEiIjFXZDc3FxlZ2erdOnSKl26dMSv53K5tHLlSl166aW+tvvvv1/16tXzJUqdOnXyvdapUydVrFhRM2bM0NNPPx3x+ADAbtxuBwBx4N5771XZsmX122+/6cYbb1TZsmVVpUoVPfLII8rJyfH1++mnn+RwOPT8889rwoQJqlu3rsqUKaOOHTvmqQG58sorQ64M+dfG/PTTT6pSpYokaeTIkb5by+yocXn++ed16aWXqnLlyipTpozatGmT5xa9jh076oILLgh5/nnnnacuXbr4jnNzczVx4kQ1a9ZMpUuXVlpamh544AEdPnw44Lx69erpf/7nf7Ro0SK1bdtWZcqU0WuvvZZvnPPnz9fp06cDPuQX5KqrrpIk7dmzx9f2yiuvqFmzZkpKSlKNGjXUr18/U7e7mZkj6a+6o4ceekgzZ870XWfhwoW+1858v5566ikNHTpUklS/fn3f9/Onn34Ka66DuVyugATpjJtuukmStH379oB2p9OpK6+8UnPmzCl0DgAgHpEkAUCcyMnJUZcuXVS5cmU9//zz6tixo8aPH6+pU6fm6fvmm2/qxRdfVL9+/TRixAht3bpVV111lQ4cOBDWNatUqaJXX31V0l8feN966y299dZb6t69e5Hfz6RJk9S6dWs9/fTTGj16tBITE3Xrrbdq/vz5vj533323Nm/enCfB+/bbb/Xjjz/qrrvu8rU98MADGjp0qDp06KBJkybpvvvu08yZM9WlSxd5vd6A83fs2KEePXrommuu0aRJk9SqVat841y1apUqV66sunXrmnpfu3btkiRVrlxZ0l+JSb9+/VSjRg2NHz9eN998s1577TV17tw5T1xW5uiML774QoMHD9btt9+uSZMmhdwEonv37urRo4ckacKECb7vZ5UqVcKaa7MyMjIkSeecc06e19q0aaOtW7fq2LFjYY8LADFnAACiatq0aYYk49tvv/W19erVy5BkPP300wF9W7dubbRp08Z3vGfPHkOSUaZMGePXX3/1ta9Zs8aQZAwePNjX1rFjR6Njx455rt+rVy+jbt26vuPff//dkGQ8+eSTpuJftmyZIcl4//33C+yXlZUVcJydnW00b97cuOqqq3xtR44cMUqXLm0MGzYsoO+AAQOMlJQU48SJE4ZhGMaKFSsMScbMmTMD+i1cuDBPe926dQ1JxsKFC029n8suuyxgjoPf5xtvvGH8/vvvxr59+4z58+cb9erVMxwOh/Htt98aBw8eNFwul9G5c2cjJyfHd+5LL73kO/eM4Hk3O0eGYRiSjISEBOP777/PE2fw9+65554zJBl79uwJ6Gd2rsPRqVMno3z58sbhw4fzvDZr1ixDkrFmzZqwxwWAWGMlCQDiSJ8+fQKOL7/88pA7qd14442qWbOm7/iiiy7SxRdfrM8++yzi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twMARFS1atV8X6mpqXI4HAFtZcuWzXO73ZVXXqn+/ftr0KBBqlixotLS0vT6668rMzNT9913n8qVK6eGDRtqwYIFAdfaunWrrrvuOpUtW1ZpaWm6++679ccff+Qb288//6zrr79eFStWVEpKipo1a6bPPvtMP/30k/72t79JkipWrCiHw6F7771XkpSbm6sxY8aofv36KlOmjC644AJ98MEHvjG//PJLORwOzZ8/Xy1btlTp0qV1ySWXaOvWrfZNKgAgokiSAABxacaMGTrnnHO0du1a9e/fX3379tWtt96qSy+9VBs2bFDnzp119913KysrS5J05MgRXXXVVWrdurXWrVunhQsX6sCBA7rtttvyvUa/fv106tQpffXVV9qyZYvGjRunsmXLqnbt2vrwww8lSTt27ND+/fs1adIkSdKYMWP05ptvasqUKfr+++81ePBg3XXXXVq+fHnA2EOHDtX48eP17bffqkqVKrr++uvl9XojNFsAADs5jHi7CRwAUGJNnz5dgwYN0pEjRwLa7733Xh05ckSffPKJpL9WknJycrRixQpJUk5OjlJTU9W9e3e9+eabkqSMjAxVr15dq1ev1iWXXKJ//etfWrFihRYtWuQb99dff1Xt2rW1Y8cONW7cOE88LVu21M0336wnn3wyz2uhapJOnTqlSpUqacmSJWrfvr2v7z/+8Q9lZWVp1qxZvvPeffdd3X777ZKkQ4cOqVatWpo+fXqBSRsAID5QkwQAiEstW7b0/XepUqVUuXJltWjRwteWlpYmSTp48KAk6bvvvtOyZctC1jft2rUrZJI0YMAA9e3bV59//rk6deqkm2++OeC6wf79738rKytL11xzTUB7dna2WrduHdDmn0RVqlRJ5513nrZv317QWwYAxAmSJABAXHI6nQHHDocjoO3Mrnm5ubmSpBMnTuj666/XuHHj8oxVvXr1kNf4xz/+oS5dumj+/Pn6/PPPNWbMGI0fP179+/cP2f/EiROSpPnz56tmzZoBryUlJZl8ZwCAeEeSBAAoES688EJ9+OGHqlevnhITzf95q127tvr06aM+ffpoxIgRev3119W/f3+5XC5Jf93qd8b555+vpKQk/fLLL+rYsWOB437zzTeqU6eOJOnw4cP68ccf1bRpUwvvDAAQbWzcAAAoEfr166dDhw6pR48e+vbbb7Vr1y4tWrRI9913X0Ci42/QoEFatGiR9uzZow0bNmjZsmW+RKZu3bpyOByaN2+efv/9d504cULlypXTI488osGDB2vGjBnatWuXNmzYoMmTJ2vGjBkBYz/99NNaunSptm7dqnvvvVfnnHMOD8wFgGKCJAkAUCLUqFFDK1euVE5Ojjp37qwWLVpo0KBBqlChghISQv+5y8nJUb9+/dS0aVNde+21aty4sV555RVJUs2aNTVy5EgNHz5caWlpeuihhyRJo0aN0uOPP64xY8b4zps/f77q168fMPbYsWM1cOBAtWnTRhkZGZo7d65vdQoAEN/Y3Q4AABuF2hUPAFC8sJIEAAAAAH5IkgAAAADAD7fbAQAAAIAfVpIAAAAAwA9JEgAAAAD4IUkCAAAAAD8kSQAAAADghyQJAAAAAPyQJAEAAACAH5IkAAAAAPBDkgQAAAAAfv4flmq4Zv2DXcIAAAAASUVORK5CYII=\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "fig, ax = plt.subplots()\n", + "time_steps = tensor1.size(0)\n", + "tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n", + "anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n", + "# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n", + "\n", + "print(target)\n", + "HTML(anim.to_html5_video())" + ], + "metadata": { + "id": "3Zf2uBFrUh7Y", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 907 + }, + "outputId": "a9e06b68-e9bd-44af-8745-cc90dc8226bd" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "5\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "" + ] + }, + "metadata": {}, + "execution_count": 20 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "fig, ax = plt.subplots()\n", + "time_steps = tensor2.size(0)\n", + "tensor2_plot = tensor2.reshape(time_steps, 10, 10)\n", + "anim = splt.animator(tensor2_plot, fig, ax, interval=10)\n", + "# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n", + "\n", + "print(target)\n", + "HTML(anim.to_html5_video())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 907 + }, + "id": "QMM2nWD3Zp4Z", + "outputId": "d55e923c-823b-48fd-8ac5-3f0142664650" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "5\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "" + ] + }, + "metadata": {}, + "execution_count": 21 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "transformed_dataset = []\n", + "\n", + "counter = 0\n", + "for sample in dataset:\n", + " events = sample[0]\n", + " target = sample[1]\n", + "\n", + " # Find unique time steps\n", + " time_steps = sorted(set(item[2] for item in events))\n", + " # print(time_steps)\n", + "\n", + " # Define matrix dimensions (assuming a fixed grid size, adjust as needed)\n", + " grid_size = (9, 9)\n", + "\n", + " # Initialize an empty tensor to store the matrices\n", + " matrices = []\n", + "\n", + " for time_step in time_steps:\n", + " # Create an empty matrix filled with zeros\n", + " matrix = torch.zeros(grid_size)\n", + "\n", + " # Fill the matrix with polarity values\n", + " for item in events:\n", + " x, y, t, p = item\n", + " if t == time_step:\n", + " matrix[y-1][x-1] = p\n", + " # if p == 1:\n", + " # matrix[y-1][x-1] = p\n", + " # else:\n", + " # matrix[y-1][x-1] = 1\n", + "\n", + " matrices.append(matrix)\n", + "\n", + " # Stack the matrices to form a tensor\n", + " tensor_of_matrices = torch.stack(matrices)\n", + "\n", + " # # Print the resulting tensor\n", + " # print(tensor_of_matrices[0])\n", + "\n", + " transformed_dataset.append((tensor_of_matrices, target))\n", + "\n", + " counter += 1\n", + " if counter % 1 == 0:\n", + " print(f\"Tensor {counter} is done!\")\n", + " if counter == 10:\n", + " break" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UoZ1MaYNwIgW", + "outputId": "f7e3d18f-3bdc-4ae6-de61-d074ab4e58a0" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Tensor 1 is done!\n", + "Tensor 2 is done!\n", + "Tensor 3 is done!\n", + "Tensor 4 is done!\n", + "Tensor 5 is done!\n", + "Tensor 6 is done!\n", + "Tensor 7 is done!\n", + "Tensor 8 is done!\n", + "Tensor 9 is done!\n", + "Tensor 10 is done!\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "spike_data_sample, target = transformed_dataset[1]\n", + "fig, ax = plt.subplots()\n", + "print(type(spike_data_sample))\n", + "spike_data_sample = spike_data_sample.transpose(1, 2)\n", + "anim = splt.animator(spike_data_sample, fig, ax, interval=5)\n", + "# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n", + "\n", + "print(target)\n", + "HTML(anim.to_html5_video())" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 925 + }, + "id": "5gcfTSBmwxTu", + "outputId": "d8c68138-b3af-4b8a-c5a2-b8d9673cd519" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "1\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "" + ] + }, + "metadata": {}, + "execution_count": 23 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "num_steps = spike_data_sample.size(0)\n", + "# Reshape\n", + "spike_plot = spike_data_sample.reshape((num_steps, -1))\n", + "print(spike_plot.size())\n", + "# raster plot\n", + "fig = plt.figure(facecolor=\"w\", figsize=(10, 5))\n", + "ax = fig.add_subplot(111)\n", + "splt.raster(spike_plot, ax, s=1.5, c=\"black\")\n", + "\n", + "plt.title(\"Input Layer\")\n", + "plt.xlabel(\"Time step\")\n", + "plt.ylabel(\"Neuron Number/Taxel Address\")\n", + "plt.show()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 504 + }, + "id": "Y7l3q58USEsQ", + "outputId": "8e166c16-cce3-43e0-ff6e-9e7b2badb959" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([168, 81])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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JQ7b9+rVS9ddd51efPHFStt78skn9dRTT1VYTk8VUHvYbDZZLBb7fGlpaY30ClXluN6qDQAAXJyneqqqPPpfZb9BdebMGb3++ut67rnn1LJlSz3zzDNOF3DZZZdp+/btKigo0Icffqjk5GRt2LDB6XbOmjRpksMIhYWFhYqOjq52ewB8j9lsVkpKit59912lpKTUWGipynG9VRsAAPCear9T9f7772vy5Mn673//q8cff1z33HOPAgOdHqG9gsTERLVp00a33nqrBgwYoJMnT6px48b29TExMUpPT79gz9kf8U4VUHvxThUAAHCG19+pOmvlypW6/PLLdf/992v06NHau3ev7r//frcEKkkqLy9XSUmJ4uPjZTabtXbtWvu67OxsHT58WAkJCW45FgD/5q3QUpXjEqgAAKg7qpyENm/erMcee0wbN27UfffdpzVr1qhZs2YuHXzSpEkaNGiQWrVqZX8va/369Vq1apWsVqtSU1OVmZmpsLAwhYaGavz48UpISKjyyH8AAAAA4GlVDlV9+vRRcHCw7rvvPsXGxmr+/PmVbvfggw9W+eDHjx/XXXfdpZycHFmtVsXFxWnVqlW6/vrrJf3+HldAQICGDRumkpISJSUl6Y033qhy+wAAAADgaVV+p6p169YymUwXbsxk0o8//uiWwtyFd6oAAAAASD4w+t/BgwfddlAAAAAAqC2cHqgCAAAAAPB/CFUAAAAA4AJCFQAAAAC4gFAFAAAAAC4gVAEAAACAC6o8+t8flZeXa9++fTp+/LjKy8sd1l1zzTVuKQwAAAAA/IHToWrjxo26/fbbdejQIZ37E1cmk0llZWVuKw4AAAAAfJ3Toeq+++5Tz549tXz5ckVGRl70B4EBAAAAoDZzOlTt3btXH374odq2beuJegAAAADArzg9UEXv3r21b98+T9QCAAAAAH7H6Z6q8ePH6+GHH1Zubq66du0qs9nssD4uLs5txQEAAACArzMZ5442cREBARU7t0wmkwzD8MmBKgoLC2W1WlVQUKDQ0FBvlwMAAADASzyVDZzuqTpw4IDbDg4AAAAA/s7pUBUTE+OJOgAAAADAL1Xrx3/379+vGTNmaPfu3ZKkTp066aGHHlKbNm3cWhwAAAAA+DqnR/9btWqVOnXqpM2bNysuLk5xcXHatGmTOnfurNWrV3uiRgAAAADwWU4PVNG9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GzbMYTuX7ycDbterVy8jLS3NPl9WVmZERUUZU6dO9WJV+KPjx48bkowNGzbYl/Xr18946KGHvFcUjClTphjdunWrdF1+fr5hNpuNRYsW2Zft3r3bkGRkZWXVUIU4n4ceesho06aNUV5ebhgG95MvkGR8/PHH9vny8nIjIiLCmDZtmn1Zfn6+ERQUZCxYsMAwDMPYtWuXIcn4+uuv7dusWLHCMJlMxk8//VRjtdcl516nymzevNmQZBw6dMi+LCYmxnjllVc8WxzsKrtOycnJxs0333zefbifal5V7qebb77Z6N+/v8Myd9xP9FS5WWlpqbZu3arExET7soCAACUmJiorK8uLleGPCgoKJElhYWEOy99//301a9ZMXbp00aRJk3Tq1ClvlFen7d27V1FRUbr00ks1atQoHT58WJK0detW2Ww2h3urQ4cOatWqFfeWl5WWluof//iHUlJSZDKZ7Mu5n3zLgQMHlJub63APWa1W9e7d234PZWVlqXHjxurZs6d9m8TERAUEBGjTpk01XjN+V1BQIJPJpMaNGzssf+GFF9S0aVN1795d06ZN05kzZ7xTYB22fv16tWjRQpdddpnGjRunX3/91b6O+8n35OXlafny5UpNTa2wztX7KdBdReJ3v/zyi8rKyhQeHu6wPDw8XHv27PFSVfij8vJypaenq2/fvurSpYt9+e23366YmBhFRUXpu+++02OPPabs7GwtXrzYi9XWLb1799bcuXN12WWXKScnR0899ZSuvvpq7dy5U7m5ubJYLBX+UREeHq7c3FzvFAxJ0pIlS5Sfn6/Ro0fbl3E/+Z6z90llfz+dXZebm6sWLVo4rA8MDFRYWBj3mZecPn1ajz32mEaOHKnQ0FD78gcffFA9evRQWFiYvvrqK02aNEk5OTl6+eWXvVht3TJw4EANHTpUsbGx2r9/v/7yl79o0KBBysrKUr169biffNB7772nRo0aVXh1wB33E6EKdU5aWpp27tzp8K6OJIdnnLt27arIyEgNGDBA+/fvV5s2bWq6zDpp0KBB9j/HxcWpd+/eiomJ0T//+U8FBwd7sTJcyOzZszVo0CBFRUXZl3E/Aa6z2WwaMWKEDMPQm2++6bAuMzPT/ue4uDhZLBbde++9mjp1qoKCgmq61Drptttus/+5a9euiouLU5s2bbR+/XoNGDDAi5XhfN59912NGjVK9evXd1jujvuJx//crFmzZqpXr16FEcny8vIUERHhpapw1gMPPKBly5Zp3bp1uuSSSy64be/evSVJ+/btq4nSUInGjRurffv22rdvnyIiIlRaWqr8/HyHbbi3vOvQoUNas2aN7r777gtux/3kfWfvkwv9/RQREVFhUKUzZ87oxIkT3Gc17GygOnTokFavXu3QS1WZ3r1768yZMzp48GDNFIgKLr30UjVr1sz+3znuJ9/yxRdfKDs7+6J/X0nVu58IVW5msVgUHx+vtWvX2peVl5dr7dq1SkhI8GJldZthGHrggQf08ccf61//+pdiY2Mvus/27dslSZGRkR6uDudTVFSk/fv3KzIyUvHx8TKbzQ73VnZ2tg4fPsy95UVz5sxRixYtdOONN15wO+4n74uNjVVERITDPVRYWKhNmzbZ76GEhATl5+dr69at9m3+9a9/qby83B6M4XlnA9XevXu1Zs0aNW3a9KL7bN++XQEBARUeN0PNOXr0qH799Vf7f+e4n3zL7NmzFR8fr27dul102+rcTzz+5wGZmZlKTk5Wz5491atXL82YMUPFxcUaM2aMt0urs9LS0jR//nx98sknatSokf1ZZqvVquDgYO3fv1/z58/Xn/70JzVt2lTfffedMjIydM011yguLs7L1dcdEyZM0ODBgxUTE6Njx45pypQpqlevnkaOHCmr1arU1FRlZmYqLCxMoaGhGj9+vBISEtSnTx9vl14nlZeXa86cOUpOTlZg4P/9dcL95D1FRUUOvYEHDhzQ9u3bFRYWplatWik9PV3PPvus2rVrp9jYWD3xxBOKiorSkCFDJEkdO3bUwIEDNXbsWM2aNUs2m00PPPCAbrvtNofHO+GaC12nyMhI3XLLLdq2bZuWLVumsrIy+99ZYWFhslgsysrK0qZNm3TdddepUaNGysrKUkZGhu644w41adLEW6dV61zoOoWFhempp57SsGHDFBERof379+vRRx9V27ZtlZSUJIn7qaZc7L970u//A2nRokWaPn16hf3ddj+5NHYgzuu1114zWrVqZVgsFqNXr17Gxo0bvV1SnSap0mnOnDmGYRjG4cOHjWuuucYICwszgoKCjLZt2xqPPPKIUVBQ4N3C65hbb73ViIyMNCwWi9GyZUvj1ltvNfbt22df/9///te4//77jSZNmhgNGjQw/vznPxs5OTlerLhuW7VqlSHJyM7OdljO/eQ969atq/S/dcnJyYZh/D6s+hNPPGGEh4cbQUFBxoABAypcv19//dUYOXKkERISYoSGhhpjxowxfvvtNy+cTe11oet04MCB8/6dtW7dOsMwDGPr1q1G7969DavVatSvX9/o2LGj8fzzzxunT5/27onVMhe6TqdOnTJuuOEGo3nz5obZbDZiYmKMsWPHGrm5uQ5tcD953sX+u2cYhvHWW28ZwcHBRn5+foX93XU/mQzDMKoewQAAAAAAf8Q7VQAAAADgAkIVAAAAALiAUAUAAAAALiBUAQAAAIALCFUAAAAA4AJCFQAAAAC4gFAFAAAAAC4gVAEAAACACwhVAACvGz16tIYMGeLtMgAAqJZAbxcAAKjdTCbTBddPmTJFM2fOlGEYNVRR1axfv17XXXedTp48qcaNG3u7HACADyNUAQA8Kicnx/7nhQsXavLkycrOzrYvCwkJUUhIiDdKAwDALXj8DwDgUREREfbJarXKZDI5LAsJCanw+N+1116r8ePHKz09XU2aNFF4eLjeeecdFRcXa8yYMWrUqJHatm2rFStWOBxr586dGjRokEJCQhQeHq4777xTv/zyy3lrO3TokAYPHqwmTZqoYcOG6ty5sz777DMdPHhQ1113nSSpSZMmMplMGj16tCSpvLxcU6dOVWxsrIKDg9WtWzd9+OGH9jbXr18vk8mk5cuXKy4uTvXr11efPn20c+dO932oAACfQqgCAPik9957T82aNdPmzZs1fvx4jRs3TsOHD9eVV16pbdu26YYbbtCdd96pU6dOSZLy8/PVv39/de/eXVu2bNHKlSuVl5enESNGnPcYaWlpKikp0b///W/t2LFDL774okJCQhQdHa2PPvpIkpSdna2cnBzNnDlTkjR16lTNmzdPs2bN0vfff6+MjAzdcccd2rBhg0PbjzzyiKZPn66vv/5azZs31+DBg2Wz2Tz0aQEAvMlk+NpD7ACAWmvu3LlKT09Xfn6+w/LRo0crPz9fS5YskfR7T1VZWZm++OILSVJZWZmsVquGDh2qefPmSZJyc3MVGRmprKws9enTR88++6y++OILrVq1yt7u0aNHFR0drezsbLVv375CPXFxcRo2bJimTJlSYV1l71SVlJQoLCxMa9asUUJCgn3bu+++W6dOndL8+fPt+33wwQe69dZbJUknTpzQJZdcorlz514w5AEA/BPvVAEAfFJcXJz9z/Xq1VPTpk3VtWtX+7Lw8HBJ0vHjxyVJ3377rdatW1fp+1n79++vNFQ9+OCDGjdunD7//HMlJiZq2LBhDsc91759+3Tq1Cldf/31DstLS0vVvXt3h2V/DF1hYWG67LLLtHv37gudMgDATxGqAAA+yWw2O8ybTCaHZWdHFSwvL5ckFRUVafDgwXrxxRcrtBUZGVnpMe6++24lJSVp+fLl+vzzzzV16lRNnz5d48ePr3T7oqIiSdLy5cvVsmVLh3VBQUFVPDMAQG1DqAIA1Ao9evTQRx99pNatWyswsOp/vUVHR+u+++7Tfffdp0mTJumdd97R+PHjZbFYJP3+6OFZnTp1UlBQkA4fPqx+/fpdsN2NGzeqVatWkqSTJ0/qhx9+UMeOHatxZgAAX8dAFQCAWiEtLU0nTpzQyJEj9fXXX2v//v1atWqVxowZ4xCM/ig9PV2rVq3SgQMHtG3bNq1bt84efGJiYmQymbRs2TL9/PPPKioqUqNGjTRhwgRlZGTovffe0/79+7Vt2za99tpreu+99xzafvrpp7V27Vrt3LlTo0ePVrNmzfiBYwCopQhVAIBaISoqSl9++aXKysp0ww03qGvXrkpPT1fjxo0VEFD5X3dlZWVKS0tTx44dNXDgQLVv315vvPGGJKlly5Z66qmnNHHiRIWHh+uBBx6QJD3zzDN64oknNHXqVPt+y5cvV2xsrEPbL7zwgh566CHFx8crNzdXS5cutfd+AQBqF0b/AwDAjSobNRAAULvRUwUAAAAALiBUAQAAAIALePwPAAAAAFxATxUAAAAAuIBQBQAAAAAuIFQBAAAAgAsIVQAAAADgAkIVAAAAALiAUAUAAAAALiBUAQAAAIALCFUAAAAA4IL/D2all+Ni6H4kAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [ + "spike_data_sample.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bXAQ5uwNPWyS", + "outputId": "e62e2e36-40d6-4b2f-ba8d-b01fd5e6d5bb" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "torch.Size([168, 9, 9])" + ] + }, + "metadata": {}, + "execution_count": 25 + } + ] + }, + { + "cell_type": "code", + "source": [ + "transform.shape" + ], + "metadata": { + "id": "Z8OC_Jwvw1uG", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "436e0f9c-e188-448f-ef9b-4acd0f2fa65c" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "torch.Size([159, 2, 10, 10])" + ] + }, + "metadata": {}, + "execution_count": 26 + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "ZsM1fecnPrmL" + }, + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file From 583b77c47e042ef5fa62f183426cc9065fe77320 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 00:45:30 -0800 Subject: [PATCH 02/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 9043367b..561040bb 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -54,6 +54,12 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb + * - `Tutorial 8 `_ + - Training on STMNIST with Tonic + snnTorch + - .. image:: https://colab.research.google.com/assets/colab-badge.svg + :alt: Open In Colab + :target: https://colab.research.google.com/drive/1YOoq_E_ndtO9VRCUQwmflLPNr5FssATq?usp=sharing + .. list-table:: @@ -83,4 +89,4 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable - — -Future tutorials on spiking neurons and training are under development. \ No newline at end of file +Future tutorials on spiking neurons and training are under development. From e4068a9859d4e46192f3b417ca1b5d796a59f4bf Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:42:56 -0800 Subject: [PATCH 03/13] Add files via upload --- examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb diff --git a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb new file mode 100644 index 00000000..0f324eac --- /dev/null +++ b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"markdown","metadata":{"id":"0PD5VPOUr4bs"},"source":["[](https://github.com/jeshraghian/snntorch/)\n","[](https://github.com/neuromorphs/tonic/)\n","\n","\n","# Training on ST-MNIST with Tonic + snnTorch\n","\n","##### By:\n","#### Dylan Louie (djlouie@ucsc.edu),\n","####Hannah Cohen Sandler (hcohensa@ucsc.edu),\n","####Shatoparba Banerjee (sbaner12@ucsc.edu)\n","##### Credits to our Professor: Jason K. Eshraghian (www.ncg.ucsc.edu)\n","\n","\n"," \"Open\n","\n"]},{"cell_type":"markdown","metadata":{"id":"iawcPZ7DtDqK"},"source":["For a comprehensive overview on how SNNs work, and what is going on under the hood, [then you might be interested in the snnTorch tutorial series available here.](https://snntorch.readthedocs.io/en/latest/tutorials/index.html)\n","The snnTorch tutorial series is based on the following paper. If you find these resources or code useful in your work, please consider citing the following source:\n","\n","> [Jason K. Eshraghian, Max Ward, Emre Neftci, Xinxin Wang, Gregor Lenz, Girish Dwivedi, Mohammed Bennamoun, Doo Seok Jeong, and Wei D. Lu. \"Training Spiking Neural Networks Using Lessons From Deep Learning\". Proceedings of the IEEE, 111(9) September 2023.](https://ieeexplore.ieee.org/abstract/document/10242251) "]},{"cell_type":"code","execution_count":98,"metadata":{"id":"W-v36rDBv41L","executionInfo":{"status":"ok","timestamp":1702496302809,"user_tz":480,"elapsed":12457,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["!pip install tonic --quiet\n","!pip install snntorch --quiet"]},{"cell_type":"code","execution_count":99,"metadata":{"id":"6WWIF2I1v7sA","executionInfo":{"status":"ok","timestamp":1702496302809,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["import tonic\n","import tonic.transforms as transforms # Not to be mistaken with torchdata.transfroms\n","from tonic import DiskCachedDataset\n","import torch\n","from torch.utils.data import random_split\n","from torch.utils.data import DataLoader\n","import torchvision\n","import torch.nn as nn\n","import snntorch as snn\n","from snntorch import surrogate\n","import snntorch.spikeplot as splt\n","from snntorch import functional as SF\n","from snntorch import utils\n","import matplotlib.pyplot as plt\n","from IPython.display import HTML\n","from IPython.display import display\n","import numpy as np\n","import torchdata\n","import os\n","from ipywidgets import IntProgress\n","import time"]},{"cell_type":"markdown","metadata":{"id":"McXriEu-tJV6"},"source":["# 1. STMNIST"]},{"cell_type":"markdown","metadata":{"id":"wsV-uUeZ6a2A"},"source":["## 1.1 A Description\n","\n","The Spiking Tactile-MNIST (ST-MNIST) dataset is a novel neuromorphic collection featuring handwritten digits (0-9) inscribed by 23 individuals on a 100-taxel biomimetic event-based tactile sensor array. This dataset, publicly available to facilitate research in tactile perception, captures the dynamic pressure changes associated with natural writing. The tactile sensing system, Asynchronously Coded Electronic Skin (ACES), emulates the human peripheral nervous system, transmitting fast-adapting (FA) responses as asynchronous electrical events.\n","\n","More information about the ST-MNIST dataset can found by the paper written by its authors:\n","\n","> H. H. See, B. Lim, S. Li, H. Yao, W. Cheng, H. Soh, and B. C. K. Tee, \"ST-MNIST - The Spiking Tactile-MNIST Neuromorphic Dataset,\" A PREPRINT, May 2020. [Online]. Available: https://arxiv.org/abs/2005.04319 \n","\n"]},{"cell_type":"markdown","metadata":{"id":"Ickp0FA4_nBR"},"source":["##1.2 Download the STMNIST dataset\n","\n","The data of ST-MNIST is provided with the MAT format. We are working in Python, so we need a way to import that MAT data into Python. Luckily, Tonic has created a function that creates an IterDataPipe that reads out and transforms the data into an (x, y, t, p) format when provided a path to it. (More down below)\n","\n","The first thing you must do is download the compressed dataset by accessing: https://scholarbank.nus.edu.sg/bitstream/10635/168106/2/STMNIST%20dataset%20NUS%20Tee%20Research%20Group.zip\n","\n","The zip file that you download will be titled `STMNIST dataset NUS Tee Research Group`. You must create a folder/directory titled `STMNIST` and then put that zip file in the folder/directory. This will be necessary for the Tonic class we use later.\n","\n","You then must either put it somewhere you can provide a path to it on your local machine or your Google Drive. For the purposes of this tutorial we will assume Google Drive."]},{"cell_type":"markdown","metadata":{"id":"DnDx0axoCphC"},"source":["## 1.3 Mount to Drive\n","Assuming you now have the `STMNIST` directory containing the zip file somewhere in your Google Drive. We must now \"mount\" Google Drive to this notebook so that it can access it. This is done with the code below:"]},{"cell_type":"code","execution_count":100,"metadata":{"id":"c2PcG-B3v9K8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702496303765,"user_tz":480,"elapsed":958,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"c3902405-8c9a-4f13-ddf9-2abb8bcdbb55"},"outputs":[{"output_type":"stream","name":"stdout","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"]}],"source":["# Load the Drive helper and mount\n","from google.colab import drive\n","\n","# This will prompt for authorization.\n","drive.mount('/content/drive')"]},{"cell_type":"markdown","source":["Here is the path to the file in our drive, change it to where it is in yours"],"metadata":{"id":"1yJJr7k4q0p-"}},{"cell_type":"code","execution_count":101,"metadata":{"id":"00hHZOeuv-8k","executionInfo":{"status":"ok","timestamp":1702496303765,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# After executing the cell above, Drive files will be present in \"/content/drive/My Drive\".\n","# Here is the path to the file in our drive, change it to where it is in yours\n","root = \"/content/drive/My Drive/STMNIST_Tutorial\" # similar to os.path.join('drive', 'My Drive', 'Finalized_STMNIST')"]},{"cell_type":"markdown","source":["The following cell blocks is to make sure you edited the above path correctly. If you get a `FileNotFoundError: [Errno 2] No such file or directory:` error or a `ls: cannot access '/content/drive/My Drive/the/path/you/put/in': No such file or directory` error that means you didn't edit the above path correctly and you are pathing to a directory that doesn't exist. Furthermore make sure that the directory STMNIST (which you made and has your zip file is in) is in the directory you are pathing to."],"metadata":{"id":"1434lW43N5aR"}},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 1\n","os.listdir(root) # same as os.listdir(\"/content/drive/My Drive/STMNIST_Tutorial\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2FqIu1QaHPi4","executionInfo":{"status":"ok","timestamp":1702496351818,"user_tz":480,"elapsed":169,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"9d7da518-2c0e-441b-8866-269906567ae9"},"execution_count":105,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['STMNIST', 'ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb']"]},"metadata":{},"execution_count":105}]},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 2\n","!ls \"/content/drive/My Drive/STMNIST_Tutorial\""],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ynCJsU_HHOxV","executionInfo":{"status":"ok","timestamp":1702496354637,"user_tz":480,"elapsed":171,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"93e024de-c4f8-480d-b429-9b877a72ada2"},"execution_count":106,"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb\n"]}]},{"cell_type":"markdown","metadata":{"id":"OOfqmhKcIOR0"},"source":["## 1.4 ST-MNIST through Tonic\n","Now we call the `tonic` function to create the class that returns a IterDataPipe of the dataset. The docs for that function can be found here: https://tonic.readthedocs.io/en/latest/generated/tonic.prototype.datasets.STMNIST.html#tonic.prototype.datasets.STMNIST"]},{"cell_type":"code","execution_count":107,"metadata":{"id":"4r9zaUjHwAcM","executionInfo":{"status":"ok","timestamp":1702496365403,"user_tz":480,"elapsed":355,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["dataset = tonic.prototype.datasets.STMNIST(root=root,\n"," keep_compressed = False, shuffle = False)"]},{"cell_type":"markdown","metadata":{"id":"AgwoqxsAMdqP"},"source":["Because the dataset is an IterDataPipe, it can not be indexed into. Instead, we use `next(iter())` in order to iterate through it.\n","\n","In the above code `dataset` has been set to the returned DataPipe, so now I will just refer to `dataset`. Tonic formats the STMNIST dataset into an `(x, y, t, p)` format just like its other datasets so that the data will be compatable with other parts of its library. Where `x` is the position on the x-axis, `y` is the position on the y-axis, `t` is a timestamp, and `p` is polarity (1 or 0).\n","\n","Each iteration of dataset returns a tuple. The first index of the tuple contains a numpy array of `(x, y, t, p)` tuples which represents a series of sparse matrix through time of the recordings on the tactile sensor. The second index is a integer 0-9 which is the \"label\" of the data representing what number the afformentioned events is a drawing of."]},{"cell_type":"code","execution_count":108,"metadata":{"id":"2nRzg5A0RegL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702496366543,"user_tz":480,"elapsed":357,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"19ebec11-4933-4942-8bd2-695f860d691a"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","4389\n","(2, 3, 199891, 0)\n","8\n"]}],"source":["print(type(dataset))\n","events, target = next(iter(dataset))\n","print(type(events))\n","print(len(events))\n","print(events[0])\n","print(target)"]},{"cell_type":"markdown","metadata":{"id":"7mWT1BXPdeuM"},"source":["Now that the data is out of the MAT file and into the (x,y,t,p) format we now need it to be in a form that our neural network can read. Luckily Tonic has transformations that do that for us as its other datasets use the (x,y,t,p) format. When you run the code below, the `.ToFrame()` function from `tonic.transforms` changes it from an (x,y,t,p) format to a numpy array matrix."]},{"cell_type":"code","execution_count":42,"metadata":{"id":"Alt1gJkWSqjy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491043756,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"de418cf3-426b-41bb-f40a-50237888cd5c"},"outputs":[{"output_type":"stream","name":"stdout","text":["----------------------------\n","\n","----------------------------\n","1518\n","----------------------------\n","\n","----------------------------\n","2\n","----------------------------\n","[[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 3 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","\n"," [[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 3 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[0 0 0 0 0 0 0 0 0 0]\n","----------------------------\n","\n","----------------------------\n","0\n"]}],"source":["sensor_size = tuple(tonic.prototype.datasets.STMNIST.sensor_size.values()) # The sensor size for STMNIST is (10, 10, 2) btw\n","# transforms is the same as tonic.transforms check the imports above if you want to make sure\n","frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=sensor_size,\n"," time_window=1000)\n"," ])\n","\n","copy_events = frame_transform(events)\n","print('----------------------------')\n","print(type(copy_events))\n","print('----------------------------')\n","print(len(copy_events))\n","print('----------------------------')\n","print(type(copy_events[0]))\n","print('----------------------------')\n","print(len(copy_events[0]))\n","print('----------------------------')\n","print(copy_events[0])\n","print('----------------------------')\n","print(type(copy_events[0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0]))\n","print('----------------------------')\n","print(copy_events[0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0][0])"]},{"cell_type":"markdown","metadata":{"id":"AbRLjFPEqf6M"},"source":["### 1.4.1 The advantages of ST-MNIST over N-MNIST\n","At the time of release, the closest neuromorphic dataset to ST-MNIST was the N-MNIST dataset which used a moving motion-sensing event-based camera on static images of the original MNIST set (2-d digit classification) to simulate movement. What makes the ST-MNIST dataset better is that the dataset is actually taken from people writing on 10 by 10 tactile pixel sensors. That means when a neural network learns from a dataset it actually has to look at it temporally rather than purely spatially. In N-MNIST every frame would have the digit fully shown, however, for ST-MNIST it only shows parts of it as the participants write over it. That means that as a neuromorphic dataset taking advantage of the spiking and temporal benefits of a SNN ST-MNIST is better than N-MNIST.\n"]},{"cell_type":"markdown","metadata":{"id":"l3CJDa1LnUzd"},"source":["Using `tonic.utils.plot_animation`, the frame transform, and also some rotation. We can create an animation of the data and visualize this."]},{"cell_type":"code","execution_count":43,"metadata":{"id":"kOFkuUfrplsg","executionInfo":{"status":"ok","timestamp":1702491044156,"user_tz":480,"elapsed":401,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Iterate to a new iteration\n","events, target = next(iter(dataset))"]},{"cell_type":"code","execution_count":44,"metadata":{"id":"maDf7TLHmUiw","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702491044590,"user_tz":480,"elapsed":437,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"cb4630d8-d489-46b7-966f-979f81e7abe1"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 0\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGVElEQVR4nO3csW1VQRRFUQb9HIkSyNyOK6EqQjJqISSniUtsyUYjsR/zQGvFE5xs6yazZmbeAcAfen96AAD/B0EBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJx+7DtdaVOwC4sZ1PVVwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAxOP0AHjh6fn0gtd9/3p6AdyeCwWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJNTOz9XCtq7cAcFM7qXChAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoAicfpARzw9Pn0grd9+nl6weu+fTm9AG7PhQJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYDEmpnZerjW1Vv4Wz6eHvAbH04PeMOP0wPgrJ1UuFAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYDEmpnZerjW1VsAuKmdVLhQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBIPHYfTgzV+4A4B/nQgEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASDxCwvHKByDTyT+AAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":44}],"source":["from IPython.display import HTML\n","\n","frame_transform_tonic_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=90000,\n",")\n","\n","frames = frame_transform_tonic_visual(events)\n","frames = frames / np.max(frames)\n","frames = np.rot90(frames, k=-1, axes=(2, 3))\n","frames = np.flip(frames, axis=3)\n","\n","# Print out the Target\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","animation = tonic.utils.plot_animation(frames)\n","\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"w52aUd2qoyXV"},"source":["We can also use `snntorch.spikeplot`"]},{"cell_type":"code","execution_count":45,"metadata":{"id":"bPwRVZgqo8EH","colab":{"base_uri":"https://localhost:8080/","height":925},"executionInfo":{"status":"ok","timestamp":1702491047680,"user_tz":480,"elapsed":3092,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"af750230-a488-441d-927f-2da59b4c02b7"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 0\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n"},"metadata":{}}],"source":["frame_transform_snntorch_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=8000,\n",")\n","\n","tran = frame_transform_snntorch_visual(events)\n","tran = np.rot90(tran, k=-1, axes=(2, 3))\n","tran = np.flip(tran, axis=3)\n","tran = torch.from_numpy(tran)\n","\n","tensor1 = tran[:, 0:1, :, :]\n","tensor2 = tran[:, 1:2, :, :]\n","\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","\n","fig, ax = plt.subplots()\n","time_steps = tensor1.size(0)\n","tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n","anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n","# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n","\n","display(HTML(anim.to_html5_video()))"]},{"cell_type":"code","execution_count":46,"metadata":{"id":"F5eZvTHHr5qS","executionInfo":{"status":"ok","timestamp":1702491047904,"user_tz":480,"elapsed":226,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_sensor_size = tonic.datasets.NMNIST.sensor_size\n","nmnist_frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=nmnist_sensor_size,\n"," time_window=3000)\n"," ])\n","\n","nmnist_dataset = tonic.datasets.NMNIST(save_to='./tmp/nmnist_example_data', transform=nmnist_frame_transform, train=False)"]},{"cell_type":"code","execution_count":47,"metadata":{"id":"Tz3HlO9zsdls","executionInfo":{"status":"ok","timestamp":1702491047904,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_events, nmnist_target = nmnist_dataset[0]"]},{"cell_type":"code","execution_count":48,"metadata":{"id":"pe47llhqu00o","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":4675,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"fd373c32-2630-45cf-dfa5-b46b1b600012"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of N-MNIST\n","The target label is: 8\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGe0lEQVR4nO3cMY4bMRAAQdPYL+qVeuTcBwzfLtw8rayqeIIBk8YkXDMzvwDgH/1+9QIA/B8EBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJI6zg2utnXsAcGNnPlVxoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AcBePC7PPbVvwvlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMSamTk1uNbuXQC4qTOpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAInj1QsAFzwuzj+3bAF/5EIBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJNbMzKnBtXbvAtSufNXimxb+4kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhK9XAPiWr1cA+DGCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkjlcvALyhx8X555YtuBkXCgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASCxZmZODa61excAbupMKlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AsNHjwuxz2xZ8CBcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7FwBu6kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQOF69wEd4XJx/btniM1x5a+8MKRcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7F+5m1zcmvqKBt3MmFS4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQMLXKwB8y9crAPwYQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMRxdnBmdu4BwJtzoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJD4AihVRw5/WD3pAAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":48}],"source":["# Print out the Target\n","print('Animation of N-MNIST')\n","print('The target label is:',nmnist_target)\n","# normalize values to between 0-1\n","nmnist_events_fraction = nmnist_events / np.max(nmnist_events)\n","animation = tonic.utils.plot_animation(nmnist_events_fraction)\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"92McQkLgd_xI"},"source":["A printout of the sensor size of the ST-MNIST and N-MNIST dataset. (10, 10, 2) menas a 10 by 10 pixel dataset with a channel size of 2. (34, 34, 2) means a 34 by 34 pixel dataset with a channel size of 2."]},{"cell_type":"code","execution_count":49,"metadata":{"id":"mou11FujsL-v","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":14,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"434c36d7-b445-4e92-aa76-9e5f707dea81"},"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST {'x': 10, 'y': 10, 'p': 2}\n","NMNIST (34, 34, 2)\n"]}],"source":["print('STMNIST', tonic.prototype.datasets.STMNIST.sensor_size)\n","print('NMNIST', tonic.datasets.NMNIST.sensor_size)"]},{"cell_type":"markdown","metadata":{"id":"CzYgPlxWfdm_"},"source":["There is a total of 6953 recordings in this dataset. This lines up with what is said in the ST-MNIST paper. They invited in 23 participants to write around 30 times each for 9 digits."]},{"cell_type":"code","execution_count":50,"metadata":{"id":"_v1auSbyepQr","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":12,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8edb9613-7c90-4d0f-ae67-b3d1691f8c98"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n"]}],"source":["print(len(dataset)) # 23 participants writing around 30 times each for 9 digits 23*30*9 = 6210"]},{"cell_type":"markdown","metadata":{"id":"tlX9jWV0f_az"},"source":["##1.5 Lets create a trainset and testset!"]},{"cell_type":"markdown","metadata":{"id":"hqQzVEHEgSFp"},"source":["Unfortunately unlike N-MNIST, ST-MNIST isn't already seperated into a trainset and testset on tonic. That means we will have to seperate that manually. For this example you could do 80% of the dataset for the trainset and 20% for the testset which we calculate below."]},{"cell_type":"code","execution_count":51,"metadata":{"id":"ZXw_xyfetX_K","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":11,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"a93982aa-2e9a-4671-9510-63d20ab07ea5"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n","5562\n","1391\n"]}],"source":["# Calculate the sizes for the training and testing sets\n","total_size = len(dataset)\n","print(total_size)\n","# train_size is 80% of total size\n","train_size = int(0.8 * total_size)\n","print(train_size)\n","test_size = total_size - train_size\n","print(test_size)"]},{"cell_type":"code","execution_count":52,"metadata":{"id":"d_6BFKiXJdWU","executionInfo":{"status":"ok","timestamp":1702491052753,"user_tz":480,"elapsed":186,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["sensor_size = tonic.prototype.datasets.STMNIST.sensor_size\n","sensor_size = tuple(sensor_size.values())\n","\n","# Define a transform\n","frame_transform = transforms.Compose([transforms.ToFrame(sensor_size=sensor_size, time_window=1000)])"]},{"cell_type":"markdown","metadata":{"id":"iSMhDsHliQk5"},"source":["The following code reads out the entirety of the dataset from the IterDataPipe and then transforms the events using the `frame_transform` above. It also seperates out the data into a trainset and a testset. Remember that each time a piece of data is read out of the datapipe it is read and transformed from the MAT files using tonic. On top of that we are to the .ToFrame() transform over it each time. Thus, this takes some time.\n","\n","**You have two options here:**\n","\n","Transform and tain on a small part of the dataset, this is faster and is the default for the sake of a short easy to run tutorial. The default for this shorter transform is 640 pieces of data for the trainset and 320 pieaces of data for the testset. This takes ~4-5 minutes. Feel free to change this, just be aware that the number of pieces of data we transform and the time it takes have an inverse relationship.\n","\n","**Or** you can transform and convert the entire dataset; this takes ~30-60 minutes. To do that comment out the `shorter_transform_STMNIST` cell block and uncomment the `full_transform_STMNIST` cell block and run that instead. If you choose this: kickback, take a break and eat a snack while this happens. perhaps even count kangaroos to take a nap or do a shoey and get schwasted instead.\n","\n","Note: A smaller dataset generally means a higher accuracy but less generalizability on new data when training a neural network on it given the same amount of time."]},{"cell_type":"code","source":["def shorter_transform_STMNIST(data, transform):\n"," short_train_size = 640\n"," short_test_size = 320\n","\n"," train_bar = IntProgress(min=0, max=short_train_size)\n"," test_bar = IntProgress(min=0, max=short_test_size)\n","\n"," testset = []\n"," trainset = []\n","\n"," print('Porting over and transforming the trainset.')\n"," display(train_bar)\n"," for _ in range(short_train_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," trainset.append((events, target))\n"," train_bar.value += 1\n"," print('Porting over and transforming the testset.')\n"," display(test_bar)\n"," for _ in range(short_test_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," testset.append((events, target))\n"," test_bar.value += 1\n","\n"," return (trainset, testset)\n","\n","# Get the start time\n","start_time = time.time()\n","\n","# Call the function\n","trainset, testset = shorter_transform_STMNIST(dataset, frame_transform)\n","\n","# Get the end time\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":133,"referenced_widgets":["6dd945b6627844c1b3808b9ea8ab6646","fb003723433d4e8db855b590fdfbfedd","dc2254cf2e894a21a689246a66f0dfce","aec192c607bf40b9a45a1f2b064ba30e","845cc10adccf489f8fecf05cc6fe2f93","d3ea533e5b164139abba9ab6f2c0a5ac"]},"id":"c0qw8uduLpZv","executionInfo":{"status":"ok","timestamp":1702491266338,"user_tz":480,"elapsed":213588,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"cb18839a-6b13-43cf-c00c-de3e192bc30f"},"execution_count":53,"outputs":[{"output_type":"stream","name":"stdout","text":["Porting over and transforming the trainset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=640)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"6dd945b6627844c1b3808b9ea8ab6646"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Porting over and transforming the testset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=320)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"aec192c607bf40b9a45a1f2b064ba30e"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Elapsed time: 3 minutes, 33 seconds, 820 milliseconds\n"]}]},{"cell_type":"code","execution_count":74,"metadata":{"id":"muL3A2dbMYTY","executionInfo":{"status":"ok","timestamp":1702493968118,"user_tz":480,"elapsed":166,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# def full_transform_STMNIST(data, transform):\n","# train_bar = IntProgress(min=0, max=train_size)\n","# test_bar = IntProgress(min=0, max=test_size)\n","\n","# testset = []\n","# trainset = []\n","\n","# print('Porting over and transforming the trainset.')\n","# display(train_bar)\n","# for _ in range(train_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# trainset.append((events, target))\n","# train_bar.value += 1\n","# print('Porting over and transforming the testset.')\n","# display(test_bar)\n","# for _ in range(test_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# testset.append((events, target))\n","# test_bar.value += 1\n","\n","# return (trainset, testset)\n","\n","# # Get the start time\n","# start_time = time.time()\n","\n","# # Call the function\n","# trainset, testset = full_transform_STMNIST(dataset, frame_transform)\n","\n","# # Get the end time\n","# end_time = time.time()\n","\n","# # Calculate elapsed time\n","# elapsed_time = end_time - start_time\n","\n","# # Convert elapsed time to minutes, seconds, and milliseconds\n","# minutes, seconds = divmod(elapsed_time, 60)\n","# seconds, milliseconds = divmod(seconds, 1)\n","# milliseconds = round(milliseconds * 1000)\n","\n","# # Print the elapsed time\n","# print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"98VVH_HSs-Gh"},"source":["##1.6 Dataloading and Batching\n","\n","The reason why we needed to move the data into a list instead of just using the datapipe and transforming as we moved out of it was so that we could use the DataLoader function from torch that requires an indexable class, array, etc."]},{"cell_type":"code","execution_count":75,"metadata":{"id":"DPxzp1fdFe_X","executionInfo":{"status":"ok","timestamp":1702493968382,"user_tz":480,"elapsed":1,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Create a DataLoader\n","dataloader = DataLoader(trainset, batch_size=64, shuffle=True)"]},{"cell_type":"markdown","metadata":{"id":"yORjaoQAuuY1"},"source":["To make our dataloading even faster we can use DiskCashedDataset from tonic which makes use of disk chaching and batching. In addition we can add an additional transformation that will change the data from numpy to a torch tensor.\n","\n","Due to variations in the lengths of event recordings, we will introduce a collation function called `tonic.collation.PadTensors()`. This function will be responsible for padding shorter recordings, ensuring uniform dimensions across all samples in a batch."]},{"cell_type":"code","execution_count":76,"metadata":{"id":"YaPsfB0ArUgQ","executionInfo":{"status":"ok","timestamp":1702493968383,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# transform = tonic.transforms.Compose([torch.from_numpy,\n","# torchvision.transforms.RandomRotation([-10,10])])\n","\n","transform = tonic.transforms.Compose([torch.from_numpy])\n","\n","cached_trainset = DiskCachedDataset(trainset, transform=transform, cache_path='./cache/stmnist/train')\n","\n","# no augmentations for the testset\n","cached_testset = DiskCachedDataset(testset, cache_path='./cache/stmnist/test')\n","\n","batch_size = 128\n","trainloader = DataLoader(cached_trainset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False), shuffle=True)\n","testloader = DataLoader(cached_testset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False))"]},{"cell_type":"markdown","metadata":{"id":"_i-s-FRuwGBR"},"source":["Here are the shapes of the data and target tensors of a single iteration of the trainloader printed below."]},{"cell_type":"code","execution_count":77,"metadata":{"id":"0so65S95BDbf","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":692,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"4a5320d9-cfe5-49e2-ea04-3b6e6229999c"},"outputs":[{"output_type":"stream","name":"stdout","text":["5\n","torch.Size([1983, 128, 2, 10, 10])\n","torch.Size([128, 2, 10, 10])\n","torch.Size([128])\n","tensor([7, 8, 5, 4, 9, 7, 7, 2, 2, 4, 1, 5, 7, 3, 8, 2, 2, 1, 8, 8, 2, 1, 0, 9,\n"," 5, 5, 1, 8, 4, 8, 4, 2, 5, 9, 9, 5, 0, 0, 6, 1, 0, 8, 7, 6, 1, 6, 0, 0,\n"," 8, 3, 7, 9, 1, 7, 0, 7, 8, 8, 5, 8, 6, 7, 5, 7, 1, 5, 9, 0, 2, 8, 6, 0,\n"," 0, 7, 2, 1, 4, 9, 4, 9, 1, 9, 7, 4, 4, 6, 6, 2, 0, 2, 6, 3, 2, 9, 8, 7,\n"," 0, 9, 8, 1, 8, 0, 1, 4, 3, 2, 2, 3, 4, 9, 1, 9, 5, 1, 7, 7, 4, 0, 5, 6,\n"," 7, 0, 1, 1, 7, 6, 2, 4])\n"]}],"source":["data_tensor, targets = next(iter(trainloader))\\\n","# length of trainloader = number of iterations per epoch\n","# For the shorter transform\n","# 640 == length of dataset\n","# 640 / 128 = 5\n","# Remember: Trainset is length 640\n","# So the trainloader should be length 5\n","# For the longer transform\n","# 5562 == length of dataset\n","# 5562 / 128 ~ 43.45\n","# Remember: Trainset is length 5562\n","# So the trainloader should be length 44\n","print(len(trainloader))\n","print(data_tensor.shape)\n","print(data_tensor[0].shape)\n","print(targets.shape)\n","print(targets)"]},{"cell_type":"markdown","metadata":{"id":"QDGPdoBUw-ME"},"source":["## 1.7 Create the Spiking Convolutional Neural Network"]},{"cell_type":"markdown","source":["Below we have by default a spiking convolutional neural network with the architecture: `10×10-32c4-64c3-MaxPool2d(2)-10o`. We also have commented out some other architectures we experimented with. Feel free to experiment with these other networks and see how it affects training on the dataset."],"metadata":{"id":"W0DjtextRipx"}},{"cell_type":"code","execution_count":78,"metadata":{"id":"W2ewqKLx8mMJ","executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n","\n","# neuron and simulation parameters\n","spike_grad = surrogate.atan()\n","beta = 0.95\n","\n","# Initialize Network\n","# 10x10-12c3-32c3-10o\n","# scnn_net = nn.Sequential(nn.Conv2d(2, 12, 3),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.MaxPool2d(2),\n","# nn.Conv2d(12, 32, 3),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.MaxPool2d(2),\n","# nn.Flatten(),\n","# nn.Linear(32*1*1, 10),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# # 10×10−6c4−24c3−10o\n","# # This is the same architecture that was used in the ST-MNIST Paper\n","# # No Max Pooling as 10x10 is already very small/low detail\n","# scnn_net = nn.Sequential(\n","# nn.Conv2d(2, 6, kernel_size=4), # 6 channels, kernel size 4x4\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# # nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n","\n","# nn.Conv2d(6, 24, kernel_size=3), # 24 channels, kernel size 3x3\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# # nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n","\n","# nn.Flatten(),\n","# nn.Linear(24 * 5 * 5, 10), # Increased size of the linear layer\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# 10×10-32c4-64c3-MaxPool2d(2)-10o\n","scnn_net = nn.Sequential(\n"," # 2 x 10 x 10\n"," nn.Conv2d(2, 32, kernel_size=4), # 32 channels, kernel size 4x4\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(10 - 4) + 1] = 7\n","\n"," # 32 x 7 x 7\n"," nn.Conv2d(32, 64, kernel_size=3), # 64 channels, kernel size 3x3\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(7 - 3) + 1] = 5\n","\n"," # 64 x 5 x 5\n"," nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n"," # Output size = [(5-2) / 2] + 1 = 2\n","\n"," # 64 x 2 x 2\n"," nn.Flatten(),\n"," # Output size = 64*2*2 = 256\n","\n"," nn.Linear(64 * 2 * 2, 10), # Increased size of the linear layer\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n",").to(device)\n","\n","# Note: In a CNN the formula for calculating the output of the Conv layer is\n","# Output size = ((Input Size - Kernel Size + 2 * Padding) / Stride ) + 1\n","# Note for a MaxPool layer the formula is\n","# Output size = ((Input size - Kernel Size) / Stride ) + 1\n","\n","optimizer = torch.optim.Adam(scnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"markdown","metadata":{"id":"Sq_jz3xYxMxO"},"source":["##1.8 Define the Forward Pass"]},{"cell_type":"code","execution_count":79,"metadata":{"id":"ydcyDZDt_qH_","executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# this time, we won't return membrane as we don't need it\n","\n","def forward_pass(net, data):\n"," spk_rec = []\n"," utils.reset(net) # resets hidden states for all LIF neurons in net\n","\n"," for step in range(data.size(0)): # data.size(0) = number of time steps\n","\n"," spk_out, mem_out = net(data[step])\n"," spk_rec.append(spk_out)\n","\n"," return torch.stack(spk_rec)"]},{"cell_type":"markdown","metadata":{"id":"9tPywf6CxWcq"},"source":["## 1.9 Create and Run the Training Loop\n","\n","The current epochs is set to 40 and is intended to be run on the smaller trainset and testset. In the smaller set each epoch has 5 iterations. Doing the math: 5 * 40 is 200 iterations over the 40 epochs. On our runs on the T4 GPU on Colab, 30 epochs on the smaller dataset takes ~25 minutes and achieves ~50% accuracy on the testset and ~50% accuracy on the trainset.\n","\n","For training on the full dataset, we recommend lowering the epochs down to 15. Remember that each epoch has 44 iterations starting at 0. Doing the math: 44 * 15 = 660 iterations over the 15 epochs. Training should once again take some time so feel free to take a break and let your computer run. On our runs with the T4 GPU on Colab 15 epochs takes ~70 min with ~70% accuracy on the full trainset and ~65% accuracy on the full testset.\n","\n","Of course feel free to adjust the epochs to make them longer or shorter if you have more or less time and would like to experiment with how that affects accuracy on the testset and trainset."]},{"cell_type":"code","execution_count":80,"metadata":{"id":"lB9lYUP0AUBL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495283579,"user_tz":480,"elapsed":1314507,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"3301c4b9-ed3c-45ab-c1f4-9dab8e17af3b"},"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 0, Iteration 0 \n","Train Loss: 193.19\n","Accuracy: 7.03%\n","\n","Epoch 0, Iteration 4 \n","Train Loss: 166.22\n","Accuracy: 11.72%\n","\n","Epoch 1, Iteration 0 \n","Train Loss: 155.76\n","Accuracy: 10.94%\n","\n","Epoch 1, Iteration 4 \n","Train Loss: 128.67\n","Accuracy: 10.94%\n","\n","Epoch 2, Iteration 0 \n","Train Loss: 122.48\n","Accuracy: 11.72%\n","\n","Epoch 2, Iteration 4 \n","Train Loss: 108.78\n","Accuracy: 15.62%\n","\n","Epoch 3, Iteration 0 \n","Train Loss: 110.45\n","Accuracy: 11.72%\n","\n","Epoch 3, Iteration 4 \n","Train Loss: 107.84\n","Accuracy: 7.03%\n","\n","Epoch 4, Iteration 0 \n","Train Loss: 103.94\n","Accuracy: 7.81%\n","\n","Epoch 4, Iteration 4 \n","Train Loss: 82.54\n","Accuracy: 9.38%\n","\n","Epoch 5, Iteration 0 \n","Train Loss: 72.82\n","Accuracy: 8.59%\n","\n","Epoch 5, Iteration 4 \n","Train Loss: 72.97\n","Accuracy: 10.16%\n","\n","Epoch 6, Iteration 0 \n","Train Loss: 71.87\n","Accuracy: 10.94%\n","\n","Epoch 6, Iteration 4 \n","Train Loss: 63.91\n","Accuracy: 14.84%\n","\n","Epoch 7, Iteration 0 \n","Train Loss: 64.48\n","Accuracy: 14.06%\n","\n","Epoch 7, Iteration 4 \n","Train Loss: 66.40\n","Accuracy: 10.94%\n","\n","Epoch 8, Iteration 0 \n","Train Loss: 65.42\n","Accuracy: 13.28%\n","\n","Epoch 8, Iteration 4 \n","Train Loss: 62.19\n","Accuracy: 10.16%\n","\n","Epoch 9, Iteration 0 \n","Train Loss: 64.78\n","Accuracy: 11.72%\n","\n","Epoch 9, Iteration 4 \n","Train Loss: 65.64\n","Accuracy: 8.59%\n","\n","Epoch 10, Iteration 0 \n","Train Loss: 64.33\n","Accuracy: 12.50%\n","\n","Epoch 10, Iteration 4 \n","Train Loss: 61.63\n","Accuracy: 10.16%\n","\n","Epoch 11, Iteration 0 \n","Train Loss: 64.52\n","Accuracy: 14.06%\n","\n","Epoch 11, Iteration 4 \n","Train Loss: 64.68\n","Accuracy: 6.25%\n","\n","Epoch 12, Iteration 0 \n","Train Loss: 64.34\n","Accuracy: 10.94%\n","\n","Epoch 12, Iteration 4 \n","Train Loss: 63.86\n","Accuracy: 10.94%\n","\n","Epoch 13, Iteration 0 \n","Train Loss: 64.05\n","Accuracy: 11.72%\n","\n","Epoch 13, Iteration 4 \n","Train Loss: 64.39\n","Accuracy: 13.28%\n","\n","Epoch 14, Iteration 0 \n","Train Loss: 63.59\n","Accuracy: 16.41%\n","\n","Epoch 14, Iteration 4 \n","Train Loss: 63.88\n","Accuracy: 13.28%\n","\n","Epoch 15, Iteration 0 \n","Train Loss: 64.43\n","Accuracy: 9.38%\n","\n","Epoch 15, Iteration 4 \n","Train Loss: 67.90\n","Accuracy: 9.38%\n","\n","Epoch 16, Iteration 0 \n","Train Loss: 74.42\n","Accuracy: 14.06%\n","\n","Epoch 16, Iteration 4 \n","Train Loss: 76.24\n","Accuracy: 8.59%\n","\n","Epoch 17, Iteration 0 \n","Train Loss: 77.33\n","Accuracy: 5.47%\n","\n","Epoch 17, Iteration 4 \n","Train Loss: 67.40\n","Accuracy: 8.59%\n","\n","Epoch 18, Iteration 0 \n","Train Loss: 65.96\n","Accuracy: 14.84%\n","\n","Epoch 18, Iteration 4 \n","Train Loss: 65.92\n","Accuracy: 16.41%\n","\n","Epoch 19, Iteration 0 \n","Train Loss: 65.77\n","Accuracy: 11.72%\n","\n","Epoch 19, Iteration 4 \n","Train Loss: 63.85\n","Accuracy: 16.41%\n","\n","Epoch 20, Iteration 0 \n","Train Loss: 64.12\n","Accuracy: 17.97%\n","\n","Epoch 20, Iteration 4 \n","Train Loss: 63.04\n","Accuracy: 21.09%\n","\n","Epoch 21, Iteration 0 \n","Train Loss: 62.61\n","Accuracy: 21.88%\n","\n","Epoch 21, Iteration 4 \n","Train Loss: 60.80\n","Accuracy: 31.25%\n","\n","Epoch 22, Iteration 0 \n","Train Loss: 56.85\n","Accuracy: 36.72%\n","\n","Epoch 22, Iteration 4 \n","Train Loss: 59.92\n","Accuracy: 28.12%\n","\n","Epoch 23, Iteration 0 \n","Train Loss: 59.07\n","Accuracy: 28.91%\n","\n","Epoch 23, Iteration 4 \n","Train Loss: 57.47\n","Accuracy: 39.84%\n","\n","Epoch 24, Iteration 0 \n","Train Loss: 59.31\n","Accuracy: 32.81%\n","\n","Epoch 24, Iteration 4 \n","Train Loss: 55.65\n","Accuracy: 33.59%\n","\n","Epoch 25, Iteration 0 \n","Train Loss: 57.65\n","Accuracy: 39.84%\n","\n","Epoch 25, Iteration 4 \n","Train Loss: 55.37\n","Accuracy: 38.28%\n","\n","Epoch 26, Iteration 0 \n","Train Loss: 54.02\n","Accuracy: 39.06%\n","\n","Epoch 26, Iteration 4 \n","Train Loss: 55.91\n","Accuracy: 39.06%\n","\n","Epoch 27, Iteration 0 \n","Train Loss: 57.34\n","Accuracy: 35.94%\n","\n","Epoch 27, Iteration 4 \n","Train Loss: 53.13\n","Accuracy: 45.31%\n","\n","Epoch 28, Iteration 0 \n","Train Loss: 54.00\n","Accuracy: 46.09%\n","\n","Epoch 28, Iteration 4 \n","Train Loss: 53.50\n","Accuracy: 41.41%\n","\n","Epoch 29, Iteration 0 \n","Train Loss: 54.04\n","Accuracy: 44.53%\n","\n","Epoch 29, Iteration 4 \n","Train Loss: 53.78\n","Accuracy: 42.19%\n","\n","Epoch 30, Iteration 0 \n","Train Loss: 51.86\n","Accuracy: 53.91%\n","\n","Epoch 30, Iteration 4 \n","Train Loss: 51.79\n","Accuracy: 50.78%\n","\n","Epoch 31, Iteration 0 \n","Train Loss: 51.04\n","Accuracy: 46.88%\n","\n","Epoch 31, Iteration 4 \n","Train Loss: 51.60\n","Accuracy: 50.00%\n","\n","Epoch 32, Iteration 0 \n","Train Loss: 53.49\n","Accuracy: 45.31%\n","\n","Epoch 32, Iteration 4 \n","Train Loss: 51.72\n","Accuracy: 53.91%\n","\n","Epoch 33, Iteration 0 \n","Train Loss: 51.84\n","Accuracy: 49.22%\n","\n","Epoch 33, Iteration 4 \n","Train Loss: 50.77\n","Accuracy: 50.78%\n","\n","Epoch 34, Iteration 0 \n","Train Loss: 50.60\n","Accuracy: 53.91%\n","\n","Epoch 34, Iteration 4 \n","Train Loss: 51.63\n","Accuracy: 49.22%\n","\n","Epoch 35, Iteration 0 \n","Train Loss: 49.02\n","Accuracy: 56.25%\n","\n","Epoch 35, Iteration 4 \n","Train Loss: 49.56\n","Accuracy: 60.94%\n","\n","Epoch 36, Iteration 0 \n","Train Loss: 51.84\n","Accuracy: 54.69%\n","\n","Epoch 36, Iteration 4 \n","Train Loss: 48.39\n","Accuracy: 60.16%\n","\n","Epoch 37, Iteration 0 \n","Train Loss: 48.87\n","Accuracy: 60.16%\n","\n","Epoch 37, Iteration 4 \n","Train Loss: 50.66\n","Accuracy: 59.38%\n","\n","Epoch 38, Iteration 0 \n","Train Loss: 49.35\n","Accuracy: 57.03%\n","\n","Epoch 38, Iteration 4 \n","Train Loss: 46.30\n","Accuracy: 59.38%\n","\n","Epoch 39, Iteration 0 \n","Train Loss: 47.08\n","Accuracy: 68.75%\n","\n","Epoch 39, Iteration 4 \n","Train Loss: 49.38\n","Accuracy: 53.12%\n","\n","Elapsed time: 21 minutes, 54 seconds, 431 milliseconds\n"]}],"source":["start_time = time.time()\n","\n","num_epochs = 40\n","\n","loss_hist = []\n","acc_hist = []\n","\n","# training loop\n","for epoch in range(num_epochs):\n"," for i, (data, targets) in enumerate(iter(trainloader)):\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," scnn_net.train()\n"," spk_rec = forward_pass(scnn_net, data)\n"," loss_val = loss_fn(spk_rec, targets)\n","\n"," # Gradient calculation + weight update\n"," optimizer.zero_grad()\n"," loss_val.backward()\n"," optimizer.step()\n","\n"," # Store loss history for future plotting\n"," loss_hist.append(loss_val.item())\n","\n"," if i%4 == 0:\n"," print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," if i%4 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"cEY6Ynbq0JmX"},"source":["# 2. Results"]},{"cell_type":"markdown","metadata":{"id":"yYSkN_kp0Lm0"},"source":["## 2.1 Plot accuracy history"]},{"cell_type":"code","execution_count":81,"metadata":{"id":"X0SYWQDJ6qhx","colab":{"base_uri":"https://localhost:8080/","height":472},"executionInfo":{"status":"ok","timestamp":1702495283922,"user_tz":480,"elapsed":345,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8cf4d847-606c-4b51-a7a8-07e061b2b280"},"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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4PTTT0dlZaXy+G233YYDDjgA8+bNQ2lpKTIzM3HmmWeiqampa79oRNQpDG6IqFs88sgjOPTQQ3HhhReivLwc5eXl6N+/P+rr63H00UdjwoQJWL58ORYuXIjKykqcfvrpmue//PLLMJvN+P777/H0008DAPR6PR599FH8/vvvePnll/H111/jX//6FwDgsMMOw8MPP4yMjAzl9a699tqQcfl8Ppx88smora3Ft99+i0WLFmHbtm0444wzNMdt3boVH3zwARYsWIAFCxbg22+/xb333ttFXy0i2h8sSxFRt8jMzITZbIbVakWfPn2U+x9//HFMmDABd999t3Lfiy++iP79+2PTpk0YNmwYAGDo0KG4//77NedU9++UlpbizjvvxCWXXIInn3wSZrMZmZmZ0Ol0mtcL9tVXX2HNmjXYvn07+vfvDwB45ZVXMHr0aCxbtgyTJ08GIAVBL730EtLT0wEAZ599Nr766ivcdddd+/eFIaKYY+aGiOJq1apV+Oabb5CWlqb8GTFiBAApWyJMmjQp5LlffvkljjnmGPTt2xfp6ek4++yzUVNTA4fDEfXrr1+/Hv3791cCGwAYNWoUsrKysH79euW+0tJSJbABgKKiIuzbt69D75WIugczN0QUV83NzZg5cybuu+++kMeKioqUf9tsNs1jO3bswIknnohLL70Ud911F3JycrB06VJccMEFcLlcsFqtMR2nyWTS3NbpdPD5fDF9DSKKDQY3RNRtzGYzvF6v5r6JEyfi3XffRWlpKYzG6H8k/frrr/D5fHjwwQeh10tJ6Lfeeqvd1ws2cuRI7N69G7t371ayN+vWrUN9fT1GjRoV9XiIKHGwLEVE3aa0tBQ///wzduzYgerqavh8Plx22WWora3FWWedhWXLlmHr1q34/PPPcd5557UZmAwZMgRutxuPPfYYtm3bhnnz5imNxurXa25uxldffYXq6uqw5apjjz0WY8eOxezZs7FixQr88ssvOOecczB16lQceOCBMf8aEFHXY3BDRN3m2muvhcFgwKhRo5Cfn49du3ahuLgY33//PbxeL4477jiMHTsWV111FbKyspSMTDjjx4/HQw89hPvuuw9jxozBa6+9hnvuuUdzzGGHHYZLLrkEZ5xxBvLz80MakgGpvPThhx8iOzsbU6ZMwbHHHotBgwbhzTffjPn7J6LuofP7/f54D4KIiIgoVpi5ISIioqTC4IaIiIiSCoMbIiIiSioMboiIiCipMLghIiKipMLghoiIiJIKgxsiIiJKKgxuiIiIKKkwuCEiIqKkwuCGiIiIkgqDGyIiIkoqDG6IiIgoqfw/8V8gEghd3LsAAAAASUVORK5CYII=\n"},"metadata":{}}],"source":["import matplotlib.pyplot as plt\n","\n","# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Train Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"hhx12ZJP0eF7"},"source":["## 2.2 Evaluate the Network on the testset"]},{"cell_type":"code","execution_count":82,"metadata":{"id":"BTjjGQHuhQ7i","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495295875,"user_tz":480,"elapsed":11955,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"6fc91514-e525-4c0d-d1c1-796ee741410b"},"outputs":[{"output_type":"stream","name":"stdout","text":["Accuracy: 52.34%\n","\n","Accuracy: 49.22%\n","\n","Accuracy: 54.69%\n","\n"]},{"output_type":"execute_result","data":{"text/plain":["Sequential(\n"," (0): Conv2d(2, 32, kernel_size=(4, 4), stride=(1, 1))\n"," (1): Leaky()\n"," (2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))\n"," (3): Leaky()\n"," (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n"," (5): Flatten(start_dim=1, end_dim=-1)\n"," (6): Linear(in_features=256, out_features=10, bias=True)\n"," (7): Leaky()\n",")"]},"metadata":{},"execution_count":82}],"source":["# Assuming your model is already trained and stored in the variable 'net'\n","# Make sure your model is in evaluation mode\n","scnn_net.eval()\n","\n","# Initialize variables to store predictions and ground truth labels\n","acc_hist = []\n","\n","# Iterate over batches in the testloader\n","with torch.no_grad():\n"," for data, targets in testloader:\n"," # Move data and targets to the device (GPU or CPU)\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," # Forward pass\n"," spk_rec = forward_pass(scnn_net, data)\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," # if i%10 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# Reset your model to training mode if needed\n","scnn_net.train()\n"]},{"cell_type":"code","execution_count":83,"metadata":{"id":"0AyNWaIts16X","colab":{"base_uri":"https://localhost:8080/","height":489},"executionInfo":{"status":"ok","timestamp":1702495296228,"user_tz":480,"elapsed":355,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"2bdf78e5-add9-4609-9cf9-cd6468a12ec9"},"outputs":[{"output_type":"stream","name":"stdout","text":["The average loss across the testloader is: 0.5208333333333334\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABq9klEQVR4nO3dd1gThx8G8Ddh7y0KgoAgG/ceVeuodQ+s1p9Wa7XODkdbt1Xrtlq3de+Be++9N7gVUdkoe0NI7vcHNS0VLSBwCXk/z8PzlMtd8h4B8/a+d4lEEAQBRERERBpEKnYAIiIiotLGAkREREQahwWIiIiINA4LEBEREWkcFiAiIiLSOCxAREREpHFYgIiIiEjjsAARERGRxmEBIiIiIo3DAkREREQaR1vsAERUvGo1bVeg9ZbPn45a1f0+6rEyMzOxfusu1KzmW+D7ioyKwcr1W3E76D7evImDibERHB3sUau6H77t16vQGS5evYEHj54Wads+g37Ew8fP8MuPQ9Ct4+eF3p6I1BcLEFEZM2XsyDzfHzp+Gtdu3nlnuXMlh49+rMzMLKxcvxUAClSAwsIj0WfQj9DT00OHNi1hV74cYuPj8fjpc6zfsrNIJebS1ZsI2Huo0NuGhkfg4eNnsCtviyMnzrIAEWkYFiCiMubzVs3yfH/v4WNcu3nnneVi2LJzH9IzMrFl1SJUKF8uz23xCYmlmuXIibOwtDDHD0P64+dJMxAZFQO7CralmqEgFAoFZLIc6Onpih2FqExhASLSQAqFAtt2HcDeQ8cQHhEFY2MjfNKoHoYP7AtTE2Pleg8fP8PS1Rvw6MlzZGZmwsrSAjWr+2LSzz8gMioGHXr2BwCsXL9VeSRowFc933s0JjwiCrY21u+UHwCwtDB/Z9mlazexdtMOPH72HFKJFNWreuO7b/uhsnMlAMDkGfNx8NgpAHlHfzfPHvzPn8HRk2fx6ScN0bh+bRgbGeLoqXP4+n/d31nv/sMn+HP9Ftx78BiynBxUtKuAjp+3RM9uHZXrvHwVhuVrN+PmnSBkZGTC1tYGn37SEEO/6aPMeevuPRzYvibPfa9Yuxkr12/Nk7dW03bw79QWft4eWLs5AK/CIjBr8i9o2rg+Nm7bjTMXLuNVWAQyM7Pg7OSAvl/6o0XTRu/kPnz8DLbt3o/nL0Khq6MNVxcn9O/9BerVroFJM37HxSs3cWz3Bmhr530ZGDpqAqJiXmP3xhX/+TMkUmcsQEQaaPq8xThw9BQ6tGmBL7q0R2RUDHbsOYgnz55jzeI50NbWRnxCIoaNngBzczP0/bIbTIyNEBn9GmcuXAYAWJib4Zcfh2Dm/KVo1rg+mjVuAABwq+z03sctX74crt+6ixu3A1G7RtUPZjx0/DQmz5iP+rVrYPjAvsjMysKufUfwzfCfsHnlQthVsEWXDp/hTVx8viO+D7n/8AnCIqIw6ecm0NHRQbMmDXD05Nl3CtDVm3fw45hfYW1piR5dO8DK0gIvQ8Nw4coNZQF69vwFvvnuZ2hraaNL+9aoUN4W4ZFRuHD5urIAFdbNO0E4efYiunduB3MzU1Qon3tkatuu/WjSsC4+a9EUspwcHD99Hr9MnokFMyahUf3ayu3/XLcFf67bAj8fTwzq1ws6Otq4/+gJbtwOQr3aNfB5y+Y4dOw0rly/jcYN6ii3i41LwM3bgRjQt2eRchOpExYgIg1zN+gB9h46jmnjR+GzFk2Vy2tV98Xwnybh5NmL+KxFUwTdf4TklFQsnjMVXh5uyvWGfNMbAGBgoI8WnzTEzPlL4eriVKARW48u7XH4+BkMHjEOVVxdULOqD2pW90O9WtWgr6+vXC89PQNzF65Ap7atMG7UcOXydq0/Rdfeg7B28w6MGzUcft6ecKxoV+gR3+ETZ2BbzgZVfb0AAK2aN8H+wyfw5FkI3N1cAAByuRwz5i2GtaUltqxaCJN/HBkTBEH533MWrgAEAZtXLkB527+PbA0f2LfAef7tVVgEtq1ZDBcnxzzLd21aAX09PeX3X3Ruh14DvsfmgD3KAhQWHolVG7ahWeP6mPXrGEilf1/s+zZ37Rp+sLWxxuETZ/IUoGOnz0EhCGjTUvxxKVFJ42XwRBrm5LmLMDYyQt1a1ZGYmKT88qziCkMDA9y8EwQAMDY2AgBcuHIdOTk5xfLYlZ0rYcuqhWjTshmiomOwddd+jBo/Da0698aeg0eV6127dQcpqWlo/ekneTJqSaXw8aqizFgUOTlynDhzAa2aNYZEIgEA1K7uB0sLcxw9eVa53pNnIYiIikHPbh3zlB8Ayu0SEpNwO/A+OrRpmaf8/HOdoqhR1eed8gMgT/lJTklFamoaqvt54/HT58rlZy9ehUKhwDd9euYpP//MJJVK8VmLpjh/+TrS0tOVtx89cRZ+3p6wr1C+yNmJ1AWPABFpmNDwSKSmpaFlp/zP04lPTAIA1Kzmi+ZNGmDl+q3YsnMfalbzRdNG9fDZp02hq6tT5Mev5GCPqeNGQi6X48WrMFy4ch0btu7Cb3MXw658edStVQ2h4ZEAgEE/js33PoyMDIv8+Fdv3kZCYhK8Pasg7K/HAXL399ipcxj+bV9IpVKER0YBgPJ8o/xEREb/5zpF8b6TsS9cvo7VG7fjaXAIsmUy5fJ/lq3wyChIpVK4OH34Kr+2rZtj/dadOHPhCtq1/hQvQ8Px6GkwxowYWjw7QaTiWICINIygEGBpYY6p40ble7uFuSmA3BfV2VPG4t6Dxzh/5TquXr+NKbP+wKbte7Bu6TwYGhp8VA4tLS24ujjB1cUJvl4eGPTjWBw9eRZ1a1WDoMgd1UwZOxJWlhb5bFv0g9dvj/L8MnlmvrffDrz/0e+P9G/vOxqkUCjyXa6n++4VX3eC7mPEuKmo7ueNn38cDGsrS2hraePA0RM4evJcoTO5ODnCs4orjpw4i3atP8WRE2ego6ONls0aF/q+iNQRCxCRhqloXwHXb91FVV/PPCOV9/H19oCvtweGftMHR0+exfhpc3H89Hl0atca+Igxzz95ueeeYxQbF6/MCACWFmaoW6vaB7ctzKgpIyMT5y5eQ8tmjfHpJw3fuX3uoj9x5MRZ1Kruh4p2uRmev3j13gz2duWV63yIiYkRUlLT3lkeFfO6wNlPn7sMXV1dLJ4zNc8RuANHT+RZr6JdBSgUCoS8DFOez/Q+bVs3x/wlqxAbF4+jp86hUb3aea4CJCrLeA4QkYZp0bQR5AoFVm/Y9s5tOTlypKSkAsg9x+SfJ/sCQBXX3BfUt+MXff3cApWaz4t7fu4E3c/3fKJL124CACo52gMA6tWuASMjQ6zZtCPf9RP+GtMBgMFfJ0+/zf0hZy5cQUZmJrp3bosWTRu989W4fm2cPn8J2dkyeFSpDPsKtti6c9879/3252JhboYaVX2w/8gJRP+rzPzzZ1fRrgJS09Lw7PkL5bLYuHicvXD1PzO/JdWSQiIBFAq5cllkVAzOXsx7H00b1YNUKsWqDVvfOcL07+ez9aefABIJ5i76ExGR0Tz5mTQKjwARaZia1XzRpf1nWLs5AE+CQ1CvVg1oa2shLDwSJ89dxMhhA9GiaSMcPHoKO/cdQtPG9VHRrgLS09Ox5+BxGBkZomG9WgByT8p1cXLE8TMX4OhgD1MTY1R2rgRXF6d8H3v9ll149DQYzZs0UK7z+NlzHD52GmamJspLy42NDDHmxyGYOP139BrwPVo1bwILczNEx7zBxas3UNXHEz//MBgA4OnuCgCYs2gF6teuAalUmvvCno+jJ8/CzNQUft6e+d7epEFd7Dl4DBev3kDzJg3wy49D8OPYqfjym+/Qvk0LWFtZ4mVoGEJehmLxnKkAgFHDB+Kb4T+j14Af0KV9a9hVsEVk9GtcunIDW1YvApB7ldmiFeswasJv6NGlPTKzsrBz3xE4OtjlOYH5QxrVq43NO/Zi+E+T0PrTT5CQmISAvYfgYF8Bz56/VK7nUNEOX/+vO1Zt2IZvvvsZzRvXh46ODh4+eQYbK0sM+8fVaRbmZmhQpwZOnr0IE2MjNKpX+90HJiqjWICINNDYkcPg6e6K3fuPYsmqDdDWkqJCeVu0adkM1f66NLxGNR88ePwUx0+fR3x8IoyNjeDt4YZp40fluUpo/OjhmPPHCvy+ZCVkshwM+KrnewtQv/91x9GTZ3E78D6OnDiLzKwsWFtZoFXzJujfp0ee+/2sRVNYW1li/Zad2LhtN2QyGWysrVDdzxsd2rRUrtescX180aU9jp8+jyMnzkIQhHwLUHxCIq7duovWnzaBlpZWvvlq16wKfX09HDlxBs2bNED9OjWxfP50rFy/FZt37IFCIaCifXl0attauU0VVxesXToXy9dsws59h5GdLUN523Jo2ezvNyc0NzPFnGnjMH/JKixcsRZ25ctj2IA+CA2PLHABql2jKib89B3Wb9mJ3xevhF0FWwwf2BeR0TF5ChAADPr6f7CrYIvtuw9i6aqN0NfXy32rgpbN37nftq0/xYUrN9CiWeOPOrmdSN1IhH8fEyUiIo1x9uJVjBo/DSsXzkR1Px+x4xCVGp4DRESkwfYePAZ7u/Ko5ustdhSiUsURGBGRBjp26hyCQ17i4tUbGDV84Ee9cSOROuIIjIhIA9Vq2g6GBgZo2awxxowYCm3t/M+LIiqrWICIiIhI4/AcICIiItI4LEBERESkcXgSdD4UCgXexMXD0MCAJwYSERGpCUEQkJ6RARsrS0ilHz7GwwKUjzdx8Wjr31fsGERERFQEhwLWwdbG+oPrsADlw9Ag91OuDwWsg5GhochpiIiIqCDS0tPR1r+v8nX8Q1iA8vF27GVkaAhjIxYgIiIidVKQ01d4EjQRERFpHBYgIiIi0jgsQERERKRxWICIiIhI47AAERERkcZhASIiIiKNwwJEREREGocFiIiIiDQOCxARERFpHBYgIiIi0jgsQERERKRxWICIiIhI47AAERERUamRyRU4++S12DFYgIiIiKj0LDv7HH3X3sCEvfdFzcECRERERKXiQWQSFp56BgCo7WwpahYWICIiIipx2TkKjAoIQo5CwGfe5dHer4KoeViAiIiIqMQtPhOMR1HJsDTSxbTOPpBIJKLmYQEiIiKiEnU/IglLzgQDAKZ29IG1sZ7IiViAiIiIqARl5cgxKiAQcoWAtn4V0Fbk0ddbLEBERERUYhadCsbj6BRYG+tiakcfseMosQARERFRiQgMS8Syc88BANM6+cDSSFfkRH9jASIiIqJilyn7e/TVoaodPvNRjdHXWyxAREREVOz+OPUMz16nwtpYD7928BY7zjtYgIiIiKhY3QlNwIq/Rl/TO/vAQoVGX2+xABEREVGxeTv6UghA5+r2aOVdXuxI+WIBIiIiomLz+4mneP4mDeVM9DCpvZfYcd6LBYiIiIiKxa1X8Vh5IQQAMKOLL8wNVW/09RYLEBEREX20jGw5RgUEQRCAbjUr4lNPW7EjfRALEBEREX20ucef4EVsGsqb6mNCO9Udfb3FAkREREQf5fqLeKy59AIAMKOrL8wMdERO9N9YgIiIiKjI0rNzMHpnIAQB+KKWA5q5lxM7UoGwABEREVGRzT76BK/i0mFnpo9x7TzFjlNgLEBERERUJFdD4rDu8ksAwKxufjDVV/3R11ssQERERFRoaVm5oy8A6FnHEY3dbEROVDgsQERERFRoM488Rlh8BuzNDTCurfqMvt5iASIiIqJCuRwci41XXwEAZnfzg7GetsiJCo8FiIiIiAosNSsHo3cGAQB616uEhq7WIicqGhYgIiIiKrDphx8hIjEDDpYG+KWNh9hxiowFiIiIiArk/NM32HItFAAwu2tVGKnh6OstFiAiIiL6T8mZMvyyK3f01beBE+pXthI50cdhASIiIqL/NP3QI0QmZaKSlSF++sxd7DgfjQWIiIiIPujsk9fYdiMMEgkwp1tVGOqq7+jrLRYgIiIieq+kDBl+2XUPANCvgTPqOFuKnKh4sAARERHRe009+BDRyZlwtjbC6NbqP/p6iwWIiIiI8nX6cQx23gqHRALM9feDga6W2JGKDQsQERERvSMp/e/R14DGLqhZqWyMvt5iASIiIqJ3/HrgAV6nZMHFxggjWlYRO06xYwEiIiKiPI4/iMbuOxGQSoC5/lWhr1N2Rl9vsQARERGRUkJaNsbuuQ8AGNikMmo4WoicqGSwABEREZHS5AMPEJuaBbdyxvihhZvYcUoMCxAREREBAI7ej8K+u5HQkkrK7OjrLRYgIiIiQlxqFsb9Nfoa9IkLqjqYixuohKnEe1nv2HMQG7ftRlx8AtxcnTH6u2/h45n/my0dOHISv85akGeZro4OLp/Yk+/60+ctxu4DRzFi6AB86d+xuKMTERGVCRP3P0BcWjbcbU3w3adld/T1lugF6Pjp85i/dBXGjBgKH093bN25D8NHT8SujStgaWGe7zZGRobYtWGF8nuJJP/7PnPhMu4/fAIb67L13gVERETF6VBQFA4FRUFLKsG87lWhp112R19viT4C2xywF53atkaHNi3h4uSIMSOGQl9fD/sPn3jvNhJIYG1lofyysnz3DPXXb2Ix548VmDp+FLS1RO95REREKik2NQsT9uWOvoY2c4WPvZnIiUqHqM1AJpPh8ZNg9PvSX7lMKpWiTs1qCHr4+L3bZWRkoN0X/SAoBLhXqYyh3/RBZedKytsVCgUmTv8dvXt0ybP8fbKzZciWyZTfp6WnF3GPiIiI1IcgCJiw9z7i07LhWcEUw5q5ih2p1IhagBKTkiFXKGBpaZ5nuaWFOV6Ghue7TSVHe0z4+Xu4uTgjNS0Nm7bvxtfDRmPH2qWwLWcNAFi/dSe0tLTQo2uHAuVYu3kHVq7f+lH7QkREpG4OBEXhyP1oaEslmOvvB11t0QdDpUbtZkN+3p7w8/ZUfl/VxxPd+gzG7gNHMLh/bzx6EoxtO/dj08o/IHnfyUH/0q9Xd/Tq3ln5fVp6Otr69y3u6ERERCrjdUomJv41+hre3A3edpox+npL1AJkbmYKLakU8fGJeZbHJyTme15PfrS1teHu5oKwiCgAwJ2gB4hPTEK77v2U68gVCixYthpbd+7Dge1r3rkPXV0d6OrqFH1HiIiI1IggCBi35z4S02XwtjPFkGaVxY5U6kQtQDo6OvBwd8X124Fo2rg+gNzzd27cCkT3zu0KdB9yuRzBIa/QsF5NAMDnrZqhTs2qedYZ/tNEfN6yOdq3aVG8O0BERKSG9t2NxImHMdDRyr3qS0dLc0Zfb4k+Auvl3wmTZ8yHl7sbvD2rYMvOfcjIzFSWlYnT56GctRWGDewLAFi5fit8vdxR0d4Oqamp2LBtN6JjXqNT29YAco8qmZuZ5nkMbS1tWFlawMmxYqnuGxERkaqJSc7EpP0PAADff+oGj/Km/7FF2SR6AWrVvAkSEpOwfO0mxMUnoIqrCxbNnqIcgUXHvIFU8nczTU5JxbS5ixAXnwBTY2N4uLti9ZI5cHFyFGsXiIiI1IIgCBi7+x6SMmTwtTfDoE80b/T1lkQQBEHsEKomNS0dTdt2x9lDO2BsZCh2HCIiomKx61Y4RgYEQldLioPfNUIVWxOxIxWrwrx+a97Qj4iISANFJ2Vi8oHc0dcPLd3KXPkpLBYgIiKiMk4QBPyyOwgpmTmo6mCOgY1dxI4kOhYgIiKiMi7gZjjOPnkDXW0p5vn7QVsDr/r6N/4EiIiIyrDIxAxMPfgQADCqVRW4ltPs0ddbLEBERERllCAI+HlXEFKyclDD0Rz9G3H09RYLEBERURm17UYYLjyLhZ62FHP9q0JLWrCPiNIELEBERERlUHhCOqb9Nfoa3dodLjbGIidSLSxAREREZczb0Vdathy1nSzQr6Gz2JFUDgsQERFRGbP5WiguBcdBX0eKOd04+soPCxAREVEZEhafjumHHwEAfv7MA07WRiInUk0sQERERGWEQiFg9M5ApGfLUcfZEl/VdxI7kspiASIiIiojNl59hash8TDU1cLcblUh5ejrvViAiIiIyoBXcWmYeeQxAGBMGw84WvHDvD+EBYiIiEjNKRQCRgcEIUMmR30XK/SqW0nsSCqPBYiIiEjNrbv8EtdfxsNIVwuzu/lx9FUALEBERERqLORNKmYfyx19jW3rCQdLjr4KggWIiIhITckVAkbvDEKmTIFGrtb4so6j2JHUBgsQERGRmlp76QVuvUqAsZ42ZnXzg0TC0VdBsQARERGpoeDXqZhz7AkAYHxbT9ibG4icSL2wABEREakZuULAqIBAZOUo0KSKDb6o7SB2JLXDAkRERKRmVl4Iwd2wRJjoa2NWV1+OvoqABYiIiEiNPItJwe/HnwIAJrbzQgUzjr6KggWIiIhITeTIFRgVEIhsuQLNPcqhW82KYkdSWyxAREREamLF+RAEhifBVF8b0ztz9PUxWICIiIjUwOPoZCw4mTv6mtzBG+XN9EVOpN5YgIiIiFSc7K/Rl0wuoIWnLTpXtxc7ktpjASIiIlJxy88+x/2IZJgZ6GB6Zx+OvooBCxAREZEKexiZjIWnnwEApnT0RjlTjr6KAwsQERGRisrO+Xv01drbFh2q2okdqcxgASIiIlJRS84E42FUMiwMdTCtE6/6Kk4sQERERCrofkQSlpwJBgBM7eQDGxM9kROVLSxAREREKubt6CtHIeBz3/Jo58fRV3FjASIiIlIxi04/w+PoFFgZ6WJqRx+x45RJLEBEREQqJCg8EUvPPgcATOvkAytjjr5KAgsQERGRisjKkWNUQCDkCgHtq9qhjW8FsSOVWSxAREREKuKPk8/wNCYV1sa6+LWDt9hxyjQWICIiIhVwNywRy8+9HX35wtJIV+REZRsLEBERkcgyZXKM3HEXCgHoVM0On/mUFztSmccCREREJLL5J57i+Zs02JjoYTJHX6WCBYiIiEhEt14l4M8LIQCAGZ19YW7I0VdpYAEiIiISSaZMjtEBgRAEoEsNe7TwshU7ksZgASIiIhLJ3GNPEBKbBltTPUxqx9FXaWIBIiIiEsGNl/FYfekFAGBmFz+YGeqInEizsAARERGVsozsv0df3WtVRDOPcmJH0jgsQERERKVs9rHHeBmXjgpm+hjfzkvsOBqJBYiIiKgUXQ2Jw9pLLwEAM7v6wVSfoy8xsAARERGVkrSsHPy0MwgA0LOOAz6pYiNyIs3FAkRERFRKZh19jND4dNibG2Ds555ix9FoLEBERESl4HJwLDZceQUAmNXVDyYcfYmKBYiIiKiEpWbl4KdduaOvXnUd0cjNWuREpC12AADYsecgNm7bjbj4BLi5OmP0d9/Cx9M933UPHDmJX2ctyLNMV0cHl0/sUX6/Yu1mHD99ATFv3kBHWxueVVwx5Js+8PHK/z6JiIhK0ozDjxCekIGKFgYYw9GXShC9AB0/fR7zl67CmBFD4ePpjq0792H46InYtXEFLC3M893GyMgQuzasUH4vkeS9vZKDPX76fhDs7cojKysLWwL2YejoCdi7eSUszM1KcG+IiIjyuvDsDTZfCwUAzO7mB2M90V96CSowAtscsBed2rZGhzYt4eLkiDEjhkJfXw/7D5947zYSSGBtZaH8srK0yHP7Zy2aom6taqhoVx6VnSvhx6HfIC0tHc+evyjp3SEiIlJKyZTh57+u+vqqfiU0qMzRl6oQtYbKZDI8fhKMfl/6K5dJpVLUqVkNQQ8fv3e7jIwMtPuiHwSFAPcqlTH0mz6o7FzpvY+x58BRGBsZoUpl52LfByIioveZfvgRIpMy4WhpiJ/beIgdh/5B1AKUmJQMuUIBS0vzPMstLczxMjQ8320qOdpjws/fw83FGalpadi0fTe+HjYaO9YuhW25v5v1hcvXMXbKbGRmZcHaygJL5k2F+XvGX9nZMmTLZMrv09LTP37niIhIo517+gZbr4cBAOZ084OhLkdfqkTtng0/b0/4ef99AllVH0906zMYuw8cweD+vZXLa1X3w5ZVC5GYlIw9h45hzORZWLdsXr7nFa3dvAMr128tjfhERKQBkjL+Hn31a+iEui5WIieifxO1AJmbmUJLKkV8fGKe5fEJie+c1/M+2tracHdzQVhEVJ7lBgb6cKhoB4eKdvD19kDnXgOw7/Bx9OvV/Z376NerO3p176z8Pi09HW39+xZ6f4iIiABg2sGHiE7OhJOVIX5qzdGXKhL1JGgdHR14uLvi+u1A5TKFQoEbtwLh51WwXxi5XI7gkFewtvpwYVIIArKzZfnepqurA2MjQ+WXkaFhwXeCiIjoH04/jkHArXBIJMBc/6ow0NUSOxLlQ/QRWC//Tpg8Yz683N3g7VkFW3buQ0ZmJtq3aQEAmDh9HspZW2HYwL4AgJXrt8LXyx0V7e2QmpqKDdt2IzrmNTq1bQ0AyMjIxJpN29GkQV1YW1kiMSkZO/YexJs3cWjRtJFYu0lERBogKV2GMbvvAQD6N3RGLSdLkRPR+4hegFo1b4KExCQsX7sJcfEJqOLqgkWzpyhHYNExbyCV/H2gKjklFdPmLkJcfAJMjY3h4e6K1UvmwMXJEUDuVWQvQ8Nx8NgpJCYlw8zUFF4ebli5aNZ7rxQjIiIqDr8efICY5Cy4WBthVGu++a4qkwiCIIgdQtWkpqWjadvuOHtoB4yNOA4jIqL/duJhDAZsuAmpBNg5uAFqOBbsXFYqPoV5/Rb9jRCJiIjUXWJ6NsbuyR19DWjswvKjBliAiIiIPtLk/Q/wJiULlW2M8GPLKmLHoQJgASIiIvoIR+9HY+/dSEglwLzu1aCvw6u+1AELEBERURHFp2Vj/N7c0degTyqjmoO5uIGowFiAiIiIimjivvuITc1GFVtjfN/CTew4VAgsQEREREVw+F4UDgZFQUsqwTz/atDT5uhLnbAAERERFVJsahbG770PABjStDJ8K+b/YdukuliAiIiICkEQBEzYex/xadnwKG+C4c05+lJHLEBERESFcDAoCkfuR0NbKsFc/6rQ1eZLqTris0ZERFRAb1KyMHFf7uhraDNX+Nhz9KWuWICIiIgKQBAEjN97DwnpMnhVMMXQZq5iR6KPwAJERERUAPsDI3HsQQx0tDj6Kgv47BEREf2H18mZmLjvAQDgu+Zu8LIzFTkRfSwWICIiog8QBAFj99xDUoYMvvZmGNS0stiRqBiwABEREX3A7tsROPnoNXS1pJjrXxU6WnzpLAv4LBIREb1HdFImfj2QO/r6voUb3MubiJyIigsLEBERUT4EQcCY3UFIzsxB1Ypm+LaJi9iRqBixABEREeUj4FY4zjx5A13t3NGXNkdfZQqfTSIion+JTMzA1AMPAQAjWlaBmy1HX2UNCxAREdE/CIKAX3bfQ0pWDqo7mmNAY46+yiIWICIion/YfiMM55++gd5foy8tqUTsSFQCWICIiIj+Ep6QjmmHHgEARrd2R2UbY5ETUUlhASIiIkLu6OvnXUFIzcpBrUoW6NfQWexIVIJYgIiIiABsvhaKS8Fx0NeRYnY3P46+yjgWICIi0nhh8emYfjh39PVTaw+4cPRV5rEAERGRRlMoBPy0Mwjp2XLUcbJE3wZOYkeiUsACREREGm3TtVe4EhIHAx0tzPH3g5SjL43AAkRERBrrVVwaZhx+DAD4pY0HKlkZiZyISgsLEBERaSSFQsDonUHIkMlRz8USvetVEjsSlaJCFyAnJydMmTIFoaGhJZGHiIioVKy/8hLXX8TDUFcLc7pV5ehLwxS6AP3www/YvXs3XFxc0LJlS2zbtg1ZWVklkY2IiKhEvIhNw6yjuaOvsZ97wsHSUOREVNqKVIDu3r2L69evw9PTE8OHD0eFChUwbNgw3L59uyQyEhERFRu5QsDogEBkyhRo6GqFXnUdxY5EIijyOUA1atTAwoULERkZiUmTJmHVqlWoXbs2qlWrhjVr1kAQhOLMWSYIgoCTD2OgUPBnQ0QklrWXXuDmqwQY6WphVlc/SCQcfWmiIhcgmUyGHTt2oEOHDhg5ciRq1aqFVatWoWvXrhg7dix69epVnDnLhDWXXuKbDTfx3bY7yJTJxY5DRKRxnr9JxZxjTwAA49t5oaIFR1+aSruwG9y+fRtr167F1q1bIZVK0adPH8yfPx8eHh7KdTp37ozatWsXa9CywERfG9pSCQ4GRSEyMQN/9qkFa2M9sWMREWkEuULAqIBAZOUo0NjNGj1qO4gdiURU6CNAtWvXxrNnz7Bs2TJERERg7ty5ecoPADg7O6NHjx7FFrKs6F7LARv614GZgQ5uhyai05JLeBqTInYsIiKNsOpCCO6EJsJET5ujLyp8AQoJCcHRo0fh7+8PHR2dfNcxMjLC2rVrPzpcWdSgsjV2D2mASlaGCE/IQNell3Hh2RuxYxERlWnBr1Mw78RTAMCEdl6wMzcQORGJrdAF6PXr17h27do7y69du4abN28WS6iyrrKNMfYMaYg6TpZIycpB37U3sPnaK7FjERGVSTlyBUYGBCE7R4Gm7jbwr1VR7EikAgpdgIYOHYqwsLB3lkdERGDo0KHFEkoTWBrpYuM3ddCluj3kCgHj9tzHtIMPIecVYkRExerPCyEIDEuEib42Znbh6ItyFboAPXz4EDVq1HhnefXq1fHw4cNiCaUp9LS1MK97VYxsWQUAsOriC3y78RbSsnJETkZEVDY8iU7BghPPAACT23ujvJm+yIlIVRS6AOnp6SEmJuad5VFRUdDWLvRFZRpPIpFg+KduWNizOnS1pTj5KAbdV1xBdFKm2NGIiNSaTK7AqIBAZMsV+NSjHLrUsBc7EqmQQhegVq1aYcyYMUhKSlIuS0xMxNixY9GyZctiDadJOlS1w9YB9WBlpIsHkcnouOQi7kck/feGRESUr+Vnn+NeRBLMDHQwvYsvR1+UR6EL0Ny5cxEWFoZKlSqhWbNmaNasGZydnREdHY158+aVREaNUbOSBfYObQjXcsaISc5C9xVXcPLhu0fbiIjowx5FJWPh6dzR168dvGFrytEX5VXoAmRvb4+goCDMnj0bXl5eqFmzJv744w/cu3cPDg58U6mP5WBpiF2DG6CxmzXSs+UYsPEmVl0I4UeLEBEVkEyuwMgdgZDJBbTyskXHanZiRyIVVKSTdoyMjDBw4MDizkJ/MTPQwZq+tTFx3wNsvR6KaYce4UVsGn7t4A1trSJ/egkRkUZYciYYD6OSYW6og2mdfTj6onwV+azlhw8fIjQ0FNnZ2XmWd+jQ4aNDEaCjJcX0zj6obGOE3w4/wuZroQiNT8eSXjVgqp//G1ASEWm6B5FJWHw6GAAwpaMPyplw9EX5K3QBCgkJQefOnXHv3j1IJBLlaOZtw5bL+SGfxUUikeCbxi5wtDTE99vu4sKzWHRbdhmrv6oNB0t+gB8R0T9l5+SOvnIUAtr4lEd7vwpiRyIVVuh5yvfffw9nZ2e8fv0ahoaGePDgAc6fP49atWrh7NmzJRCRWnmXR8Cg+rA11cPTmFR0XnoJt0MTxI5FRKRSFp9+hsfRKbA00sXUThx90YcVugBduXIFU6ZMgbW1NaRSKaRSKRo1aoQZM2bgu+++K4mMBMDH3gx7hzaEVwVTxKZmo8efV3EgMFLsWEREKuFeeBKWnH0OAJja0QfWxnoiJyJVV+gCJJfLYWJiAgCwtrZGZGTui3ClSpXw5MmT4k1HeVQwM0DAoPpo4VkO2TkKDN96B4tPP+MVYkSk0bJy5BgZcBdyhYC2fhXQlqMvKoBCFyAfHx8EBgYCAOrWrYvZs2fj0qVLmDJlClxcXIo9IOVlpKeNFb1r4euGzgCAucefYlRAELJyeO4VEWmmP04+w9OYVFgb62JqRx+x45CaKPRJ0OPHj0daWhoAYMqUKWjXrh0aN24MKysrbN++vUghduw5iI3bdiMuPgFurs4Y/d238PF0z3fdA0dO4tdZC/Is09XRweUTewAAOTk5WLp6Iy5dvYmIqGgYGxmhTs2qGD6wL2ysrYqUT9VoSSWY2N4LzjZGmLz/AXbdDkdYQjpW/K8mLIx0xY5HRFRqAsMSsfxc7uhrWidfWPLfQCqgQheg1q1bK//b1dUVjx8/Rnx8PCwsLIp0wtnx0+cxf+kqjBkxFD6e7ti6cx+Gj56IXRtXwNLCPN9tjIwMsWvDCuX3/3zYzMwsPH76HN/06QG3ys5ISUnF3MV/YsTYqdj454JC51NlvetVgqOlIYZuvo3rL+LRZdllrOlbG87WRmJHIyIqcZkyOUYGBEIhAB2r2eEzn/JiRyI1UqgRmEwmg7a2Nu7fv59nuaWlZZHPtt8csBed2rZGhzYt4eLkiDEjhkJfXw/7D5947zYSSGBtZaH8srK0UN5mbGyEpfOmoWWzxnByrAhfbw/89P0gPHoajOiY10XKqMo+qWKDXYMbwN7cAC9i09B56SVcDYkTOxYRUYmbf/Ipgl+nwtpYD5Pbe4sdh9RMoQqQjo4OHB0di+29fmQyGR4/CUbdmtX+DiSVok7Nagh6+Pi922VkZKDdF/3Q1r8vRoybiucvXn3wcVJT0yGRSGBsbJzv7dnZMqSmpSu/0tLTi7Q/YnEvb4K9QxuimoM5EtNl6L36GnbeChc7FhFRibkdmoCV50MAANM7+3D8T4VW6BHYuHHjMHbsWGzcuBGWlpYf9eCJScmQKxSwtDTPs9zSwhwvQ/N/Aa/kaI8JP38PNxdnpKalYdP23fh62GjsWLsUtuWs31k/Kysbi/5ci9afNoGxUf5vHrh28w6sXL/1o/ZFbDYmetg2sB5G7gjEoXtRGBUQiJexaRjRsgqkUr4XBhGVHZkyOUb9NfrqUt0erbw5+qLCK3QBWrx4MYKDg2FnZ4dKlSrByCjv+Sa3b98utnD58fP2hJ+3p/L7qj6e6NZnMHYfOILB/XvnWTcnJwe//DoTggD88uPQ995nv17d0at7Z+X3aenpaOvft9izlzR9HS0s6lkdztZGWHwmGIvPBONFXBrm+VeFvo6W2PGIiIrFvONPEPImDeVM9DCJoy8qokIXoE6dOhXbg5ubmUJLKkV8fGKe5fEJiXnO6/kQbW1tuLu5ICwiKs/ynJwc/DJ5JqJjXmPZ79Pfe/QHAHR1daCrWzY+X0sqlWBUa3c4WRthzO4gHAqKQkRCBlb2qQUbE74xGBGpt5sv47Hq4gsAwMyuvjAzLBv/dlPpK3QBmjRpUrE9uI6ODjzcXXH9diCaNq4PAFAoFLhxKxDdO7cr0H3I5XIEh7xCw3o1lcvelp/Q8EisWDAD5mamxZZZXXSrWREVLQzw7cZbuBuWiE5LLmFN39pwL28idjQioiLJyM4dfQlC7r9xzT1sxY5EaqzQb4RY3Hr5d8Leg8dw8OgpvHgVhhnzlyIjMxPt27QAAEycPg+L/1ynXH/l+q24euM2wiOj8fhpMCb8Ng/RMa/RqW3u5fk5OTn4adIMPHoSjGnjR0EuVyA2LgGxcQmQyWRi7KJo6rlYYc+QBnCyMkREYga6LbuMc0/fiB2LiKhIZh97jJdx6Shvqo8J7bzEjkNqrtBHgKRS6QcveS/sFWKtmjdBQmISlq/dhLj4BFRxdcGi2VOUI7DomDeQSv7uackpqZg2dxHi4hNgamwMD3dXrF4yBy5OjgCA12/icP7SNQDAl9/k/Wyy5fOno1Z1v0LlU3cuNsbYM6Qhvt10C9dfxOPrdTcwuYM3eterJHY0IqICuxYSh3WXXwL4a/RlwNEXfRyJUMgPktq3b1+e72UyGe7cuYP169fj119/Rf/+/Ys1oBhS09LRtG13nD2044PnDqmTrBw5xu6+j123c6+u69/IGWM/94QWrxAjIhWXnp2DzxZcQGh8OnrUdsDMrpr1P7JUcIV5/S70EaCOHTu+s6xbt27w9vbG9u3by0QBKov0tLUw198PztaGmHv8KVZffIFXcWn4o0d1GOkV+teAiKjUzDryGKHx6bAz08e4tp7/vQFRARTbOUD16tXDqVOniuvuqARIJBIMa+6GxV9Wh662FCcfvYb/8iuISsoQOxoRUb4uP4/F+iu5b3Y7q5sfTPQ5+qLiUSwFKCMjAwsXLoS9vX1x3B2VsHZ+dtg2sB6sjHTxMCoZnZZcwv2IJLFjERHlkZaVg592BgEAvqzriMZuNiInorKk0LOPf3/oqSAISElJgaGhITZt2lSs4ajk1HC0wN6hDfH1uht49joV/suv4I8e1fiOqkSkMmYceYTwhAzYmxtg7OccfVHxKnQBmj9/fp4CJJVKYWNjg7p168LComBvXkiqwcHSELuGNMDQzbdx4Vksvt10C+M+90T/Rs5F/nBbIqLicPFZLDZdDQUAzOnmB2Oeq0jFrNC/UX379i2BGCQWU30drO1bG5P2P8Dma6GYdugRQmLT8GsHb+hoif42UUSkgVIyZfh5V+7oq3e9Smjg+u7nPBJ9rEK/wq1duxYBAQHvLA8ICMD69euLJRSVLm0tKaZ18sH4tp6QSIAt10Lx9bobSMrQrDeOJCLVMP3wI0QkZsDB0gC/tPEQOw6VUYUuQDNmzIC19bttvFy5cpg+fXqxhKLSJ5FI8E1jF/zZuxYMdLRw4Vksui27jLD4dLGjEZEGOf/0DbZeDwMAzOlWlW/TQSWm0AUoNDQUzs7O7yyvVKkSQkNDiyUUiaelly0CBtWHrakenr1ORacll3DrVYLYsYhIAyT/Y/TVt4ET6rlYiZyIyrJCF6By5cohKCjoneWBgYGwsuIva1ngY2+GfUMbwdvOFHFp2ei58ioOBEaKHYuIyrhpBx8iKikTlawM8dNn7mLHoTKu0AWoZ8+e+O6773DmzBnI5XLI5XKcPn0a33//PXr06FESGUkE5c30sePb+mjhaYvsHAWGb72DRaeeoZCfnEJEVCBnHr/GjpvhkEhyR1+Guhx9UckqdAGaOnUq6tati08//RQGBgYwMDBAq1at0Lx5c54DVMYY6WljRe+a+KZR7shz3omnGLkjEFk5hfvAWyKiD0lKl+GX3bmTha8bOqOOs6XIiUgTFLpi6+rqYvv27Zg2bRru3r0LAwMD+Pr6olIlfrp4WaQllWB8Oy84WRth0v4H2H0nAuEJGVjRuyYsjHTFjkdEZcCUgw8Rk5wFF2sjjGrF0ReVjiIfY3Rzc4Obm1txZiEV9r96leBoaYihm2/j+st4dF56Cav71kZlG2OxoxGRGjv5MAa7bv81+vL3g4GultiRSEMUegTWtWtXzJo1653ls2fPhr+/f7GEItXUpIoNdg1pgIoWBngZl44uSy/jyvM4sWMRkZpKTM/GmD33AAADGrugZiWOvqj0FLoAnT9/Hp9//vk7y9u0aYPz588XSyhSXVVsTbBnSENUdzRHUoYMfdZcw46bYWLHIiI1NHn/A7xJyUJlGyOMaFlF7DikYQpdgFJTU6Gr++65Hzo6OkhOTi6WUKTabEz0sHVAPbTzqwCZXMBPO4Mw++hjKBS8QoyICubYg2jsvRsJqQSY618V+jocfVHpKnQB8vX1xfbt299Zvm3bNnh5eRVLKFJ9+jpaWNijOoY3dwUALD37HMO23kamjFeIEdGHxadlY9xfo6+BTSqjuiM/SJtKX6FPgp4wYQK6dOmC58+fo3nz5gCAU6dOYcuWLdi5c2exByTVJZVKMLKVO5ysjPDL7iAcvheNiMSrWNmnJsqZ6Isdj4hU1KT9DxCbmg23csb4oQUvpiFxFPoIUPv27bF3714EBwdjyJAhGDlyJCIiInD69Gm4urqWREZScV1rVsSm/nVhbqiDwLBEdF5yGU+iU8SORUQq6Mi9KBwIjISWVMLRF4mq0AUIANq2bYtLly4hLS0NISEh6N69O0aNGoWqVasWdz5SE3VdrLBnSEM4WxshIjEDXZddxtknr8WORUQqJC41C+P33gcADP6kMqo6mIsbiDRakQoQkHs12FdffQU7OzvMmzcPzZs3x9WrV4szG6kZZ2sj7BnSAHWdLZGalYOv193AxisvxY5FRCpi4r4HiEvLhrutCYZ/yokBiatQBSg6OhozZ86Em5sb/P39YWpqiqysLOzduxczZ85E7dq1SyonqQlzQ11s7F8X3WpWhEIAJux7gF8PPICcV4gRabSDQZE4dC8KWlIJ5nWvCj1tjr5IXAUuQO3bt4e7uzuCgoKwYMECREZGYtGiRSWZjdSUrrYUc7r5YXTr3Le0X3vpJQZuuInUrByRkxGRGN6kZGHCX6Ovoc1c4WNvJnIiokIUoCNHjqB///749ddf0bZtW2hpsb3T+0kkEgxt5oolX9aAnrYUpx6/hv/yK4hKyhA7GhGVIkEQMH7vPSSky+BZwRTDmnH0RaqhwAXo4sWLSElJQc2aNVG3bl0sXrwYsbGxJZmNyoC2fhWwbWA9WBvr4lFUMjouvoR74UlixyKiUrI/MBLHHsRAWyrBPP+q0NUu8qmnRMWqwL+J9erVw8qVKxEVFYVvv/0W27Ztg52dHRQKBU6cOIGUFF72TPmr7miBPUMaooqtMV6nZKH7iis49iBa7FhEVMJeJ2di4r4HAIDhzd3gZWcqciKivxW6ihsZGeHrr7/GxYsXce/ePYwcORIzZ85EuXLl0KFDh5LISGWAg6Uhdg5ugCZVbJAhk2PQplv48/xzCAJPjiYqiwRBwNg995CUIYO3nSmGNKssdiSiPD7qWKS7uztmz56N8PBwbN26tbgyURllqq+DNV/Vwv/qOUIQgOmHH2PsnnuQyRViRyOiYrbnTgROPnoNHa3cq750tDj6ItVSLL+RWlpa6NSpE/bv318cd0dlmLaWFFM7+mBiOy9IJMDW62Hot/YGkjJkYkcjomISk5yJyftzR18/tKgCj/IcfZHqYSWnUieRSPB1I2es7F0LhrpauBgci67LLiM0Ll3saET0kQRBwJjd95CcmQO/imb4tomL2JGI8sUCRKJp4WWLgEH1Ud5UH8GvU9Fp6SXcehUvdiwi+gg7b4Xj9OPX0NWSYq5/VWhz9EUqir+ZJCpvOzPsG9YQPvamiE/LRs+V17DvboTYsYioCKKSMjDlwEMAwI8tq6CKrYnIiYjejwWIRGdrqo8d39ZHSy9bZOco8P22u/jj5DNeIUakRgRBwM+77iElKwfVHMwxoLGz2JGIPogFiFSCoa42lv+vJgb+db7A/JNPMWJHILJy5CInI6KC2HEzDOefvoGuNkdfpB74G0oqQ0sqwdjPPTG9sy+0pBLsuROB/626hvi0bLGjEdEHRCRmYOrBRwCAUa2qwLWcsciJiP4bCxCpnC/rOmJdv9ow0dfGjZcJ6Lz0EoJfp4odi4jyIQgCft4ZhNSsHNRwNEf/Rrzqi9QDCxCppMZuNtg9uAEcLA3wKi4dXZZewuVgfvYckarZcj0UF4NjoffX6EtLKhE7ElGBsACRynKzNcGeIQ1Rw9EcyZk56LPmOnbcCBM7FhH9JSw+HdMP5Y6+fvrMAy42HH2R+mABIpVmbayHLQPqoX1VO+QoBPy0KwgzjzyGQsErxIjEpFAI+HlXENKy5ajtZIF+DZzEjkRUKCxApPL0dbSwsEc1fPepGwBg+bnnGLrlNjKyeYUYkVg2X3uFy8/joK8jxZxuVSHl6IvUDAsQqQWJRIIRLavg9+5VoaslxZH70ejx5xW8Ts4UOxqRxgmNS8f0w48BAL985gEnayORExEVHgsQqZUuNSpi0zd1YWGog8DwJHRacgmPo5PFjkWkMRQKAaN3BiJDJkddZ0v0qe8kdiSiImEBIrVTx9kSe4Y0hIu1ESKTMtFt2RWcefJa7FhEGmHDlZe49iIehrpaHH2RWmMBIrXkZG2E3UMaoL6LFVKzctB/3Q1suPJS7FhEZdrL2DTMPJo7+hrTxgOOVoYiJyIqOhYgUlvmhrpY/3Ud+NesCIUATNz3AJP3P4CcV4gRFTu5QsCogEBkyhRoUNkKvepWEjsS0UdhASK1pqstxexufvjpM3cAwLrLLzFgw02kZuWInIyobFl76QVuvkqAka4WZnX14+iL1B4LEKk9iUSCIU1dsbRXDehpS3H68Wt0W3YZkYkZYkcjKhNC3qRizrEnAIBxbb3gYMnRF6k/FiAqMz73rYDt39aHtbEeHkenoOOSSwgKTxQ7FpFaezv6yspRoLGbNXrWcRA7ElGxYAGiMqWagzn2Dm0Aj/ImeJOShe4rruDo/WixYxGprdUXQ3A7NBHGetqY2dUPEglHX1Q2aIsdYMeeg9i4bTfi4hPg5uqM0d99Cx9P93zXPXDkJH6dtSDPMl0dHVw+sUf5/enzl7Fr/xE8fhqMpOQUbF65EO5u/HRiTVLRwhABg+pj2JY7OPf0DQZvvoVfPvPAwCYu/MebqBCCX6dg7vGnAIAJ7Txhb24gciKi4iPqEaDjp89j/tJVGNC3Jzat/ANVKjtj+OiJiE9IfO82RkaGOLpro/LrwPY1eW7PyMxENV8vDB/Yt2TDk0oz0dfB6q9qoU/9ShAEYMaRxxiz+x5kcoXY0YjUQo5cgZEBQcjOUeCTKjboXoujLypbRD0CtDlgLzq1bY0ObVoCAMaMGIqLV29g/+ET6NvLP99tJJDA2srivffZtlVzAEBkVEzxBya1oq0lxZSOPnCxNsKUgw+x7UYYQuPTsaxXTZgZ6ogdj0ilrbzwAoFhiTDR18bMrr48ekpljmhHgGQyGR4/CUbdmtX+DiOVok7Nagh6+Pi922VkZKDdF/3Q1r8vRoybiucvXn10luxsGVLT0pVfaenpH32fpDr6NnTGqq9qwUhXC5efx6HLskt4FZcmdiwilfU0JgXzT+SOvia280IFM46+qOwR7QhQYlIy5AoFLC3N8yy3tDDHy9DwfLep5GiPCT9/DzcXZ6SmpWHT9t34etho7Fi7FLblrIucZe3mHVi5fmuRtyfV19zDFgGDGqD/+ht4/iYNnZdexp+9a6KWk6XY0YhUikyuwMgdgciWK9Dcoxy61awodiSiEqFWV4H5eXuiXetP4e7mgprVfDFn6jhYmJlh94EjH3W//Xp1x9lDO5RfhwLWFU9gUiledqbYN7QhfO3NEJ+WjS9XXsO+uxFixyJSKSvOPce9iCSY6mtjRheOvqjsEq0AmZuZQksqRXx8Yp7l8QmJsLJ8/zk+/6StrQ13NxeERUR9VBZdXR0YGxkqv4wM+SZfZVU5U31s/7YeWnnZIluuwPfb7mLByacQBH58BtHj6GT8ceoZAGByB2/YmuqLnIio5IhWgHR0dODh7orrtwOVyxQKBW7cCoSfl0eB7kMulyM45NUHT4om+jdDXW0s/19NfPtJ7tsjLDj5DD9sv4tMmVzkZETieTv6kskFtPC0Refq9mJHIipRol4F1su/EybPmA8vdzd4e1bBlp37kJGZifZtWgAAJk6fh3LWVhj21yXtK9dvha+XOyra2yE1NRUbtu1GdMxrdGrbWnmfSckpiI55gzdxcQCAV2G55xNZWVqwKJGSVCrBmDaecLIywoS997HvbiQiEjKwondNWBnriR2PqNQtPfMcDyKTYW6og+ldfDj6ojJP1ALUqnkTJCQmYfnaTYiLT0AVVxcsmj1FOQKLjnkDqeTvg1TJKamYNncR4uITYGpsDA93V6xeMgcuTo7Kdc5fupbnzRLHTpkNABjwVU98269X6ewYqY2edRzhaGmIQZtu4earBHReehlr+taGazljsaMRlZoHkUlYdDp39PVrB2+UM+Hoi8o+icCTH96RmpaOpm1zT4w2NuL5QJog+HUK+q27gbD4DJjo547IGroW/cpCInWRnaNAxyWX8CgqGZ95l8ey/9Xg0R9SW4V5/Varq8CISoprORPsHdIQNStZICUzB1+tuY5t10PFjkVU4hafCcajqGRYGOpgaieOvkhzsAAR/cXKWA+bv6mLjtXskKMQ8Mvue5hx5BEUCh4kpbLpfkQSlpwJBgBM7eQDGxOe/0aagwWI6B/0dbSw4Itq+P5TNwDAinMhGLL5NjKyeYUYlS1ZOXKM3BEIuUJAW98KaOdnJ3YkolLFAkT0LxKJBD+2rIIFX1SDrpYURx9E44s/r+B1cqbY0YiKzcJTz/AkJgVWRrqY0tFb7DhEpY4FiOg9OlW3x+YBdWFhqIOg8CR0XHIJDyOTxY5F9NECwxKx/FwIAGBaJx++9QNpJBYgog+o7WSJvUMbwsXGCFFJmfBffhmnH8eIHYuoyDJlcowKyB19ta9qhza+FcSORCQKFiCi/1DJygh7BjdEg8pWSMuW45v1N7Hu0guxYxEVyYKTz/DsdSqsjfUwpQNHX6S5WICICsDMUAfrv66DL2o5QCEAkw88xKR995EjV4gdjajAbocm4M/zzwEA0zv7wMJIV+REROJhASIqIB0tKWZ29cUvbXI/q279lVf4ZsNNpGTKRE5G9N8yZXKMDgiEQgA6VbNDK+/yYkciEhULEFEhSCQSDPqkMpb/rwb0daQ4++QN/JdfQURihtjRiD7o9xNP8fxNGmxM9DCZoy8iFiCiovjMpwK2D6wPGxM9PI5OQcfFlxAYlih2LKJ83XoVj5UXcq/6mtHZF+aGHH0RsQARFVFVB3PsHdoQHuVNEJuahS/+vIIj96LEjkWUR0a2HKMCgiAIQNcaFdHCy1bsSEQqgQWI6CPYmxtg5+AGaOpug0yZAoM338ays8/BzxgmVTHn2BO8iE2DrakeJrb3EjsOkcpgASL6SMZ62ljVpxb6NnACAMw6+hg/7wpCdg6vECNxXX8Rj7WXc9+yYWZXP5gZ6IiciEh1sAARFQNtLSkmd/DGrx28IZUAO26G46s115GUzivESBzp2TkYvTMQggB0r1URzdzLiR2JSKWwABEVo68aOGH1V7VhpKuFKyFx6LzsEl7GpokdizTQ7KNP8CouHRXM9DG+HUdfRP/GAkRUzJp5lMPOwQ1gZ6aPkDdp6Lz0Em68jBc7FmmQK8/jsO7ySwDArK5+MNXn6Ivo31iAiEqAZwVT7B3aEH4VzZCQLkOvldew50642LFIA6Rl5eCnXYEAgJ51HNCkio3IiYhUEwsQUQkpZ6qP7QPr4zPv8siWK/Dj9kD8fuIprxCjEjXzyGOExWfA3twAYz/3FDsOkcpiASIqQQa6WljaqwYGfVIZALDw1DN8v+0uMmVykZNRWXQpOBYbr74CkDv6MuHoi+i9WICISphUKsEvbTwwq6svtKUS7A+MRK9V1xCXmiV2NCpDUjJl+GlnEADgf/Uc0cjNWuRERKqNBYiolHxR2xEbvq4DU31t3HqVgE5LLyH4dYrYsaiMmH74MSISM1DRwgBj2nD0RfRfWICISlEDV2vsHtIQjpaGCIvPQOell3HxWazYsUjNnX/6BluvhwIAZnfzg5GetsiJiFQfCxBRKXMtZ4y9QxuiViULpGTm4Ku115UvXkSFlZwpwy+7ckdfX9WvhAaVOfoiKggWICIRWBrpYvOAuuhUzQ5yhYAxu+9h+uFHUCh4hRgVzm8HHyEyKROOlob4uY2H2HGI1AYLEJFI9LS1MP+LavixRRUAwJ/nQzBo0y2kZ+eInIzUxZknr7H9ZhgkEmCuf1UY6nL0RVRQLEBEIpJIJPi+hRv+6FENulpSHH8Ygy9WXEVMcqbY0UjFJWXIMGbXPQBA3wZOqONsKXIiIvXCAkSkAjpWs8eWAXVhaaSLexFJ6LTkEh5GJosdi1TY1IMPEZ2cCScrQ/zUmqMvosJiASJSEbWcLLF3SENUtjFCVFImui2/jFOPYsSORSro1KMY7LwVrhx9GehqiR2JSO2wABGpEEcrQ+we0hANXa2Qni3HgA03sebiC358BiklpmdjzO7c0dc3jZxRy4mjL6KiYAEiUjFmBjpY168OetR2gEIAphx8iIn7HiBHrhA7GqmAXw88xOuULLjYGGFkK3ex4xCpLRYgIhWkoyXFjC6+GPu5ByQSYOPVV+i//iZSMmViRyMRHX8QjT13IiD9a/Slr8PRF1FRsQARqSiJRIKBTSpjWa+a0NeR4tzTN+i27ArCE9LFjkYiSEjLxtg99wEAA5q4oIajhciJiNQbCxCRivvMpzx2fFsf5Uz08CQmBZ2WXMad0ASxY1Epm7T/AWJTs+Bazlj53lFEVHQsQERqwK+iOfYObQjPCqaITc1Cjz+v4vC9KLFjUSk5ej8K+wMjoSWVYB5HX0TFggWISE3YmRsgYFB9NPcoh6wcBYZsvo0lZ4J5hVgZF5eahXF/jb6+beKCqg7m4gYiKiNYgIjUiLGeNlb2qYV+DZ0AAHOOPcFPO4OQncMrxMqqifsfIC4tG1VsjfF9Czex4xCVGSxARGpGSyrBpPbemNLRG1IJEHArHH3WXENierbY0aiYHQyKxKGgqL9GX9Wgp83RF1FxYQEiUlN96jthdd/aMNbTxtWQeHRZehkvYtPEjkXF5E1KFibszR19DW1aGb4VzURORFS2sAARqbFm7uWwc3B92JsbICQ2DZ2XXsL1F/Fix6KPJAgCJuy9j4R0GTzKm2BYc46+iIobCxCRmvMob4o9QxugakUzJKbL0GvVVey+HS52LPoIB4KicPRBNLSlEsz1rwpdbf5TTVTc+FdFVAaUM9HHtoH18blvecjkAkbsCMTvx5/wCjE19DolExP35Y6+hjV3hY89R19EJYEFiKiMMNDVwuKeNTC4aWUAwMLTwfhu211kyuQiJ6OCEgQB4/bcR2K6DF4VTDG0mavYkYjKLBYgojJEKpXg5888MLubH7SlEhwIjMSXK68iNjVL7GhUAHvvRuDEwxjoaEkwr3tV6Gjxn2iiksK/LqIyqHstB2zoXwdmBjq4HZqITksu4VlMitix6ANikjMxef9DAMB3zd3gWcFU5EREZRsLEFEZ1aCyNXYPaYBKVoYIT8hAl6WXceHZG7FjUT4EQcDY3feQlCGDr70ZBv01xiSiksMCRFSGVbYxxp4hDVHHyRIpWTnou/YGtlwLFTsW/cuu2xE49fg1dLWkmOvP0RdRaeBfGVEZZ2mki43f1EHn6vaQKwSM3XMPvx16CLmCV4ipgqikDPx64AEA4IeWbnAvbyJyIiLNwAJEpAH0tLXwe/eqGNGyCgBg5YUXGLTpFtKzc0ROptkEQcAvu+4hJTMHVR3MMbCxi9iRiDQGCxCRhpBIJPjuUzcs7FkdutpSnHgYA//lVxCdlCl2NI0VcDMc556+ga62FHO7+UGboy+iUsO/NiIN06GqHbYOqAcrI108iExGpyWXcD8iSexYGiciMQNTD+Ze9TWyZRW42XL0RVSatMUOAAA79hzExm27ERefADdXZ4z+7lv4eLrnu+6BIyfx66wFeZbp6ujg8ok9yu8FQcCKtZux5+AxpKamoaqPJ34ZMQSOFe1LcjeI1EbNShbYO7Qh+q27geDXqei+4goW9qiOFl62YkfTCLmjryCkZOWguqM5vuHoi6jUiX4E6Pjp85i/dBUG9O2JTSv/QJXKzhg+eiLiExLfu42RkSGO7tqo/DqwfU2e29dv3YVtuw5gzIihWLdsHvQN9DF89ERkZWWX8N4QqQ8HS0PsGtwAjVytkZ4tx4CNN7H64gt+fEYp2Ho9DBeexUJPO/eqLy2pROxIRBpH9AK0OWAvOrVtjQ5tWsLFyRFjRgyFvr4e9h8+8d5tJJDA2spC+WVlaaG8TRAEbN25D/17f4GmjerBrbIzpowZgTex8Th78Upp7BKR2jAz0MHafrXRs44jBAGYevAhJuy7jxy5QuxoZVZ4Qjp+O5Q7+hrd2h2VbYxFTkSkmUQtQDKZDI+fBKNuzWrKZVKpFHVqVkPQw8fv3S4jIwPtvuiHtv59MWLcVDx/8Up5W0RUDOLiE1DnH/dpbGwEHy933HvPfWZny5Calq78SktP/+h9I1IXOlpSTO/sg/FtPSGRAJuuhqLfuhtIzpSJHa3MUSgE/LQzCGnZctSqZIF+DZ3FjkSksUQ9BygxKRlyhQKWluZ5lltamONlaHi+21RytMeEn7+Hm4szUtPSsGn7bnw9bDR2rF0K23LWiItPAABY5XOfcfGJ+d7n2s07sHL91o/dHSK1JZFI8E1jFzhYGuKHbXdx4Vksui27jNVf1YaDpaHY8cqMzddDcfl5HPR1pJjD0ReRqEQfgRWWn7cn2rX+FO5uLqhZzRdzpo6DhZkZdh84UuT77NerO84e2qH8OhSwrvgCE6mR1t7lETCoPmxN9fA0JhWdl17CndAEsWOVCaFx6Zhx+BEA4KfWHnC2NhI5EZFmE7UAmZuZQksqRfy/jszEJyTmOa/nQ7S1teHu5oKwiCgAUG7376M9ufdpnu996OrqwNjIUPllZMj/4yXN5WNvhr1DG8KzgiliU7PR48+rOBgUKXYstaZQCBi9MxDp2XLUcbJE3wZOYkci0niiFiAdHR14uLvi+u1A5TKFQoEbtwLh5+VRoPuQy+UIDnkFa6vc4mNfwRZWlha4cfuucp3UtHTcf/gEvgW8TyJNV8HMADsH1cenHuWQlaPAsC13sORMMK8QK6KNV1/h2ot4GOhoYY6/H6QcfRGJTvT3Aerl3wmTZ8yHl7sbvD2rYMvOfcjIzET7Ni0AABOnz0M5aysMG9gXALBy/Vb4ermjor0dUlNTsWHbbkTHvEantq0B5J7L0LNbR6zeuB0OFe1hX8EWy1Zvgo21JZo2qi/WbhKpHSM9bfzZpxZ+O/QIay69wJxjTxDyJg0zuvhCV1vtpueieRmbhplHci/AGPO5BypZcfRFpApEL0CtmjdBQmISlq/dhLj4BFRxdcGi2VOUo6zomDeQSv7+xzY5JRXT5i5CXHwCTI2N4eHuitVL5sDFyVG5zlc9uyIzMxPT5y5CSmoaqvl6YeHsKdDT0y31/SNSZ1pSCSa294KzjREm73+AXbfDEZ6QjuX/qwkLI/49/Ze3o68MmRz1Xazwv7qVxI5ERH+RCDym/Y7UtHQ0bZt7YrSxEc8HIgKAs09eY9iWO0jNyoGztRHW9K3NE3n/w+qLLzD14EMY6mrh2A9NeEUdUQkrzOs3j2MTUYE0dS+HXYMbwN7cAC9i09B56SVcDYkTO5bKCnmTijnHckdfYz/3ZPkhUjEsQERUYO7lTbBnaANUdTBHYroMvVdfw85b+b9nlyaTKwSM3hmETJkCjVyt0auu439vRESligWIiAqlnIk+tg+sh7a+FSCTCxgVEIi5x55AoeA0/a01F1/g1qsEGOtpY2ZXX0gkvOqLSNWwABFRoenraGFRz+oY2qwyAGDxmWAM33YHmTK5yMnEF/w6FXOOPwEAjGvriYoWHH0RqSIWICIqEqlUgtGtPTCnmx90tCQ4FBSFHn9exZuULLGjiUauyD0ilp2jQGM3a/So7SB2JCJ6DxYgIvoo/rUcsOHrujAz0MHdsER0WnIJT2NSxI4lipUXQnA3LBEmetqY1dWPoy8iFcYCREQfrX5lK+wZ0gBOVoaISMxA16WXce7pG7FjlapnMSn4/fhTAMCE9l6wMzcQORERfQgLEBEVCxcbY+wZ0hB1nC2RkpWDr9fdwKarr8SOVSpy5AqMDAhEtlyBZu428K9ZUexIRPQfWICIqNhYGOliY/866FLDHnKFgPF772PqwYeQl/ErxFacD0FQeBJM9LUxowtHX0TqgAWIiIqVnrYW5vlXxahWVQDkvhvytxtvIS0rR+RkJeNxdDIWnMwdfU1u743yZvoiJyKigmABIqJiJ5FIMKy5GxZ/WR262lKcfBQD/+VXEJWUIXa0YiWTKzAqIBAyuYAWnuXQpYa92JGIqIBYgIioxLTzs8O2gfVgZaSLh1HJ6LTkEu5HJIkdq9gsO/sc9yOSYWagg+md+YaHROqEBYiISlQNRwvsHdoQbuWMEZOcBf/lV3D8QbTYsT7ag8gkLDz1DADwawdvlDPl6ItInbAAEVGJc7A0xK4hDdDYzRoZMjm+3XQLqy6EQBDU8+To7BwFRgUEIUchoJWXLTpWsxM7EhEVEgsQEZUKU30drOlbG1/WdYQgANMOPcK4vfchkyvEjlZoS84E41FUMiwMdfAbR19EaokFiIhKjY6WFL918sH4tp6QSIAt10Lx9bobSM6UiR2twO5HJGHJmWAAwJSOPrAx0RM5EREVBQsQEZUqiUSCbxq74M/etWCgo4ULz2LRdellhMWnix3tP2XlyDEqIBA5CgFtfMqjnV8FsSMRURGxABGRKFp62SJgUH3Ymurh2etUdFpyCbdeJYgd64MWnQrG4+gUWBrpYmonH46+iNQYCxARicbH3gz7hjaCt50p4tKy0XPlVRwIjBQ7Vr6CwhOx7NxzAMDUjj6wNuboi0idsQARkajKm+ljx7f10cLTFtk5CgzfegeLTj1TqSvEsnLkGLkjEHKFgHZ+FdCWoy8itccCRESiM9LTxoreNfFNI2cAwLwTTzFyRyCycuQiJ8u14OQzPHudCmtjXUzp6CN2HCIqBixARKQStKQSjG/nhWmdfKAllWD3nQj0XnUdCWnZoua6E5qAFX+NvqZ18oWlka6oeYioeLAAEZFK+V+9SljbtzZM9LRx/WU8Oi+9hJA3qaJkyZTlXvWlEICO1ezwmU95UXIQUfFjASIildOkig12DWkAe3MDvIxLR+ell3HleVyp55h/4imev0mDjYkeJrf3LvXHJ6KSwwJERCqpiq0J9g5tiOqO5kjKkKHPmmvYcTOs1B7/1qt4/HkhBAAwvbMvLDj6IipTWICISGXZmOhh64B6aOdXATK5gJ92BmH20cdQKEr2CrGMbDlGBQRBEIAu1e3R0su2RB+PiEofCxARqTR9HS0s7FEdw5u7AgCWnn2OYVtvI1NWcleIzT3+BC9i01DORA+TOPoiKpNYgIhI5UmlEoxs5Y55/lWhoyXB4XvR+OLPq3iTklXsj3XjZTzWXHoBAJjZ1RdmhjrF/hhEJD4WICJSG11rVsSm/nVhbqiDwLBEdFpyCU+iU4rt/tOzczA6IBCCAPjXrIjmHhx9EZVVLEBEpFbqulhhz5CGcLY2QkRiBrouu4yzT14Xy33PPvoEL+PSUd5UH+PbeRXLfRKRamIBIiK142xthD1DGqCusyVSs3Lw9bob2Hjl5Ufd59WQOKy7nHsfM7v6wsyAoy+isowFiIjUkrmhLjb2r4uuNSpCIQAT9j3ArwceQF6EK8TSsnIwemcgAKBHbQc0dS9X3HGJSMWwABGR2tLVlmKuvx9Gt3YHAKy99BIDN9xEWlZOoe5n1tHHCIvPgJ2ZPsa19SyJqESkYliAiEitSSQSDG3miiVf1oCethSnHr+G//IriErKKND2l4NjseHKKwDA7G5VYaLP0ReRJmABIqIyoa1fBWwbWA/Wxrp4GJWMjosv4V540ge3Sc3KweidQQCAL+s6opGbdWlEJSIVwAJERGVGdUcL7BnSEFVsjfE6JQvdV1zBsQfR711/+uFHiEjMgL25AcZ+ztEXkSZhASKiMsXB0hA7BzdAkyo2yJDJMWjTLaw8HwJByHty9IVnb7DlWigAYE43PxjraYsRl4hEwgJERGWOqb4O1nxVC/+r5whBAH47/Ahj99yHTK4AAKRkyvDzX6OvPvUroYErR19EmoYFiIjKJG0tKaZ29MGEdl6QSICt10PRb+0NJGXI8NuhR4hMyoSDpQF+/sxD7KhEJAIe8yWiMksikaB/I2dUsjTEd9vu4GJwLD7/4wIiEnOvEJvTrSqMOPoi0kg8AkREZV4LL1sEDKqP8qb6yvLTt4ET6rlYiZyMiMTCAkREGsHbzgz7hjVEYzdrNHS1wk+fuYsdiYhExGO/RKQxbE31sbF/XbFjEJEK4BEgIiIi0jgsQERERKRxWICIiIhI47AAERERkcZhASIiIiKNwwJEREREGocFiIiIiDSO6AVox56DaP/F12jQsjO+GjwC9x89KdB2x06dQ62m7TBy3LQ8y+PiEzB5xnx81rUPGrbuiuGjJyI0PKIkohMREZGaErUAHT99HvOXrsKAvj2xaeUfqFLZGcNHT0R8QuIHt4uMisEfy9agup93nuWCIGDU+GmIiIrGvN/GY/PKP1C+fDkMGTkeGRmZJbgnREREpE5ELUCbA/aiU9vW6NCmJVycHDFmxFDo6+th/+ET791GLpdj/G9zMbBfL9hXKJ/nttDwSNx7+AS//DgE3h5V4ORYEWN+HIKsrGwcO3WupHeHiIiI1IRoBUgmk+Hxk2DUrVnt7zBSKerUrIagh4/fu92qDdtgaW6GTm1b5XufAKCnq5vnPnV1dHD33sP33md2tgypaenKr7T09CLsEREREakL0T4LLDEpGXKFApaW5nmWW1qY42VoeL7b3A16gH2HjmPLqoX53u7kWBHlbW2weOV6jB05DAb6etgcsA8xb2IRGx//3ixrN+/AyvVbi7wvREREpF7U5sNQ09LTMXH67xg3ejjMzc3yXUdbWxtzpozD1Nl/oHn7HtD664hSg7o1AeH9992vV3f06t45z2O19e9bzHtAREREqkK0AmRuZgotqRTx8Yl5lscnJMLK0uKd9cMjohEZHYMRY6YolymE3FZTt3kH7Nq4AhXtK8DT3RVbVi9CamoaZDk5sDA3w1eDR8DL3e29WXR1daCrq1M8O0ZEREQqT7QCpKOjAw93V1y/HYimjesDABQKBW7cCkT3zu3eWd/JsSK2rVmcZ9my1ZuQnpGOkcMGwracdZ7bjI2NAACh4RF49CQYg7/+X4GzCX8VK54LREREpD7evm6/fR3/EFFHYL38O2HyjPnwcneDt2cVbNm5DxmZmWjfpgUAYOL0eShnbYVhA/tCT08Xri5OebY3+avk/HP5ybMXYW5mivK25RAc8hLzFv2JTxrVQ73aNQqcKz0jAwA4BiMiIlJD6RkZyo7wPqIWoFbNmyAhMQnL125CXHwCqri6YNHsKcoRWHTMG0glhbtQLTYuHvOXrEJcQiKsrSzQtlVzfNOnR6Huw8bKEocC1sHQwAASiaRQ2/6Xt+cXHQpYByNDw2K9b1XA/VN/ZX0fuX/qr6zvI/ev6ARBQHpGBmysLP9zXdFPgv6iS3t80aV9vrf9+cfMD247ecyP7yzr0bUDenTt8FGZpFIpbG2s/3vFj2BkaAhjo7L3i/0W90/9lfV95P6pv7K+j9y/ovmvIz9vif5RGERERESljQWIiIiINA4LUCnT1dHBgK96QlenbF52z/1Tf2V9H7l/6q+s7yP3r3RIhIJcK0ZERERUhvAIEBEREWkcFiAiIiLSOCxAREREpHFYgIiIiEjjiP5GiOpux56D2LhtN+LiE+Dm6ozR330LH0/3965/8uxFLFu9CVHRMXCoaIfh3/ZFo3q1lbcLgoAVazdjz8FjSE1NQ1UfT/wyYggcK9qXxu68ozD7t+fgURw6dhrPX7wCAHhWccWQAX3yrD95xnwcPHYqz3b1a9fAojlTIJbC7OOBIyfx66wFeZbp6ujg8ok9yu/V+Tkc+P0vuB14/53lDevVwh8zJwNQrefwduB9bNy2C4+ePkdsXDzmTh2n/GzB97l5Jwjzl65GyMtXsLWxQf/eXyg/fuetwv5dl6TC7uPp85exc99hPA0OgUwmg4uTIwb2/RL169RUrrNi7WasXL81z3aVHCpi18blJbYf71PY/bt5JwiDfhz7zvKjuzbC2urvD9JWleewsPuX398XALg4OWLHuqUAVOv5W7t5B86cv4KXoeHQ09OFn7cnhn/bF06OFT+4nUq8FgpUZMdOnRPqtego7Dt8XHj+4pUwbc5CoWnb7kJcfEK+69+991Co06y9sH7rTiHkZaiwdNUGoe6nHYVnz18o11m7OUD45PPuwpkLV4SnwSHCj2OnCB16fC1kZmaVzk79Q2H3b9zU2cKOPQeFx0+fCy9ehgqTZ8wXPvm8uxDz+o1ynUnTfxeGj54ovImNV34lJaeU0h69q7D7uP/wCaHJ5/558sfGxedZR52fw8Sk5Dz7FhzyUqjTrL2w//AJ5Tqq9BxevHpDWLJyg3D6/CWh5idthTPnL39w/fDIKKFh6y7C70tWCiEvQ4Vtu/YLdZq1Fy5fu6lcp7A/s5JW2H2cu3CFsG5LgHD/0RPhVVi4sPjPdULdTzsKj54GK9dZvmaT4P/V4DzPYUJCYknvSr4Ku383bgcKNT9pK7wMDc+TXy6XK9dRpeewsPuXkpKaZ7+iY94Izdv3EJav2aRcR5Wev2GjJgj7D58QgkNeCk+ePRe++3mS0LZ7XyE9PeO926jKayEL0EfoM+hHYeb8pcrv5XK58FnX3sLaTTvyXf+XyTOF73+enGfZV4NGCL/NXSQIgiAoFAqhVef/CRu27lLenpKSKtRv0Uk4evJsCezBhxV2//4tJydHaNKmm3Dg6EnlsknTfxdGjJ1a7FmLqrD7uP/wCeGTz7u/9/7K2nO4ecdeoUmbbnn+MVO15/Ctgry4/LF8jeD/1eA8y36ZPFMYNmqC8vuP/ZmVpILsY378vxos/Llui/L75Ws2CT2/Hlac0YpFYQpQ8gdKt6o+h0V5/s6cvyzUatpOiIyKUS5T1edPEAQhPiFRqPlJW+HW3XvvXUdVXgt5DlARyWQyPH4SjLo1qymXSaVS1KlZDUEPH+e7TdCDx6jzj/UBoH6dGrj31/oRUTGIi0/Is46xsRF8vNyV65SWouzfv2VmZSEnRw4zE5M8y2/dvYeWnXqhS+9vMeP3JUhMSi7O6AVW1H3MyMhAuy/6oa1/X4wYN1U58gPK3nO47/BxtGreBAYG+nmWq8pzWFj3HjzO8/MAcv8G3/48iuNnpmoUCgXS0jNgamKcZ3loRCQ+69oHHXv2x/hpcxAd81qkhEXz5TffoXWX3hgycjzu3nuoXF7WnsN9h4+jTs1qqFC+XJ7lqvr8paamAcA7v2//pCqvhTwHqIgSk5IhVyhgaWmeZ7mlhTlehobnu01cfEK+68fFJypvBwCrD6xTWoqyf/+2aMU6WFtb5vklrl+nBpo1aQD7CrYIj4jCklUb8N3Pk7B2yVxoaWkV4x78t6LsYyVHe0z4+Xu4uTgjNS0Nm7bvxtfDRmPH2qWwLWddpp7D+4+e4PmLV5jw03d5lqvSc1hY7/sbTEtLR2ZWFlJSUj/6917VbNy+GxkZGWjZrLFymY+XOyb/8iMqOdgjNi4eK9dvxTff/Yzta5eo/KePW1tZYsyIofByd0O2TIa9h47h2x/GYP2yefCo4los/3apijexcbh87RamTRidZ7mqPn8KhQLzFq9EVR8vuLo4vXc9VXktZAGiErFucwCOnz6PFQtmQE9PV7m89aefKP/b1cUJrpWd0enLb3Dr7r13/o9AFfl5e8LP21P5fVUfT3TrMxi7DxzB4P69RUxW/PYdPgFXF6d3ThxV9+dQkxw9eRYr12/FvGkTYGlhrlzesG4t5X+7VXaGj6c72vX4GifOXESntq1ESFpwTo4V85xgW9XHExGR0dgcsA9Tx40UMVnxO3jsFIyNjdG0Ub08y1X1+Zu1YBmev3iFVYtmi5ahMDgCKyJzM1NoSaWI/1cbjU9IhJWlRb7bWFlavGd9c+XtAN5puP9cp7QUZf/e2rhtN9Zt2YnFc6bCrbLzB9etaFce5mamCIuI+tjIhfYx+/iWtrY23N1clPnLynOYkZGJ46fPo+PnLf/zccR8DgvrfX+DRkaG0NfTK5bfCVVx7NQ5TJ2zCDMn/YK6tap9cF0TE2NUqmiP8IjI0glXzLw9qiizl5XnUBAE7D98Ap+3agad//jMLFV4/mYtWIaLV25g+YLpsC1n/cF1VeW1kAWoiHR0dODh7orrtwOVyxQKBW7cCoSfl0e+2/h5e+DG7bt5ll27eQe+f61vX8EWVpYWedZJTUvH/YdPlOuUlqLsHwCs37oTqzZuw6LZv8LLw+0/HyfmdSySklNgbWVZLLkLo6j7+E9yuRzBIa+Ul9+WhecQyL1EVZYtQ5uWzf7zccR8DgvL19sjz88DAK7dvKv8eRTH74QqOHrqHKbM+gO/TRiNRvVr/+f66ekZCI+MUovnMD9PgkOU2cvKc3jr7j2ERUQV6H9CxHz+BEHArAXLcPbiFSyb/xvsK5T/z21U5bWQI7CP0Mu/EybPmA8vdzd4e1bBlp37kJGZqXxPkYnT56GctRWGDewLAOjRtQMGfv8LNm3fjUb1auPY6fN4+CQYY0cOAwBIJBL07NYRqzduh0NFe9hXsMWy1ZtgY22Jpo0+/N4mqrB/67bsxIq1mzBt/GhUKG+L2LjcOa6hgT4MDQ2Qnp6Bleu3onmTBrCytEB4ZBQWrlgLB/sKqF+7RqnvX1H2ceX6rfD1ckdFezukpqZiw7bdiI55jU5tWwNQ/+fwrX2Hj+OTRvVgbmaaZ7mqPYfp6Rl5jjxFRMfgybMQmJkao7xtOSz+cx1ex8Zhytjc0UjXDm2wY89B/LF8DTq2aYkbd4Jw8swFLJg5SXkf//UzK22F3cejJ89i0oz5GDV8IHw83ZV/h/p6ujA2NgIALFi6Go0b1EEF23J4ExePFWs3QyqV5hlvqur+bQnYB7sKtqjs5Iis7GzsO3QcN+8EYfE/3odKlZ7Dwu7fW/sOn4CPp3u+59Ko0vM3a8EyHD15DvN+Gw9DA0Pl75uxce5RVUB1XwtZgD5Cq+ZNkJCYhOVrNyEuPgFVXF2waPYU5eG76Jg3kEr+PshW1ccTv00YjaWrN2LJqg1wsLfD3Gnj8vyCf9WzKzIzMzF97iKkpKahmq8XFs6ekuc8mtJS2P3bte8wZLIc/DxpRp77GfBVT3zbrxekWlI8C3mBg8dOISU1DTZWlqhXuzoGff0/6Op++BBvSSnsPianpGLa3EWIi0+AqbExPNxdsXrJHLg4OSrXUefnEABehobj7r2HWDx36jv3p2rP4cMnz/K8Kd78JasAAO1af4rJY35EbFwComPeKG+3r1AeC2ZMwu9LVmHbrv0oZ2ON8aO/y/Mmgf/1Mytthd3H3QeOQi6XY9aCZZi1YJly+dv1ASDmTSzGTZ2DpORkWJiZoaqvF9YtnQcLc7NS2qu/FXb/ZDkyLFi6Gm9i46CvrwdXFycsnTcNtar7KddRpeewsPsH5F5Jdfr8ZYwaPiDf+1Sl52/nvsMAgG9/GJNn+aSff1AWTlV9LZQIgiAU270RERERqQGeA0REREQahwWIiIiINA4LEBEREWkcFiAiIiLSOCxAREREpHFYgIiIiEjjsAARERGRxmEBIiLKh5OTExYsWCB2DCIqISxARCS6vn37olOnTgCApk2b4ocffii1x163bh3Mzc3fWX7jxg0MHDiw1HIQUeniR2EQUZmUnZ0NXd2iv22+jY1NMaYhIlXDI0BEpDL69u2Lc+fO4Y8//oBEIoFEIsHLly8BAPfv30ebNm1gbGwMW1tb9O7dG7GxscptmzZtimHDhuGHH36AtbU1WrfO/YDa33//Hb6+vjAyMoKDgwOGDBmC1NRUAMDZs2fRr18/JCUlKR9v8uTJAN4dgYWGhqJjx44wNjaGqakpunfvjpiYGOXtkydPRrVq1bBx40Y4OTnBzMwMPXr0QEpKSsn+0IioSFiAiEhl/PHHH6hfvz4GDBiAqKgoREVFwcHBAYmJiWjevDmqV6+Omzdv4ujRo4iJiUH37t3zbL9+/Xro6uri0qVLWL58OQBAKpVi4cKFePDgAdavX4/Tp0/jp59+AgA0aNAACxYsgKmpqfLxRo0a9U4uhUKBjh07Ij4+HufOncOJEycQEhKCL774Is96z58/x969e3Hw4EEcPHgQ586dw8yZM0vop0VEH4MjMCJSGWZmZtDV1YWhoSHKly+vXL548WJUr14d06dPVy5bs2YNHBwc8PTpU1SpUgUA4ObmhtmzZ+e5z3+eT+Tk5IRp06Zh0KBBWLp0KXR1dWFmZgaJRJLn8f7t1KlTuHfvHl68eAEHBwcAwIYNG+Dt7Y0bN26gdu3aAHKL0rp162BiYgIA6N27N06dOoXffvvt434wRFTseASIiFReYGAgzpw5A2NjY+WXh4cHgNyjLm/VrFnznW1PnjyJTz/9FPb29jAxMUHv3r0RFxeH9PT0Aj/+o0eP4ODgoCw/AODl5QVzc3M8evRIuczJyUlZfgCgQoUKeP36daH2lYhKB48AEZHKS01NRfv27TFr1qx3bqtQoYLyv42MjPLc9vLlS7Rr1w6DBw/Gb7/9BktLS1y8eBH9+/dHdnY2DA0NizWnjo5Onu8lEgkUCkWxPgYRFQ8WICJSKbq6upDL5XmW1ahRA7t27YKTkxO0tQv+z9atW7egUCgwb948SKW5B7x37Njxn4/3b56enggLC0NYWJjyKNDDhw+RmJgILy+vAuchItXBERgRqRQnJydcu3YNL1++RGxsLBQKBYYOHYr4+Hj07NkTN27cwPPnz3Hs2DH069fvg+XF1dUVMpkMixYtQkhICDZu3Kg8Ofqfj5eamopTp04hNjY239FYixYt4Ovri169euH27du4fv06+vTpg08++QS1atUq9p8BEZU8FiAiUimjRo2ClpYWvLy8YGNjg9DQUNjZ2eHSpUuQy+Vo1aoVfH198cMPP8Dc3Fx5ZCc/VatWxe+//45Zs2bBx8cHmzdvxowZM/Ks06BBAwwaNAhffPEFbGxs3jmJGsgdZe3btw8WFhZo0qQJWrRoARcXF2zfvr3Y95+ISodEEARB7BBEREREpYlHgIiIiEjjsAARERGRxmEBIiIiIo3DAkREREQahwWIiIiINA4LEBEREWkcFiAiIiLSOCxAREREpHFYgIiIiEjjsAARERGRxmEBIiIiIo3DAkREREQa5/+Vkls4t/fl+wAAAABJRU5ErkJggg==\n"},"metadata":{}}],"source":["import matplotlib.pyplot as plt\n","import statistics\n","\n","print(\"The average loss across the testloader is:\", statistics.mean(acc_hist))\n","# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Test Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"1a-oeEzK0Xvt"},"source":["## 2.3 Visualize Spike Recordings\n","\n","The following visual takes ~9 minutes to create. This visual is a spike count histogram that shows the spikes"]},{"cell_type":"code","execution_count":84,"metadata":{"id":"ZJArj6jlXBEs","executionInfo":{"status":"ok","timestamp":1702495299571,"user_tz":480,"elapsed":3345,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["spk_rec = forward_pass(scnn_net, data)"]},{"cell_type":"code","execution_count":85,"metadata":{"id":"tJSBM-ctXETI","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":643694,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"e51c8f06-5974-452c-8efd-f9c516ea3c34"},"outputs":[{"output_type":"stream","name":"stdout","text":["The target label is: 1\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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1vgJmTuvISv37Z0tN9skhx96QLbcbOOl+hzjJ7xT/nn99dZuEcSTpHPnztlq802z1eabltsmvjM5Bx55/CLbOv3Mn+f0M39enn7v+fr3PPrEmFx70215duy4zJw5K9XVXbLG6kPy0V13yuGH7p+ePXq02N4Nt9zZYnu/PeeHSZI/XnJ5xr70SkoLStlko2E58dhPtKgPAIomjANAhZn17uwc+/mvZ+KkyeW2Mc+9kC994zv59Vln5K9XXZ97H3ikPG/ipMm54JLLM3X6jHznmye12NazY1/MN779g0z/t9vrp06bkTvu+XvuvPeBfPa4T+Qznzqy1fV16dK5/PPfH348f/jTX7PHiOFZa82hS/lJl6y5uTn/99Nf5YZb7mzR3tjUlBdffjUvvvxqbrz1zvzqrDMyZLVVl7id626+I7feeW9KpVK57fGnns1TY57PD7/7rew+YvgyqxkAloYwDgAV5rU33kqSbLLR+mlubs64l/+RJJk/f35OOuX0NDQ0ZNCA/llzjdXz9LPPp6lpfpKFV4WPP/rwcjidNn1mTj71+3l39sJn2quqqrLpRuund++VMu6lVzN95qyUSqX89o+XZs2hq2fPj+7Sqvo233Sj/OP1N5MsDM2//eOf89s//jm9V+qVjTcclm223Dx77rZLi5DcvXu37LbrTpn17uwWt/VvvMGwrDpoQIvlkuS3F17aIoj3W2XlbDBsncyZU5vnX3w5pVIpb709MV//n//Ln3//ixZ/IHi/W+64J7169szGGw7LxHcm5+2JC6/qNy9YkO//5JfZcrON02+VlVv1uQFgWRLGAaACffmzx+aYIz+eUqmUE77yrYx57oUkSUNDQzbecFh+//MfpVu3brny2pty5s9/kyQplUp5aszz5RD858uvLgfxzp065fe/PDNbbLpRkmReQ0NO/MopeeGlV5Ikv/njn1sdxo858uO5856/Z05tXYv22XNq88jjT+eRx5/Oby64JIcdMipf/fxn0qVL56zct09+csZpi4ymftjBoxYZTX3WrHfzlyuuLU/vOnz7/OT0U8u34N957wM55Xs/TpK8+tobufPev2efPUYuttZBAwfkwnPPysAB/dPc3Jzv/PDs3HbXfUmS2rq6XH/LHTnuqNGt+twAsCwJ4wBQYXr27JEjP3ZQkoVXszfecFg5jCfJJw47ON26LbyCvNXmm7RYd9qMGeWfH3z0ifLP3bp3y6VXXJNLr7im3FZbX1/++a3xE/L2hHey+pDV/mN9qw9eNRee+9P85Be/zWNPPbPYZZoXLMhfr7ohPbr3yBc+c/R/3Ob7Pf70s2lobCxPz5w5K6ed8ZPy9IIFC1os/+CjTy4xjB920H4ZOKB/koXPsn/2uE+Uw3iSPPH0c8I4AO1CGAeACjNktVVTU1Ndnu7RvXuL+eu879nsf5/X2NhU/nnipCnln+vq6nP3/Q994H7fmTylVWE8SdZac2jOO/sHGf/2xDz8+FMZ89wLeXLMc5k+Y2aL5f523U353KePSqdOnVq13YV1T24x/dwLL33g8pMmT1nivLXXWqPF9NAhg1Nd3aV8a//kKVNbXRcALEvCOABUmF49W44QXlVV9W/zey6X/c6b17DU6wxdfXCGrj44ow/ZP6VSKQ88/HhOOf3MNDQs3NbsObWZOevd5fpc9tLWXZWq/7wQACxnwjgAdFCrDRqQN956O0kyZPCque4vf1gm2502fUb691tlkfaqqqrsstN22WrzjfPI40+X2zt37tximf9ktUEDW0x/79STs//eu3+oWl9/462MGL59eXrCxElpbPrX3QODBg5Y3GoAsNy1/p4xAGCFstP2W5d/njBxUi669MpFnree9e7sXHPjrfnpr37X6u3+z/fPytf+5/t54JHHM39+c4t570yaUh79PUlW7tsnfXqvVJ7u2rWmxfJTp8/Iv9v2I1ukuvpf1wsu+NNf886klreil0qlPDd2XH74s1/n+Q+4jf3K627OlKnTkix81vx3F17aYv7WW262xHUBYHlyZRwAOqijDz80N9xyZ3nU81+ff3H+dv3NWWfNNVLVqSoT35mcN8dPyIIFC/KRLTZt9XZLpVLuf/DR3P/go+nWrWvWX3ft9O3bJ7W1dXnuhXHl57GTZL+9Ptriavjqg1dLVVVV+b3fF/zprxnz7Nh069Y1Q1ZbNSd9/tNZuW+fHPGxA3PJX69Okoyf8E4OPuqEbLLhsPTt2ydz5tTmH6+/mdlzapMke+226xJrnTxlag4/7ovZeMP1M/GdSRk/4Z3yvJ49e+Sg/fZs9ecGgGVJGAeADmpA/34554ffyTe/+6PMmDkrSTJp8tRMmrzooGWdO7f+Zrn3h+t58xry7Nhxi11u8003ymePPapFW98+vTN8+23ywCOPJ0kaGhvz0GNPJknWX3ft8nJfOuGYzJg5KzfddneShe8zX9J+Pqj2ww4elauvvyWPPvF0i/ZOnTrl2//vy94xDkC7EcYBoAPbcvNNcuXFv8lV19+SBx55PG+8OT51dfXp2rVrBg3snw2HrZsdtvtIPrrzjq3e5k+//z958NEn8uSY5/LSq6/lnUlTylff+6zUK8PWWzt7jNg5+++zR7p06bzI+mf8z9fzq99flAcffjzTZ8xM87/dOp8sfM789FO/lv333j3X3Xx7nhs7LtNmzEpzc3P69F4paw4dkq023yS77To8GwxbZ4m17j5iePbefUTOv/iyPP/iS1nQvCCbbLR+TjjmSLeoA9Cuqkrv3ScGALCCu+GWO3P6mT8vT//2nB9mm602b7+CAGAJDOAGAAAABRPGAQAAoGDCOAAAABTMM+MAAABQMFfGAQAAoGDCOAAAABRMGAcAAICCCeMAAABQMGEcAAAACiaMAwAAQMGEcQAAACiYMA4AAAAF+/8ACmcpooeX2AAAAABJRU5ErkJggg==\n"},"metadata":{}}],"source":["from IPython.display import HTML\n","\n","start_time = time.time()\n","\n","idx = 0\n","\n","fig, ax = plt.subplots(facecolor='w', figsize=(12, 7))\n","labels=['0', '1', '2', '3', '4', '5', '6', '7', '8','9']\n","print(f\"The target label is: {targets[idx]}\")\n","\n","# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n","\n","# Plot spike count histogram\n","anim = splt.spike_count(spk_rec[:, idx].detach().cpu(), fig, ax, labels=labels,\n"," animate=True, interpolate=1)\n","\n","display(HTML(anim.to_html5_video()))\n","# anim.save(\"spike_bar.mp4\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)"]},{"cell_type":"code","execution_count":86,"metadata":{"id":"ssI8LLReFGY-","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"41b576a2-84ac-42fc-c986-f1babfeefa21"},"outputs":[{"output_type":"stream","name":"stdout","text":["Elapsed time: 10 minutes, 43 seconds, 29 milliseconds\n"]}],"source":["# Print the result\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"OgY3fTk40u2j"},"source":["## 3 Run some Linear Networks for fun?\n","\n","Below commented out are some Fully Connected Linear Networks of different depth feel free to also run if you want."]},{"cell_type":"code","execution_count":87,"metadata":{"id":"Qe4ZCcPrxILT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# # FCN Network Architecture\n","# num_inputs = 10*10*2\n","# num_hidden = 1000\n","# num_outputs = 10\n","\n","# # fcsnn_net = nn.Sequential(nn.Linear(num_inputs, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_outputs),\n","# # snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# # ).to(device)\n","\n","# fcsnn_net = nn.Sequential(nn.Flatten(),\n","# nn.Linear(num_inputs, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_outputs),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# optimizer = torch.optim.Adam(fcsnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","# loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"code","execution_count":88,"metadata":{"id":"NR95_6rwxtHT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# num_epochs = 10\n","# num_iters = 50\n","\n","# fcsnn_loss_hist = []\n","# fcsnn_acc_hist = []\n","\n","# # training loop\n","# for epoch in range(num_epochs):\n","# for i, (data, targets) in enumerate(iter(trainloader)):\n","# data = data.to(device)\n","# targets = targets.to(device)\n","\n","# fcsnn_net.train()\n","# spk_rec = forward_pass(fcsnn_net, data)\n","# loss_val = loss_fn(spk_rec, targets)\n","\n","# # Gradient calculation + weight update\n","# optimizer.zero_grad()\n","# loss_val.backward()\n","# optimizer.step()\n","\n","# # Store loss history for future plotting\n","# loss_hist.append(loss_val.item())\n","\n","# if i%4 == 0:\n","# print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n","# acc = SF.accuracy_rate(spk_rec, targets)\n","# acc_hist.append(acc)\n","\n","# if i%4 == 0:\n","# print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# # This will end training after 50 iterations by default\n","# # if i == num_iters:\n","# # break"]},{"cell_type":"code","execution_count":89,"metadata":{"id":"CanrIqh28RnT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# import matplotlib.pyplot as plt\n","\n","# # Plot Loss\n","# fig = plt.figure(facecolor=\"w\")\n","# plt.plot(acc_hist)\n","# plt.title(\"Train Set Accuracy\")\n","# plt.xlabel(\"Iteration\")\n","# plt.ylabel(\"Accuracy\")\n","# plt.show()"]},{"cell_type":"code","execution_count":90,"metadata":{"id":"xqnwmc6Z-W9o","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# fcsnn_net_seven_layers = nn.Sequential(nn.Flatten(),\n","# nn.Linear(num_inputs, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_outputs),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# optimizer = torch.optim.Adam(fcsnn_net_seven_layers.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","# loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"code","execution_count":91,"metadata":{"id":"sy-ZhyqN-wwu","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# num_epochs = 10\n","# num_iters = 50\n","\n","# fcsnn_loss_hist = []\n","# fcsnn_acc_hist = []\n","\n","# # training loop\n","# for epoch in range(num_epochs):\n","# for i, (data, targets) in enumerate(iter(trainloader)):\n","# data = data.to(device)\n","# targets = targets.to(device)\n","\n","# fcsnn_net_seven_layers.train()\n","# spk_rec = forward_pass(fcsnn_net_seven_layers, data)\n","# loss_val = loss_fn(spk_rec, targets)\n","\n","# # Gradient calculation + weight update\n","# optimizer.zero_grad()\n","# loss_val.backward()\n","# optimizer.step()\n","\n","# # Store loss history for future plotting\n","# loss_hist.append(loss_val.item())\n","\n","# if i%4 == 0:\n","# print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n","# acc = SF.accuracy_rate(spk_rec, targets)\n","# acc_hist.append(acc)\n","\n","# if i%4 == 0:\n","# print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# # This will end training after 50 iterations by default\n","# # if i == num_iters:\n","# # break"]},{"cell_type":"code","execution_count":92,"metadata":{"id":"XFrA769b-2ZO","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# import matplotlib.pyplot as plt\n","\n","# # Plot Loss\n","# fig = plt.figure(facecolor=\"w\")\n","# plt.plot(acc_hist)\n","# plt.title(\"Train Set Accuracy\")\n","# plt.xlabel(\"Iteration\")\n","# plt.ylabel(\"Accuracy\")\n","# plt.show()"]}],"metadata":{"colab":{"provenance":[{"file_id":"17lDMQYpEjA_oD-VmIG__qTlv1EdV9tjY","timestamp":1701726922112},{"file_id":"1j8MtYqWS5jQABVHORXeC9DR-DEX9tAmd","timestamp":1701120116694},{"file_id":"1Yy7yVKCye-TEzyVYB8217Au-DTzMzpKY","timestamp":1698117894739}],"gpuType":"T4"},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"name":"python"},"widgets":{"application/vnd.jupyter.widget-state+json":{"6dd945b6627844c1b3808b9ea8ab6646":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_fb003723433d4e8db855b590fdfbfedd","max":640,"min":0,"orientation":"horizontal","style":"IPY_MODEL_dc2254cf2e894a21a689246a66f0dfce","value":640}},"fb003723433d4e8db855b590fdfbfedd":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"dc2254cf2e894a21a689246a66f0dfce":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"aec192c607bf40b9a45a1f2b064ba30e":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_845cc10adccf489f8fecf05cc6fe2f93","max":320,"min":0,"orientation":"horizontal","style":"IPY_MODEL_d3ea533e5b164139abba9ab6f2c0a5ac","value":320}},"845cc10adccf489f8fecf05cc6fe2f93":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"d3ea533e5b164139abba9ab6f2c0a5ac":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}}}},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0} \ No newline at end of file From 1ef05a3ca2583051bcaf8e1af6ce2cf4bdbfed42 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:48:45 -0800 Subject: [PATCH 04/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 561040bb..4ded18d9 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -54,12 +54,6 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb - * - `Tutorial 8 `_ - - Training on STMNIST with Tonic + snnTorch - - .. image:: https://colab.research.google.com/assets/colab-badge.svg - :alt: Open In Colab - :target: https://colab.research.google.com/drive/1YOoq_E_ndtO9VRCUQwmflLPNr5FssATq?usp=sharing - .. list-table:: From e164e608f4854663e939582dd225706e7c8f91a5 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:50:56 -0800 Subject: [PATCH 05/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 4ded18d9..a51950fe 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -54,7 +54,11 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb - + * - `Tutorial 8 `_ + - The Leaky Integrate and Fire Neuron + - .. image:: https://colab.research.google.com/assets/colab-badge.svg + :alt: Open In Colab + :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_2_lif_neuron.ipynb .. list-table:: :widths: 70 32 From 9042c3c5e99a98b1b8852f9448ce4a4955fb4796 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:51:47 -0800 Subject: [PATCH 06/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index a51950fe..e77c36f8 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -42,7 +42,7 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable * - `Tutorial 6 `_ - - Surrogate Gradient Descent in a Convolutional SNN + - Training on ST-MNIST with Tonic + SNNTorch - .. image:: https://colab.research.google.com/assets/colab-badge.svg :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_6_CNN.ipynb From 79f10f098b9180fffc208bf97287000a0a02e18d Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:53:30 -0800 Subject: [PATCH 07/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index e77c36f8..9e2665ff 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -58,7 +58,7 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable - The Leaky Integrate and Fire Neuron - .. image:: https://colab.research.google.com/assets/colab-badge.svg :alt: Open In Colab - :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_2_lif_neuron.ipynb + :target: https://colab.research.google.com/drive/1P2yQCDmp7TilNrEqj_cBzS7vscIs0L_o?usp=sharing .. list-table:: :widths: 70 32 From cdb01e6cc44ada0bf064bf3b69b9dbde8fd6317e Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:55:23 -0800 Subject: [PATCH 08/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 9e2665ff..94d6d35e 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -54,8 +54,8 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb - * - `Tutorial 8 `_ - - The Leaky Integrate and Fire Neuron + * - `Tutorial 8`_ + - Training on ST-MNIST with Tonic + snnTorch Tutorial - .. image:: https://colab.research.google.com/assets/colab-badge.svg :alt: Open In Colab :target: https://colab.research.google.com/drive/1P2yQCDmp7TilNrEqj_cBzS7vscIs0L_o?usp=sharing From 8775c200c2d9676a62a4a6244e853bf52c96a3e1 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:55:43 -0800 Subject: [PATCH 09/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 94d6d35e..9e5825bd 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -54,7 +54,7 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb - * - `Tutorial 8`_ + * - Tutorial 8 - Training on ST-MNIST with Tonic + snnTorch Tutorial - .. image:: https://colab.research.google.com/assets/colab-badge.svg :alt: Open In Colab From 4bf72aa4c298624ecb0c95c19028ac7325b46478 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:33:42 -0800 Subject: [PATCH 10/13] Update tutorials.rst --- docs/tutorials/tutorials.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index 9e5825bd..b3958f2a 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -40,14 +40,12 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_5_FCN.ipynb - * - `Tutorial 6 `_ - - Training on ST-MNIST with Tonic + SNNTorch + - Surrogate Gradient Descent in a Convolutional SNN - .. image:: https://colab.research.google.com/assets/colab-badge.svg :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_6_CNN.ipynb - * - `Tutorial 7 `_ - Neuromorphic Datasets with Tonic + snnTorch - .. image:: https://colab.research.google.com/assets/colab-badge.svg From 4d8d087cb4a36203e6f718d39f4c8611b2f5a031 Mon Sep 17 00:00:00 2001 From: shatoparbabanerjee <87339945+shatoparbabanerjee@users.noreply.github.com> Date: Thu, 14 Dec 2023 21:38:55 -0800 Subject: [PATCH 11/13] Add files via upload --- examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb diff --git a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb new file mode 100644 index 00000000..4d923f77 --- /dev/null +++ b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"markdown","metadata":{"id":"0PD5VPOUr4bs"},"source":["[](https://github.com/jeshraghian/snntorch/)\n","[](https://github.com/neuromorphs/tonic/)\n","\n","\n","# Training on ST-MNIST with Tonic + snnTorch Tutorial\n","\n","##### By:\n","#### Dylan Louie (djlouie@ucsc.edu),\n","#### Hannah Cohen Sandler (hcohensa@ucsc.edu),\n","#### Shatoparba Banerjee (sbaner12@ucsc.edu)\n","##### Credits to our Professor: Jason K. Eshraghian (www.ncg.ucsc.edu)\n","\n","\n"," \"Open\n",""]},{"cell_type":"markdown","metadata":{"id":"iawcPZ7DtDqK"},"source":["For a comprehensive overview on how SNNs work, and what is going on under the hood, [then you might be interested in the snnTorch tutorial series available here.](https://snntorch.readthedocs.io/en/latest/tutorials/index.html)\n","The snnTorch tutorial series is based on the following paper. If you find these resources or code useful in your work, please consider citing the following source:\n","\n","> [Jason K. Eshraghian, Max Ward, Emre Neftci, Xinxin Wang, Gregor Lenz, Girish Dwivedi, Mohammed Bennamoun, Doo Seok Jeong, and Wei D. Lu. \"Training Spiking Neural Networks Using Lessons From Deep Learning\". Proceedings of the IEEE, 111(9) September 2023.](https://ieeexplore.ieee.org/abstract/document/10242251) "]},{"cell_type":"code","execution_count":1,"metadata":{"id":"W-v36rDBv41L","executionInfo":{"status":"ok","timestamp":1702537684903,"user_tz":480,"elapsed":20885,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["!pip install tonic --quiet\n","!pip install snntorch --quiet"]},{"cell_type":"code","execution_count":2,"metadata":{"id":"6WWIF2I1v7sA","executionInfo":{"status":"ok","timestamp":1702537694860,"user_tz":480,"elapsed":9960,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["import tonic\n","import tonic.transforms as transforms # Not to be mistaken with torchdata.transfroms\n","from tonic import DiskCachedDataset\n","import torch\n","from torch.utils.data import random_split\n","from torch.utils.data import DataLoader\n","import torchvision\n","import torch.nn as nn\n","import snntorch as snn\n","from snntorch import surrogate\n","import snntorch.spikeplot as splt\n","from snntorch import functional as SF\n","from snntorch import utils\n","import matplotlib.pyplot as plt\n","from IPython.display import HTML\n","from IPython.display import display\n","import numpy as np\n","import torchdata\n","import os\n","from ipywidgets import IntProgress\n","import time\n","import statistics"]},{"cell_type":"markdown","metadata":{"id":"McXriEu-tJV6"},"source":["# 1. STMNIST"]},{"cell_type":"markdown","metadata":{"id":"wsV-uUeZ6a2A"},"source":["## 1.1 A Description\n","\n","The Spiking Tactile-MNIST (ST-MNIST) dataset is a novel neuromorphic collection featuring handwritten digits (0-9) inscribed by 23 individuals on a 100-taxel biomimetic event-based tactile sensor array. This dataset, publicly available to facilitate research in tactile perception, captures the dynamic pressure changes associated with natural writing. The tactile sensing system, Asynchronously Coded Electronic Skin (ACES), emulates the human peripheral nervous system, transmitting fast-adapting (FA) responses as asynchronous electrical events.\n","\n","More information about the ST-MNIST dataset can found by the paper written by its authors:\n","\n","> H. H. See, B. Lim, S. Li, H. Yao, W. Cheng, H. Soh, and B. C. K. Tee, \"ST-MNIST - The Spiking Tactile-MNIST Neuromorphic Dataset,\" A PREPRINT, May 2020. [Online]. Available: https://arxiv.org/abs/2005.04319 \n","\n"]},{"cell_type":"markdown","metadata":{"id":"Ickp0FA4_nBR"},"source":["## 1.2 Download the STMNIST dataset\n","\n","The data of ST-MNIST is provided with the MAT format. We are working in Python, so we need a way to import that MAT data into Python. Luckily, Tonic has created a function that creates an IterDataPipe that reads out and transforms the data into an (x, y, t, p) format when provided a path to it. (More down below)\n","\n","The first thing you must do is download the compressed dataset by accessing: https://scholarbank.nus.edu.sg/bitstream/10635/168106/2/STMNIST%20dataset%20NUS%20Tee%20Research%20Group.zip\n","\n","The zip file that you download will be titled `STMNIST dataset NUS Tee Research Group`. You must create a folder/directory titled `STMNIST` and then put that zip file in the folder/directory. This will be necessary for the Tonic class we use later.\n","\n","You then must either put it somewhere you can provide a path to it on your local machine or your Google Drive. For the purposes of this tutorial we will assume Google Drive."]},{"cell_type":"markdown","metadata":{"id":"DnDx0axoCphC"},"source":["## 1.3 Mount to Drive\n","Assuming you now have the `STMNIST` directory containing the zip file somewhere in your Google Drive. We must now \"mount\" Google Drive to this notebook so that it can access it. This is done with the code below:"]},{"cell_type":"code","execution_count":3,"metadata":{"id":"c2PcG-B3v9K8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":1243,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"07c02c45-7db1-42d9-ce97-34fb8831b7d4"},"outputs":[{"output_type":"stream","name":"stdout","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"]}],"source":["# Load the Drive helper and mount\n","from google.colab import drive\n","\n","# This will prompt for authorization.\n","drive.mount('/content/drive')"]},{"cell_type":"code","execution_count":4,"metadata":{"id":"00hHZOeuv-8k","executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":5,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# After executing the cell above, Drive files will be present in \"/content/drive/My Drive\".\n","# Here is the path to the file in our drive, change it to where it is in yours\n","root = \"/content/drive/My Drive/STMNIST_Tutorial\" # similar to os.path.join('drive', 'My Drive', 'Finalized_STMNIST')"]},{"cell_type":"markdown","source":["The following cell blocks is to make sure you edited the above path correctly. If you get a `FileNotFoundError: [Errno 2] No such file or directory:` error or a `ls: cannot access '/content/drive/My Drive/the/path/you/put/in': No such file or directory` error that means you didn't edit the above path correctly and you are pathing to a directory that doesn't exist. Furthermore make sure that the directory STMNIST (which you made and has your zip file is in) is in the directory you are pathing to."],"metadata":{"id":"1434lW43N5aR"}},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 1\n","os.listdir(root) # same as os.listdir(\"/content/drive/My Drive/STMNIST_Tutorial\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2FqIu1QaHPi4","executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"f99d55f8-7ea4-4fe8-c8b5-d323576351df"},"execution_count":5,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['STMNIST', 'ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb']"]},"metadata":{},"execution_count":5}]},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 2\n","!ls \"/content/drive/My Drive/STMNIST_Tutorial\""],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ynCJsU_HHOxV","executionInfo":{"status":"ok","timestamp":1702537696267,"user_tz":480,"elapsed":170,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8c9b957d-adf5-4765-bc67-d743371a98df"},"execution_count":6,"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb\n"]}]},{"cell_type":"markdown","metadata":{"id":"OOfqmhKcIOR0"},"source":["## 1.4 ST-MNIST through Tonic\n","\n","1. List item\n","2. List item\n","\n","\n","Now we call the `tonic` function to create the class that returns a IterDataPipe of the dataset. The docs for that function can be found here: https://tonic.readthedocs.io/en/latest/generated/tonic.prototype.datasets.STMNIST.html#tonic.prototype.datasets.STMNIST"]},{"cell_type":"code","execution_count":7,"metadata":{"id":"4r9zaUjHwAcM","executionInfo":{"status":"ok","timestamp":1702537696525,"user_tz":480,"elapsed":260,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["dataset = tonic.prototype.datasets.STMNIST(root=root,\n"," keep_compressed = False, shuffle = False)"]},{"cell_type":"markdown","metadata":{"id":"AgwoqxsAMdqP"},"source":["Because the dataset is an IterDataPipe, it can not be indexed into. Instead, we use `next(iter())` in order to iterate through it.\n","\n","In the above code `dataset` has been set to the returned DataPipe, so now I will just refer to `dataset`. Tonic formats the STMNIST dataset into an `(x, y, t, p)` format just like its other datasets so that the data will be compatable with other parts of its library. Where `x` is the position on the x-axis, `y` is the position on the y-axis, `t` is a timestamp, and `p` is polarity (1 or 0).\n","\n","Each iteration of dataset returns a tuple. The first index of the tuple contains a numpy array of `(x, y, t, p)` tuples which represents a series of sparse matrix through time of the recordings on the tactile sensor. The second index is a integer 0-9 which is the \"label\" of the data representing what number the afformentioned events is a drawing of."]},{"cell_type":"code","execution_count":8,"metadata":{"id":"2nRzg5A0RegL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696746,"user_tz":480,"elapsed":223,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"05222d60-e5a0-4e54-8ca4-3244e3a78631"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","1115\n","(7, 8, 200257, 1)\n","6\n"]}],"source":["print(type(dataset))\n","events, target = next(iter(dataset))\n","print(type(events))\n","print(len(events))\n","print(events[0])\n","print(target)"]},{"cell_type":"markdown","metadata":{"id":"7mWT1BXPdeuM"},"source":["Now that the data is out of the MAT file and into the (x,y,t,p) format we now need it to be in a form that our neural network can read. Luckily Tonic has transformations that do that for us as its other datasets use the (x,y,t,p) format. When you run the code below, the `.ToFrame()` function from `tonic.transforms` changes it from an (x,y,t,p) format to a numpy array matrix."]},{"cell_type":"code","execution_count":9,"metadata":{"id":"Alt1gJkWSqjy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696746,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"12fec926-75d5-4b5b-c2cb-63eabfc8b9d2"},"outputs":[{"output_type":"stream","name":"stdout","text":["----------------------------\n","\n","----------------------------\n","644\n","----------------------------\n","\n","----------------------------\n","2\n","----------------------------\n","[[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","\n"," [[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[0 0 0 0 0 0 0 0 0 0]\n","----------------------------\n","\n","----------------------------\n","0\n"]}],"source":["sensor_size = tuple(tonic.prototype.datasets.STMNIST.sensor_size.values()) # The sensor size for STMNIST is (10, 10, 2) btw\n","# transforms is the same as tonic.transforms check the imports above if you want to make sure\n","frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=sensor_size,\n"," time_window=1000)\n"," ])\n","\n","copy_events = frame_transform(events)\n","print('----------------------------')\n","print(type(copy_events))\n","print('----------------------------')\n","print(len(copy_events))\n","print('----------------------------')\n","print(type(copy_events[0]))\n","print('----------------------------')\n","print(len(copy_events[0]))\n","print('----------------------------')\n","print(copy_events[0])\n","print('----------------------------')\n","print(type(copy_events[0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0]))\n","print('----------------------------')\n","print(copy_events[0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0][0])"]},{"cell_type":"markdown","metadata":{"id":"AbRLjFPEqf6M"},"source":["### 1.4.1 The advantages of ST-MNIST over N-MNIST\n","At the time of release, the closest neuromorphic dataset to ST-MNIST was the N-MNIST dataset which used a moving motion-sensing event-based camera on static images of the original MNIST set (non-temporal 2-d digit classification) to simulate movement. What makes the ST-MNIST dataset better is that the dataset is actually taken from people writing on 10 by 10 tactile pixel sensors. That means when a neural network learns from a dataset it actually has to look at it temporally rather than purely spatially. In N-MNIST every frame would have the digit fully shown, however, for ST-MNIST it only shows parts of it as the participants write over it. That means that as a neuromorphic dataset taking advantage of the spiking and temporal benefits of a SNN ST-MNIST is better than N-MNIST.\n"]},{"cell_type":"markdown","metadata":{"id":"l3CJDa1LnUzd"},"source":["Using `tonic.utils.plot_animation`, the frame transform, and also some rotation. We can create an animation of the data and visualize this."]},{"cell_type":"code","execution_count":10,"metadata":{"id":"kOFkuUfrplsg","executionInfo":{"status":"ok","timestamp":1702537697615,"user_tz":480,"elapsed":871,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Iterate to a new iteration\n","events, target = next(iter(dataset))"]},{"cell_type":"code","execution_count":11,"metadata":{"id":"maDf7TLHmUiw","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702537697616,"user_tz":480,"elapsed":10,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"83ea920e-1d1a-4eff-dc13-6a5022084fec"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 7\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAG40lEQVR4nO3cIW5UURiGYS6ZoKrKAhrELAAMiwDBJhAo1oIBwTrYQ7uGGqpwVfUHTTLT3DDv9Ewnz6OP+HLNm9/cZYwxXgDAgV7OHgDAeRAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQ2Kx9uCzLMXcAcMLW/FTFhQJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQ2swfAP7bvZy/Y7fZm9oJn6OvsAY/4NnvAWXKhAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILGMMcaqh8ty7C0AT+Pq5+wFu919nr1grzWpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJzewBwJl6+2n2gv3+3M1ecJZcKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEhsZg8AztXr2QP2e/d99oLdrmcPOIwLBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASGxmD4Bn4eJy9oL9Hu5nL9jt7mL2gv1ebWcv2ONm9oCDuFAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQWMYYY9XDZTn2FjhdF5ezF+z3cD97wW5XJ/zN7k70m52wNalwoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAIlljDFWPVyWY28BeBpf3s9esNuPm9kL9lqTChcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEssYY6x6+PvXsbf8nzcfZy8AOHtrUuFCASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEpvVL68/HHHGAS5nD3jE/ewBz9B2O3vBbre3sxfAyXOhAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILGMMcbsEQA8fy4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEn8BHHxC+cFz7O0AAAAASUVORK5CYII=\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":11}],"source":["frame_transform_tonic_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=90000,\n",")\n","\n","frames = frame_transform_tonic_visual(events)\n","frames = frames / np.max(frames)\n","frames = np.rot90(frames, k=-1, axes=(2, 3))\n","frames = np.flip(frames, axis=3)\n","\n","# Print out the Target\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","animation = tonic.utils.plot_animation(frames)\n","\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"w52aUd2qoyXV"},"source":["We can also use `snntorch.spikeplot`"]},{"cell_type":"code","execution_count":12,"metadata":{"id":"bPwRVZgqo8EH","colab":{"base_uri":"https://localhost:8080/","height":926},"executionInfo":{"status":"ok","timestamp":1702537699047,"user_tz":480,"elapsed":1437,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"79316d31-e2e6-4ad8-edd2-bcc3808cfd66"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 7\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n"},"metadata":{}}],"source":["frame_transform_snntorch_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=8000,\n",")\n","\n","tran = frame_transform_snntorch_visual(events)\n","tran = np.rot90(tran, k=-1, axes=(2, 3))\n","tran = np.flip(tran, axis=3)\n","tran = torch.from_numpy(tran)\n","\n","tensor1 = tran[:, 0:1, :, :]\n","tensor2 = tran[:, 1:2, :, :]\n","\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","\n","fig, ax = plt.subplots()\n","time_steps = tensor1.size(0)\n","tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n","anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n","\n","display(HTML(anim.to_html5_video()))"]},{"cell_type":"code","execution_count":13,"metadata":{"id":"F5eZvTHHr5qS","executionInfo":{"status":"ok","timestamp":1702537699247,"user_tz":480,"elapsed":202,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_sensor_size = tonic.datasets.NMNIST.sensor_size\n","nmnist_frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=nmnist_sensor_size,\n"," time_window=3000)\n"," ])\n","\n","nmnist_dataset = tonic.datasets.NMNIST(save_to='./tmp/nmnist_example_data', transform=nmnist_frame_transform, train=False)"]},{"cell_type":"code","execution_count":14,"metadata":{"id":"Tz3HlO9zsdls","executionInfo":{"status":"ok","timestamp":1702537699248,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_events, nmnist_target = nmnist_dataset[0]"]},{"cell_type":"code","execution_count":15,"metadata":{"id":"pe47llhqu00o","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":9050,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"5560d6c9-9f25-4e4c-abe9-48f03cdcd4b8"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of N-MNIST\n","The target label is: 8\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGe0lEQVR4nO3cMY4bMRAAQdPYL+qVeuTcBwzfLtw8rayqeIIBk8YkXDMzvwDgH/1+9QIA/B8EBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJI6zg2utnXsAcGNnPlVxoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AcBePC7PPbVvwvlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMSamTk1uNbuXQC4qTOpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAInj1QsAFzwuzj+3bAF/5EIBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJNbMzKnBtXbvAtSufNXimxb+4kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhK9XAPiWr1cA+DGCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkjlcvALyhx8X555YtuBkXCgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASCxZmZODa61excAbupMKlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AsNHjwuxz2xZ8CBcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7FwBu6kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQOF69wEd4XJx/btniM1x5a+8MKRcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7F+5m1zcmvqKBt3MmFS4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQMLXKwB8y9crAPwYQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMRxdnBmdu4BwJtzoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJD4AihVRw5/WD3pAAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":15}],"source":["# Print out the Target\n","print('Animation of N-MNIST')\n","print('The target label is:',nmnist_target)\n","# normalize values to between 0-1\n","nmnist_events_fraction = nmnist_events / np.max(nmnist_events)\n","animation = tonic.utils.plot_animation(nmnist_events_fraction)\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"92McQkLgd_xI"},"source":["A printout of the sensor size of the ST-MNIST and N-MNIST dataset. (10, 10, 2) menas a 10 by 10 pixel dataset with a channel size of 2. (34, 34, 2) means a 34 by 34 pixel dataset with a channel size of 2."]},{"cell_type":"code","execution_count":16,"metadata":{"id":"mou11FujsL-v","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":21,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"2f78c469-6ea2-463c-b0b7-71f1adb5bc64"},"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST {'x': 10, 'y': 10, 'p': 2}\n","NMNIST (34, 34, 2)\n"]}],"source":["print('STMNIST', tonic.prototype.datasets.STMNIST.sensor_size)\n","print('NMNIST', tonic.datasets.NMNIST.sensor_size)"]},{"cell_type":"markdown","metadata":{"id":"CzYgPlxWfdm_"},"source":["There is a total of 6953 recordings in this dataset. This lines up with what is said in the ST-MNIST paper. They invited in 23 participants to write around 30 times each for 9 digits."]},{"cell_type":"code","execution_count":17,"metadata":{"id":"_v1auSbyepQr","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":18,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"7708b995-4238-4421-98b2-c99ee1811789"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n"]}],"source":["print(len(dataset)) # 23 participants writing around 30 times each for 9 digits 23*30*9 = 6210"]},{"cell_type":"markdown","metadata":{"id":"tlX9jWV0f_az"},"source":["## 1.5 Lets create a trainset and testset!"]},{"cell_type":"markdown","metadata":{"id":"hqQzVEHEgSFp"},"source":["Unfortunately unlike N-MNIST, ST-MNIST isn't already seperated into a trainset and testset on tonic. That means we will have to seperate that manually. For this example you could do 80% of the dataset for the trainset and 20% for the testset which we calculate below."]},{"cell_type":"code","execution_count":18,"metadata":{"id":"ZXw_xyfetX_K","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":17,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"97dca7f1-2132-4d40-ad35-5257fd6bf9c7"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n","5562\n","1391\n"]}],"source":["# Calculate the sizes for the training and testing sets\n","total_size = len(dataset)\n","print(total_size)\n","# train_size is 80% of total size\n","train_size = int(0.8 * total_size)\n","print(train_size)\n","test_size = total_size - train_size\n","print(test_size)"]},{"cell_type":"code","execution_count":19,"metadata":{"id":"d_6BFKiXJdWU","executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":16,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["sensor_size = tonic.prototype.datasets.STMNIST.sensor_size\n","sensor_size = tuple(sensor_size.values())\n","\n","# Define a transform\n","frame_transform = transforms.Compose([transforms.ToFrame(sensor_size=sensor_size, time_window=1000)])"]},{"cell_type":"markdown","metadata":{"id":"iSMhDsHliQk5"},"source":["The following code reads out the entirety of the dataset from the IterDataPipe and then transforms the events using the `frame_transform` above. It also seperates out the data into a trainset and a testset. Remember that each time a piece of data is read out of the datapipe it is read and transformed from the MAT files using tonic. On top of that we are to the .ToFrame() transform over it each time. Thus, this takes some time.\n","\n","**You have two options here:**\n","\n","Transform and tain on a small part of the dataset, this is faster and is the default for the sake of a short easy to run tutorial. The default for this shorter transform is 640 pieces of data for the trainset and 320 pieces of data for the testset. This takes ~4-5 minutes. Feel free to change this, just be aware that the number of pieces of data we transform and the time it takes have an inverse relationship.\n","\n","**Or** you can transform and convert the entire dataset; this takes ~30-60 minutes. To do that comment out the `shorter_transform_STMNIST` cell block and uncomment the `full_transform_STMNIST` cell block and run that instead. If you choose this: kickback, take a break and eat a snack while this happens. perhaps even count kangaroos to take a nap or do a shoey and get schwasted instead.\n","\n","Note: A smaller dataset generally means a higher accuracy but less generalizability on new data when training a neural network on it given the same amount of time."]},{"cell_type":"code","source":["def shorter_transform_STMNIST(data, transform):\n"," short_train_size = 640\n"," short_test_size = 320\n","\n"," train_bar = IntProgress(min=0, max=short_train_size)\n"," test_bar = IntProgress(min=0, max=short_test_size)\n","\n"," testset = []\n"," trainset = []\n","\n"," print('Porting over and transforming the trainset.')\n"," display(train_bar)\n"," for _ in range(short_train_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," trainset.append((events, target))\n"," train_bar.value += 1\n"," print('Porting over and transforming the testset.')\n"," display(test_bar)\n"," for _ in range(short_test_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," testset.append((events, target))\n"," test_bar.value += 1\n","\n"," return (trainset, testset)\n","\n","# Get the start time\n","start_time = time.time()\n","\n","# Call the function\n","trainset, testset = shorter_transform_STMNIST(dataset, frame_transform)\n","\n","# Get the end time\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":135,"referenced_widgets":["b9415441caa94336b3419889cb5c5fc8","c5510f1d3b4f440ea0ead2601e0b0550","92c8f35c46834aacacb25460c5ba338b","1af14dcea1524a3ca16d74e948aaf62b","6da1b1c1ba0e4eaab9d9a292b2daa486","e7af9d3e054e49c4a3d0e3dc3fa660cf"]},"id":"c0qw8uduLpZv","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":186720,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"518ee215-d2b2-4432-9666-5968aa5e40ac"},"execution_count":20,"outputs":[{"output_type":"stream","name":"stdout","text":["Porting over and transforming the trainset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=640)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"b9415441caa94336b3419889cb5c5fc8"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Porting over and transforming the testset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=320)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"1af14dcea1524a3ca16d74e948aaf62b"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Elapsed time: 3 minutes, 6 seconds, 970 milliseconds\n"]}]},{"cell_type":"code","execution_count":21,"metadata":{"id":"muL3A2dbMYTY","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":12,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# def full_transform_STMNIST(data, transform):\n","# train_bar = IntProgress(min=0, max=train_size)\n","# test_bar = IntProgress(min=0, max=test_size)\n","\n","# testset = []\n","# trainset = []\n","\n","# print('Porting over and transforming the trainset.')\n","# display(train_bar)\n","# for _ in range(train_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# trainset.append((events, target))\n","# train_bar.value += 1\n","# print('Porting over and transforming the testset.')\n","# display(test_bar)\n","# for _ in range(test_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# testset.append((events, target))\n","# test_bar.value += 1\n","\n","# return (trainset, testset)\n","\n","# # Get the start time\n","# start_time = time.time()\n","\n","# # Call the function\n","# trainset, testset = full_transform_STMNIST(dataset, frame_transform)\n","\n","# # Get the end time\n","# end_time = time.time()\n","\n","# # Calculate elapsed time\n","# elapsed_time = end_time - start_time\n","\n","# # Convert elapsed time to minutes, seconds, and milliseconds\n","# minutes, seconds = divmod(elapsed_time, 60)\n","# seconds, milliseconds = divmod(seconds, 1)\n","# milliseconds = round(milliseconds * 1000)\n","\n","# # Print the elapsed time\n","# print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"98VVH_HSs-Gh"},"source":["## 1.6 Dataloading and Batching\n","\n","The reason why we needed to move the data into a list instead of just using the datapipe and transforming as we moved out of it was so that we could use the DataLoader function from torch that requires an indexable class, array, etc."]},{"cell_type":"code","execution_count":22,"metadata":{"id":"DPxzp1fdFe_X","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Create a DataLoader\n","dataloader = DataLoader(trainset, batch_size=64, shuffle=True)"]},{"cell_type":"markdown","metadata":{"id":"yORjaoQAuuY1"},"source":["To make our dataloading even faster we can use DiskCashedDataset from tonic which makes use of disk chaching and batching. In addition we can add an additional transformation that will change the data from numpy to a torch tensor.\n","\n","Due to variations in the lengths of event recordings, we will introduce a collation function called `tonic.collation.PadTensors()`. This function will be responsible for padding shorter recordings, ensuring uniform dimensions across all samples in a batch."]},{"cell_type":"code","execution_count":23,"metadata":{"id":"YaPsfB0ArUgQ","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["transform = tonic.transforms.Compose([torch.from_numpy])\n","\n","cached_trainset = DiskCachedDataset(trainset, transform=transform, cache_path='./cache/stmnist/train')\n","\n","# no augmentations for the testset\n","cached_testset = DiskCachedDataset(testset, cache_path='./cache/stmnist/test')\n","\n","batch_size = 128\n","trainloader = DataLoader(cached_trainset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False), shuffle=True)\n","testloader = DataLoader(cached_testset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False))"]},{"cell_type":"markdown","metadata":{"id":"_i-s-FRuwGBR"},"source":["Here are the shapes of the data and target tensors of a single iteration of the trainloader printed below."]},{"cell_type":"code","execution_count":24,"metadata":{"id":"0so65S95BDbf","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537896173,"user_tz":480,"elapsed":1176,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"d06a3767-4ab1-4662-8154-c7d02124bebd"},"outputs":[{"output_type":"stream","name":"stdout","text":["5\n","torch.Size([1993, 128, 2, 10, 10])\n","torch.Size([128, 2, 10, 10])\n","torch.Size([128])\n","tensor([8, 0, 0, 8, 1, 0, 4, 1, 2, 3, 2, 3, 9, 6, 7, 8, 3, 1, 3, 9, 3, 7, 7, 6,\n"," 3, 0, 7, 6, 6, 2, 9, 1, 2, 2, 5, 1, 6, 9, 4, 5, 7, 4, 6, 1, 3, 0, 0, 5,\n"," 5, 1, 5, 4, 7, 8, 2, 7, 2, 9, 5, 6, 2, 4, 9, 0, 8, 4, 4, 7, 5, 6, 0, 5,\n"," 2, 4, 9, 1, 2, 4, 2, 7, 7, 0, 8, 4, 1, 3, 4, 5, 4, 7, 9, 2, 9, 1, 8, 6,\n"," 7, 3, 2, 3, 9, 8, 1, 9, 1, 8, 2, 1, 1, 5, 8, 3, 3, 1, 6, 7, 2, 5, 1, 7,\n"," 7, 9, 4, 0, 8, 2, 4, 1])\n"]}],"source":["data_tensor, targets = next(iter(trainloader))\\\n","# length of trainloader = number of iterations per epoch\n","# For the shorter transform\n","# 640 == length of dataset\n","# 640 / 128 = 5\n","# Remember: Trainset is length 640\n","# So the trainloader should be length 5\n","# For the longer transform\n","# 5562 == length of dataset\n","# 5562 / 128 ~ 43.45\n","# Remember: Trainset is length 5562\n","# So the trainloader should be length 44\n","print(len(trainloader))\n","print(data_tensor.shape)\n","print(data_tensor[0].shape)\n","print(targets.shape)\n","print(targets)"]},{"cell_type":"markdown","metadata":{"id":"QDGPdoBUw-ME"},"source":["## 1.7 Create the Spiking Convolutional Neural Network"]},{"cell_type":"markdown","source":["Below we have by default a spiking convolutional neural network with the architecture: `10×10-32c4-64c3-MaxPool2d(2)-10o`."],"metadata":{"id":"PRdPJemVH8uR"}},{"cell_type":"code","execution_count":25,"metadata":{"id":"W2ewqKLx8mMJ","executionInfo":{"status":"ok","timestamp":1702537901396,"user_tz":480,"elapsed":5224,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n","\n","# neuron and simulation parameters\n","spike_grad = surrogate.atan()\n","beta = 0.95\n","\n","# 10×10-32c4-64c3-MaxPool2d(2)-10o\n","# This is the same architecture that was used in the STMNIST Paper\n","# No Max Pooling as 10x10 is already very small/low detail\n","scnn_net = nn.Sequential(\n"," # 2 x 10 x 10\n"," nn.Conv2d(2, 32, kernel_size=4), # 32 channels, kernel size 4x4\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(10 - 4) + 1] = 7\n","\n"," # 32 x 7 x 7\n"," nn.Conv2d(32, 64, kernel_size=3), # 64 channels, kernel size 3x3\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(7 - 3) + 1] = 5\n","\n"," # 64 x 5 x 5\n"," nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n"," # Output size = [(5-2) / 2] + 1 = 2\n","\n"," # 64 x 2 x 2\n"," nn.Flatten(),\n"," # Output size = 64*2*2 = 256\n","\n"," nn.Linear(64 * 2 * 2, 10), # Increased size of the linear layer\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n",").to(device)\n","\n","# Note: In a CNN the formula for calculating the output of the Conv layer is\n","# Output size = ((Input Size - Kernel Size + 2 * Padding) / Stride ) + 1\n","# Note for a MaxPool layer the formula is\n","# Output size = ((Input size - Kernel Size) / Stride ) + 1\n","\n","optimizer = torch.optim.Adam(scnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"markdown","metadata":{"id":"Sq_jz3xYxMxO"},"source":["## 1.8 Define the Forward Pass"]},{"cell_type":"code","execution_count":26,"metadata":{"id":"ydcyDZDt_qH_","executionInfo":{"status":"ok","timestamp":1702537901397,"user_tz":480,"elapsed":11,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["def forward_pass(net, data):\n"," spk_rec = []\n"," utils.reset(net) # resets hidden states for all LIF neurons in net\n","\n"," for step in range(data.size(0)): # data.size(0) = number of time steps\n","\n"," spk_out, mem_out = net(data[step])\n"," spk_rec.append(spk_out)\n","\n"," return torch.stack(spk_rec)"]},{"cell_type":"markdown","metadata":{"id":"9tPywf6CxWcq"},"source":["## 1.9 Create and Run the Training Loop\n","\n","The current epochs is set to 40 and is intended to be run on the smaller trainset and testset. In the smaller set each epoch has 5 iterations. Doing the math: 5 * 40 is 200 iterations over the 40 epochs. On our runs on the T4 GPU on Colab, 30 epochs on the smaller dataset takes ~25 minutes and achieves ~50% accuracy on the testset and ~50% accuracy on the trainset.\n","\n","For training on the full dataset, we recommend lowering the epochs down to 15. Remember that each epoch has 44 iterations starting at 0. Doing the math: 44 * 15 = 660 iterations over the 15 epochs. Training should once again take some time so feel free to take a break and let your computer run. On our runs with the T4 GPU on Colab 15 epochs takes ~70 min with ~70% accuracy on the full trainset and ~65% accuracy on the full testset.\n","\n","Of course feel free to adjust the epochs to make them longer or shorter if you have more or less time and would like to experiment with how that affects accuracy on the testset and trainset."]},{"cell_type":"code","execution_count":27,"metadata":{"id":"lB9lYUP0AUBL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539105640,"user_tz":480,"elapsed":1204253,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"561fd004-e7ad-4cda-e84d-d326b29b4fb6"},"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 0, Iteration 0 \n","Train Loss: 187.81\n","Accuracy: 7.81%\n","\n","Epoch 0, Iteration 4 \n","Train Loss: 176.25\n","Accuracy: 10.94%\n","\n","Epoch 1, Iteration 0 \n","Train Loss: 157.28\n","Accuracy: 7.81%\n","\n","Epoch 1, Iteration 4 \n","Train Loss: 159.94\n","Accuracy: 14.06%\n","\n","Epoch 2, Iteration 0 \n","Train Loss: 165.89\n","Accuracy: 9.38%\n","\n","Epoch 2, Iteration 4 \n","Train Loss: 159.88\n","Accuracy: 10.94%\n","\n","Epoch 3, Iteration 0 \n","Train Loss: 162.16\n","Accuracy: 10.16%\n","\n","Epoch 3, Iteration 4 \n","Train Loss: 155.06\n","Accuracy: 14.06%\n","\n","Epoch 4, Iteration 0 \n","Train Loss: 149.63\n","Accuracy: 10.16%\n","\n","Epoch 4, Iteration 4 \n","Train Loss: 145.48\n","Accuracy: 11.72%\n","\n","Epoch 5, Iteration 0 \n","Train Loss: 144.21\n","Accuracy: 10.16%\n","\n","Epoch 5, Iteration 4 \n","Train Loss: 82.61\n","Accuracy: 14.06%\n","\n","Epoch 6, Iteration 0 \n","Train Loss: 73.82\n","Accuracy: 13.28%\n","\n","Epoch 6, Iteration 4 \n","Train Loss: 75.70\n","Accuracy: 8.59%\n","\n","Epoch 7, Iteration 0 \n","Train Loss: 77.11\n","Accuracy: 9.38%\n","\n","Epoch 7, Iteration 4 \n","Train Loss: 85.57\n","Accuracy: 10.16%\n","\n","Epoch 8, Iteration 0 \n","Train Loss: 92.13\n","Accuracy: 10.94%\n","\n","Epoch 8, Iteration 4 \n","Train Loss: 120.03\n","Accuracy: 7.81%\n","\n","Epoch 9, Iteration 0 \n","Train Loss: 107.87\n","Accuracy: 12.50%\n","\n","Epoch 9, Iteration 4 \n","Train Loss: 105.17\n","Accuracy: 8.59%\n","\n","Epoch 10, Iteration 0 \n","Train Loss: 107.01\n","Accuracy: 6.25%\n","\n","Epoch 10, Iteration 4 \n","Train Loss: 95.13\n","Accuracy: 3.91%\n","\n","Epoch 11, Iteration 0 \n","Train Loss: 94.15\n","Accuracy: 5.47%\n","\n","Epoch 11, Iteration 4 \n","Train Loss: 80.65\n","Accuracy: 14.84%\n","\n","Epoch 12, Iteration 0 \n","Train Loss: 80.67\n","Accuracy: 18.75%\n","\n","Epoch 12, Iteration 4 \n","Train Loss: 74.08\n","Accuracy: 5.47%\n","\n","Epoch 13, Iteration 0 \n","Train Loss: 72.87\n","Accuracy: 10.16%\n","\n","Epoch 13, Iteration 4 \n","Train Loss: 69.58\n","Accuracy: 14.06%\n","\n","Epoch 14, Iteration 0 \n","Train Loss: 69.41\n","Accuracy: 13.28%\n","\n","Epoch 14, Iteration 4 \n","Train Loss: 70.49\n","Accuracy: 8.59%\n","\n","Epoch 15, Iteration 0 \n","Train Loss: 65.84\n","Accuracy: 16.41%\n","\n","Epoch 15, Iteration 4 \n","Train Loss: 66.85\n","Accuracy: 17.97%\n","\n","Epoch 16, Iteration 0 \n","Train Loss: 64.81\n","Accuracy: 19.53%\n","\n","Epoch 16, Iteration 4 \n","Train Loss: 63.56\n","Accuracy: 17.97%\n","\n","Epoch 17, Iteration 0 \n","Train Loss: 64.15\n","Accuracy: 17.19%\n","\n","Epoch 17, Iteration 4 \n","Train Loss: 64.05\n","Accuracy: 16.41%\n","\n","Epoch 18, Iteration 0 \n","Train Loss: 64.32\n","Accuracy: 21.88%\n","\n","Epoch 18, Iteration 4 \n","Train Loss: 61.53\n","Accuracy: 27.34%\n","\n","Epoch 19, Iteration 0 \n","Train Loss: 61.77\n","Accuracy: 23.44%\n","\n","Epoch 19, Iteration 4 \n","Train Loss: 62.81\n","Accuracy: 19.53%\n","\n","Epoch 20, Iteration 0 \n","Train Loss: 63.38\n","Accuracy: 17.19%\n","\n","Epoch 20, Iteration 4 \n","Train Loss: 61.96\n","Accuracy: 22.66%\n","\n","Epoch 21, Iteration 0 \n","Train Loss: 59.59\n","Accuracy: 29.69%\n","\n","Epoch 21, Iteration 4 \n","Train Loss: 62.97\n","Accuracy: 23.44%\n","\n","Epoch 22, Iteration 0 \n","Train Loss: 60.30\n","Accuracy: 25.78%\n","\n","Epoch 22, Iteration 4 \n","Train Loss: 60.43\n","Accuracy: 31.25%\n","\n","Epoch 23, Iteration 0 \n","Train Loss: 59.96\n","Accuracy: 28.12%\n","\n","Epoch 23, Iteration 4 \n","Train Loss: 60.53\n","Accuracy: 34.38%\n","\n","Epoch 24, Iteration 0 \n","Train Loss: 59.84\n","Accuracy: 34.38%\n","\n","Epoch 24, Iteration 4 \n","Train Loss: 61.22\n","Accuracy: 32.81%\n","\n","Epoch 25, Iteration 0 \n","Train Loss: 58.51\n","Accuracy: 28.91%\n","\n","Epoch 25, Iteration 4 \n","Train Loss: 60.79\n","Accuracy: 29.69%\n","\n","Epoch 26, Iteration 0 \n","Train Loss: 58.33\n","Accuracy: 36.72%\n","\n","Epoch 26, Iteration 4 \n","Train Loss: 59.02\n","Accuracy: 36.72%\n","\n","Epoch 27, Iteration 0 \n","Train Loss: 58.91\n","Accuracy: 29.69%\n","\n","Epoch 27, Iteration 4 \n","Train Loss: 58.19\n","Accuracy: 31.25%\n","\n","Epoch 28, Iteration 0 \n","Train Loss: 56.42\n","Accuracy: 34.38%\n","\n","Epoch 28, Iteration 4 \n","Train Loss: 55.82\n","Accuracy: 41.41%\n","\n","Epoch 29, Iteration 0 \n","Train Loss: 57.21\n","Accuracy: 39.06%\n","\n","Epoch 29, Iteration 4 \n","Train Loss: 57.77\n","Accuracy: 35.16%\n","\n","Epoch 30, Iteration 0 \n","Train Loss: 59.45\n","Accuracy: 32.03%\n","\n","Epoch 30, Iteration 4 \n","Train Loss: 56.68\n","Accuracy: 33.59%\n","\n","Epoch 31, Iteration 0 \n","Train Loss: 57.80\n","Accuracy: 33.59%\n","\n","Epoch 31, Iteration 4 \n","Train Loss: 60.10\n","Accuracy: 31.25%\n","\n","Epoch 32, Iteration 0 \n","Train Loss: 55.65\n","Accuracy: 40.62%\n","\n","Epoch 32, Iteration 4 \n","Train Loss: 57.91\n","Accuracy: 37.50%\n","\n","Epoch 33, Iteration 0 \n","Train Loss: 57.15\n","Accuracy: 39.84%\n","\n","Epoch 33, Iteration 4 \n","Train Loss: 56.07\n","Accuracy: 39.84%\n","\n","Epoch 34, Iteration 0 \n","Train Loss: 54.63\n","Accuracy: 37.50%\n","\n","Epoch 34, Iteration 4 \n","Train Loss: 55.54\n","Accuracy: 45.31%\n","\n","Epoch 35, Iteration 0 \n","Train Loss: 56.43\n","Accuracy: 43.75%\n","\n","Epoch 35, Iteration 4 \n","Train Loss: 54.71\n","Accuracy: 41.41%\n","\n","Epoch 36, Iteration 0 \n","Train Loss: 53.87\n","Accuracy: 38.28%\n","\n","Epoch 36, Iteration 4 \n","Train Loss: 56.83\n","Accuracy: 41.41%\n","\n","Epoch 37, Iteration 0 \n","Train Loss: 55.19\n","Accuracy: 46.09%\n","\n","Epoch 37, Iteration 4 \n","Train Loss: 55.22\n","Accuracy: 43.75%\n","\n","Epoch 38, Iteration 0 \n","Train Loss: 55.57\n","Accuracy: 42.97%\n","\n","Epoch 38, Iteration 4 \n","Train Loss: 55.16\n","Accuracy: 42.97%\n","\n","Epoch 39, Iteration 0 \n","Train Loss: 53.61\n","Accuracy: 47.66%\n","\n","Epoch 39, Iteration 4 \n","Train Loss: 55.44\n","Accuracy: 44.53%\n","\n","Elapsed time: 20 minutes, 4 seconds, 11 milliseconds\n"]}],"source":["start_time = time.time()\n","\n","num_epochs = 40\n","\n","loss_hist = []\n","acc_hist = []\n","\n","# training loop\n","for epoch in range(num_epochs):\n"," for i, (data, targets) in enumerate(iter(trainloader)):\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," scnn_net.train()\n"," spk_rec = forward_pass(scnn_net, data)\n"," loss_val = loss_fn(spk_rec, targets)\n","\n"," # Gradient calculation + weight update\n"," optimizer.zero_grad()\n"," loss_val.backward()\n"," optimizer.step()\n","\n"," # Store loss history for future plotting\n"," loss_hist.append(loss_val.item())\n","\n"," if i%4 == 0:\n"," print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," if i%4 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"cEY6Ynbq0JmX"},"source":["# 2. Results"]},{"cell_type":"markdown","metadata":{"id":"yYSkN_kp0Lm0"},"source":["## 2.1 Plot accuracy history"]},{"cell_type":"code","execution_count":28,"metadata":{"id":"X0SYWQDJ6qhx","colab":{"base_uri":"https://localhost:8080/","height":472},"executionInfo":{"status":"ok","timestamp":1702539106031,"user_tz":480,"elapsed":405,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"1e880dbd-7e37-4910-f41c-b8375e29dd4b"},"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACjyUlEQVR4nO2deZgU5bn27+p9menZZ2B2QAGRVUBEI24oGtw1IvGIEo8mRk40JCd+JMc1OWLUGI0xemLiEnEhJi6JJm4grggKIpugrMM2M8w+093Ta31/VL9Vb1VX9TLTs/U8v+viYqa6lre6mamb+9kEURRFEARBEARBZAmmgV4AQRAEQRBEJiFxQxAEQRBEVkHihiAIgiCIrILEDUEQBEEQWQWJG4IgCIIgsgoSNwRBEARBZBUkbgiCIAiCyCpI3BAEQRAEkVWQuCEIgiAIIqsgcUMQBADg2muvRW1t7UAvgyAIoteQuCGIQY4gCCn9WbNmzUAvNY59+/Zh8eLFGDNmDBwOB0aMGIE5c+bgjjvu6NH5/vWvf+HOO+/s0bEnnngiBEHAY4891qPjCYIYOgg0W4ogBjcrVqxQff+Xv/wF77zzDp599lnV9rPPPhtlZWU9vk4oFEI0GoXdbu/xOXh27dqFmTNnwul04nvf+x5qa2tx5MgRbNy4Ef/+97/R3d2d9jmXLFmCRx99FOn+2vrmm28wduxY1NbWoqKiAh999FHa1yYIYuhgGegFEASRmP/4j/9Qff/pp5/inXfeiduuxefzweVypXwdq9Xao/UZ8dvf/hZdXV3YtGkTampqVK81NjZm9FrJWLFiBUpLS/Gb3/wGl19+Ofbt2zcoQ3DRaBTBYBAOh2Ogl0IQQxoKSxFEFnD66adj4sSJ2LBhA+bMmQOXy4Wf//znAIDXXnsN8+fPR3l5Oex2O8aMGYNf/vKXiEQiqnNoc2727dsHQRDwwAMP4I9//CPGjBkDu92OmTNn4rPPPku6pt27d6OysjJO2ABAaWlp3LZ///vfOPXUU+F2u5Gbm4v58+dj27ZtqvU9+uijANShulR4/vnncfnll+P8889HXl4enn/+ed391q1bh29/+9soKCiA2+3G5MmT8fDDD6v22bFjB6644gqUlJTA6XRi3Lhx+MUvfqFap55wuvPOO+PWKwgClixZgueeew7HH3887HY73nzzTQDAAw88gJNPPhlFRUVwOp2YPn06/va3v+mue8WKFTjxxBPhcrlQUFCAOXPm4O233wYAXHPNNSguLkYoFIo77pxzzsG4ceOM3ziCGKKQuCGILKG5uRnnnXcepk6dioceeghnnHEGAODpp59GTk4Oli5diocffhjTp0/H7bffjv/3//5fSud9/vnncf/99+P73/8+fvWrX2Hfvn249NJLdR+WPDU1NThw4ABWr16d9BrPPvss5s+fj5ycHPz617/Gbbfdhu3bt+Nb3/oW9u3bBwD4/ve/j7PPPlven/1Jxrp167Br1y4sXLgQNpsNl156KZ577rm4/d555x3MmTMH27dvx80334zf/OY3OOOMM/D666/L+2zevBmzZs3C6tWrcf311+Phhx/GxRdfjH/+859J12HE6tWr8eMf/xgLFizAww8/LAujhx9+GNOmTcPdd9+Ne+65BxaLBd/5znfwxhtvqI6/6667cPXVV8NqteLuu+/GXXfdhaqqKvl9v/rqq9Hc3Iy33npLdVx9fT1Wr16d1AEkiCGJSBDEkOKmm24StT+6p512mghAfPzxx+P29/l8cdu+//3viy6XS+zu7pa3XXPNNWJNTY38/d69e0UAYlFRkdjS0iJvf+2110QA4j//+c+E69y6davodDpFAOLUqVPFm2++WXz11VdFr9er2q+zs1PMz88Xr7/+etX2+vp6MS8vT7Vd796TsWTJErGqqkqMRqOiKIri22+/LQIQv/jiC3mfcDgsjho1SqypqRFbW1tVx7PjRFEU58yZI+bm5or79+833Ef7PjLuuOOOuLUDEE0mk7ht27a4/bWfWzAYFCdOnCieeeaZ8rZvvvlGNJlM4iWXXCJGIhHdNUUiEbGyslJcsGCB6vUHH3xQFARB3LNnT9y1CWKoQ84NQWQJdrsdixcvjtvudDrlrzs7O9HU1IRTTz0VPp8PO3bsSHreBQsWoKCgQP7+1FNPBQDs2bMn4XHHH388Nm3ahP/4j//Avn37ZJejrKwMTzzxhLzfO++8g7a2NixcuBBNTU3yH7PZjFmzZuG9995LukYjwuEwVq5ciQULFsghoTPPPBOlpaUq9+aLL77A3r17ccsttyA/P191Dnbc0aNH8cEHH+B73/seqqurdffpCaeddhomTJgQt53/3FpbW9He3o5TTz0VGzdulLe/+uqriEajuP3222EyqX+dszWZTCZcddVV+Mc//oHOzk759eeeew4nn3wyRo0a1eO1E8RghcQNQWQJFRUVsNlscdu3bduGSy65BHl5efB4PCgpKZFDEe3t7UnPq32QM6HT2tqa9NixY8fi2WefRVNTEzZv3iyHV2644Qa8++67AKRKJkASHSUlJao/b7/9dq+Sj99++20cPXoUJ554Inbt2oVdu3Zh7969OOOMM/DCCy8gGo0CkPKDAGDixImG52JiLtE+PcFIXLz++us46aST4HA4UFhYiJKSEjz22GOqz2z37t0wmUy64ohn0aJF8Pv9eOWVVwAAO3fuxIYNG3D11Vdn7kYIYhBB1VIEkSXw/9NntLW14bTTToPH48Hdd98t95vZuHEjbr31Vvnhngiz2ay7XUyjHNtsNmPSpEmYNGkSZs+ejTPOOAPPPfcc5s6dK6/h2WefxYgRI+KOtVh6/muKuTNXXHGF7uvvv/++nJuUKYxcHG0CN0Pvc/vwww9x4YUXYs6cOfjDH/6AkSNHwmq14qmnnjJMhk7EhAkTMH36dKxYsQKLFi3CihUrYLPZDN8XghjqkLghiCxmzZo1aG5uxssvv4w5c+bI2/fu3Ttga5oxYwYA4MiRIwCAMWPGAJAqqObOnZvw2HTCP16vF6+99hoWLFiAyy+/PO71H/3oR3juuedwxhlnyGvYunWr4RpGjx4t75OIgoICtLW1xW3fv39/ymv/+9//DofDgbfeekvVd+ipp55S7TdmzBhEo1Fs374dU6dOTXjORYsWYenSpThy5Aief/55zJ8/XxVuJIhsgsJSBJHFMNeFd1mCwSD+8Ic/9Pm1P/zwQ92Kqn/9618AIJcgz5s3Dx6PB/fcc4/u/kePHpW/drvdAKArHrS88sor8Hq9uOmmm3D55ZfH/Tn//PPx97//HYFAACeccAJGjRqFhx56KO7c7L0rKSnBnDlz8OSTT6Kurk53H0ASHO3t7di8ebO87ciRI3JIKBXMZjMEQVC5Pfv27cOrr76q2u/iiy+GyWTC3XffHefCaZ21hQsXQhAE3HzzzdizZw9VSRFZDTk3BJHFnHzyySgoKMA111yDH/3oRxAEAc8++2zaHX57wq9//Wts2LABl156KSZPngwA2LhxI/7yl7+gsLAQt9xyCwDA4/Hgsccew9VXX40TTjgBV155JUpKSlBXV4c33ngDp5xyCn7/+98DAKZPnw5Acl3mzZsHs9mMK6+8Uvf6zz33HIqKinDyySfrvn7hhRfiiSeewBtvvIFLL70Ujz32GC644AJMnToVixcvxsiRI7Fjxw5s27ZNLqP+3e9+h29961s44YQTcMMNN2DUqFHYt28f3njjDWzatAkAcOWVV+LWW2/FJZdcgh/96Efw+Xx47LHHMHbsWFUycCLmz5+PBx98EOeeey6++93vorGxEY8++iiOOeYYlWg65phj8Itf/AK//OUvceqpp+LSSy+F3W7HZ599hvLycixfvlzet6SkBOeeey5eeukl5OfnY/78+SmthSCGJANZqkUQRPoYlYIff/zxuvt//PHH4kknnSQ6nU6xvLxc/NnPfia+9dZbIgDxvffek/czKgW///77484JQLzjjjsSrvPjjz8Wb7rpJnHixIliXl6eaLVaxerqavHaa68Vd+/eHbf/e++9J86bN0/My8sTHQ6HOGbMGPHaa68VP//8c3mfcDgs/td//ZdYUlIiCoJgWBbe0NAgWiwW8eqrrzZcn8/nE10ul3jJJZfI2z766CPx7LPPFnNzc0W32y1OnjxZfOSRR1THbd26VbzkkkvE/Px80eFwiOPGjRNvu+021T5vv/22OHHiRNFms4njxo0TV6xYYVgKftNNN+mu789//rN47LHHina7XRw/frz41FNP6Z5DFEXxySefFKdNmyba7XaxoKBAPO2008R33nknbr+//vWvIgDxhhtuMHxfCCIboNlSBEEQw4TXXnsNF198MT744AO5pJ8gshESNwRBEMOE888/H1999RV27drVq948BDHYoZwbgiCILOfFF1/E5s2b8cYbb+Dhhx8mYUNkPeTcEARBZDmCICAnJwcLFizA448/3qveQQQxFKB/4QRBEFkO/R+WGG5QnxuCIAiCILIKEjcEQRAEQWQVwy4sFY1GcfjwYeTm5lJSHUEQBEEMEURRRGdnJ8rLy2EyJfZmhp24OXz4MKqqqgZ6GQRBEARB9IADBw6gsrIy4T7DTtzk5uYCkN4cj8czwKshCIIgCCIVOjo6UFVVJT/HEzHsxA0LRXk8HhI3BEEQBDHESCWlhBKKCYIgCILIKkjcEARBEASRVZC4IQiCIAgiqyBxQxAEQRBEVkHihiAIgiCIrILEDUEQBEEQWQWJG4IgCIIgsgoSNwRBEARBZBUkbgiCIAiCyCpI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\n"},"metadata":{}}],"source":["# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Train Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"hhx12ZJP0eF7"},"source":["## 2.2 Evaluate the Network on the testset"]},{"cell_type":"code","execution_count":29,"metadata":{"id":"BTjjGQHuhQ7i","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539115375,"user_tz":480,"elapsed":9349,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"6becfb70-8d44-4333-aec8-4ada1307d0d6"},"outputs":[{"output_type":"stream","name":"stdout","text":["Accuracy: 42.97%\n","\n","Accuracy: 40.62%\n","\n","Accuracy: 40.62%\n","\n"]},{"output_type":"execute_result","data":{"text/plain":["Sequential(\n"," (0): Conv2d(2, 32, kernel_size=(4, 4), stride=(1, 1))\n"," (1): Leaky()\n"," (2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))\n"," (3): Leaky()\n"," (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n"," (5): Flatten(start_dim=1, end_dim=-1)\n"," (6): Linear(in_features=256, out_features=10, bias=True)\n"," (7): Leaky()\n",")"]},"metadata":{},"execution_count":29}],"source":["# Make sure your model is in evaluation mode\n","scnn_net.eval()\n","\n","# Initialize variables to store predictions and ground truth labels\n","acc_hist = []\n","\n","# Iterate over batches in the testloader\n","with torch.no_grad():\n"," for data, targets in testloader:\n"," # Move data and targets to the device (GPU or CPU)\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," # Forward pass\n"," spk_rec = forward_pass(scnn_net, data)\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," # if i%10 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# Reset your model to training mode if needed\n","scnn_net.train()\n"]},{"cell_type":"markdown","source":["# 2.2.1 Calculate and print the average testset accuracy"],"metadata":{"id":"AqyOIw89IZdw"}},{"cell_type":"code","execution_count":30,"metadata":{"id":"0AyNWaIts16X","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539115376,"user_tz":480,"elapsed":13,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"944d2258-d09a-4ed6-ea9e-9a5683fffe40"},"outputs":[{"output_type":"stream","name":"stdout","text":["The average loss across the testloader is: 0.4140625\n"]}],"source":["print(\"The average loss across the testloader is:\", statistics.mean(acc_hist))"]},{"cell_type":"markdown","metadata":{"id":"1a-oeEzK0Xvt"},"source":["## 2.3 Visualize Spike Recordings\n","\n","The following visual takes ~10 minutes to create. This visual is a spike count histogram that shows the spikes counts for a single target and single piece of data using the spike recording list. Essentially if the target label is 1 than the label with the most spikes should be 1 given the neural network identifies the data as 1 correctly."]},{"cell_type":"code","execution_count":31,"metadata":{"id":"ZJArj6jlXBEs","executionInfo":{"status":"ok","timestamp":1702539119080,"user_tz":480,"elapsed":3715,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["spk_rec = forward_pass(scnn_net, data)"]},{"cell_type":"code","execution_count":32,"metadata":{"id":"tJSBM-ctXETI","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702539598183,"user_tz":480,"elapsed":479115,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"7f041155-780a-4346-bbfd-bcd3f505240c"},"outputs":[{"output_type":"stream","name":"stdout","text":["The target label is: 3\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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\n"},"metadata":{}}],"source":["from IPython.display import HTML\n","\n","start_time = time.time()\n","\n","idx = 0\n","\n","fig, ax = plt.subplots(facecolor='w', figsize=(12, 7))\n","labels=['0', '1', '2', '3', '4', '5', '6', '7', '8','9']\n","print(f\"The target label is: {targets[idx]}\")\n","\n","# Plot spike count histogram\n","anim = splt.spike_count(spk_rec[:, idx].detach().cpu(), fig, ax, labels=labels,\n"," animate=True, interpolate=1)\n","\n","display(HTML(anim.to_html5_video()))\n","# anim.save(\"spike_bar.mp4\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)"]},{"cell_type":"code","execution_count":33,"metadata":{"id":"ssI8LLReFGY-","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539598183,"user_tz":480,"elapsed":7,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"9a8bda1e-2c4b-4cb6-d14a-29ab45f425fe"},"outputs":[{"output_type":"stream","name":"stdout","text":["Elapsed time: 7 minutes, 58 seconds, 538 milliseconds\n"]}],"source":["# Print the result\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]}],"metadata":{"colab":{"provenance":[{"file_id":"17lDMQYpEjA_oD-VmIG__qTlv1EdV9tjY","timestamp":1701726922112},{"file_id":"1j8MtYqWS5jQABVHORXeC9DR-DEX9tAmd","timestamp":1701120116694},{"file_id":"1Yy7yVKCye-TEzyVYB8217Au-DTzMzpKY","timestamp":1698117894739}],"gpuType":"T4"},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"name":"python"},"widgets":{"application/vnd.jupyter.widget-state+json":{"b9415441caa94336b3419889cb5c5fc8":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_c5510f1d3b4f440ea0ead2601e0b0550","max":640,"min":0,"orientation":"horizontal","style":"IPY_MODEL_92c8f35c46834aacacb25460c5ba338b","value":640}},"c5510f1d3b4f440ea0ead2601e0b0550":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"92c8f35c46834aacacb25460c5ba338b":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"1af14dcea1524a3ca16d74e948aaf62b":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_6da1b1c1ba0e4eaab9d9a292b2daa486","max":320,"min":0,"orientation":"horizontal","style":"IPY_MODEL_e7af9d3e054e49c4a3d0e3dc3fa660cf","value":320}},"6da1b1c1ba0e4eaab9d9a292b2daa486":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"e7af9d3e054e49c4a3d0e3dc3fa660cf":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}}}},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0} \ No newline at end of file From 28c2d0ca05a9a2da287fbd604d43176faad7fc74 Mon Sep 17 00:00:00 2001 From: jeshraghian Date: Fri, 8 Mar 2024 15:36:09 -0800 Subject: [PATCH 12/13] update stmnist ipynb tutorial --- ...T_Tutorial_with_snnTorch_and_Tonic-2.ipynb | 1 - ...IST_Tutorial_with_snnTorch_and_Tonic.ipynb | 1 - examples/stmnist_snntorch.ipynb | 4496 +++++++++++++++++ 3 files changed, 4496 insertions(+), 2 deletions(-) delete mode 100644 examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb delete mode 100644 examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb create mode 100644 examples/stmnist_snntorch.ipynb diff --git a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb deleted file mode 100644 index 4d923f77..00000000 --- a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic-2.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"cells":[{"cell_type":"markdown","metadata":{"id":"0PD5VPOUr4bs"},"source":["[](https://github.com/jeshraghian/snntorch/)\n","[](https://github.com/neuromorphs/tonic/)\n","\n","\n","# Training on ST-MNIST with Tonic + snnTorch Tutorial\n","\n","##### By:\n","#### Dylan Louie (djlouie@ucsc.edu),\n","#### Hannah Cohen Sandler (hcohensa@ucsc.edu),\n","#### Shatoparba Banerjee (sbaner12@ucsc.edu)\n","##### Credits to our Professor: Jason K. Eshraghian (www.ncg.ucsc.edu)\n","\n","\n"," \"Open\n",""]},{"cell_type":"markdown","metadata":{"id":"iawcPZ7DtDqK"},"source":["For a comprehensive overview on how SNNs work, and what is going on under the hood, [then you might be interested in the snnTorch tutorial series available here.](https://snntorch.readthedocs.io/en/latest/tutorials/index.html)\n","The snnTorch tutorial series is based on the following paper. If you find these resources or code useful in your work, please consider citing the following source:\n","\n","> [Jason K. Eshraghian, Max Ward, Emre Neftci, Xinxin Wang, Gregor Lenz, Girish Dwivedi, Mohammed Bennamoun, Doo Seok Jeong, and Wei D. Lu. \"Training Spiking Neural Networks Using Lessons From Deep Learning\". Proceedings of the IEEE, 111(9) September 2023.](https://ieeexplore.ieee.org/abstract/document/10242251) "]},{"cell_type":"code","execution_count":1,"metadata":{"id":"W-v36rDBv41L","executionInfo":{"status":"ok","timestamp":1702537684903,"user_tz":480,"elapsed":20885,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["!pip install tonic --quiet\n","!pip install snntorch --quiet"]},{"cell_type":"code","execution_count":2,"metadata":{"id":"6WWIF2I1v7sA","executionInfo":{"status":"ok","timestamp":1702537694860,"user_tz":480,"elapsed":9960,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["import tonic\n","import tonic.transforms as transforms # Not to be mistaken with torchdata.transfroms\n","from tonic import DiskCachedDataset\n","import torch\n","from torch.utils.data import random_split\n","from torch.utils.data import DataLoader\n","import torchvision\n","import torch.nn as nn\n","import snntorch as snn\n","from snntorch import surrogate\n","import snntorch.spikeplot as splt\n","from snntorch import functional as SF\n","from snntorch import utils\n","import matplotlib.pyplot as plt\n","from IPython.display import HTML\n","from IPython.display import display\n","import numpy as np\n","import torchdata\n","import os\n","from ipywidgets import IntProgress\n","import time\n","import statistics"]},{"cell_type":"markdown","metadata":{"id":"McXriEu-tJV6"},"source":["# 1. STMNIST"]},{"cell_type":"markdown","metadata":{"id":"wsV-uUeZ6a2A"},"source":["## 1.1 A Description\n","\n","The Spiking Tactile-MNIST (ST-MNIST) dataset is a novel neuromorphic collection featuring handwritten digits (0-9) inscribed by 23 individuals on a 100-taxel biomimetic event-based tactile sensor array. This dataset, publicly available to facilitate research in tactile perception, captures the dynamic pressure changes associated with natural writing. The tactile sensing system, Asynchronously Coded Electronic Skin (ACES), emulates the human peripheral nervous system, transmitting fast-adapting (FA) responses as asynchronous electrical events.\n","\n","More information about the ST-MNIST dataset can found by the paper written by its authors:\n","\n","> H. H. See, B. Lim, S. Li, H. Yao, W. Cheng, H. Soh, and B. C. K. Tee, \"ST-MNIST - The Spiking Tactile-MNIST Neuromorphic Dataset,\" A PREPRINT, May 2020. [Online]. Available: https://arxiv.org/abs/2005.04319 \n","\n"]},{"cell_type":"markdown","metadata":{"id":"Ickp0FA4_nBR"},"source":["## 1.2 Download the STMNIST dataset\n","\n","The data of ST-MNIST is provided with the MAT format. We are working in Python, so we need a way to import that MAT data into Python. Luckily, Tonic has created a function that creates an IterDataPipe that reads out and transforms the data into an (x, y, t, p) format when provided a path to it. (More down below)\n","\n","The first thing you must do is download the compressed dataset by accessing: https://scholarbank.nus.edu.sg/bitstream/10635/168106/2/STMNIST%20dataset%20NUS%20Tee%20Research%20Group.zip\n","\n","The zip file that you download will be titled `STMNIST dataset NUS Tee Research Group`. You must create a folder/directory titled `STMNIST` and then put that zip file in the folder/directory. This will be necessary for the Tonic class we use later.\n","\n","You then must either put it somewhere you can provide a path to it on your local machine or your Google Drive. For the purposes of this tutorial we will assume Google Drive."]},{"cell_type":"markdown","metadata":{"id":"DnDx0axoCphC"},"source":["## 1.3 Mount to Drive\n","Assuming you now have the `STMNIST` directory containing the zip file somewhere in your Google Drive. We must now \"mount\" Google Drive to this notebook so that it can access it. This is done with the code below:"]},{"cell_type":"code","execution_count":3,"metadata":{"id":"c2PcG-B3v9K8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":1243,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"07c02c45-7db1-42d9-ce97-34fb8831b7d4"},"outputs":[{"output_type":"stream","name":"stdout","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"]}],"source":["# Load the Drive helper and mount\n","from google.colab import drive\n","\n","# This will prompt for authorization.\n","drive.mount('/content/drive')"]},{"cell_type":"code","execution_count":4,"metadata":{"id":"00hHZOeuv-8k","executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":5,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# After executing the cell above, Drive files will be present in \"/content/drive/My Drive\".\n","# Here is the path to the file in our drive, change it to where it is in yours\n","root = \"/content/drive/My Drive/STMNIST_Tutorial\" # similar to os.path.join('drive', 'My Drive', 'Finalized_STMNIST')"]},{"cell_type":"markdown","source":["The following cell blocks is to make sure you edited the above path correctly. If you get a `FileNotFoundError: [Errno 2] No such file or directory:` error or a `ls: cannot access '/content/drive/My Drive/the/path/you/put/in': No such file or directory` error that means you didn't edit the above path correctly and you are pathing to a directory that doesn't exist. Furthermore make sure that the directory STMNIST (which you made and has your zip file is in) is in the directory you are pathing to."],"metadata":{"id":"1434lW43N5aR"}},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 1\n","os.listdir(root) # same as os.listdir(\"/content/drive/My Drive/STMNIST_Tutorial\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2FqIu1QaHPi4","executionInfo":{"status":"ok","timestamp":1702537696100,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"f99d55f8-7ea4-4fe8-c8b5-d323576351df"},"execution_count":5,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['STMNIST', 'ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb']"]},"metadata":{},"execution_count":5}]},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 2\n","!ls \"/content/drive/My Drive/STMNIST_Tutorial\""],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ynCJsU_HHOxV","executionInfo":{"status":"ok","timestamp":1702537696267,"user_tz":480,"elapsed":170,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8c9b957d-adf5-4765-bc67-d743371a98df"},"execution_count":6,"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb\n"]}]},{"cell_type":"markdown","metadata":{"id":"OOfqmhKcIOR0"},"source":["## 1.4 ST-MNIST through Tonic\n","\n","1. List item\n","2. List item\n","\n","\n","Now we call the `tonic` function to create the class that returns a IterDataPipe of the dataset. The docs for that function can be found here: https://tonic.readthedocs.io/en/latest/generated/tonic.prototype.datasets.STMNIST.html#tonic.prototype.datasets.STMNIST"]},{"cell_type":"code","execution_count":7,"metadata":{"id":"4r9zaUjHwAcM","executionInfo":{"status":"ok","timestamp":1702537696525,"user_tz":480,"elapsed":260,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["dataset = tonic.prototype.datasets.STMNIST(root=root,\n"," keep_compressed = False, shuffle = False)"]},{"cell_type":"markdown","metadata":{"id":"AgwoqxsAMdqP"},"source":["Because the dataset is an IterDataPipe, it can not be indexed into. Instead, we use `next(iter())` in order to iterate through it.\n","\n","In the above code `dataset` has been set to the returned DataPipe, so now I will just refer to `dataset`. Tonic formats the STMNIST dataset into an `(x, y, t, p)` format just like its other datasets so that the data will be compatable with other parts of its library. Where `x` is the position on the x-axis, `y` is the position on the y-axis, `t` is a timestamp, and `p` is polarity (1 or 0).\n","\n","Each iteration of dataset returns a tuple. The first index of the tuple contains a numpy array of `(x, y, t, p)` tuples which represents a series of sparse matrix through time of the recordings on the tactile sensor. The second index is a integer 0-9 which is the \"label\" of the data representing what number the afformentioned events is a drawing of."]},{"cell_type":"code","execution_count":8,"metadata":{"id":"2nRzg5A0RegL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696746,"user_tz":480,"elapsed":223,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"05222d60-e5a0-4e54-8ca4-3244e3a78631"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","1115\n","(7, 8, 200257, 1)\n","6\n"]}],"source":["print(type(dataset))\n","events, target = next(iter(dataset))\n","print(type(events))\n","print(len(events))\n","print(events[0])\n","print(target)"]},{"cell_type":"markdown","metadata":{"id":"7mWT1BXPdeuM"},"source":["Now that the data is out of the MAT file and into the (x,y,t,p) format we now need it to be in a form that our neural network can read. Luckily Tonic has transformations that do that for us as its other datasets use the (x,y,t,p) format. When you run the code below, the `.ToFrame()` function from `tonic.transforms` changes it from an (x,y,t,p) format to a numpy array matrix."]},{"cell_type":"code","execution_count":9,"metadata":{"id":"Alt1gJkWSqjy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537696746,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"12fec926-75d5-4b5b-c2cb-63eabfc8b9d2"},"outputs":[{"output_type":"stream","name":"stdout","text":["----------------------------\n","\n","----------------------------\n","644\n","----------------------------\n","\n","----------------------------\n","2\n","----------------------------\n","[[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","\n"," [[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [2 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[0 0 0 0 0 0 0 0 0 0]\n","----------------------------\n","\n","----------------------------\n","0\n"]}],"source":["sensor_size = tuple(tonic.prototype.datasets.STMNIST.sensor_size.values()) # The sensor size for STMNIST is (10, 10, 2) btw\n","# transforms is the same as tonic.transforms check the imports above if you want to make sure\n","frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=sensor_size,\n"," time_window=1000)\n"," ])\n","\n","copy_events = frame_transform(events)\n","print('----------------------------')\n","print(type(copy_events))\n","print('----------------------------')\n","print(len(copy_events))\n","print('----------------------------')\n","print(type(copy_events[0]))\n","print('----------------------------')\n","print(len(copy_events[0]))\n","print('----------------------------')\n","print(copy_events[0])\n","print('----------------------------')\n","print(type(copy_events[0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0]))\n","print('----------------------------')\n","print(copy_events[0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0][0])"]},{"cell_type":"markdown","metadata":{"id":"AbRLjFPEqf6M"},"source":["### 1.4.1 The advantages of ST-MNIST over N-MNIST\n","At the time of release, the closest neuromorphic dataset to ST-MNIST was the N-MNIST dataset which used a moving motion-sensing event-based camera on static images of the original MNIST set (non-temporal 2-d digit classification) to simulate movement. What makes the ST-MNIST dataset better is that the dataset is actually taken from people writing on 10 by 10 tactile pixel sensors. That means when a neural network learns from a dataset it actually has to look at it temporally rather than purely spatially. In N-MNIST every frame would have the digit fully shown, however, for ST-MNIST it only shows parts of it as the participants write over it. That means that as a neuromorphic dataset taking advantage of the spiking and temporal benefits of a SNN ST-MNIST is better than N-MNIST.\n"]},{"cell_type":"markdown","metadata":{"id":"l3CJDa1LnUzd"},"source":["Using `tonic.utils.plot_animation`, the frame transform, and also some rotation. We can create an animation of the data and visualize this."]},{"cell_type":"code","execution_count":10,"metadata":{"id":"kOFkuUfrplsg","executionInfo":{"status":"ok","timestamp":1702537697615,"user_tz":480,"elapsed":871,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Iterate to a new iteration\n","events, target = next(iter(dataset))"]},{"cell_type":"code","execution_count":11,"metadata":{"id":"maDf7TLHmUiw","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702537697616,"user_tz":480,"elapsed":10,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"83ea920e-1d1a-4eff-dc13-6a5022084fec"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 7\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAG40lEQVR4nO3cIW5UURiGYS6ZoKrKAhrELAAMiwDBJhAo1oIBwTrYQ7uGGqpwVfUHTTLT3DDv9Ewnz6OP+HLNm9/cZYwxXgDAgV7OHgDAeRAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQ2Kx9uCzLMXcAcMLW/FTFhQJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQ2swfAP7bvZy/Y7fZm9oJn6OvsAY/4NnvAWXKhAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILGMMcaqh8ty7C0AT+Pq5+wFu919nr1grzWpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJzewBwJl6+2n2gv3+3M1ecJZcKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEhsZg8AztXr2QP2e/d99oLdrmcPOIwLBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASGxmD4Bn4eJy9oL9Hu5nL9jt7mL2gv1ebWcv2ONm9oCDuFAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQWMYYY9XDZTn2FjhdF5ezF+z3cD97wW5XJ/zN7k70m52wNalwoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAIlljDFWPVyWY28BeBpf3s9esNuPm9kL9lqTChcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEssYY6x6+PvXsbf8nzcfZy8AOHtrUuFCASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEpvVL68/HHHGAS5nD3jE/ewBz9B2O3vBbre3sxfAyXOhAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILGMMcbsEQA8fy4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEn8BHHxC+cFz7O0AAAAASUVORK5CYII=\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":11}],"source":["frame_transform_tonic_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=90000,\n",")\n","\n","frames = frame_transform_tonic_visual(events)\n","frames = frames / np.max(frames)\n","frames = np.rot90(frames, k=-1, axes=(2, 3))\n","frames = np.flip(frames, axis=3)\n","\n","# Print out the Target\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","animation = tonic.utils.plot_animation(frames)\n","\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"w52aUd2qoyXV"},"source":["We can also use `snntorch.spikeplot`"]},{"cell_type":"code","execution_count":12,"metadata":{"id":"bPwRVZgqo8EH","colab":{"base_uri":"https://localhost:8080/","height":926},"executionInfo":{"status":"ok","timestamp":1702537699047,"user_tz":480,"elapsed":1437,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"79316d31-e2e6-4ad8-edd2-bcc3808cfd66"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 7\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n"},"metadata":{}}],"source":["frame_transform_snntorch_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=8000,\n",")\n","\n","tran = frame_transform_snntorch_visual(events)\n","tran = np.rot90(tran, k=-1, axes=(2, 3))\n","tran = np.flip(tran, axis=3)\n","tran = torch.from_numpy(tran)\n","\n","tensor1 = tran[:, 0:1, :, :]\n","tensor2 = tran[:, 1:2, :, :]\n","\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","\n","fig, ax = plt.subplots()\n","time_steps = tensor1.size(0)\n","tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n","anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n","\n","display(HTML(anim.to_html5_video()))"]},{"cell_type":"code","execution_count":13,"metadata":{"id":"F5eZvTHHr5qS","executionInfo":{"status":"ok","timestamp":1702537699247,"user_tz":480,"elapsed":202,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_sensor_size = tonic.datasets.NMNIST.sensor_size\n","nmnist_frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=nmnist_sensor_size,\n"," time_window=3000)\n"," ])\n","\n","nmnist_dataset = tonic.datasets.NMNIST(save_to='./tmp/nmnist_example_data', transform=nmnist_frame_transform, train=False)"]},{"cell_type":"code","execution_count":14,"metadata":{"id":"Tz3HlO9zsdls","executionInfo":{"status":"ok","timestamp":1702537699248,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_events, nmnist_target = nmnist_dataset[0]"]},{"cell_type":"code","execution_count":15,"metadata":{"id":"pe47llhqu00o","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":9050,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"5560d6c9-9f25-4e4c-abe9-48f03cdcd4b8"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of N-MNIST\n","The target label is: 8\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGe0lEQVR4nO3cMY4bMRAAQdPYL+qVeuTcBwzfLtw8rayqeIIBk8YkXDMzvwDgH/1+9QIA/B8EBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJI6zg2utnXsAcGNnPlVxoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AcBePC7PPbVvwvlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMSamTk1uNbuXQC4qTOpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAInj1QsAFzwuzj+3bAF/5EIBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJNbMzKnBtXbvAtSufNXimxb+4kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhK9XAPiWr1cA+DGCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkjlcvALyhx8X555YtuBkXCgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASCxZmZODa61excAbupMKlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AsNHjwuxz2xZ8CBcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7FwBu6kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQOF69wEd4XJx/btniM1x5a+8MKRcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7F+5m1zcmvqKBt3MmFS4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQMLXKwB8y9crAPwYQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMRxdnBmdu4BwJtzoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJD4AihVRw5/WD3pAAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":15}],"source":["# Print out the Target\n","print('Animation of N-MNIST')\n","print('The target label is:',nmnist_target)\n","# normalize values to between 0-1\n","nmnist_events_fraction = nmnist_events / np.max(nmnist_events)\n","animation = tonic.utils.plot_animation(nmnist_events_fraction)\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"92McQkLgd_xI"},"source":["A printout of the sensor size of the ST-MNIST and N-MNIST dataset. (10, 10, 2) menas a 10 by 10 pixel dataset with a channel size of 2. (34, 34, 2) means a 34 by 34 pixel dataset with a channel size of 2."]},{"cell_type":"code","execution_count":16,"metadata":{"id":"mou11FujsL-v","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":21,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"2f78c469-6ea2-463c-b0b7-71f1adb5bc64"},"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST {'x': 10, 'y': 10, 'p': 2}\n","NMNIST (34, 34, 2)\n"]}],"source":["print('STMNIST', tonic.prototype.datasets.STMNIST.sensor_size)\n","print('NMNIST', tonic.datasets.NMNIST.sensor_size)"]},{"cell_type":"markdown","metadata":{"id":"CzYgPlxWfdm_"},"source":["There is a total of 6953 recordings in this dataset. This lines up with what is said in the ST-MNIST paper. They invited in 23 participants to write around 30 times each for 9 digits."]},{"cell_type":"code","execution_count":17,"metadata":{"id":"_v1auSbyepQr","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":18,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"7708b995-4238-4421-98b2-c99ee1811789"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n"]}],"source":["print(len(dataset)) # 23 participants writing around 30 times each for 9 digits 23*30*9 = 6210"]},{"cell_type":"markdown","metadata":{"id":"tlX9jWV0f_az"},"source":["## 1.5 Lets create a trainset and testset!"]},{"cell_type":"markdown","metadata":{"id":"hqQzVEHEgSFp"},"source":["Unfortunately unlike N-MNIST, ST-MNIST isn't already seperated into a trainset and testset on tonic. That means we will have to seperate that manually. For this example you could do 80% of the dataset for the trainset and 20% for the testset which we calculate below."]},{"cell_type":"code","execution_count":18,"metadata":{"id":"ZXw_xyfetX_K","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":17,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"97dca7f1-2132-4d40-ad35-5257fd6bf9c7"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n","5562\n","1391\n"]}],"source":["# Calculate the sizes for the training and testing sets\n","total_size = len(dataset)\n","print(total_size)\n","# train_size is 80% of total size\n","train_size = int(0.8 * total_size)\n","print(train_size)\n","test_size = total_size - train_size\n","print(test_size)"]},{"cell_type":"code","execution_count":19,"metadata":{"id":"d_6BFKiXJdWU","executionInfo":{"status":"ok","timestamp":1702537708295,"user_tz":480,"elapsed":16,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["sensor_size = tonic.prototype.datasets.STMNIST.sensor_size\n","sensor_size = tuple(sensor_size.values())\n","\n","# Define a transform\n","frame_transform = transforms.Compose([transforms.ToFrame(sensor_size=sensor_size, time_window=1000)])"]},{"cell_type":"markdown","metadata":{"id":"iSMhDsHliQk5"},"source":["The following code reads out the entirety of the dataset from the IterDataPipe and then transforms the events using the `frame_transform` above. It also seperates out the data into a trainset and a testset. Remember that each time a piece of data is read out of the datapipe it is read and transformed from the MAT files using tonic. On top of that we are to the .ToFrame() transform over it each time. Thus, this takes some time.\n","\n","**You have two options here:**\n","\n","Transform and tain on a small part of the dataset, this is faster and is the default for the sake of a short easy to run tutorial. The default for this shorter transform is 640 pieces of data for the trainset and 320 pieces of data for the testset. This takes ~4-5 minutes. Feel free to change this, just be aware that the number of pieces of data we transform and the time it takes have an inverse relationship.\n","\n","**Or** you can transform and convert the entire dataset; this takes ~30-60 minutes. To do that comment out the `shorter_transform_STMNIST` cell block and uncomment the `full_transform_STMNIST` cell block and run that instead. If you choose this: kickback, take a break and eat a snack while this happens. perhaps even count kangaroos to take a nap or do a shoey and get schwasted instead.\n","\n","Note: A smaller dataset generally means a higher accuracy but less generalizability on new data when training a neural network on it given the same amount of time."]},{"cell_type":"code","source":["def shorter_transform_STMNIST(data, transform):\n"," short_train_size = 640\n"," short_test_size = 320\n","\n"," train_bar = IntProgress(min=0, max=short_train_size)\n"," test_bar = IntProgress(min=0, max=short_test_size)\n","\n"," testset = []\n"," trainset = []\n","\n"," print('Porting over and transforming the trainset.')\n"," display(train_bar)\n"," for _ in range(short_train_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," trainset.append((events, target))\n"," train_bar.value += 1\n"," print('Porting over and transforming the testset.')\n"," display(test_bar)\n"," for _ in range(short_test_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," testset.append((events, target))\n"," test_bar.value += 1\n","\n"," return (trainset, testset)\n","\n","# Get the start time\n","start_time = time.time()\n","\n","# Call the function\n","trainset, testset = shorter_transform_STMNIST(dataset, frame_transform)\n","\n","# Get the end time\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":135,"referenced_widgets":["b9415441caa94336b3419889cb5c5fc8","c5510f1d3b4f440ea0ead2601e0b0550","92c8f35c46834aacacb25460c5ba338b","1af14dcea1524a3ca16d74e948aaf62b","6da1b1c1ba0e4eaab9d9a292b2daa486","e7af9d3e054e49c4a3d0e3dc3fa660cf"]},"id":"c0qw8uduLpZv","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":186720,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"518ee215-d2b2-4432-9666-5968aa5e40ac"},"execution_count":20,"outputs":[{"output_type":"stream","name":"stdout","text":["Porting over and transforming the trainset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=640)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"b9415441caa94336b3419889cb5c5fc8"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Porting over and transforming the testset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=320)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"1af14dcea1524a3ca16d74e948aaf62b"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Elapsed time: 3 minutes, 6 seconds, 970 milliseconds\n"]}]},{"cell_type":"code","execution_count":21,"metadata":{"id":"muL3A2dbMYTY","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":12,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# def full_transform_STMNIST(data, transform):\n","# train_bar = IntProgress(min=0, max=train_size)\n","# test_bar = IntProgress(min=0, max=test_size)\n","\n","# testset = []\n","# trainset = []\n","\n","# print('Porting over and transforming the trainset.')\n","# display(train_bar)\n","# for _ in range(train_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# trainset.append((events, target))\n","# train_bar.value += 1\n","# print('Porting over and transforming the testset.')\n","# display(test_bar)\n","# for _ in range(test_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# testset.append((events, target))\n","# test_bar.value += 1\n","\n","# return (trainset, testset)\n","\n","# # Get the start time\n","# start_time = time.time()\n","\n","# # Call the function\n","# trainset, testset = full_transform_STMNIST(dataset, frame_transform)\n","\n","# # Get the end time\n","# end_time = time.time()\n","\n","# # Calculate elapsed time\n","# elapsed_time = end_time - start_time\n","\n","# # Convert elapsed time to minutes, seconds, and milliseconds\n","# minutes, seconds = divmod(elapsed_time, 60)\n","# seconds, milliseconds = divmod(seconds, 1)\n","# milliseconds = round(milliseconds * 1000)\n","\n","# # Print the elapsed time\n","# print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"98VVH_HSs-Gh"},"source":["## 1.6 Dataloading and Batching\n","\n","The reason why we needed to move the data into a list instead of just using the datapipe and transforming as we moved out of it was so that we could use the DataLoader function from torch that requires an indexable class, array, etc."]},{"cell_type":"code","execution_count":22,"metadata":{"id":"DPxzp1fdFe_X","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Create a DataLoader\n","dataloader = DataLoader(trainset, batch_size=64, shuffle=True)"]},{"cell_type":"markdown","metadata":{"id":"yORjaoQAuuY1"},"source":["To make our dataloading even faster we can use DiskCashedDataset from tonic which makes use of disk chaching and batching. In addition we can add an additional transformation that will change the data from numpy to a torch tensor.\n","\n","Due to variations in the lengths of event recordings, we will introduce a collation function called `tonic.collation.PadTensors()`. This function will be responsible for padding shorter recordings, ensuring uniform dimensions across all samples in a batch."]},{"cell_type":"code","execution_count":23,"metadata":{"id":"YaPsfB0ArUgQ","executionInfo":{"status":"ok","timestamp":1702537894999,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["transform = tonic.transforms.Compose([torch.from_numpy])\n","\n","cached_trainset = DiskCachedDataset(trainset, transform=transform, cache_path='./cache/stmnist/train')\n","\n","# no augmentations for the testset\n","cached_testset = DiskCachedDataset(testset, cache_path='./cache/stmnist/test')\n","\n","batch_size = 128\n","trainloader = DataLoader(cached_trainset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False), shuffle=True)\n","testloader = DataLoader(cached_testset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False))"]},{"cell_type":"markdown","metadata":{"id":"_i-s-FRuwGBR"},"source":["Here are the shapes of the data and target tensors of a single iteration of the trainloader printed below."]},{"cell_type":"code","execution_count":24,"metadata":{"id":"0so65S95BDbf","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702537896173,"user_tz":480,"elapsed":1176,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"d06a3767-4ab1-4662-8154-c7d02124bebd"},"outputs":[{"output_type":"stream","name":"stdout","text":["5\n","torch.Size([1993, 128, 2, 10, 10])\n","torch.Size([128, 2, 10, 10])\n","torch.Size([128])\n","tensor([8, 0, 0, 8, 1, 0, 4, 1, 2, 3, 2, 3, 9, 6, 7, 8, 3, 1, 3, 9, 3, 7, 7, 6,\n"," 3, 0, 7, 6, 6, 2, 9, 1, 2, 2, 5, 1, 6, 9, 4, 5, 7, 4, 6, 1, 3, 0, 0, 5,\n"," 5, 1, 5, 4, 7, 8, 2, 7, 2, 9, 5, 6, 2, 4, 9, 0, 8, 4, 4, 7, 5, 6, 0, 5,\n"," 2, 4, 9, 1, 2, 4, 2, 7, 7, 0, 8, 4, 1, 3, 4, 5, 4, 7, 9, 2, 9, 1, 8, 6,\n"," 7, 3, 2, 3, 9, 8, 1, 9, 1, 8, 2, 1, 1, 5, 8, 3, 3, 1, 6, 7, 2, 5, 1, 7,\n"," 7, 9, 4, 0, 8, 2, 4, 1])\n"]}],"source":["data_tensor, targets = next(iter(trainloader))\\\n","# length of trainloader = number of iterations per epoch\n","# For the shorter transform\n","# 640 == length of dataset\n","# 640 / 128 = 5\n","# Remember: Trainset is length 640\n","# So the trainloader should be length 5\n","# For the longer transform\n","# 5562 == length of dataset\n","# 5562 / 128 ~ 43.45\n","# Remember: Trainset is length 5562\n","# So the trainloader should be length 44\n","print(len(trainloader))\n","print(data_tensor.shape)\n","print(data_tensor[0].shape)\n","print(targets.shape)\n","print(targets)"]},{"cell_type":"markdown","metadata":{"id":"QDGPdoBUw-ME"},"source":["## 1.7 Create the Spiking Convolutional Neural Network"]},{"cell_type":"markdown","source":["Below we have by default a spiking convolutional neural network with the architecture: `10×10-32c4-64c3-MaxPool2d(2)-10o`."],"metadata":{"id":"PRdPJemVH8uR"}},{"cell_type":"code","execution_count":25,"metadata":{"id":"W2ewqKLx8mMJ","executionInfo":{"status":"ok","timestamp":1702537901396,"user_tz":480,"elapsed":5224,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n","\n","# neuron and simulation parameters\n","spike_grad = surrogate.atan()\n","beta = 0.95\n","\n","# 10×10-32c4-64c3-MaxPool2d(2)-10o\n","# This is the same architecture that was used in the STMNIST Paper\n","# No Max Pooling as 10x10 is already very small/low detail\n","scnn_net = nn.Sequential(\n"," # 2 x 10 x 10\n"," nn.Conv2d(2, 32, kernel_size=4), # 32 channels, kernel size 4x4\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(10 - 4) + 1] = 7\n","\n"," # 32 x 7 x 7\n"," nn.Conv2d(32, 64, kernel_size=3), # 64 channels, kernel size 3x3\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(7 - 3) + 1] = 5\n","\n"," # 64 x 5 x 5\n"," nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n"," # Output size = [(5-2) / 2] + 1 = 2\n","\n"," # 64 x 2 x 2\n"," nn.Flatten(),\n"," # Output size = 64*2*2 = 256\n","\n"," nn.Linear(64 * 2 * 2, 10), # Increased size of the linear layer\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n",").to(device)\n","\n","# Note: In a CNN the formula for calculating the output of the Conv layer is\n","# Output size = ((Input Size - Kernel Size + 2 * Padding) / Stride ) + 1\n","# Note for a MaxPool layer the formula is\n","# Output size = ((Input size - Kernel Size) / Stride ) + 1\n","\n","optimizer = torch.optim.Adam(scnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"markdown","metadata":{"id":"Sq_jz3xYxMxO"},"source":["## 1.8 Define the Forward Pass"]},{"cell_type":"code","execution_count":26,"metadata":{"id":"ydcyDZDt_qH_","executionInfo":{"status":"ok","timestamp":1702537901397,"user_tz":480,"elapsed":11,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["def forward_pass(net, data):\n"," spk_rec = []\n"," utils.reset(net) # resets hidden states for all LIF neurons in net\n","\n"," for step in range(data.size(0)): # data.size(0) = number of time steps\n","\n"," spk_out, mem_out = net(data[step])\n"," spk_rec.append(spk_out)\n","\n"," return torch.stack(spk_rec)"]},{"cell_type":"markdown","metadata":{"id":"9tPywf6CxWcq"},"source":["## 1.9 Create and Run the Training Loop\n","\n","The current epochs is set to 40 and is intended to be run on the smaller trainset and testset. In the smaller set each epoch has 5 iterations. Doing the math: 5 * 40 is 200 iterations over the 40 epochs. On our runs on the T4 GPU on Colab, 30 epochs on the smaller dataset takes ~25 minutes and achieves ~50% accuracy on the testset and ~50% accuracy on the trainset.\n","\n","For training on the full dataset, we recommend lowering the epochs down to 15. Remember that each epoch has 44 iterations starting at 0. Doing the math: 44 * 15 = 660 iterations over the 15 epochs. Training should once again take some time so feel free to take a break and let your computer run. On our runs with the T4 GPU on Colab 15 epochs takes ~70 min with ~70% accuracy on the full trainset and ~65% accuracy on the full testset.\n","\n","Of course feel free to adjust the epochs to make them longer or shorter if you have more or less time and would like to experiment with how that affects accuracy on the testset and trainset."]},{"cell_type":"code","execution_count":27,"metadata":{"id":"lB9lYUP0AUBL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539105640,"user_tz":480,"elapsed":1204253,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"561fd004-e7ad-4cda-e84d-d326b29b4fb6"},"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 0, Iteration 0 \n","Train Loss: 187.81\n","Accuracy: 7.81%\n","\n","Epoch 0, Iteration 4 \n","Train Loss: 176.25\n","Accuracy: 10.94%\n","\n","Epoch 1, Iteration 0 \n","Train Loss: 157.28\n","Accuracy: 7.81%\n","\n","Epoch 1, Iteration 4 \n","Train Loss: 159.94\n","Accuracy: 14.06%\n","\n","Epoch 2, Iteration 0 \n","Train Loss: 165.89\n","Accuracy: 9.38%\n","\n","Epoch 2, Iteration 4 \n","Train Loss: 159.88\n","Accuracy: 10.94%\n","\n","Epoch 3, Iteration 0 \n","Train Loss: 162.16\n","Accuracy: 10.16%\n","\n","Epoch 3, Iteration 4 \n","Train Loss: 155.06\n","Accuracy: 14.06%\n","\n","Epoch 4, Iteration 0 \n","Train Loss: 149.63\n","Accuracy: 10.16%\n","\n","Epoch 4, Iteration 4 \n","Train Loss: 145.48\n","Accuracy: 11.72%\n","\n","Epoch 5, Iteration 0 \n","Train Loss: 144.21\n","Accuracy: 10.16%\n","\n","Epoch 5, Iteration 4 \n","Train Loss: 82.61\n","Accuracy: 14.06%\n","\n","Epoch 6, Iteration 0 \n","Train Loss: 73.82\n","Accuracy: 13.28%\n","\n","Epoch 6, Iteration 4 \n","Train Loss: 75.70\n","Accuracy: 8.59%\n","\n","Epoch 7, Iteration 0 \n","Train Loss: 77.11\n","Accuracy: 9.38%\n","\n","Epoch 7, Iteration 4 \n","Train Loss: 85.57\n","Accuracy: 10.16%\n","\n","Epoch 8, Iteration 0 \n","Train Loss: 92.13\n","Accuracy: 10.94%\n","\n","Epoch 8, Iteration 4 \n","Train Loss: 120.03\n","Accuracy: 7.81%\n","\n","Epoch 9, Iteration 0 \n","Train Loss: 107.87\n","Accuracy: 12.50%\n","\n","Epoch 9, Iteration 4 \n","Train Loss: 105.17\n","Accuracy: 8.59%\n","\n","Epoch 10, Iteration 0 \n","Train Loss: 107.01\n","Accuracy: 6.25%\n","\n","Epoch 10, Iteration 4 \n","Train Loss: 95.13\n","Accuracy: 3.91%\n","\n","Epoch 11, Iteration 0 \n","Train Loss: 94.15\n","Accuracy: 5.47%\n","\n","Epoch 11, Iteration 4 \n","Train Loss: 80.65\n","Accuracy: 14.84%\n","\n","Epoch 12, Iteration 0 \n","Train Loss: 80.67\n","Accuracy: 18.75%\n","\n","Epoch 12, Iteration 4 \n","Train Loss: 74.08\n","Accuracy: 5.47%\n","\n","Epoch 13, Iteration 0 \n","Train Loss: 72.87\n","Accuracy: 10.16%\n","\n","Epoch 13, Iteration 4 \n","Train Loss: 69.58\n","Accuracy: 14.06%\n","\n","Epoch 14, Iteration 0 \n","Train Loss: 69.41\n","Accuracy: 13.28%\n","\n","Epoch 14, Iteration 4 \n","Train Loss: 70.49\n","Accuracy: 8.59%\n","\n","Epoch 15, Iteration 0 \n","Train Loss: 65.84\n","Accuracy: 16.41%\n","\n","Epoch 15, Iteration 4 \n","Train Loss: 66.85\n","Accuracy: 17.97%\n","\n","Epoch 16, Iteration 0 \n","Train Loss: 64.81\n","Accuracy: 19.53%\n","\n","Epoch 16, Iteration 4 \n","Train Loss: 63.56\n","Accuracy: 17.97%\n","\n","Epoch 17, Iteration 0 \n","Train Loss: 64.15\n","Accuracy: 17.19%\n","\n","Epoch 17, Iteration 4 \n","Train Loss: 64.05\n","Accuracy: 16.41%\n","\n","Epoch 18, Iteration 0 \n","Train Loss: 64.32\n","Accuracy: 21.88%\n","\n","Epoch 18, Iteration 4 \n","Train Loss: 61.53\n","Accuracy: 27.34%\n","\n","Epoch 19, Iteration 0 \n","Train Loss: 61.77\n","Accuracy: 23.44%\n","\n","Epoch 19, Iteration 4 \n","Train Loss: 62.81\n","Accuracy: 19.53%\n","\n","Epoch 20, Iteration 0 \n","Train Loss: 63.38\n","Accuracy: 17.19%\n","\n","Epoch 20, Iteration 4 \n","Train Loss: 61.96\n","Accuracy: 22.66%\n","\n","Epoch 21, Iteration 0 \n","Train Loss: 59.59\n","Accuracy: 29.69%\n","\n","Epoch 21, Iteration 4 \n","Train Loss: 62.97\n","Accuracy: 23.44%\n","\n","Epoch 22, Iteration 0 \n","Train Loss: 60.30\n","Accuracy: 25.78%\n","\n","Epoch 22, Iteration 4 \n","Train Loss: 60.43\n","Accuracy: 31.25%\n","\n","Epoch 23, Iteration 0 \n","Train Loss: 59.96\n","Accuracy: 28.12%\n","\n","Epoch 23, Iteration 4 \n","Train Loss: 60.53\n","Accuracy: 34.38%\n","\n","Epoch 24, Iteration 0 \n","Train Loss: 59.84\n","Accuracy: 34.38%\n","\n","Epoch 24, Iteration 4 \n","Train Loss: 61.22\n","Accuracy: 32.81%\n","\n","Epoch 25, Iteration 0 \n","Train Loss: 58.51\n","Accuracy: 28.91%\n","\n","Epoch 25, Iteration 4 \n","Train Loss: 60.79\n","Accuracy: 29.69%\n","\n","Epoch 26, Iteration 0 \n","Train Loss: 58.33\n","Accuracy: 36.72%\n","\n","Epoch 26, Iteration 4 \n","Train Loss: 59.02\n","Accuracy: 36.72%\n","\n","Epoch 27, Iteration 0 \n","Train Loss: 58.91\n","Accuracy: 29.69%\n","\n","Epoch 27, Iteration 4 \n","Train Loss: 58.19\n","Accuracy: 31.25%\n","\n","Epoch 28, Iteration 0 \n","Train Loss: 56.42\n","Accuracy: 34.38%\n","\n","Epoch 28, Iteration 4 \n","Train Loss: 55.82\n","Accuracy: 41.41%\n","\n","Epoch 29, Iteration 0 \n","Train Loss: 57.21\n","Accuracy: 39.06%\n","\n","Epoch 29, Iteration 4 \n","Train Loss: 57.77\n","Accuracy: 35.16%\n","\n","Epoch 30, Iteration 0 \n","Train Loss: 59.45\n","Accuracy: 32.03%\n","\n","Epoch 30, Iteration 4 \n","Train Loss: 56.68\n","Accuracy: 33.59%\n","\n","Epoch 31, Iteration 0 \n","Train Loss: 57.80\n","Accuracy: 33.59%\n","\n","Epoch 31, Iteration 4 \n","Train Loss: 60.10\n","Accuracy: 31.25%\n","\n","Epoch 32, Iteration 0 \n","Train Loss: 55.65\n","Accuracy: 40.62%\n","\n","Epoch 32, Iteration 4 \n","Train Loss: 57.91\n","Accuracy: 37.50%\n","\n","Epoch 33, Iteration 0 \n","Train Loss: 57.15\n","Accuracy: 39.84%\n","\n","Epoch 33, Iteration 4 \n","Train Loss: 56.07\n","Accuracy: 39.84%\n","\n","Epoch 34, Iteration 0 \n","Train Loss: 54.63\n","Accuracy: 37.50%\n","\n","Epoch 34, Iteration 4 \n","Train Loss: 55.54\n","Accuracy: 45.31%\n","\n","Epoch 35, Iteration 0 \n","Train Loss: 56.43\n","Accuracy: 43.75%\n","\n","Epoch 35, Iteration 4 \n","Train Loss: 54.71\n","Accuracy: 41.41%\n","\n","Epoch 36, Iteration 0 \n","Train Loss: 53.87\n","Accuracy: 38.28%\n","\n","Epoch 36, Iteration 4 \n","Train Loss: 56.83\n","Accuracy: 41.41%\n","\n","Epoch 37, Iteration 0 \n","Train Loss: 55.19\n","Accuracy: 46.09%\n","\n","Epoch 37, Iteration 4 \n","Train Loss: 55.22\n","Accuracy: 43.75%\n","\n","Epoch 38, Iteration 0 \n","Train Loss: 55.57\n","Accuracy: 42.97%\n","\n","Epoch 38, Iteration 4 \n","Train Loss: 55.16\n","Accuracy: 42.97%\n","\n","Epoch 39, Iteration 0 \n","Train Loss: 53.61\n","Accuracy: 47.66%\n","\n","Epoch 39, Iteration 4 \n","Train Loss: 55.44\n","Accuracy: 44.53%\n","\n","Elapsed time: 20 minutes, 4 seconds, 11 milliseconds\n"]}],"source":["start_time = time.time()\n","\n","num_epochs = 40\n","\n","loss_hist = []\n","acc_hist = []\n","\n","# training loop\n","for epoch in range(num_epochs):\n"," for i, (data, targets) in enumerate(iter(trainloader)):\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," scnn_net.train()\n"," spk_rec = forward_pass(scnn_net, data)\n"," loss_val = loss_fn(spk_rec, targets)\n","\n"," # Gradient calculation + weight update\n"," optimizer.zero_grad()\n"," loss_val.backward()\n"," optimizer.step()\n","\n"," # Store loss history for future plotting\n"," loss_hist.append(loss_val.item())\n","\n"," if i%4 == 0:\n"," print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," if i%4 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"cEY6Ynbq0JmX"},"source":["# 2. Results"]},{"cell_type":"markdown","metadata":{"id":"yYSkN_kp0Lm0"},"source":["## 2.1 Plot accuracy history"]},{"cell_type":"code","execution_count":28,"metadata":{"id":"X0SYWQDJ6qhx","colab":{"base_uri":"https://localhost:8080/","height":472},"executionInfo":{"status":"ok","timestamp":1702539106031,"user_tz":480,"elapsed":405,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"1e880dbd-7e37-4910-f41c-b8375e29dd4b"},"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACjyUlEQVR4nO2deZgU5bn27+p9menZZ2B2QAGRVUBEI24oGtw1IvGIEo8mRk40JCd+JMc1OWLUGI0xemLiEnEhJi6JJm4grggKIpugrMM2M8w+093Ta31/VL9Vb1VX9TLTs/U8v+viYqa6lre6mamb+9kEURRFEARBEARBZAmmgV4AQRAEQRBEJiFxQxAEQRBEVkHihiAIgiCIrILEDUEQBEEQWQWJG4IgCIIgsgoSNwRBEARBZBUkbgiCIAiCyCpI3BAEQRAEkVWQuCEIgiAIIqsgcUMQBADg2muvRW1t7UAvgyAIoteQuCGIQY4gCCn9WbNmzUAvNY59+/Zh8eLFGDNmDBwOB0aMGIE5c+bgjjvu6NH5/vWvf+HOO+/s0bEnnngiBEHAY4891qPjCYIYOgg0W4ogBjcrVqxQff+Xv/wF77zzDp599lnV9rPPPhtlZWU9vk4oFEI0GoXdbu/xOXh27dqFmTNnwul04nvf+x5qa2tx5MgRbNy4Ef/+97/R3d2d9jmXLFmCRx99FOn+2vrmm28wduxY1NbWoqKiAh999FHa1yYIYuhgGegFEASRmP/4j/9Qff/pp5/inXfeiduuxefzweVypXwdq9Xao/UZ8dvf/hZdXV3YtGkTampqVK81NjZm9FrJWLFiBUpLS/Gb3/wGl19+Ofbt2zcoQ3DRaBTBYBAOh2Ogl0IQQxoKSxFEFnD66adj4sSJ2LBhA+bMmQOXy4Wf//znAIDXXnsN8+fPR3l5Oex2O8aMGYNf/vKXiEQiqnNoc2727dsHQRDwwAMP4I9//CPGjBkDu92OmTNn4rPPPku6pt27d6OysjJO2ABAaWlp3LZ///vfOPXUU+F2u5Gbm4v58+dj27ZtqvU9+uijANShulR4/vnncfnll+P8889HXl4enn/+ed391q1bh29/+9soKCiA2+3G5MmT8fDDD6v22bFjB6644gqUlJTA6XRi3Lhx+MUvfqFap55wuvPOO+PWKwgClixZgueeew7HH3887HY73nzzTQDAAw88gJNPPhlFRUVwOp2YPn06/va3v+mue8WKFTjxxBPhcrlQUFCAOXPm4O233wYAXHPNNSguLkYoFIo77pxzzsG4ceOM3ziCGKKQuCGILKG5uRnnnXcepk6dioceeghnnHEGAODpp59GTk4Oli5diocffhjTp0/H7bffjv/3//5fSud9/vnncf/99+P73/8+fvWrX2Hfvn249NJLdR+WPDU1NThw4ABWr16d9BrPPvss5s+fj5ycHPz617/Gbbfdhu3bt+Nb3/oW9u3bBwD4/ve/j7PPPlven/1Jxrp167Br1y4sXLgQNpsNl156KZ577rm4/d555x3MmTMH27dvx80334zf/OY3OOOMM/D666/L+2zevBmzZs3C6tWrcf311+Phhx/GxRdfjH/+859J12HE6tWr8eMf/xgLFizAww8/LAujhx9+GNOmTcPdd9+Ne+65BxaLBd/5znfwxhtvqI6/6667cPXVV8NqteLuu+/GXXfdhaqqKvl9v/rqq9Hc3Iy33npLdVx9fT1Wr16d1AEkiCGJSBDEkOKmm24StT+6p512mghAfPzxx+P29/l8cdu+//3viy6XS+zu7pa3XXPNNWJNTY38/d69e0UAYlFRkdjS0iJvf+2110QA4j//+c+E69y6davodDpFAOLUqVPFm2++WXz11VdFr9er2q+zs1PMz88Xr7/+etX2+vp6MS8vT7Vd796TsWTJErGqqkqMRqOiKIri22+/LQIQv/jiC3mfcDgsjho1SqypqRFbW1tVx7PjRFEU58yZI+bm5or79+833Ef7PjLuuOOOuLUDEE0mk7ht27a4/bWfWzAYFCdOnCieeeaZ8rZvvvlGNJlM4iWXXCJGIhHdNUUiEbGyslJcsGCB6vUHH3xQFARB3LNnT9y1CWKoQ84NQWQJdrsdixcvjtvudDrlrzs7O9HU1IRTTz0VPp8PO3bsSHreBQsWoKCgQP7+1FNPBQDs2bMn4XHHH388Nm3ahP/4j//Avn37ZJejrKwMTzzxhLzfO++8g7a2NixcuBBNTU3yH7PZjFmzZuG9995LukYjwuEwVq5ciQULFsghoTPPPBOlpaUq9+aLL77A3r17ccsttyA/P191Dnbc0aNH8cEHH+B73/seqqurdffpCaeddhomTJgQt53/3FpbW9He3o5TTz0VGzdulLe/+uqriEajuP3222EyqX+dszWZTCZcddVV+Mc//oHOzk759eeeew4nn3wyRo0a1eO1E8RghcQNQWQJFRUVsNlscdu3bduGSy65BHl5efB4PCgpKZFDEe3t7UnPq32QM6HT2tqa9NixY8fi2WefRVNTEzZv3iyHV2644Qa8++67AKRKJkASHSUlJao/b7/9dq+Sj99++20cPXoUJ554Inbt2oVdu3Zh7969OOOMM/DCCy8gGo0CkPKDAGDixImG52JiLtE+PcFIXLz++us46aST4HA4UFhYiJKSEjz22GOqz2z37t0wmUy64ohn0aJF8Pv9eOWVVwAAO3fuxIYNG3D11Vdn7kYIYhBB1VIEkSXw/9NntLW14bTTToPH48Hdd98t95vZuHEjbr31Vvnhngiz2ay7XUyjHNtsNmPSpEmYNGkSZs+ejTPOOAPPPfcc5s6dK6/h2WefxYgRI+KOtVh6/muKuTNXXHGF7uvvv/++nJuUKYxcHG0CN0Pvc/vwww9x4YUXYs6cOfjDH/6AkSNHwmq14qmnnjJMhk7EhAkTMH36dKxYsQKLFi3CihUrYLPZDN8XghjqkLghiCxmzZo1aG5uxssvv4w5c+bI2/fu3Ttga5oxYwYA4MiRIwCAMWPGAJAqqObOnZvw2HTCP16vF6+99hoWLFiAyy+/PO71H/3oR3juuedwxhlnyGvYunWr4RpGjx4t75OIgoICtLW1xW3fv39/ymv/+9//DofDgbfeekvVd+ipp55S7TdmzBhEo1Fs374dU6dOTXjORYsWYenSpThy5Aief/55zJ8/XxVuJIhsgsJSBJHFMNeFd1mCwSD+8Ic/9Pm1P/zwQ92Kqn/9618AIJcgz5s3Dx6PB/fcc4/u/kePHpW/drvdAKArHrS88sor8Hq9uOmmm3D55ZfH/Tn//PPx97//HYFAACeccAJGjRqFhx56KO7c7L0rKSnBnDlz8OSTT6Kurk53H0ASHO3t7di8ebO87ciRI3JIKBXMZjMEQVC5Pfv27cOrr76q2u/iiy+GyWTC3XffHefCaZ21hQsXQhAE3HzzzdizZw9VSRFZDTk3BJHFnHzyySgoKMA111yDH/3oRxAEAc8++2zaHX57wq9//Wts2LABl156KSZPngwA2LhxI/7yl7+gsLAQt9xyCwDA4/Hgsccew9VXX40TTjgBV155JUpKSlBXV4c33ngDp5xyCn7/+98DAKZPnw5Acl3mzZsHs9mMK6+8Uvf6zz33HIqKinDyySfrvn7hhRfiiSeewBtvvIFLL70Ujz32GC644AJMnToVixcvxsiRI7Fjxw5s27ZNLqP+3e9+h29961s44YQTcMMNN2DUqFHYt28f3njjDWzatAkAcOWVV+LWW2/FJZdcgh/96Efw+Xx47LHHMHbsWFUycCLmz5+PBx98EOeeey6++93vorGxEY8++iiOOeYYlWg65phj8Itf/AK//OUvceqpp+LSSy+F3W7HZ599hvLycixfvlzet6SkBOeeey5eeukl5OfnY/78+SmthSCGJANZqkUQRPoYlYIff/zxuvt//PHH4kknnSQ6nU6xvLxc/NnPfia+9dZbIgDxvffek/czKgW///77484JQLzjjjsSrvPjjz8Wb7rpJnHixIliXl6eaLVaxerqavHaa68Vd+/eHbf/e++9J86bN0/My8sTHQ6HOGbMGPHaa68VP//8c3mfcDgs/td//ZdYUlIiCoJgWBbe0NAgWiwW8eqrrzZcn8/nE10ul3jJJZfI2z766CPx7LPPFnNzc0W32y1OnjxZfOSRR1THbd26VbzkkkvE/Px80eFwiOPGjRNvu+021T5vv/22OHHiRNFms4njxo0TV6xYYVgKftNNN+mu789//rN47LHHina7XRw/frz41FNP6Z5DFEXxySefFKdNmyba7XaxoKBAPO2008R33nknbr+//vWvIgDxhhtuMHxfCCIboNlSBEEQw4TXXnsNF198MT744AO5pJ8gshESNwRBEMOE888/H1999RV27drVq948BDHYoZwbgiCILOfFF1/E5s2b8cYbb+Dhhx8mYUNkPeTcEARBZDmCICAnJwcLFizA448/3qveQQQxFKB/4QRBEFkO/R+WGG5QnxuCIAiCILIKEjcEQRAEQWQVwy4sFY1GcfjwYeTm5lJSHUEQBEEMEURRRGdnJ8rLy2EyJfZmhp24OXz4MKqqqgZ6GQRBEARB9IADBw6gsrIy4T7DTtzk5uYCkN4cj8czwKshCIIgCCIVOjo6UFVVJT/HEzHsxA0LRXk8HhI3BEEQBDHESCWlhBKKCYIgCILIKkjcEARBEASRVZC4IQiCIAgiqyBxQxAEQRBEVkHihiAIgiCIrILEDUEQBEEQWQWJG4IgCIIgsgoSNwRBEARBZBUkbgiCIAiCyCpI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\n"},"metadata":{}}],"source":["# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Train Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"hhx12ZJP0eF7"},"source":["## 2.2 Evaluate the Network on the testset"]},{"cell_type":"code","execution_count":29,"metadata":{"id":"BTjjGQHuhQ7i","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539115375,"user_tz":480,"elapsed":9349,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"6becfb70-8d44-4333-aec8-4ada1307d0d6"},"outputs":[{"output_type":"stream","name":"stdout","text":["Accuracy: 42.97%\n","\n","Accuracy: 40.62%\n","\n","Accuracy: 40.62%\n","\n"]},{"output_type":"execute_result","data":{"text/plain":["Sequential(\n"," (0): Conv2d(2, 32, kernel_size=(4, 4), stride=(1, 1))\n"," (1): Leaky()\n"," (2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))\n"," (3): Leaky()\n"," (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n"," (5): Flatten(start_dim=1, end_dim=-1)\n"," (6): Linear(in_features=256, out_features=10, bias=True)\n"," (7): Leaky()\n",")"]},"metadata":{},"execution_count":29}],"source":["# Make sure your model is in evaluation mode\n","scnn_net.eval()\n","\n","# Initialize variables to store predictions and ground truth labels\n","acc_hist = []\n","\n","# Iterate over batches in the testloader\n","with torch.no_grad():\n"," for data, targets in testloader:\n"," # Move data and targets to the device (GPU or CPU)\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," # Forward pass\n"," spk_rec = forward_pass(scnn_net, data)\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," # if i%10 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# Reset your model to training mode if needed\n","scnn_net.train()\n"]},{"cell_type":"markdown","source":["# 2.2.1 Calculate and print the average testset accuracy"],"metadata":{"id":"AqyOIw89IZdw"}},{"cell_type":"code","execution_count":30,"metadata":{"id":"0AyNWaIts16X","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539115376,"user_tz":480,"elapsed":13,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"944d2258-d09a-4ed6-ea9e-9a5683fffe40"},"outputs":[{"output_type":"stream","name":"stdout","text":["The average loss across the testloader is: 0.4140625\n"]}],"source":["print(\"The average loss across the testloader is:\", statistics.mean(acc_hist))"]},{"cell_type":"markdown","metadata":{"id":"1a-oeEzK0Xvt"},"source":["## 2.3 Visualize Spike Recordings\n","\n","The following visual takes ~10 minutes to create. This visual is a spike count histogram that shows the spikes counts for a single target and single piece of data using the spike recording list. Essentially if the target label is 1 than the label with the most spikes should be 1 given the neural network identifies the data as 1 correctly."]},{"cell_type":"code","execution_count":31,"metadata":{"id":"ZJArj6jlXBEs","executionInfo":{"status":"ok","timestamp":1702539119080,"user_tz":480,"elapsed":3715,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["spk_rec = forward_pass(scnn_net, data)"]},{"cell_type":"code","execution_count":32,"metadata":{"id":"tJSBM-ctXETI","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702539598183,"user_tz":480,"elapsed":479115,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"7f041155-780a-4346-bbfd-bcd3f505240c"},"outputs":[{"output_type":"stream","name":"stdout","text":["The target label is: 3\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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\n"},"metadata":{}}],"source":["from IPython.display import HTML\n","\n","start_time = time.time()\n","\n","idx = 0\n","\n","fig, ax = plt.subplots(facecolor='w', figsize=(12, 7))\n","labels=['0', '1', '2', '3', '4', '5', '6', '7', '8','9']\n","print(f\"The target label is: {targets[idx]}\")\n","\n","# Plot spike count histogram\n","anim = splt.spike_count(spk_rec[:, idx].detach().cpu(), fig, ax, labels=labels,\n"," animate=True, interpolate=1)\n","\n","display(HTML(anim.to_html5_video()))\n","# anim.save(\"spike_bar.mp4\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)"]},{"cell_type":"code","execution_count":33,"metadata":{"id":"ssI8LLReFGY-","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702539598183,"user_tz":480,"elapsed":7,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"9a8bda1e-2c4b-4cb6-d14a-29ab45f425fe"},"outputs":[{"output_type":"stream","name":"stdout","text":["Elapsed time: 7 minutes, 58 seconds, 538 milliseconds\n"]}],"source":["# Print the result\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]}],"metadata":{"colab":{"provenance":[{"file_id":"17lDMQYpEjA_oD-VmIG__qTlv1EdV9tjY","timestamp":1701726922112},{"file_id":"1j8MtYqWS5jQABVHORXeC9DR-DEX9tAmd","timestamp":1701120116694},{"file_id":"1Yy7yVKCye-TEzyVYB8217Au-DTzMzpKY","timestamp":1698117894739}],"gpuType":"T4"},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"name":"python"},"widgets":{"application/vnd.jupyter.widget-state+json":{"b9415441caa94336b3419889cb5c5fc8":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_c5510f1d3b4f440ea0ead2601e0b0550","max":640,"min":0,"orientation":"horizontal","style":"IPY_MODEL_92c8f35c46834aacacb25460c5ba338b","value":640}},"c5510f1d3b4f440ea0ead2601e0b0550":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"92c8f35c46834aacacb25460c5ba338b":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"1af14dcea1524a3ca16d74e948aaf62b":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_6da1b1c1ba0e4eaab9d9a292b2daa486","max":320,"min":0,"orientation":"horizontal","style":"IPY_MODEL_e7af9d3e054e49c4a3d0e3dc3fa660cf","value":320}},"6da1b1c1ba0e4eaab9d9a292b2daa486":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"e7af9d3e054e49c4a3d0e3dc3fa660cf":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}}}},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb b/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb deleted file mode 100644 index 0f324eac..00000000 --- a/examples/ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"cells":[{"cell_type":"markdown","metadata":{"id":"0PD5VPOUr4bs"},"source":["[](https://github.com/jeshraghian/snntorch/)\n","[](https://github.com/neuromorphs/tonic/)\n","\n","\n","# Training on ST-MNIST with Tonic + snnTorch\n","\n","##### By:\n","#### Dylan Louie (djlouie@ucsc.edu),\n","####Hannah Cohen Sandler (hcohensa@ucsc.edu),\n","####Shatoparba Banerjee (sbaner12@ucsc.edu)\n","##### Credits to our Professor: Jason K. Eshraghian (www.ncg.ucsc.edu)\n","\n","\n"," \"Open\n","\n"]},{"cell_type":"markdown","metadata":{"id":"iawcPZ7DtDqK"},"source":["For a comprehensive overview on how SNNs work, and what is going on under the hood, [then you might be interested in the snnTorch tutorial series available here.](https://snntorch.readthedocs.io/en/latest/tutorials/index.html)\n","The snnTorch tutorial series is based on the following paper. If you find these resources or code useful in your work, please consider citing the following source:\n","\n","> [Jason K. Eshraghian, Max Ward, Emre Neftci, Xinxin Wang, Gregor Lenz, Girish Dwivedi, Mohammed Bennamoun, Doo Seok Jeong, and Wei D. Lu. \"Training Spiking Neural Networks Using Lessons From Deep Learning\". Proceedings of the IEEE, 111(9) September 2023.](https://ieeexplore.ieee.org/abstract/document/10242251) "]},{"cell_type":"code","execution_count":98,"metadata":{"id":"W-v36rDBv41L","executionInfo":{"status":"ok","timestamp":1702496302809,"user_tz":480,"elapsed":12457,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["!pip install tonic --quiet\n","!pip install snntorch --quiet"]},{"cell_type":"code","execution_count":99,"metadata":{"id":"6WWIF2I1v7sA","executionInfo":{"status":"ok","timestamp":1702496302809,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["import tonic\n","import tonic.transforms as transforms # Not to be mistaken with torchdata.transfroms\n","from tonic import DiskCachedDataset\n","import torch\n","from torch.utils.data import random_split\n","from torch.utils.data import DataLoader\n","import torchvision\n","import torch.nn as nn\n","import snntorch as snn\n","from snntorch import surrogate\n","import snntorch.spikeplot as splt\n","from snntorch import functional as SF\n","from snntorch import utils\n","import matplotlib.pyplot as plt\n","from IPython.display import HTML\n","from IPython.display import display\n","import numpy as np\n","import torchdata\n","import os\n","from ipywidgets import IntProgress\n","import time"]},{"cell_type":"markdown","metadata":{"id":"McXriEu-tJV6"},"source":["# 1. STMNIST"]},{"cell_type":"markdown","metadata":{"id":"wsV-uUeZ6a2A"},"source":["## 1.1 A Description\n","\n","The Spiking Tactile-MNIST (ST-MNIST) dataset is a novel neuromorphic collection featuring handwritten digits (0-9) inscribed by 23 individuals on a 100-taxel biomimetic event-based tactile sensor array. This dataset, publicly available to facilitate research in tactile perception, captures the dynamic pressure changes associated with natural writing. The tactile sensing system, Asynchronously Coded Electronic Skin (ACES), emulates the human peripheral nervous system, transmitting fast-adapting (FA) responses as asynchronous electrical events.\n","\n","More information about the ST-MNIST dataset can found by the paper written by its authors:\n","\n","> H. H. See, B. Lim, S. Li, H. Yao, W. Cheng, H. Soh, and B. C. K. Tee, \"ST-MNIST - The Spiking Tactile-MNIST Neuromorphic Dataset,\" A PREPRINT, May 2020. [Online]. Available: https://arxiv.org/abs/2005.04319 \n","\n"]},{"cell_type":"markdown","metadata":{"id":"Ickp0FA4_nBR"},"source":["##1.2 Download the STMNIST dataset\n","\n","The data of ST-MNIST is provided with the MAT format. We are working in Python, so we need a way to import that MAT data into Python. Luckily, Tonic has created a function that creates an IterDataPipe that reads out and transforms the data into an (x, y, t, p) format when provided a path to it. (More down below)\n","\n","The first thing you must do is download the compressed dataset by accessing: https://scholarbank.nus.edu.sg/bitstream/10635/168106/2/STMNIST%20dataset%20NUS%20Tee%20Research%20Group.zip\n","\n","The zip file that you download will be titled `STMNIST dataset NUS Tee Research Group`. You must create a folder/directory titled `STMNIST` and then put that zip file in the folder/directory. This will be necessary for the Tonic class we use later.\n","\n","You then must either put it somewhere you can provide a path to it on your local machine or your Google Drive. For the purposes of this tutorial we will assume Google Drive."]},{"cell_type":"markdown","metadata":{"id":"DnDx0axoCphC"},"source":["## 1.3 Mount to Drive\n","Assuming you now have the `STMNIST` directory containing the zip file somewhere in your Google Drive. We must now \"mount\" Google Drive to this notebook so that it can access it. This is done with the code below:"]},{"cell_type":"code","execution_count":100,"metadata":{"id":"c2PcG-B3v9K8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702496303765,"user_tz":480,"elapsed":958,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"c3902405-8c9a-4f13-ddf9-2abb8bcdbb55"},"outputs":[{"output_type":"stream","name":"stdout","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"]}],"source":["# Load the Drive helper and mount\n","from google.colab import drive\n","\n","# This will prompt for authorization.\n","drive.mount('/content/drive')"]},{"cell_type":"markdown","source":["Here is the path to the file in our drive, change it to where it is in yours"],"metadata":{"id":"1yJJr7k4q0p-"}},{"cell_type":"code","execution_count":101,"metadata":{"id":"00hHZOeuv-8k","executionInfo":{"status":"ok","timestamp":1702496303765,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# After executing the cell above, Drive files will be present in \"/content/drive/My Drive\".\n","# Here is the path to the file in our drive, change it to where it is in yours\n","root = \"/content/drive/My Drive/STMNIST_Tutorial\" # similar to os.path.join('drive', 'My Drive', 'Finalized_STMNIST')"]},{"cell_type":"markdown","source":["The following cell blocks is to make sure you edited the above path correctly. If you get a `FileNotFoundError: [Errno 2] No such file or directory:` error or a `ls: cannot access '/content/drive/My Drive/the/path/you/put/in': No such file or directory` error that means you didn't edit the above path correctly and you are pathing to a directory that doesn't exist. Furthermore make sure that the directory STMNIST (which you made and has your zip file is in) is in the directory you are pathing to."],"metadata":{"id":"1434lW43N5aR"}},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 1\n","os.listdir(root) # same as os.listdir(\"/content/drive/My Drive/STMNIST_Tutorial\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2FqIu1QaHPi4","executionInfo":{"status":"ok","timestamp":1702496351818,"user_tz":480,"elapsed":169,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"9d7da518-2c0e-441b-8866-269906567ae9"},"execution_count":105,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['STMNIST', 'ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb']"]},"metadata":{},"execution_count":105}]},{"cell_type":"code","source":["# Make sure that the folder STMNIST (which your zip file is in) is in the folder the path directs to way 2\n","!ls \"/content/drive/My Drive/STMNIST_Tutorial\""],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ynCJsU_HHOxV","executionInfo":{"status":"ok","timestamp":1702496354637,"user_tz":480,"elapsed":171,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"93e024de-c4f8-480d-b429-9b877a72ada2"},"execution_count":106,"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST ST-MNIST_Tutorial_with_snnTorch_and_Tonic.ipynb\n"]}]},{"cell_type":"markdown","metadata":{"id":"OOfqmhKcIOR0"},"source":["## 1.4 ST-MNIST through Tonic\n","Now we call the `tonic` function to create the class that returns a IterDataPipe of the dataset. The docs for that function can be found here: https://tonic.readthedocs.io/en/latest/generated/tonic.prototype.datasets.STMNIST.html#tonic.prototype.datasets.STMNIST"]},{"cell_type":"code","execution_count":107,"metadata":{"id":"4r9zaUjHwAcM","executionInfo":{"status":"ok","timestamp":1702496365403,"user_tz":480,"elapsed":355,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["dataset = tonic.prototype.datasets.STMNIST(root=root,\n"," keep_compressed = False, shuffle = False)"]},{"cell_type":"markdown","metadata":{"id":"AgwoqxsAMdqP"},"source":["Because the dataset is an IterDataPipe, it can not be indexed into. Instead, we use `next(iter())` in order to iterate through it.\n","\n","In the above code `dataset` has been set to the returned DataPipe, so now I will just refer to `dataset`. Tonic formats the STMNIST dataset into an `(x, y, t, p)` format just like its other datasets so that the data will be compatable with other parts of its library. Where `x` is the position on the x-axis, `y` is the position on the y-axis, `t` is a timestamp, and `p` is polarity (1 or 0).\n","\n","Each iteration of dataset returns a tuple. The first index of the tuple contains a numpy array of `(x, y, t, p)` tuples which represents a series of sparse matrix through time of the recordings on the tactile sensor. The second index is a integer 0-9 which is the \"label\" of the data representing what number the afformentioned events is a drawing of."]},{"cell_type":"code","execution_count":108,"metadata":{"id":"2nRzg5A0RegL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702496366543,"user_tz":480,"elapsed":357,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"19ebec11-4933-4942-8bd2-695f860d691a"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","4389\n","(2, 3, 199891, 0)\n","8\n"]}],"source":["print(type(dataset))\n","events, target = next(iter(dataset))\n","print(type(events))\n","print(len(events))\n","print(events[0])\n","print(target)"]},{"cell_type":"markdown","metadata":{"id":"7mWT1BXPdeuM"},"source":["Now that the data is out of the MAT file and into the (x,y,t,p) format we now need it to be in a form that our neural network can read. Luckily Tonic has transformations that do that for us as its other datasets use the (x,y,t,p) format. When you run the code below, the `.ToFrame()` function from `tonic.transforms` changes it from an (x,y,t,p) format to a numpy array matrix."]},{"cell_type":"code","execution_count":42,"metadata":{"id":"Alt1gJkWSqjy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491043756,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"de418cf3-426b-41bb-f40a-50237888cd5c"},"outputs":[{"output_type":"stream","name":"stdout","text":["----------------------------\n","\n","----------------------------\n","1518\n","----------------------------\n","\n","----------------------------\n","2\n","----------------------------\n","[[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 3 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","\n"," [[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[[0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 3 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]\n"," [0 0 0 0 0 0 0 0 0 0]]\n","----------------------------\n","\n","----------------------------\n","10\n","----------------------------\n","[0 0 0 0 0 0 0 0 0 0]\n","----------------------------\n","\n","----------------------------\n","0\n"]}],"source":["sensor_size = tuple(tonic.prototype.datasets.STMNIST.sensor_size.values()) # The sensor size for STMNIST is (10, 10, 2) btw\n","# transforms is the same as tonic.transforms check the imports above if you want to make sure\n","frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=sensor_size,\n"," time_window=1000)\n"," ])\n","\n","copy_events = frame_transform(events)\n","print('----------------------------')\n","print(type(copy_events))\n","print('----------------------------')\n","print(len(copy_events))\n","print('----------------------------')\n","print(type(copy_events[0]))\n","print('----------------------------')\n","print(len(copy_events[0]))\n","print('----------------------------')\n","print(copy_events[0])\n","print('----------------------------')\n","print(type(copy_events[0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0]))\n","print('----------------------------')\n","print(copy_events[0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0]))\n","print('----------------------------')\n","print(len(copy_events[0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0])\n","print('----------------------------')\n","print(type(copy_events[0][0][0][0]))\n","print('----------------------------')\n","print(copy_events[0][0][0][0])"]},{"cell_type":"markdown","metadata":{"id":"AbRLjFPEqf6M"},"source":["### 1.4.1 The advantages of ST-MNIST over N-MNIST\n","At the time of release, the closest neuromorphic dataset to ST-MNIST was the N-MNIST dataset which used a moving motion-sensing event-based camera on static images of the original MNIST set (2-d digit classification) to simulate movement. What makes the ST-MNIST dataset better is that the dataset is actually taken from people writing on 10 by 10 tactile pixel sensors. That means when a neural network learns from a dataset it actually has to look at it temporally rather than purely spatially. In N-MNIST every frame would have the digit fully shown, however, for ST-MNIST it only shows parts of it as the participants write over it. That means that as a neuromorphic dataset taking advantage of the spiking and temporal benefits of a SNN ST-MNIST is better than N-MNIST.\n"]},{"cell_type":"markdown","metadata":{"id":"l3CJDa1LnUzd"},"source":["Using `tonic.utils.plot_animation`, the frame transform, and also some rotation. We can create an animation of the data and visualize this."]},{"cell_type":"code","execution_count":43,"metadata":{"id":"kOFkuUfrplsg","executionInfo":{"status":"ok","timestamp":1702491044156,"user_tz":480,"elapsed":401,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Iterate to a new iteration\n","events, target = next(iter(dataset))"]},{"cell_type":"code","execution_count":44,"metadata":{"id":"maDf7TLHmUiw","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702491044590,"user_tz":480,"elapsed":437,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"cb4630d8-d489-46b7-966f-979f81e7abe1"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 0\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGVElEQVR4nO3csW1VQRRFUQb9HIkSyNyOK6EqQjJqISSniUtsyUYjsR/zQGvFE5xs6yazZmbeAcAfen96AAD/B0EBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJx+7DtdaVOwC4sZ1PVVwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAxOP0AHjh6fn0gtd9/3p6AdyeCwWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgCJNTOz9XCtq7cAcFM7qXChAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoAicfpARzw9Pn0grd9+nl6weu+fTm9AG7PhQJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYDEmpnZerjW1Vv4Wz6eHvAbH04PeMOP0wPgrJ1UuFAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYDEmpnZerjW1VsAuKmdVLhQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBIPHYfTgzV+4A4B/nQgEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASDxCwvHKByDTyT+AAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":44}],"source":["from IPython.display import HTML\n","\n","frame_transform_tonic_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=90000,\n",")\n","\n","frames = frame_transform_tonic_visual(events)\n","frames = frames / np.max(frames)\n","frames = np.rot90(frames, k=-1, axes=(2, 3))\n","frames = np.flip(frames, axis=3)\n","\n","# Print out the Target\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","animation = tonic.utils.plot_animation(frames)\n","\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"w52aUd2qoyXV"},"source":["We can also use `snntorch.spikeplot`"]},{"cell_type":"code","execution_count":45,"metadata":{"id":"bPwRVZgqo8EH","colab":{"base_uri":"https://localhost:8080/","height":925},"executionInfo":{"status":"ok","timestamp":1702491047680,"user_tz":480,"elapsed":3092,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"af750230-a488-441d-927f-2da59b4c02b7"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of ST-MNIST\n","The target label is: 0\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n"},"metadata":{}}],"source":["frame_transform_snntorch_visual = tonic.transforms.ToFrame(\n"," sensor_size=(10, 10, 2),\n"," time_window=8000,\n",")\n","\n","tran = frame_transform_snntorch_visual(events)\n","tran = np.rot90(tran, k=-1, axes=(2, 3))\n","tran = np.flip(tran, axis=3)\n","tran = torch.from_numpy(tran)\n","\n","tensor1 = tran[:, 0:1, :, :]\n","tensor2 = tran[:, 1:2, :, :]\n","\n","print('Animation of ST-MNIST')\n","print('The target label is:',target)\n","\n","fig, ax = plt.subplots()\n","time_steps = tensor1.size(0)\n","tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n","anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n","# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n","\n","display(HTML(anim.to_html5_video()))"]},{"cell_type":"code","execution_count":46,"metadata":{"id":"F5eZvTHHr5qS","executionInfo":{"status":"ok","timestamp":1702491047904,"user_tz":480,"elapsed":226,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_sensor_size = tonic.datasets.NMNIST.sensor_size\n","nmnist_frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n"," transforms.ToFrame(sensor_size=nmnist_sensor_size,\n"," time_window=3000)\n"," ])\n","\n","nmnist_dataset = tonic.datasets.NMNIST(save_to='./tmp/nmnist_example_data', transform=nmnist_frame_transform, train=False)"]},{"cell_type":"code","execution_count":47,"metadata":{"id":"Tz3HlO9zsdls","executionInfo":{"status":"ok","timestamp":1702491047904,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["nmnist_events, nmnist_target = nmnist_dataset[0]"]},{"cell_type":"code","execution_count":48,"metadata":{"id":"pe47llhqu00o","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":4675,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"fd373c32-2630-45cf-dfa5-b46b1b600012"},"outputs":[{"output_type":"stream","name":"stdout","text":["Animation of N-MNIST\n","The target label is: 8\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGe0lEQVR4nO3cMY4bMRAAQdPYL+qVeuTcBwzfLtw8rayqeIIBk8YkXDMzvwDgH/1+9QIA/B8EBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJI6zg2utnXsAcGNnPlVxoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AcBePC7PPbVvwvlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMSamTk1uNbuXQC4qTOpcKEAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAInj1QsAFzwuzj+3bAF/5EIBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJNbMzKnBtXbvAtSufNXimxb+4kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhK9XAPiWr1cA+DGCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkjlcvALyhx8X555YtuBkXCgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASCxZmZODa61excAbupMKlwoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJA4Xr0AsNHjwuxz2xZ8CBcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7FwBu6kwqXCgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQOF69wEd4XJx/btniM1x5a+8MKRcKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBILFmZk4NrrV7F+5m1zcmvqKBt3MmFS4UABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQMLXKwB8y9crAPwYQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgMRxdnBmdu4BwJtzoQCQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJD4AihVRw5/WD3pAAAAAElFTkSuQmCC\n"},"metadata":{}},{"output_type":"execute_result","data":{"text/plain":[""],"text/html":["\n","\n","\n","\n","\n","\n","
\n"," \n","
\n"," \n","
\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n"," \n"," \n"," \n"," \n"," \n"," \n","
\n","
\n","
\n","\n","\n","\n"]},"metadata":{},"execution_count":48}],"source":["# Print out the Target\n","print('Animation of N-MNIST')\n","print('The target label is:',nmnist_target)\n","# normalize values to between 0-1\n","nmnist_events_fraction = nmnist_events / np.max(nmnist_events)\n","animation = tonic.utils.plot_animation(nmnist_events_fraction)\n","# Display the animation inline in a Jupyter notebook\n","HTML(animation.to_jshtml())"]},{"cell_type":"markdown","metadata":{"id":"92McQkLgd_xI"},"source":["A printout of the sensor size of the ST-MNIST and N-MNIST dataset. (10, 10, 2) menas a 10 by 10 pixel dataset with a channel size of 2. (34, 34, 2) means a 34 by 34 pixel dataset with a channel size of 2."]},{"cell_type":"code","execution_count":49,"metadata":{"id":"mou11FujsL-v","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":14,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"434c36d7-b445-4e92-aa76-9e5f707dea81"},"outputs":[{"output_type":"stream","name":"stdout","text":["STMNIST {'x': 10, 'y': 10, 'p': 2}\n","NMNIST (34, 34, 2)\n"]}],"source":["print('STMNIST', tonic.prototype.datasets.STMNIST.sensor_size)\n","print('NMNIST', tonic.datasets.NMNIST.sensor_size)"]},{"cell_type":"markdown","metadata":{"id":"CzYgPlxWfdm_"},"source":["There is a total of 6953 recordings in this dataset. This lines up with what is said in the ST-MNIST paper. They invited in 23 participants to write around 30 times each for 9 digits."]},{"cell_type":"code","execution_count":50,"metadata":{"id":"_v1auSbyepQr","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":12,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8edb9613-7c90-4d0f-ae67-b3d1691f8c98"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n"]}],"source":["print(len(dataset)) # 23 participants writing around 30 times each for 9 digits 23*30*9 = 6210"]},{"cell_type":"markdown","metadata":{"id":"tlX9jWV0f_az"},"source":["##1.5 Lets create a trainset and testset!"]},{"cell_type":"markdown","metadata":{"id":"hqQzVEHEgSFp"},"source":["Unfortunately unlike N-MNIST, ST-MNIST isn't already seperated into a trainset and testset on tonic. That means we will have to seperate that manually. For this example you could do 80% of the dataset for the trainset and 20% for the testset which we calculate below."]},{"cell_type":"code","execution_count":51,"metadata":{"id":"ZXw_xyfetX_K","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702491052577,"user_tz":480,"elapsed":11,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"a93982aa-2e9a-4671-9510-63d20ab07ea5"},"outputs":[{"output_type":"stream","name":"stdout","text":["6953\n","5562\n","1391\n"]}],"source":["# Calculate the sizes for the training and testing sets\n","total_size = len(dataset)\n","print(total_size)\n","# train_size is 80% of total size\n","train_size = int(0.8 * total_size)\n","print(train_size)\n","test_size = total_size - train_size\n","print(test_size)"]},{"cell_type":"code","execution_count":52,"metadata":{"id":"d_6BFKiXJdWU","executionInfo":{"status":"ok","timestamp":1702491052753,"user_tz":480,"elapsed":186,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["sensor_size = tonic.prototype.datasets.STMNIST.sensor_size\n","sensor_size = tuple(sensor_size.values())\n","\n","# Define a transform\n","frame_transform = transforms.Compose([transforms.ToFrame(sensor_size=sensor_size, time_window=1000)])"]},{"cell_type":"markdown","metadata":{"id":"iSMhDsHliQk5"},"source":["The following code reads out the entirety of the dataset from the IterDataPipe and then transforms the events using the `frame_transform` above. It also seperates out the data into a trainset and a testset. Remember that each time a piece of data is read out of the datapipe it is read and transformed from the MAT files using tonic. On top of that we are to the .ToFrame() transform over it each time. Thus, this takes some time.\n","\n","**You have two options here:**\n","\n","Transform and tain on a small part of the dataset, this is faster and is the default for the sake of a short easy to run tutorial. The default for this shorter transform is 640 pieces of data for the trainset and 320 pieaces of data for the testset. This takes ~4-5 minutes. Feel free to change this, just be aware that the number of pieces of data we transform and the time it takes have an inverse relationship.\n","\n","**Or** you can transform and convert the entire dataset; this takes ~30-60 minutes. To do that comment out the `shorter_transform_STMNIST` cell block and uncomment the `full_transform_STMNIST` cell block and run that instead. If you choose this: kickback, take a break and eat a snack while this happens. perhaps even count kangaroos to take a nap or do a shoey and get schwasted instead.\n","\n","Note: A smaller dataset generally means a higher accuracy but less generalizability on new data when training a neural network on it given the same amount of time."]},{"cell_type":"code","source":["def shorter_transform_STMNIST(data, transform):\n"," short_train_size = 640\n"," short_test_size = 320\n","\n"," train_bar = IntProgress(min=0, max=short_train_size)\n"," test_bar = IntProgress(min=0, max=short_test_size)\n","\n"," testset = []\n"," trainset = []\n","\n"," print('Porting over and transforming the trainset.')\n"," display(train_bar)\n"," for _ in range(short_train_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," trainset.append((events, target))\n"," train_bar.value += 1\n"," print('Porting over and transforming the testset.')\n"," display(test_bar)\n"," for _ in range(short_test_size):\n"," events, target = next(iter(dataset))\n"," events = transform(events)\n"," testset.append((events, target))\n"," test_bar.value += 1\n","\n"," return (trainset, testset)\n","\n","# Get the start time\n","start_time = time.time()\n","\n","# Call the function\n","trainset, testset = shorter_transform_STMNIST(dataset, frame_transform)\n","\n","# Get the end time\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":133,"referenced_widgets":["6dd945b6627844c1b3808b9ea8ab6646","fb003723433d4e8db855b590fdfbfedd","dc2254cf2e894a21a689246a66f0dfce","aec192c607bf40b9a45a1f2b064ba30e","845cc10adccf489f8fecf05cc6fe2f93","d3ea533e5b164139abba9ab6f2c0a5ac"]},"id":"c0qw8uduLpZv","executionInfo":{"status":"ok","timestamp":1702491266338,"user_tz":480,"elapsed":213588,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"cb18839a-6b13-43cf-c00c-de3e192bc30f"},"execution_count":53,"outputs":[{"output_type":"stream","name":"stdout","text":["Porting over and transforming the trainset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=640)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"6dd945b6627844c1b3808b9ea8ab6646"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Porting over and transforming the testset.\n"]},{"output_type":"display_data","data":{"text/plain":["IntProgress(value=0, max=320)"],"application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"aec192c607bf40b9a45a1f2b064ba30e"}},"metadata":{}},{"output_type":"stream","name":"stdout","text":["Elapsed time: 3 minutes, 33 seconds, 820 milliseconds\n"]}]},{"cell_type":"code","execution_count":74,"metadata":{"id":"muL3A2dbMYTY","executionInfo":{"status":"ok","timestamp":1702493968118,"user_tz":480,"elapsed":166,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# def full_transform_STMNIST(data, transform):\n","# train_bar = IntProgress(min=0, max=train_size)\n","# test_bar = IntProgress(min=0, max=test_size)\n","\n","# testset = []\n","# trainset = []\n","\n","# print('Porting over and transforming the trainset.')\n","# display(train_bar)\n","# for _ in range(train_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# trainset.append((events, target))\n","# train_bar.value += 1\n","# print('Porting over and transforming the testset.')\n","# display(test_bar)\n","# for _ in range(test_size):\n","# events, target = next(iter(dataset))\n","# events = transform(events)\n","# testset.append((events, target))\n","# test_bar.value += 1\n","\n","# return (trainset, testset)\n","\n","# # Get the start time\n","# start_time = time.time()\n","\n","# # Call the function\n","# trainset, testset = full_transform_STMNIST(dataset, frame_transform)\n","\n","# # Get the end time\n","# end_time = time.time()\n","\n","# # Calculate elapsed time\n","# elapsed_time = end_time - start_time\n","\n","# # Convert elapsed time to minutes, seconds, and milliseconds\n","# minutes, seconds = divmod(elapsed_time, 60)\n","# seconds, milliseconds = divmod(seconds, 1)\n","# milliseconds = round(milliseconds * 1000)\n","\n","# # Print the elapsed time\n","# print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"98VVH_HSs-Gh"},"source":["##1.6 Dataloading and Batching\n","\n","The reason why we needed to move the data into a list instead of just using the datapipe and transforming as we moved out of it was so that we could use the DataLoader function from torch that requires an indexable class, array, etc."]},{"cell_type":"code","execution_count":75,"metadata":{"id":"DPxzp1fdFe_X","executionInfo":{"status":"ok","timestamp":1702493968382,"user_tz":480,"elapsed":1,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# Create a DataLoader\n","dataloader = DataLoader(trainset, batch_size=64, shuffle=True)"]},{"cell_type":"markdown","metadata":{"id":"yORjaoQAuuY1"},"source":["To make our dataloading even faster we can use DiskCashedDataset from tonic which makes use of disk chaching and batching. In addition we can add an additional transformation that will change the data from numpy to a torch tensor.\n","\n","Due to variations in the lengths of event recordings, we will introduce a collation function called `tonic.collation.PadTensors()`. This function will be responsible for padding shorter recordings, ensuring uniform dimensions across all samples in a batch."]},{"cell_type":"code","execution_count":76,"metadata":{"id":"YaPsfB0ArUgQ","executionInfo":{"status":"ok","timestamp":1702493968383,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# transform = tonic.transforms.Compose([torch.from_numpy,\n","# torchvision.transforms.RandomRotation([-10,10])])\n","\n","transform = tonic.transforms.Compose([torch.from_numpy])\n","\n","cached_trainset = DiskCachedDataset(trainset, transform=transform, cache_path='./cache/stmnist/train')\n","\n","# no augmentations for the testset\n","cached_testset = DiskCachedDataset(testset, cache_path='./cache/stmnist/test')\n","\n","batch_size = 128\n","trainloader = DataLoader(cached_trainset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False), shuffle=True)\n","testloader = DataLoader(cached_testset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False))"]},{"cell_type":"markdown","metadata":{"id":"_i-s-FRuwGBR"},"source":["Here are the shapes of the data and target tensors of a single iteration of the trainloader printed below."]},{"cell_type":"code","execution_count":77,"metadata":{"id":"0so65S95BDbf","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":692,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"4a5320d9-cfe5-49e2-ea04-3b6e6229999c"},"outputs":[{"output_type":"stream","name":"stdout","text":["5\n","torch.Size([1983, 128, 2, 10, 10])\n","torch.Size([128, 2, 10, 10])\n","torch.Size([128])\n","tensor([7, 8, 5, 4, 9, 7, 7, 2, 2, 4, 1, 5, 7, 3, 8, 2, 2, 1, 8, 8, 2, 1, 0, 9,\n"," 5, 5, 1, 8, 4, 8, 4, 2, 5, 9, 9, 5, 0, 0, 6, 1, 0, 8, 7, 6, 1, 6, 0, 0,\n"," 8, 3, 7, 9, 1, 7, 0, 7, 8, 8, 5, 8, 6, 7, 5, 7, 1, 5, 9, 0, 2, 8, 6, 0,\n"," 0, 7, 2, 1, 4, 9, 4, 9, 1, 9, 7, 4, 4, 6, 6, 2, 0, 2, 6, 3, 2, 9, 8, 7,\n"," 0, 9, 8, 1, 8, 0, 1, 4, 3, 2, 2, 3, 4, 9, 1, 9, 5, 1, 7, 7, 4, 0, 5, 6,\n"," 7, 0, 1, 1, 7, 6, 2, 4])\n"]}],"source":["data_tensor, targets = next(iter(trainloader))\\\n","# length of trainloader = number of iterations per epoch\n","# For the shorter transform\n","# 640 == length of dataset\n","# 640 / 128 = 5\n","# Remember: Trainset is length 640\n","# So the trainloader should be length 5\n","# For the longer transform\n","# 5562 == length of dataset\n","# 5562 / 128 ~ 43.45\n","# Remember: Trainset is length 5562\n","# So the trainloader should be length 44\n","print(len(trainloader))\n","print(data_tensor.shape)\n","print(data_tensor[0].shape)\n","print(targets.shape)\n","print(targets)"]},{"cell_type":"markdown","metadata":{"id":"QDGPdoBUw-ME"},"source":["## 1.7 Create the Spiking Convolutional Neural Network"]},{"cell_type":"markdown","source":["Below we have by default a spiking convolutional neural network with the architecture: `10×10-32c4-64c3-MaxPool2d(2)-10o`. We also have commented out some other architectures we experimented with. Feel free to experiment with these other networks and see how it affects training on the dataset."],"metadata":{"id":"W0DjtextRipx"}},{"cell_type":"code","execution_count":78,"metadata":{"id":"W2ewqKLx8mMJ","executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n","\n","# neuron and simulation parameters\n","spike_grad = surrogate.atan()\n","beta = 0.95\n","\n","# Initialize Network\n","# 10x10-12c3-32c3-10o\n","# scnn_net = nn.Sequential(nn.Conv2d(2, 12, 3),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.MaxPool2d(2),\n","# nn.Conv2d(12, 32, 3),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.MaxPool2d(2),\n","# nn.Flatten(),\n","# nn.Linear(32*1*1, 10),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# # 10×10−6c4−24c3−10o\n","# # This is the same architecture that was used in the ST-MNIST Paper\n","# # No Max Pooling as 10x10 is already very small/low detail\n","# scnn_net = nn.Sequential(\n","# nn.Conv2d(2, 6, kernel_size=4), # 6 channels, kernel size 4x4\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# # nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n","\n","# nn.Conv2d(6, 24, kernel_size=3), # 24 channels, kernel size 3x3\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# # nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n","\n","# nn.Flatten(),\n","# nn.Linear(24 * 5 * 5, 10), # Increased size of the linear layer\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# 10×10-32c4-64c3-MaxPool2d(2)-10o\n","scnn_net = nn.Sequential(\n"," # 2 x 10 x 10\n"," nn.Conv2d(2, 32, kernel_size=4), # 32 channels, kernel size 4x4\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(10 - 4) + 1] = 7\n","\n"," # 32 x 7 x 7\n"," nn.Conv2d(32, 64, kernel_size=3), # 64 channels, kernel size 3x3\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n"," # Output size = [(7 - 3) + 1] = 5\n","\n"," # 64 x 5 x 5\n"," nn.MaxPool2d(2), # Max pooling with kernel size 2x2\n"," # Output size = [(5-2) / 2] + 1 = 2\n","\n"," # 64 x 2 x 2\n"," nn.Flatten(),\n"," # Output size = 64*2*2 = 256\n","\n"," nn.Linear(64 * 2 * 2, 10), # Increased size of the linear layer\n"," snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n",").to(device)\n","\n","# Note: In a CNN the formula for calculating the output of the Conv layer is\n","# Output size = ((Input Size - Kernel Size + 2 * Padding) / Stride ) + 1\n","# Note for a MaxPool layer the formula is\n","# Output size = ((Input size - Kernel Size) / Stride ) + 1\n","\n","optimizer = torch.optim.Adam(scnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"markdown","metadata":{"id":"Sq_jz3xYxMxO"},"source":["##1.8 Define the Forward Pass"]},{"cell_type":"code","execution_count":79,"metadata":{"id":"ydcyDZDt_qH_","executionInfo":{"status":"ok","timestamp":1702493969073,"user_tz":480,"elapsed":2,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# this time, we won't return membrane as we don't need it\n","\n","def forward_pass(net, data):\n"," spk_rec = []\n"," utils.reset(net) # resets hidden states for all LIF neurons in net\n","\n"," for step in range(data.size(0)): # data.size(0) = number of time steps\n","\n"," spk_out, mem_out = net(data[step])\n"," spk_rec.append(spk_out)\n","\n"," return torch.stack(spk_rec)"]},{"cell_type":"markdown","metadata":{"id":"9tPywf6CxWcq"},"source":["## 1.9 Create and Run the Training Loop\n","\n","The current epochs is set to 40 and is intended to be run on the smaller trainset and testset. In the smaller set each epoch has 5 iterations. Doing the math: 5 * 40 is 200 iterations over the 40 epochs. On our runs on the T4 GPU on Colab, 30 epochs on the smaller dataset takes ~25 minutes and achieves ~50% accuracy on the testset and ~50% accuracy on the trainset.\n","\n","For training on the full dataset, we recommend lowering the epochs down to 15. Remember that each epoch has 44 iterations starting at 0. Doing the math: 44 * 15 = 660 iterations over the 15 epochs. Training should once again take some time so feel free to take a break and let your computer run. On our runs with the T4 GPU on Colab 15 epochs takes ~70 min with ~70% accuracy on the full trainset and ~65% accuracy on the full testset.\n","\n","Of course feel free to adjust the epochs to make them longer or shorter if you have more or less time and would like to experiment with how that affects accuracy on the testset and trainset."]},{"cell_type":"code","execution_count":80,"metadata":{"id":"lB9lYUP0AUBL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495283579,"user_tz":480,"elapsed":1314507,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"3301c4b9-ed3c-45ab-c1f4-9dab8e17af3b"},"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 0, Iteration 0 \n","Train Loss: 193.19\n","Accuracy: 7.03%\n","\n","Epoch 0, Iteration 4 \n","Train Loss: 166.22\n","Accuracy: 11.72%\n","\n","Epoch 1, Iteration 0 \n","Train Loss: 155.76\n","Accuracy: 10.94%\n","\n","Epoch 1, Iteration 4 \n","Train Loss: 128.67\n","Accuracy: 10.94%\n","\n","Epoch 2, Iteration 0 \n","Train Loss: 122.48\n","Accuracy: 11.72%\n","\n","Epoch 2, Iteration 4 \n","Train Loss: 108.78\n","Accuracy: 15.62%\n","\n","Epoch 3, Iteration 0 \n","Train Loss: 110.45\n","Accuracy: 11.72%\n","\n","Epoch 3, Iteration 4 \n","Train Loss: 107.84\n","Accuracy: 7.03%\n","\n","Epoch 4, Iteration 0 \n","Train Loss: 103.94\n","Accuracy: 7.81%\n","\n","Epoch 4, Iteration 4 \n","Train Loss: 82.54\n","Accuracy: 9.38%\n","\n","Epoch 5, Iteration 0 \n","Train Loss: 72.82\n","Accuracy: 8.59%\n","\n","Epoch 5, Iteration 4 \n","Train Loss: 72.97\n","Accuracy: 10.16%\n","\n","Epoch 6, Iteration 0 \n","Train Loss: 71.87\n","Accuracy: 10.94%\n","\n","Epoch 6, Iteration 4 \n","Train Loss: 63.91\n","Accuracy: 14.84%\n","\n","Epoch 7, Iteration 0 \n","Train Loss: 64.48\n","Accuracy: 14.06%\n","\n","Epoch 7, Iteration 4 \n","Train Loss: 66.40\n","Accuracy: 10.94%\n","\n","Epoch 8, Iteration 0 \n","Train Loss: 65.42\n","Accuracy: 13.28%\n","\n","Epoch 8, Iteration 4 \n","Train Loss: 62.19\n","Accuracy: 10.16%\n","\n","Epoch 9, Iteration 0 \n","Train Loss: 64.78\n","Accuracy: 11.72%\n","\n","Epoch 9, Iteration 4 \n","Train Loss: 65.64\n","Accuracy: 8.59%\n","\n","Epoch 10, Iteration 0 \n","Train Loss: 64.33\n","Accuracy: 12.50%\n","\n","Epoch 10, Iteration 4 \n","Train Loss: 61.63\n","Accuracy: 10.16%\n","\n","Epoch 11, Iteration 0 \n","Train Loss: 64.52\n","Accuracy: 14.06%\n","\n","Epoch 11, Iteration 4 \n","Train Loss: 64.68\n","Accuracy: 6.25%\n","\n","Epoch 12, Iteration 0 \n","Train Loss: 64.34\n","Accuracy: 10.94%\n","\n","Epoch 12, Iteration 4 \n","Train Loss: 63.86\n","Accuracy: 10.94%\n","\n","Epoch 13, Iteration 0 \n","Train Loss: 64.05\n","Accuracy: 11.72%\n","\n","Epoch 13, Iteration 4 \n","Train Loss: 64.39\n","Accuracy: 13.28%\n","\n","Epoch 14, Iteration 0 \n","Train Loss: 63.59\n","Accuracy: 16.41%\n","\n","Epoch 14, Iteration 4 \n","Train Loss: 63.88\n","Accuracy: 13.28%\n","\n","Epoch 15, Iteration 0 \n","Train Loss: 64.43\n","Accuracy: 9.38%\n","\n","Epoch 15, Iteration 4 \n","Train Loss: 67.90\n","Accuracy: 9.38%\n","\n","Epoch 16, Iteration 0 \n","Train Loss: 74.42\n","Accuracy: 14.06%\n","\n","Epoch 16, Iteration 4 \n","Train Loss: 76.24\n","Accuracy: 8.59%\n","\n","Epoch 17, Iteration 0 \n","Train Loss: 77.33\n","Accuracy: 5.47%\n","\n","Epoch 17, Iteration 4 \n","Train Loss: 67.40\n","Accuracy: 8.59%\n","\n","Epoch 18, Iteration 0 \n","Train Loss: 65.96\n","Accuracy: 14.84%\n","\n","Epoch 18, Iteration 4 \n","Train Loss: 65.92\n","Accuracy: 16.41%\n","\n","Epoch 19, Iteration 0 \n","Train Loss: 65.77\n","Accuracy: 11.72%\n","\n","Epoch 19, Iteration 4 \n","Train Loss: 63.85\n","Accuracy: 16.41%\n","\n","Epoch 20, Iteration 0 \n","Train Loss: 64.12\n","Accuracy: 17.97%\n","\n","Epoch 20, Iteration 4 \n","Train Loss: 63.04\n","Accuracy: 21.09%\n","\n","Epoch 21, Iteration 0 \n","Train Loss: 62.61\n","Accuracy: 21.88%\n","\n","Epoch 21, Iteration 4 \n","Train Loss: 60.80\n","Accuracy: 31.25%\n","\n","Epoch 22, Iteration 0 \n","Train Loss: 56.85\n","Accuracy: 36.72%\n","\n","Epoch 22, Iteration 4 \n","Train Loss: 59.92\n","Accuracy: 28.12%\n","\n","Epoch 23, Iteration 0 \n","Train Loss: 59.07\n","Accuracy: 28.91%\n","\n","Epoch 23, Iteration 4 \n","Train Loss: 57.47\n","Accuracy: 39.84%\n","\n","Epoch 24, Iteration 0 \n","Train Loss: 59.31\n","Accuracy: 32.81%\n","\n","Epoch 24, Iteration 4 \n","Train Loss: 55.65\n","Accuracy: 33.59%\n","\n","Epoch 25, Iteration 0 \n","Train Loss: 57.65\n","Accuracy: 39.84%\n","\n","Epoch 25, Iteration 4 \n","Train Loss: 55.37\n","Accuracy: 38.28%\n","\n","Epoch 26, Iteration 0 \n","Train Loss: 54.02\n","Accuracy: 39.06%\n","\n","Epoch 26, Iteration 4 \n","Train Loss: 55.91\n","Accuracy: 39.06%\n","\n","Epoch 27, Iteration 0 \n","Train Loss: 57.34\n","Accuracy: 35.94%\n","\n","Epoch 27, Iteration 4 \n","Train Loss: 53.13\n","Accuracy: 45.31%\n","\n","Epoch 28, Iteration 0 \n","Train Loss: 54.00\n","Accuracy: 46.09%\n","\n","Epoch 28, Iteration 4 \n","Train Loss: 53.50\n","Accuracy: 41.41%\n","\n","Epoch 29, Iteration 0 \n","Train Loss: 54.04\n","Accuracy: 44.53%\n","\n","Epoch 29, Iteration 4 \n","Train Loss: 53.78\n","Accuracy: 42.19%\n","\n","Epoch 30, Iteration 0 \n","Train Loss: 51.86\n","Accuracy: 53.91%\n","\n","Epoch 30, Iteration 4 \n","Train Loss: 51.79\n","Accuracy: 50.78%\n","\n","Epoch 31, Iteration 0 \n","Train Loss: 51.04\n","Accuracy: 46.88%\n","\n","Epoch 31, Iteration 4 \n","Train Loss: 51.60\n","Accuracy: 50.00%\n","\n","Epoch 32, Iteration 0 \n","Train Loss: 53.49\n","Accuracy: 45.31%\n","\n","Epoch 32, Iteration 4 \n","Train Loss: 51.72\n","Accuracy: 53.91%\n","\n","Epoch 33, Iteration 0 \n","Train Loss: 51.84\n","Accuracy: 49.22%\n","\n","Epoch 33, Iteration 4 \n","Train Loss: 50.77\n","Accuracy: 50.78%\n","\n","Epoch 34, Iteration 0 \n","Train Loss: 50.60\n","Accuracy: 53.91%\n","\n","Epoch 34, Iteration 4 \n","Train Loss: 51.63\n","Accuracy: 49.22%\n","\n","Epoch 35, Iteration 0 \n","Train Loss: 49.02\n","Accuracy: 56.25%\n","\n","Epoch 35, Iteration 4 \n","Train Loss: 49.56\n","Accuracy: 60.94%\n","\n","Epoch 36, Iteration 0 \n","Train Loss: 51.84\n","Accuracy: 54.69%\n","\n","Epoch 36, Iteration 4 \n","Train Loss: 48.39\n","Accuracy: 60.16%\n","\n","Epoch 37, Iteration 0 \n","Train Loss: 48.87\n","Accuracy: 60.16%\n","\n","Epoch 37, Iteration 4 \n","Train Loss: 50.66\n","Accuracy: 59.38%\n","\n","Epoch 38, Iteration 0 \n","Train Loss: 49.35\n","Accuracy: 57.03%\n","\n","Epoch 38, Iteration 4 \n","Train Loss: 46.30\n","Accuracy: 59.38%\n","\n","Epoch 39, Iteration 0 \n","Train Loss: 47.08\n","Accuracy: 68.75%\n","\n","Epoch 39, Iteration 4 \n","Train Loss: 49.38\n","Accuracy: 53.12%\n","\n","Elapsed time: 21 minutes, 54 seconds, 431 milliseconds\n"]}],"source":["start_time = time.time()\n","\n","num_epochs = 40\n","\n","loss_hist = []\n","acc_hist = []\n","\n","# training loop\n","for epoch in range(num_epochs):\n"," for i, (data, targets) in enumerate(iter(trainloader)):\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," scnn_net.train()\n"," spk_rec = forward_pass(scnn_net, data)\n"," loss_val = loss_fn(spk_rec, targets)\n","\n"," # Gradient calculation + weight update\n"," optimizer.zero_grad()\n"," loss_val.backward()\n"," optimizer.step()\n","\n"," # Store loss history for future plotting\n"," loss_hist.append(loss_val.item())\n","\n"," if i%4 == 0:\n"," print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," if i%4 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)\n","\n","# Print the elapsed time\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"cEY6Ynbq0JmX"},"source":["# 2. Results"]},{"cell_type":"markdown","metadata":{"id":"yYSkN_kp0Lm0"},"source":["## 2.1 Plot accuracy history"]},{"cell_type":"code","execution_count":81,"metadata":{"id":"X0SYWQDJ6qhx","colab":{"base_uri":"https://localhost:8080/","height":472},"executionInfo":{"status":"ok","timestamp":1702495283922,"user_tz":480,"elapsed":345,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"8cf4d847-606c-4b51-a7a8-07e061b2b280"},"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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4PTTT0dlZaXy+G233YYDDjgA8+bNQ2lpKTIzM3HmmWeiqampa79oRNQpDG6IqFs88sgjOPTQQ3HhhReivLwc5eXl6N+/P+rr63H00UdjwoQJWL58ORYuXIjKykqcfvrpmue//PLLMJvN+P777/H0008DAPR6PR599FH8/vvvePnll/H111/jX//6FwDgsMMOw8MPP4yMjAzl9a699tqQcfl8Ppx88smora3Ft99+i0WLFmHbtm0444wzNMdt3boVH3zwARYsWIAFCxbg22+/xb333ttFXy0i2h8sSxFRt8jMzITZbIbVakWfPn2U+x9//HFMmDABd999t3Lfiy++iP79+2PTpk0YNmwYAGDo0KG4//77NedU9++UlpbizjvvxCWXXIInn3wSZrMZmZmZ0Ol0mtcL9tVXX2HNmjXYvn07+vfvDwB45ZVXMHr0aCxbtgyTJ08GIAVBL730EtLT0wEAZ599Nr766ivcdddd+/eFIaKYY+aGiOJq1apV+Oabb5CWlqb8GTFiBAApWyJMmjQp5LlffvkljjnmGPTt2xfp6ek4++yzUVNTA4fDEfXrr1+/Hv3791cCGwAYNWoUsrKysH79euW+0tJSJbABgKKiIuzbt69D75WIugczN0QUV83NzZg5cybuu+++kMeKioqUf9tsNs1jO3bswIknnohLL70Ud911F3JycrB06VJccMEFcLlcsFqtMR2nyWTS3NbpdPD5fDF9DSKKDQY3RNRtzGYzvF6v5r6JEyfi3XffRWlpKYzG6H8k/frrr/D5fHjwwQeh10tJ6Lfeeqvd1ws2cuRI7N69G7t371ayN+vWrUN9fT1GjRoV9XiIKHGwLEVE3aa0tBQ///wzduzYgerqavh8Plx22WWora3FWWedhWXLlmHr1q34/PPPcd5557UZmAwZMgRutxuPPfYYtm3bhnnz5imNxurXa25uxldffYXq6uqw5apjjz0WY8eOxezZs7FixQr88ssvOOecczB16lQceOCBMf8aEFHXY3BDRN3m2muvhcFgwKhRo5Cfn49du3ahuLgY33//PbxeL4477jiMHTsWV111FbKyspSMTDjjx4/HQw89hPvuuw9jxozBa6+9hnvuuUdzzGGHHYZLLrkEZ5xxBvLz80MakgGpvPThhx8iOzsbU6ZMwbHHHotBgwbhzTffjPn7J6LuofP7/f54D4KIiIgoVpi5ISIioqTC4IaIiIiSCoMbIiIiSioMboiIiCipMLghIiKipMLghoiIiJIKgxsiIiJKKgxuiIiIKKkwuCEiIqKkwuCGiIiIkgqDGyIiIkoqDG6IiIgoqfw/8V8gEghd3LsAAAAASUVORK5CYII=\n"},"metadata":{}}],"source":["import matplotlib.pyplot as plt\n","\n","# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Train Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"hhx12ZJP0eF7"},"source":["## 2.2 Evaluate the Network on the testset"]},{"cell_type":"code","execution_count":82,"metadata":{"id":"BTjjGQHuhQ7i","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495295875,"user_tz":480,"elapsed":11955,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"6fc91514-e525-4c0d-d1c1-796ee741410b"},"outputs":[{"output_type":"stream","name":"stdout","text":["Accuracy: 52.34%\n","\n","Accuracy: 49.22%\n","\n","Accuracy: 54.69%\n","\n"]},{"output_type":"execute_result","data":{"text/plain":["Sequential(\n"," (0): Conv2d(2, 32, kernel_size=(4, 4), stride=(1, 1))\n"," (1): Leaky()\n"," (2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))\n"," (3): Leaky()\n"," (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n"," (5): Flatten(start_dim=1, end_dim=-1)\n"," (6): Linear(in_features=256, out_features=10, bias=True)\n"," (7): Leaky()\n",")"]},"metadata":{},"execution_count":82}],"source":["# Assuming your model is already trained and stored in the variable 'net'\n","# Make sure your model is in evaluation mode\n","scnn_net.eval()\n","\n","# Initialize variables to store predictions and ground truth labels\n","acc_hist = []\n","\n","# Iterate over batches in the testloader\n","with torch.no_grad():\n"," for data, targets in testloader:\n"," # Move data and targets to the device (GPU or CPU)\n"," data = data.to(device)\n"," targets = targets.to(device)\n","\n"," # Forward pass\n"," spk_rec = forward_pass(scnn_net, data)\n","\n"," acc = SF.accuracy_rate(spk_rec, targets)\n"," acc_hist.append(acc)\n","\n"," # if i%10 == 0:\n"," print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# Reset your model to training mode if needed\n","scnn_net.train()\n"]},{"cell_type":"code","execution_count":83,"metadata":{"id":"0AyNWaIts16X","colab":{"base_uri":"https://localhost:8080/","height":489},"executionInfo":{"status":"ok","timestamp":1702495296228,"user_tz":480,"elapsed":355,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"2bdf78e5-add9-4609-9cf9-cd6468a12ec9"},"outputs":[{"output_type":"stream","name":"stdout","text":["The average loss across the testloader is: 0.5208333333333334\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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\n"},"metadata":{}}],"source":["import matplotlib.pyplot as plt\n","import statistics\n","\n","print(\"The average loss across the testloader is:\", statistics.mean(acc_hist))\n","# Plot Loss\n","fig = plt.figure(facecolor=\"w\")\n","plt.plot(acc_hist)\n","plt.title(\"Test Set Accuracy\")\n","plt.xlabel(\"Iteration\")\n","plt.ylabel(\"Accuracy\")\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"1a-oeEzK0Xvt"},"source":["## 2.3 Visualize Spike Recordings\n","\n","The following visual takes ~9 minutes to create. This visual is a spike count histogram that shows the spikes"]},{"cell_type":"code","execution_count":84,"metadata":{"id":"ZJArj6jlXBEs","executionInfo":{"status":"ok","timestamp":1702495299571,"user_tz":480,"elapsed":3345,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["spk_rec = forward_pass(scnn_net, data)"]},{"cell_type":"code","execution_count":85,"metadata":{"id":"tJSBM-ctXETI","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":643694,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"e51c8f06-5974-452c-8efd-f9c516ea3c34"},"outputs":[{"output_type":"stream","name":"stdout","text":["The target label is: 1\n"]},{"output_type":"display_data","data":{"text/plain":[""],"text/html":[""]},"metadata":{}},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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1vgJmTuvISv37Z0tN9skhx96QLbcbOOl+hzjJ7xT/nn99dZuEcSTpHPnztlq802z1eabltsmvjM5Bx55/CLbOv3Mn+f0M39enn7v+fr3PPrEmFx70215duy4zJw5K9XVXbLG6kPy0V13yuGH7p+ePXq02N4Nt9zZYnu/PeeHSZI/XnJ5xr70SkoLStlko2E58dhPtKgPAIomjANAhZn17uwc+/mvZ+KkyeW2Mc+9kC994zv59Vln5K9XXZ97H3ikPG/ipMm54JLLM3X6jHznmye12NazY1/MN779g0z/t9vrp06bkTvu+XvuvPeBfPa4T+Qznzqy1fV16dK5/PPfH348f/jTX7PHiOFZa82hS/lJl6y5uTn/99Nf5YZb7mzR3tjUlBdffjUvvvxqbrz1zvzqrDMyZLVVl7id626+I7feeW9KpVK57fGnns1TY57PD7/7rew+YvgyqxkAloYwDgAV5rU33kqSbLLR+mlubs64l/+RJJk/f35OOuX0NDQ0ZNCA/llzjdXz9LPPp6lpfpKFV4WPP/rwcjidNn1mTj71+3l39sJn2quqqrLpRuund++VMu6lVzN95qyUSqX89o+XZs2hq2fPj+7Sqvo233Sj/OP1N5MsDM2//eOf89s//jm9V+qVjTcclm223Dx77rZLi5DcvXu37LbrTpn17uwWt/VvvMGwrDpoQIvlkuS3F17aIoj3W2XlbDBsncyZU5vnX3w5pVIpb709MV//n//Ln3//ixZ/IHi/W+64J7169szGGw7LxHcm5+2JC6/qNy9YkO//5JfZcrON02+VlVv1uQFgWRLGAaACffmzx+aYIz+eUqmUE77yrYx57oUkSUNDQzbecFh+//MfpVu3brny2pty5s9/kyQplUp5aszz5RD858uvLgfxzp065fe/PDNbbLpRkmReQ0NO/MopeeGlV5Ikv/njn1sdxo858uO5856/Z05tXYv22XNq88jjT+eRx5/Oby64JIcdMipf/fxn0qVL56zct09+csZpi4ymftjBoxYZTX3WrHfzlyuuLU/vOnz7/OT0U8u34N957wM55Xs/TpK8+tobufPev2efPUYuttZBAwfkwnPPysAB/dPc3Jzv/PDs3HbXfUmS2rq6XH/LHTnuqNGt+twAsCwJ4wBQYXr27JEjP3ZQkoVXszfecFg5jCfJJw47ON26LbyCvNXmm7RYd9qMGeWfH3z0ifLP3bp3y6VXXJNLr7im3FZbX1/++a3xE/L2hHey+pDV/mN9qw9eNRee+9P85Be/zWNPPbPYZZoXLMhfr7ohPbr3yBc+c/R/3Ob7Pf70s2lobCxPz5w5K6ed8ZPy9IIFC1os/+CjTy4xjB920H4ZOKB/koXPsn/2uE+Uw3iSPPH0c8I4AO1CGAeACjNktVVTU1Ndnu7RvXuL+eu879nsf5/X2NhU/nnipCnln+vq6nP3/Q994H7fmTylVWE8SdZac2jOO/sHGf/2xDz8+FMZ89wLeXLMc5k+Y2aL5f523U353KePSqdOnVq13YV1T24x/dwLL33g8pMmT1nivLXXWqPF9NAhg1Nd3aV8a//kKVNbXRcALEvCOABUmF49W44QXlVV9W/zey6X/c6b17DU6wxdfXCGrj44ow/ZP6VSKQ88/HhOOf3MNDQs3NbsObWZOevd5fpc9tLWXZWq/7wQACxnwjgAdFCrDRqQN956O0kyZPCque4vf1gm2502fUb691tlkfaqqqrsstN22WrzjfPI40+X2zt37tximf9ktUEDW0x/79STs//eu3+oWl9/462MGL59eXrCxElpbPrX3QODBg5Y3GoAsNy1/p4xAGCFstP2W5d/njBxUi669MpFnree9e7sXHPjrfnpr37X6u3+z/fPytf+5/t54JHHM39+c4t570yaUh79PUlW7tsnfXqvVJ7u2rWmxfJTp8/Iv9v2I1ukuvpf1wsu+NNf886klreil0qlPDd2XH74s1/n+Q+4jf3K627OlKnTkix81vx3F17aYv7WW262xHUBYHlyZRwAOqijDz80N9xyZ3nU81+ff3H+dv3NWWfNNVLVqSoT35mcN8dPyIIFC/KRLTZt9XZLpVLuf/DR3P/go+nWrWvWX3ft9O3bJ7W1dXnuhXHl57GTZL+9Ptriavjqg1dLVVVV+b3fF/zprxnz7Nh069Y1Q1ZbNSd9/tNZuW+fHPGxA3PJX69Okoyf8E4OPuqEbLLhsPTt2ydz5tTmH6+/mdlzapMke+226xJrnTxlag4/7ovZeMP1M/GdSRk/4Z3yvJ49e+Sg/fZs9ecGgGVJGAeADmpA/34554ffyTe/+6PMmDkrSTJp8tRMmrzooGWdO7f+Zrn3h+t58xry7Nhxi11u8003ymePPapFW98+vTN8+23ywCOPJ0kaGhvz0GNPJknWX3ft8nJfOuGYzJg5KzfddneShe8zX9J+Pqj2ww4elauvvyWPPvF0i/ZOnTrl2//vy94xDkC7EcYBoAPbcvNNcuXFv8lV19+SBx55PG+8OT51dfXp2rVrBg3snw2HrZsdtvtIPrrzjq3e5k+//z958NEn8uSY5/LSq6/lnUlTylff+6zUK8PWWzt7jNg5+++zR7p06bzI+mf8z9fzq99flAcffjzTZ8xM87/dOp8sfM789FO/lv333j3X3Xx7nhs7LtNmzEpzc3P69F4paw4dkq023yS77To8GwxbZ4m17j5iePbefUTOv/iyPP/iS1nQvCCbbLR+TjjmSLeoA9Cuqkrv3ScGALCCu+GWO3P6mT8vT//2nB9mm602b7+CAGAJDOAGAAAABRPGAQAAoGDCOAAAABTMM+MAAABQMFfGAQAAoGDCOAAAABRMGAcAAICCCeMAAABQMGEcAAAACiaMAwAAQMGEcQAAACiYMA4AAAAF+/8ACmcpooeX2AAAAABJRU5ErkJggg==\n"},"metadata":{}}],"source":["from IPython.display import HTML\n","\n","start_time = time.time()\n","\n","idx = 0\n","\n","fig, ax = plt.subplots(facecolor='w', figsize=(12, 7))\n","labels=['0', '1', '2', '3', '4', '5', '6', '7', '8','9']\n","print(f\"The target label is: {targets[idx]}\")\n","\n","# plt.rcParams['animation.ffmpeg_path'] = 'C:\\\\path\\\\to\\\\your\\\\ffmpeg.exe'\n","\n","# Plot spike count histogram\n","anim = splt.spike_count(spk_rec[:, idx].detach().cpu(), fig, ax, labels=labels,\n"," animate=True, interpolate=1)\n","\n","display(HTML(anim.to_html5_video()))\n","# anim.save(\"spike_bar.mp4\")\n","\n","end_time = time.time()\n","\n","# Calculate elapsed time\n","elapsed_time = end_time - start_time\n","\n","# Convert elapsed time to minutes, seconds, and milliseconds\n","minutes, seconds = divmod(elapsed_time, 60)\n","seconds, milliseconds = divmod(seconds, 1)\n","milliseconds = round(milliseconds * 1000)"]},{"cell_type":"code","execution_count":86,"metadata":{"id":"ssI8LLReFGY-","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}},"outputId":"41b576a2-84ac-42fc-c986-f1babfeefa21"},"outputs":[{"output_type":"stream","name":"stdout","text":["Elapsed time: 10 minutes, 43 seconds, 29 milliseconds\n"]}],"source":["# Print the result\n","print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")"]},{"cell_type":"markdown","metadata":{"id":"OgY3fTk40u2j"},"source":["## 3 Run some Linear Networks for fun?\n","\n","Below commented out are some Fully Connected Linear Networks of different depth feel free to also run if you want."]},{"cell_type":"code","execution_count":87,"metadata":{"id":"Qe4ZCcPrxILT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":4,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# # FCN Network Architecture\n","# num_inputs = 10*10*2\n","# num_hidden = 1000\n","# num_outputs = 10\n","\n","# # fcsnn_net = nn.Sequential(nn.Linear(num_inputs, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_hidden),\n","# # snn.Leaky(beta=beta),\n","# # nn.Linear(num_hidden, num_outputs),\n","# # snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# # ).to(device)\n","\n","# fcsnn_net = nn.Sequential(nn.Flatten(),\n","# nn.Linear(num_inputs, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_outputs),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# optimizer = torch.optim.Adam(fcsnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","# loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"code","execution_count":88,"metadata":{"id":"NR95_6rwxtHT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# num_epochs = 10\n","# num_iters = 50\n","\n","# fcsnn_loss_hist = []\n","# fcsnn_acc_hist = []\n","\n","# # training loop\n","# for epoch in range(num_epochs):\n","# for i, (data, targets) in enumerate(iter(trainloader)):\n","# data = data.to(device)\n","# targets = targets.to(device)\n","\n","# fcsnn_net.train()\n","# spk_rec = forward_pass(fcsnn_net, data)\n","# loss_val = loss_fn(spk_rec, targets)\n","\n","# # Gradient calculation + weight update\n","# optimizer.zero_grad()\n","# loss_val.backward()\n","# optimizer.step()\n","\n","# # Store loss history for future plotting\n","# loss_hist.append(loss_val.item())\n","\n","# if i%4 == 0:\n","# print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n","# acc = SF.accuracy_rate(spk_rec, targets)\n","# acc_hist.append(acc)\n","\n","# if i%4 == 0:\n","# print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# # This will end training after 50 iterations by default\n","# # if i == num_iters:\n","# # break"]},{"cell_type":"code","execution_count":89,"metadata":{"id":"CanrIqh28RnT","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# import matplotlib.pyplot as plt\n","\n","# # Plot Loss\n","# fig = plt.figure(facecolor=\"w\")\n","# plt.plot(acc_hist)\n","# plt.title(\"Train Set Accuracy\")\n","# plt.xlabel(\"Iteration\")\n","# plt.ylabel(\"Accuracy\")\n","# plt.show()"]},{"cell_type":"code","execution_count":90,"metadata":{"id":"xqnwmc6Z-W9o","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# fcsnn_net_seven_layers = nn.Sequential(nn.Flatten(),\n","# nn.Linear(num_inputs, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_hidden),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True),\n","# nn.Linear(num_hidden, num_outputs),\n","# snn.Leaky(beta=beta, spike_grad=spike_grad, init_hidden=True, output=True)\n","# ).to(device)\n","\n","# optimizer = torch.optim.Adam(fcsnn_net_seven_layers.parameters(), lr=2e-2, betas=(0.9, 0.999))\n","# loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)"]},{"cell_type":"code","execution_count":91,"metadata":{"id":"sy-ZhyqN-wwu","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# num_epochs = 10\n","# num_iters = 50\n","\n","# fcsnn_loss_hist = []\n","# fcsnn_acc_hist = []\n","\n","# # training loop\n","# for epoch in range(num_epochs):\n","# for i, (data, targets) in enumerate(iter(trainloader)):\n","# data = data.to(device)\n","# targets = targets.to(device)\n","\n","# fcsnn_net_seven_layers.train()\n","# spk_rec = forward_pass(fcsnn_net_seven_layers, data)\n","# loss_val = loss_fn(spk_rec, targets)\n","\n","# # Gradient calculation + weight update\n","# optimizer.zero_grad()\n","# loss_val.backward()\n","# optimizer.step()\n","\n","# # Store loss history for future plotting\n","# loss_hist.append(loss_val.item())\n","\n","# if i%4 == 0:\n","# print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n","\n","# acc = SF.accuracy_rate(spk_rec, targets)\n","# acc_hist.append(acc)\n","\n","# if i%4 == 0:\n","# print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n","\n","# # This will end training after 50 iterations by default\n","# # if i == num_iters:\n","# # break"]},{"cell_type":"code","execution_count":92,"metadata":{"id":"XFrA769b-2ZO","executionInfo":{"status":"ok","timestamp":1702495943264,"user_tz":480,"elapsed":3,"user":{"displayName":"Dylan Louie","userId":"10934343627659142774"}}},"outputs":[],"source":["# import matplotlib.pyplot as plt\n","\n","# # Plot Loss\n","# fig = plt.figure(facecolor=\"w\")\n","# plt.plot(acc_hist)\n","# plt.title(\"Train Set Accuracy\")\n","# plt.xlabel(\"Iteration\")\n","# plt.ylabel(\"Accuracy\")\n","# plt.show()"]}],"metadata":{"colab":{"provenance":[{"file_id":"17lDMQYpEjA_oD-VmIG__qTlv1EdV9tjY","timestamp":1701726922112},{"file_id":"1j8MtYqWS5jQABVHORXeC9DR-DEX9tAmd","timestamp":1701120116694},{"file_id":"1Yy7yVKCye-TEzyVYB8217Au-DTzMzpKY","timestamp":1698117894739}],"gpuType":"T4"},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"name":"python"},"widgets":{"application/vnd.jupyter.widget-state+json":{"6dd945b6627844c1b3808b9ea8ab6646":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_fb003723433d4e8db855b590fdfbfedd","max":640,"min":0,"orientation":"horizontal","style":"IPY_MODEL_dc2254cf2e894a21a689246a66f0dfce","value":640}},"fb003723433d4e8db855b590fdfbfedd":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"dc2254cf2e894a21a689246a66f0dfce":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"aec192c607bf40b9a45a1f2b064ba30e":{"model_module":"@jupyter-widgets/controls","model_name":"IntProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"","description":"","description_tooltip":null,"layout":"IPY_MODEL_845cc10adccf489f8fecf05cc6fe2f93","max":320,"min":0,"orientation":"horizontal","style":"IPY_MODEL_d3ea533e5b164139abba9ab6f2c0a5ac","value":320}},"845cc10adccf489f8fecf05cc6fe2f93":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"d3ea533e5b164139abba9ab6f2c0a5ac":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}}}},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0} \ No newline at end of file diff --git a/examples/stmnist_snntorch.ipynb b/examples/stmnist_snntorch.ipynb new file mode 100644 index 00000000..746fa90c --- /dev/null +++ b/examples/stmnist_snntorch.ipynb @@ -0,0 +1,4496 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "0PD5VPOUr4bs" + }, + "source": [ + "[](https://github.com/jeshraghian/snntorch/)\n", + "[](https://github.com/neuromorphs/tonic/)\n", + "\n", + "\n", + "# Training on ST-MNIST with Tonic + snnTorch Tutorial\n", + "\n", + "##### By Dylan Louie (djlouie@ucsc.edu), Hannah Cohen Sandler (hcohensa@ucsc.edu), Shatoparba Banerjee (sbaner12@ucsc.edu)\n", + "\n", + "\n", + " \"Open\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iawcPZ7DtDqK" + }, + "source": [ + "For a comprehensive overview on how SNNs work, and what is going on under the hood, [then you might be interested in the snnTorch tutorial series available here.](https://snntorch.readthedocs.io/en/latest/tutorials/index.html)\n", + "The snnTorch tutorial series is based on the following paper. If you find these resources or code useful in your work, please consider citing the following source:\n", + "\n", + "> [Jason K. Eshraghian, Max Ward, Emre Neftci, Xinxin Wang, Gregor Lenz, Girish Dwivedi, Mohammed Bennamoun, Doo Seok Jeong, and Wei D. Lu. \"Training Spiking Neural Networks Using Lessons From Deep Learning\". Proceedings of the IEEE, 111(9) September 2023.](https://ieeexplore.ieee.org/abstract/document/10242251) " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "W-v36rDBv41L", + "outputId": "e548b514-1e5f-4d0d-e8f3-fdd55f228fa8" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m110.7/110.7 kB\u001b[0m \u001b[31m3.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m107.5/107.5 kB\u001b[0m \u001b[31m8.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.4/50.4 kB\u001b[0m \u001b[31m7.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m109.0/109.0 kB\u001b[0m \u001b[31m3.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.2/76.2 kB\u001b[0m \u001b[31m11.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h" + ] + } + ], + "source": [ + "!pip install tonic --quiet\n", + "!pip install snntorch --quiet" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "6WWIF2I1v7sA" + }, + "outputs": [], + "source": [ + "# tonic imports\n", + "import tonic\n", + "import tonic.transforms as transforms # Not to be mistaken with torchdata.transfroms\n", + "from tonic import DiskCachedDataset\n", + "\n", + "# torch imports\n", + "import torch\n", + "from torch.utils.data import random_split\n", + "from torch.utils.data import DataLoader\n", + "import torchvision\n", + "import torch.nn as nn\n", + "\n", + "# snntorch imports\n", + "import snntorch as snn\n", + "from snntorch import surrogate\n", + "import snntorch.spikeplot as splt\n", + "from snntorch import functional as SF\n", + "from snntorch import utils\n", + "\n", + "# other imports\n", + "import matplotlib.pyplot as plt\n", + "from IPython.display import HTML\n", + "from IPython.display import display\n", + "import numpy as np\n", + "import torchdata\n", + "import os\n", + "from ipywidgets import IntProgress\n", + "import time\n", + "import statistics" + ] + }, + { + "cell_type": "code", + "source": [ + "#@title Plotting Settings\n", + "def print_frame(copy_events):\n", + " print('----------------------------')\n", + " print(copy_events[0])\n", + " print('----------------------------')\n", + " print(copy_events[0][0])\n", + " print('----------------------------')\n", + " print(copy_events[0][0][0])" + ], + "metadata": { + "cellView": "form", + "id": "EtBwOxn9Ludx" + }, + "execution_count": 19, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "McXriEu-tJV6" + }, + "source": [ + "# 1. The ST-MNIST Dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wsV-uUeZ6a2A" + }, + "source": [ + "## 1.1 Introduction\n", + "\n", + "The Spiking Tactile-MNIST (ST-MNIST) dataset features handwritten digits (0-9) inscribed by 23 individuals on a 100-taxel biomimetic event-based tactile sensor array. This dataset captures the dynamic pressure changes associated with natural writing. The tactile sensing system, Asynchronously Coded Electronic Skin (ACES), emulates the human peripheral nervous system, transmitting fast-adapting (FA) responses as asynchronous electrical events.\n", + "\n", + "More information about the ST-MNIST dataset can be found in the following paper:\n", + "\n", + "> H. H. See, B. Lim, S. Li, H. Yao, W. Cheng, H. Soh, and B. C. K. Tee, \"ST-MNIST - The Spiking Tactile-MNIST Neuromorphic Dataset,\" A PREPRINT, May 2020. [Online]. Available: https://arxiv.org/abs/2005.04319 " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Ickp0FA4_nBR" + }, + "source": [ + "## 1.2 Downloading the ST-MNIST dataset\n", + "\n", + "ST-MNIST is in the `MAT` format. Tonic can be used transform this into an event-based format (x, y, t, p).\n", + "\n", + "1. Download the compressed dataset by accessing: https://scholarbank.nus.edu.sg/bitstream/10635/168106/2/STMNIST%20dataset%20NUS%20Tee%20Research%20Group.zip\n", + "\n", + "2. The zip file is `STMNIST dataset NUS Tee Research Group`. Create a parent folder titled `STMNIST` and place the zip file inside.\n", + "\n", + "3. If running in a cloud-based environment, e.g., on Colab, you will need to do this in Google Drive." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DnDx0axoCphC" + }, + "source": [ + "## 1.3 Mount to Drive\n", + "You may need to authorize the following to access Google Drive:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "c2PcG-B3v9K8", + "outputId": "7d67801b-2855-40ef-b338-789419af0b50" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Mounted at /content/drive\n" + ] + } + ], + "source": [ + "# Load the Drive helper and mount\n", + "from google.colab import drive\n", + "drive.mount('/content/drive')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yer7x6Mpwf9q" + }, + "source": [ + "After executing the cell above, Drive files will be present in \"/content/drive/MyDrive\". You may need to change the `root` file to your own path." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "00hHZOeuv-8k", + "outputId": "e60a16e7-3baf-4a20-d1cf-bc99dfb18022" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " 'STMNIST dataset NUS Tee Research Group.zip',\n", + " 'data_submission']" + ] + }, + "metadata": {}, + "execution_count": 52 + } + ], + "source": [ + "root = \"/content/drive/My Drive/\" # similar to os.path.join('content', 'drive', 'My Drive')\n", + "os.listdir(os.path.join(root, 'STMNIST')) # confirm the file exists" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OOfqmhKcIOR0" + }, + "source": [ + "## 1.4 ST-MNIST Using Tonic\n", + "\n", + "`Tonic` will be used to convert the dataset into a format compatible with PyTorch/snnTorch. The documentation can be found [here](https://tonic.readthedocs.io/en/latest/generated/tonic.prototype.datasets.STMNIST.html#tonic.prototype.datasets.STMNIST)." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "id": "4r9zaUjHwAcM" + }, + "outputs": [], + "source": [ + "dataset = tonic.prototype.datasets.STMNIST(root=root, keep_compressed = False, shuffle = False)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AgwoqxsAMdqP" + }, + "source": [ + "Tonic formats the STMNIST dataset into `(x, y, t, p)` tuples.\n", + "* `x` is the position on the x-axis\n", + "* `y` is the position on the y-axis\n", + "* `t` is a timestamp\n", + "* `p` is polarity; +1 if taxel pressed down, 0 if taxel released\n", + "\n", + "Each sample also contains the label, which is an integer 0-9 that corresponds to what digit is being drawn.\n", + "\n", + "An example of one of the events is shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2nRzg5A0RegL", + "outputId": "1ffb205a-ae3d-4ac5-e762-8124ab1938de" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "(2, 7, 199838, 0)\n", + "6\n" + ] + } + ], + "source": [ + "events, target = next(iter(dataset))\n", + "print(events[0])\n", + "print(target)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7mWT1BXPdeuM" + }, + "source": [ + "The `.ToFrame()` function from `tonic.transforms` transforms events from an (x, y, t, p) tuple to a numpy array matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Alt1gJkWSqjy", + "outputId": "78706825-055c-4f0d-d11d-1774b8529d50" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "----------------------------\n", + "[[[0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 3 4 0 0 0 0 0 0 0]\n", + " [0 2 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]]\n", + "\n", + " [[0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 4 0 0 0 0 0 0 0]\n", + " [0 6 3 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]]]\n", + "----------------------------\n", + "[[0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 3 4 0 0 0 0 0 0 0]\n", + " [0 2 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]\n", + " [0 0 0 0 0 0 0 0 0 0]]\n", + "----------------------------\n", + "[0 0 0 0 0 0 0 0 0 0]\n" + ] + } + ], + "source": [ + "sensor_size = tuple(tonic.prototype.datasets.STMNIST.sensor_size.values()) # The sensor size for STMNIST is (10, 10, 2)\n", + "\n", + "# filter noisy pixels and integrate events into 1ms frames\n", + "frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n", + " transforms.ToFrame(sensor_size=sensor_size,\n", + " time_window=20000)\n", + " ])\n", + "\n", + "transformed_events = frame_transform(events)\n", + "\n", + "print_frame(transformed_events)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l3CJDa1LnUzd" + }, + "source": [ + "## 1.5 Visualizations\n", + "\n", + "\n", + "Using `tonic.utils.plot_animation`, the frame transform, and also some rotation. We can create an animation of the data and visualize this." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "id": "kOFkuUfrplsg" + }, + "outputs": [], + "source": [ + "# Iterate to a new iteration\n", + "events, target = next(iter(dataset))" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "maDf7TLHmUiw", + "outputId": "06bbdc7d-68bf-4d93-fe90-80db5631cb4c" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Animation of ST-MNIST\n", + "The target label is: 3\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAGVCAYAAADZmQcFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAGKUlEQVR4nO3csW0DMRQFQdO4CtyKe3K3asUuga7gBALaAyVhJmbwssVPOOac8wMAHvS5ewAA70FQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJA4lh9OMa4csd7+t494MRt9wDg1ax8quJCASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEsfuAQ/72T3gjr/dA07cdg+453f3gBNfuwfA03OhAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBIDHmnHPp4RhXbwHgSa2kwoUCQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoACUEBICEoACQEBYCEoACQEBQAEoICQEJQAEgICgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAAlBASAhKAAkBAWAhKAAkBAUABKCAkBCUABICAoAiWP14Zzzyh0AvDgXCgAJQQEgISgAJAQFgISgAJAQFAASggJAQlAASAgKAIl/sNgYRltEIekAAAAASUVORK5CYII=\n" + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + " \n", + "
\n", + " \n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 57 + } + ], + "source": [ + "frame_transform_tonic_visual = tonic.transforms.ToFrame(\n", + " sensor_size=(10, 10, 2),\n", + " time_window=10000,\n", + ")\n", + "\n", + "frames = frame_transform_tonic_visual(events)\n", + "frames = frames / np.max(frames)\n", + "frames = np.rot90(frames, k=-1, axes=(2, 3))\n", + "frames = np.flip(frames, axis=3)\n", + "\n", + "# Print out the Target\n", + "print('Animation of ST-MNIST')\n", + "print('The target label is:',target)\n", + "animation = tonic.utils.plot_animation(frames)\n", + "\n", + "# Display the animation inline in a Jupyter notebook\n", + "HTML(animation.to_jshtml())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "w52aUd2qoyXV" + }, + "source": [ + "We can also use `snntorch.spikeplot`" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 926 + }, + "id": "bPwRVZgqo8EH", + "outputId": "a6eb9949-9b37-4fbc-a9e4-c06a1ba5183a" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Animation of ST-MNIST\n", + "The target label is: 3\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "" + ] + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAE4ElEQVR4nO3VMQHAMAzAsKz8OWefKbSHhMCfv93dAYCZObcDAHiHKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBATAGAmAIAMQUAYgoAxBQAiCkAEFMAIKYAQEwBgJgCADEFAGIKAMQUAIgpABBTACCmAEBMAYCYAgAxBQBiCgDEFACIKQAQUwAgpgBAfu8DBwYENNNsAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ], + "source": [ + "frame_transform_snntorch_visual = tonic.transforms.ToFrame(\n", + " sensor_size=(10, 10, 2),\n", + " time_window=8000,\n", + ")\n", + "\n", + "tran = frame_transform_snntorch_visual(events)\n", + "tran = np.rot90(tran, k=-1, axes=(2, 3))\n", + "tran = np.flip(tran, axis=3)\n", + "tran = torch.from_numpy(tran)\n", + "\n", + "tensor1 = tran[:, 0:1, :, :]\n", + "tensor2 = tran[:, 1:2, :, :]\n", + "\n", + "print('Animation of ST-MNIST')\n", + "print('The target label is:',target)\n", + "\n", + "fig, ax = plt.subplots()\n", + "time_steps = tensor1.size(0)\n", + "tensor1_plot = tensor1.reshape(time_steps, 10, 10)\n", + "anim = splt.animator(tensor1_plot, fig, ax, interval=10)\n", + "\n", + "display(HTML(anim.to_html5_video()))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CzYgPlxWfdm_" + }, + "source": [ + "There is a total of 6953 recordings in this dataset. The developers of ST-MNIST invited 23 participants to write each 10 digit approx. 30 times each: 23\\*30\\*10 = 6,900." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_v1auSbyepQr", + "outputId": "aa10b1b1-52f9-43fb-a183-27e5724fc1b0" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "6953\n" + ] + } + ], + "source": [ + "print(len(dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tlX9jWV0f_az" + }, + "source": [ + "## 1.6 Lets create a trainset and testset!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hqQzVEHEgSFp" + }, + "source": [ + "ST-MNIST isn't already seperated into a trainset and testset in Tonic. That means we will have to seperate it manually. In the process of seperating the data we will transform them using `.ToFrame()` as well." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "id": "d_6BFKiXJdWU" + }, + "outputs": [], + "source": [ + "sensor_size = tonic.prototype.datasets.STMNIST.sensor_size\n", + "sensor_size = tuple(sensor_size.values())\n", + "\n", + "# Define a transform\n", + "frame_transform = transforms.Compose([transforms.ToFrame(sensor_size=sensor_size, time_window=20000)])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iSMhDsHliQk5" + }, + "source": [ + "The following code reads out the a portion of the dataset, transforms the events using `frame_transform` defined above, and then seperates the data into a trainset and a testset. On top of that, `.ToFrame()` is applied each time. Thus, this code snippet might take a few minutes.\n", + "\n", + "For speed, we will just use a subset of the dataset. By default, 640 training samples and 320 testing samples. Feel free to change this if you have more patience than us." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136, + "referenced_widgets": [ + "8a99b133e85f4bb695664801a50839c8", + "fdbee8d3a50947f4ae15bc96922fa93e", + "65b936fc7fd940db8eab6847ea05d7ca", + "755b25b8bc1943389b5f9cd53f3c7862", + "54aed6bf532945ee9c8f756d69714673", + "156f838174924805b49be2ad66e793b5" + ] + }, + "id": "c0qw8uduLpZv", + "outputId": "415f5422-77bf-459d-9f57-73df1ba4703a" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Porting over and transforming the trainset.\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "IntProgress(value=0, max=640)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "8a99b133e85f4bb695664801a50839c8" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Porting over and transforming the testset.\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "IntProgress(value=0, max=320)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "755b25b8bc1943389b5f9cd53f3c7862" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Elapsed time: 2 minutes, 48 seconds, 514 milliseconds\n" + ] + } + ], + "source": [ + "def shorter_transform_STMNIST(data, transform):\n", + " short_train_size = 640\n", + " short_test_size = 320\n", + "\n", + " train_bar = IntProgress(min=0, max=short_train_size)\n", + " test_bar = IntProgress(min=0, max=short_test_size)\n", + "\n", + " testset = []\n", + " trainset = []\n", + "\n", + " print('Porting over and transforming the trainset.')\n", + " display(train_bar)\n", + " for _ in range(short_train_size):\n", + " events, target = next(iter(dataset))\n", + " events = transform(events)\n", + " trainset.append((events, target))\n", + " train_bar.value += 1\n", + " print('Porting over and transforming the testset.')\n", + " display(test_bar)\n", + " for _ in range(short_test_size):\n", + " events, target = next(iter(dataset))\n", + " events = transform(events)\n", + " testset.append((events, target))\n", + " test_bar.value += 1\n", + "\n", + " return (trainset, testset)\n", + "\n", + "start_time = time.time()\n", + "trainset, testset = shorter_transform_STMNIST(dataset, frame_transform)\n", + "elapsed_time = time.time() - start_time\n", + "\n", + "# Convert elapsed time to minutes, seconds, and milliseconds\n", + "minutes, seconds = divmod(elapsed_time, 60)\n", + "seconds, milliseconds = divmod(seconds, 1)\n", + "milliseconds = round(milliseconds * 1000)\n", + "\n", + "# Print the elapsed time\n", + "print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "98VVH_HSs-Gh" + }, + "source": [ + "## 1.6 Dataloading and Batching\n" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "id": "DPxzp1fdFe_X" + }, + "outputs": [], + "source": [ + "# Create a DataLoader\n", + "dataloader = DataLoader(trainset, batch_size=32, shuffle=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yORjaoQAuuY1" + }, + "source": [ + "For faster dataloading, we can use `DiskCashedDataset(...)` from Tonic.\n", + "\n", + "Due to variations in the lengths of event recordings, `tonic.collation.PadTensors()` will be used to prevent irregular tensor shapes. Shorter recordings are padded, ensuring uniform dimensions across all samples in a batch." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "id": "YaPsfB0ArUgQ" + }, + "outputs": [], + "source": [ + "transform = tonic.transforms.Compose([torch.from_numpy])\n", + "\n", + "cached_trainset = DiskCachedDataset(trainset, transform=transform, cache_path='./cache/stmnist/train')\n", + "\n", + "# no augmentations for the testset\n", + "cached_testset = DiskCachedDataset(testset, cache_path='./cache/stmnist/test')\n", + "\n", + "batch_size = 32\n", + "trainloader = DataLoader(cached_trainset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False), shuffle=True)\n", + "testloader = DataLoader(cached_testset, batch_size=batch_size, collate_fn=tonic.collation.PadTensors(batch_first=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0so65S95BDbf", + "outputId": "4a670cd0-1f61-4e89-b124-e357f526ec86" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([89, 32, 2, 10, 10])\n" + ] + } + ], + "source": [ + "# Query the shape of a sample: time x batch x dimensions\n", + "data_tensor, targets = next(iter(trainloader))\n", + "print(data_tensor.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QDGPdoBUw-ME" + }, + "source": [ + "## 1.7 Create the Spiking Convolutional Neural Network" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PRdPJemVH8uR" + }, + "source": [ + "Below we have by default a spiking convolutional neural network with the architecture: `10×10-32c4-64c3-MaxPool2d(2)-10o`." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "id": "W2ewqKLx8mMJ" + }, + "outputs": [], + "source": [ + "device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n", + "\n", + "# neuron and simulation parameters\n", + "beta = 0.95\n", + "\n", + "# This is the same architecture that was used in the STMNIST Paper\n", + "scnn_net = nn.Sequential(\n", + " nn.Conv2d(2, 32, kernel_size=4),\n", + " snn.Leaky(beta=beta, init_hidden=True),\n", + " nn.Conv2d(32, 64, kernel_size=3),\n", + " snn.Leaky(beta=beta, init_hidden=True),\n", + " nn.MaxPool2d(2),\n", + " nn.Flatten(),\n", + " nn.Linear(64 * 2 * 2, 10), # Increased size of the linear layer\n", + " snn.Leaky(beta=beta, init_hidden=True, output=True)\n", + ").to(device)\n", + "\n", + "optimizer = torch.optim.Adam(scnn_net.parameters(), lr=2e-2, betas=(0.9, 0.999))\n", + "loss_fn = SF.mse_count_loss(correct_rate=0.8, incorrect_rate=0.2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Sq_jz3xYxMxO" + }, + "source": [ + "## 1.8 Define the Forward Pass" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "id": "ydcyDZDt_qH_" + }, + "outputs": [], + "source": [ + "def forward_pass(net, data):\n", + " spk_rec = []\n", + " utils.reset(net) # resets hidden states for all LIF neurons in net\n", + "\n", + " for step in range(data.size(0)): # data.size(0) = number of time steps\n", + "\n", + " spk_out, mem_out = net(data[step])\n", + " spk_rec.append(spk_out)\n", + "\n", + " return torch.stack(spk_rec)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9tPywf6CxWcq" + }, + "source": [ + "## 1.9 Create and Run the Training Loop\n", + "\n", + "This might take a while, so kick back, take a break and eat a snack while this happens; perhaps even count kangaroos to take a nap or do a shoey and get schwasted instead." + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "lB9lYUP0AUBL", + "outputId": "dff0092d-4425-4c07-919e-7eb1bcb92700" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Epoch 0, Iteration 0 \n", + "Train Loss: 8.06\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 0, Iteration 4 \n", + "Train Loss: 42.37\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 0, Iteration 8 \n", + "Train Loss: 7.07\n", + "Accuracy: 15.62%\n", + "\n", + "Epoch 0, Iteration 12 \n", + "Train Loss: 8.73\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 0, Iteration 16 \n", + "Train Loss: 7.33\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 1, Iteration 0 \n", + "Train Loss: 5.88\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 1, Iteration 4 \n", + "Train Loss: 3.02\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 1, Iteration 8 \n", + "Train Loss: 3.61\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 1, Iteration 12 \n", + "Train Loss: 3.38\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 1, Iteration 16 \n", + "Train Loss: 3.45\n", + "Accuracy: 0.00%\n", + "\n", + "Epoch 2, Iteration 0 \n", + "Train Loss: 2.98\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 2, Iteration 4 \n", + "Train Loss: 3.33\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 2, Iteration 8 \n", + "Train Loss: 3.26\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 2, Iteration 12 \n", + "Train Loss: 2.90\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 2, Iteration 16 \n", + "Train Loss: 2.99\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 3, Iteration 0 \n", + "Train Loss: 3.11\n", + "Accuracy: 18.75%\n", + "\n", + "Epoch 3, Iteration 4 \n", + "Train Loss: 2.86\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 3, Iteration 8 \n", + "Train Loss: 3.27\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 3, Iteration 12 \n", + "Train Loss: 3.13\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 3, Iteration 16 \n", + "Train Loss: 3.16\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 4, Iteration 0 \n", + "Train Loss: 3.20\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 4, Iteration 4 \n", + "Train Loss: 3.12\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 4, Iteration 8 \n", + "Train Loss: 3.29\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 4, Iteration 12 \n", + "Train Loss: 2.98\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 4, Iteration 16 \n", + "Train Loss: 3.03\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 5, Iteration 0 \n", + "Train Loss: 2.92\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 5, Iteration 4 \n", + "Train Loss: 2.93\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 5, Iteration 8 \n", + "Train Loss: 2.95\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 5, Iteration 12 \n", + "Train Loss: 2.98\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 5, Iteration 16 \n", + "Train Loss: 2.96\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 6, Iteration 0 \n", + "Train Loss: 2.97\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 6, Iteration 4 \n", + "Train Loss: 3.07\n", + "Accuracy: 15.62%\n", + "\n", + "Epoch 6, Iteration 8 \n", + "Train Loss: 3.13\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 6, Iteration 12 \n", + "Train Loss: 3.19\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 6, Iteration 16 \n", + "Train Loss: 3.22\n", + "Accuracy: 12.50%\n", + "\n", + "Epoch 7, Iteration 0 \n", + "Train Loss: 3.06\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 7, Iteration 4 \n", + "Train Loss: 3.30\n", + "Accuracy: 15.62%\n", + "\n", + "Epoch 7, Iteration 8 \n", + "Train Loss: 3.24\n", + "Accuracy: 3.12%\n", + "\n", + "Epoch 7, Iteration 12 \n", + "Train Loss: 3.13\n", + "Accuracy: 15.62%\n", + "\n", + "Epoch 7, Iteration 16 \n", + "Train Loss: 3.50\n", + "Accuracy: 18.75%\n", + "\n", + "Epoch 8, Iteration 0 \n", + "Train Loss: 2.94\n", + "Accuracy: 6.25%\n", + "\n", + "Epoch 8, Iteration 4 \n", + "Train Loss: 3.46\n", + "Accuracy: 9.38%\n", + "\n", + "Epoch 8, Iteration 8 \n", + "Train Loss: 3.23\n", + "Accuracy: 21.88%\n", + "\n", + "Epoch 8, Iteration 12 \n", + "Train Loss: 2.72\n", + "Accuracy: 28.12%\n", + "\n", + "Epoch 8, Iteration 16 \n", + "Train Loss: 3.14\n", + "Accuracy: 15.62%\n", + "\n", + "Epoch 9, Iteration 0 \n", + "Train Loss: 2.97\n", + "Accuracy: 25.00%\n", + "\n", + "Epoch 9, Iteration 4 \n", + "Train Loss: 2.71\n", + "Accuracy: 18.75%\n", + "\n", + "Epoch 9, Iteration 8 \n", + "Train Loss: 2.88\n", + "Accuracy: 34.38%\n", + "\n", + "Epoch 9, Iteration 12 \n", + "Train Loss: 2.61\n", + "Accuracy: 40.62%\n", + "\n", + "Epoch 9, Iteration 16 \n", + "Train Loss: 3.06\n", + "Accuracy: 21.88%\n", + "\n", + "Epoch 10, Iteration 0 \n", + "Train Loss: 2.65\n", + "Accuracy: 34.38%\n", + "\n", + "Epoch 10, Iteration 4 \n", + "Train Loss: 2.90\n", + "Accuracy: 40.62%\n", + "\n", + "Epoch 10, Iteration 8 \n", + "Train Loss: 2.99\n", + "Accuracy: 21.88%\n", + "\n", + "Epoch 10, Iteration 12 \n", + "Train Loss: 2.54\n", + "Accuracy: 59.38%\n", + "\n", + "Epoch 10, Iteration 16 \n", + "Train Loss: 2.50\n", + "Accuracy: 40.62%\n", + "\n", + "Epoch 11, Iteration 0 \n", + "Train Loss: 2.62\n", + "Accuracy: 43.75%\n", + "\n", + "Epoch 11, Iteration 4 \n", + "Train Loss: 2.35\n", + "Accuracy: 50.00%\n", + "\n", + "Epoch 11, Iteration 8 \n", + "Train Loss: 2.42\n", + "Accuracy: 59.38%\n", + "\n", + "Epoch 11, Iteration 12 \n", + "Train Loss: 2.31\n", + "Accuracy: 65.62%\n", + "\n", + "Epoch 11, Iteration 16 \n", + "Train Loss: 2.71\n", + "Accuracy: 50.00%\n", + "\n", + "Epoch 12, Iteration 0 \n", + "Train Loss: 2.17\n", + "Accuracy: 59.38%\n", + "\n", + "Epoch 12, Iteration 4 \n", + "Train Loss: 1.95\n", + "Accuracy: 68.75%\n", + "\n", + "Epoch 12, Iteration 8 \n", + "Train Loss: 2.27\n", + "Accuracy: 59.38%\n", + "\n", + "Epoch 12, Iteration 12 \n", + "Train Loss: 2.13\n", + "Accuracy: 65.62%\n", + "\n", + "Epoch 12, Iteration 16 \n", + "Train Loss: 1.89\n", + "Accuracy: 75.00%\n", + "\n", + "Epoch 13, Iteration 0 \n", + "Train Loss: 2.04\n", + "Accuracy: 59.38%\n", + "\n", + "Epoch 13, Iteration 4 \n", + "Train Loss: 1.98\n", + "Accuracy: 71.88%\n", + "\n", + "Epoch 13, Iteration 8 \n", + "Train Loss: 2.18\n", + "Accuracy: 62.50%\n", + "\n", + "Epoch 13, Iteration 12 \n", + "Train Loss: 2.13\n", + "Accuracy: 62.50%\n", + "\n", + "Epoch 13, Iteration 16 \n", + "Train Loss: 1.89\n", + "Accuracy: 75.00%\n", + "\n", + "Epoch 14, Iteration 0 \n", + "Train Loss: 1.77\n", + "Accuracy: 78.12%\n", + "\n", + "Epoch 14, Iteration 4 \n", + "Train Loss: 2.01\n", + "Accuracy: 71.88%\n", + "\n", + "Epoch 14, Iteration 8 \n", + "Train Loss: 2.11\n", + "Accuracy: 62.50%\n", + "\n", + "Epoch 14, Iteration 12 \n", + "Train Loss: 2.18\n", + "Accuracy: 68.75%\n", + "\n", + "Epoch 14, Iteration 16 \n", + "Train Loss: 2.02\n", + "Accuracy: 62.50%\n", + "\n", + "Epoch 15, Iteration 0 \n", + "Train Loss: 1.36\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 15, Iteration 4 \n", + "Train Loss: 1.83\n", + "Accuracy: 75.00%\n", + "\n", + "Epoch 15, Iteration 8 \n", + "Train Loss: 2.13\n", + "Accuracy: 68.75%\n", + "\n", + "Epoch 15, Iteration 12 \n", + "Train Loss: 1.86\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 15, Iteration 16 \n", + "Train Loss: 1.95\n", + "Accuracy: 71.88%\n", + "\n", + "Epoch 16, Iteration 0 \n", + "Train Loss: 1.38\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 16, Iteration 4 \n", + "Train Loss: 1.86\n", + "Accuracy: 78.12%\n", + "\n", + "Epoch 16, Iteration 8 \n", + "Train Loss: 1.59\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 16, Iteration 12 \n", + "Train Loss: 2.07\n", + "Accuracy: 75.00%\n", + "\n", + "Epoch 16, Iteration 16 \n", + "Train Loss: 1.87\n", + "Accuracy: 78.12%\n", + "\n", + "Epoch 17, Iteration 0 \n", + "Train Loss: 1.85\n", + "Accuracy: 68.75%\n", + "\n", + "Epoch 17, Iteration 4 \n", + "Train Loss: 1.90\n", + "Accuracy: 78.12%\n", + "\n", + "Epoch 17, Iteration 8 \n", + "Train Loss: 1.88\n", + "Accuracy: 71.88%\n", + "\n", + "Epoch 17, Iteration 12 \n", + "Train Loss: 1.89\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 17, Iteration 16 \n", + "Train Loss: 1.41\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 18, Iteration 0 \n", + "Train Loss: 1.37\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 18, Iteration 4 \n", + "Train Loss: 1.57\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 18, Iteration 8 \n", + "Train Loss: 1.50\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 18, Iteration 12 \n", + "Train Loss: 1.55\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 18, Iteration 16 \n", + "Train Loss: 1.50\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 19, Iteration 0 \n", + "Train Loss: 1.69\n", + "Accuracy: 78.12%\n", + "\n", + "Epoch 19, Iteration 4 \n", + "Train Loss: 1.53\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 19, Iteration 8 \n", + "Train Loss: 1.60\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 19, Iteration 12 \n", + "Train Loss: 1.29\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 19, Iteration 16 \n", + "Train Loss: 1.73\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 20, Iteration 0 \n", + "Train Loss: 1.44\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 20, Iteration 4 \n", + "Train Loss: 1.48\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 20, Iteration 8 \n", + "Train Loss: 1.53\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 20, Iteration 12 \n", + "Train Loss: 1.69\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 20, Iteration 16 \n", + "Train Loss: 1.34\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 21, Iteration 0 \n", + "Train Loss: 1.45\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 21, Iteration 4 \n", + "Train Loss: 1.28\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 21, Iteration 8 \n", + "Train Loss: 1.90\n", + "Accuracy: 68.75%\n", + "\n", + "Epoch 21, Iteration 12 \n", + "Train Loss: 1.54\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 21, Iteration 16 \n", + "Train Loss: 1.59\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 22, Iteration 0 \n", + "Train Loss: 1.44\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 22, Iteration 4 \n", + "Train Loss: 1.18\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 22, Iteration 8 \n", + "Train Loss: 1.33\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 22, Iteration 12 \n", + "Train Loss: 1.78\n", + "Accuracy: 81.25%\n", + "\n", + "Epoch 22, Iteration 16 \n", + "Train Loss: 1.45\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 23, Iteration 0 \n", + "Train Loss: 1.07\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 23, Iteration 4 \n", + "Train Loss: 1.26\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 23, Iteration 8 \n", + "Train Loss: 1.46\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 23, Iteration 12 \n", + "Train Loss: 1.54\n", + "Accuracy: 84.38%\n", + "\n", + "Epoch 23, Iteration 16 \n", + "Train Loss: 1.63\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 24, Iteration 0 \n", + "Train Loss: 1.29\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 24, Iteration 4 \n", + "Train Loss: 1.27\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 24, Iteration 8 \n", + "Train Loss: 1.43\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 24, Iteration 12 \n", + "Train Loss: 1.17\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 24, Iteration 16 \n", + "Train Loss: 1.28\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 25, Iteration 0 \n", + "Train Loss: 1.26\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 25, Iteration 4 \n", + "Train Loss: 1.26\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 25, Iteration 8 \n", + "Train Loss: 1.00\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 25, Iteration 12 \n", + "Train Loss: 1.35\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 25, Iteration 16 \n", + "Train Loss: 1.14\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 26, Iteration 0 \n", + "Train Loss: 0.86\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 26, Iteration 4 \n", + "Train Loss: 1.12\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 26, Iteration 8 \n", + "Train Loss: 1.12\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 26, Iteration 12 \n", + "Train Loss: 1.23\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 26, Iteration 16 \n", + "Train Loss: 1.31\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 27, Iteration 0 \n", + "Train Loss: 1.22\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 27, Iteration 4 \n", + "Train Loss: 0.96\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 27, Iteration 8 \n", + "Train Loss: 1.23\n", + "Accuracy: 87.50%\n", + "\n", + "Epoch 27, Iteration 12 \n", + "Train Loss: 0.96\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 27, Iteration 16 \n", + "Train Loss: 1.18\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 28, Iteration 0 \n", + "Train Loss: 1.11\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 28, Iteration 4 \n", + "Train Loss: 1.06\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 28, Iteration 8 \n", + "Train Loss: 1.19\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 28, Iteration 12 \n", + "Train Loss: 1.04\n", + "Accuracy: 96.88%\n", + "\n", + "Epoch 28, Iteration 16 \n", + "Train Loss: 1.11\n", + "Accuracy: 93.75%\n", + "\n", + "Epoch 29, Iteration 0 \n", + "Train Loss: 0.86\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 29, Iteration 4 \n", + "Train Loss: 1.24\n", + "Accuracy: 90.62%\n", + "\n", + "Epoch 29, Iteration 8 \n", + "Train Loss: 0.93\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 29, Iteration 12 \n", + "Train Loss: 0.97\n", + "Accuracy: 100.00%\n", + "\n", + "Epoch 29, Iteration 16 \n", + "Train Loss: 1.38\n", + "Accuracy: 87.50%\n", + "\n", + "Elapsed time: 2 minutes, 45 seconds, 187 milliseconds\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "num_epochs = 30\n", + "\n", + "loss_hist = []\n", + "acc_hist = []\n", + "\n", + "# training loop\n", + "for epoch in range(num_epochs):\n", + " for i, (data, targets) in enumerate(iter(trainloader)):\n", + " data = data.to(device)\n", + " targets = targets.to(device)\n", + "\n", + " scnn_net.train()\n", + " spk_rec = forward_pass(scnn_net, data)\n", + " loss_val = loss_fn(spk_rec, targets)\n", + "\n", + " # Gradient calculation + weight update\n", + " optimizer.zero_grad()\n", + " loss_val.backward()\n", + " optimizer.step()\n", + "\n", + " # Store loss history for future plotting\n", + " loss_hist.append(loss_val.item())\n", + "\n", + " # Print loss every 4 iterations\n", + " if i%4 == 0:\n", + " print(f\"Epoch {epoch}, Iteration {i} \\nTrain Loss: {loss_val.item():.2f}\")\n", + "\n", + " # Calculate accuracy rate and then append it to accuracy history\n", + " acc = SF.accuracy_rate(spk_rec, targets)\n", + " acc_hist.append(acc)\n", + "\n", + " # Print accuracy every 4 iterations\n", + " if i%4 == 0:\n", + " print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n", + "\n", + "end_time = time.time()\n", + "\n", + "# Calculate elapsed time\n", + "elapsed_time = end_time - start_time\n", + "\n", + "# Convert elapsed time to minutes, seconds, and milliseconds\n", + "minutes, seconds = divmod(elapsed_time, 60)\n", + "seconds, milliseconds = divmod(seconds, 1)\n", + "milliseconds = round(milliseconds * 1000)\n", + "\n", + "# Print the elapsed time\n", + "print(f\"Elapsed time: {int(minutes)} minutes, {int(seconds)} seconds, {milliseconds} milliseconds\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "h6wfP5Jjbf2V" + }, + "source": [ + "Uncomment the code below if you want to save the model" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "id": "g9Fq4CYvbinS" + }, + "outputs": [], + "source": [ + "# torch.save(scnn_net.state_dict(), 'scnn_net.pth')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cEY6Ynbq0JmX" + }, + "source": [ + "# 2. Results" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yYSkN_kp0Lm0" + }, + "source": [ + "## 2.1 Plot accuracy history" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 472 + }, + "id": "X0SYWQDJ6qhx", + "outputId": "a16dd2e9-71ae-4552-ed57-b94550531454" + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACXhUlEQVR4nO2dd3wUdf7/X9s3PYGQ0AJBQIp0EAQLoigqFvA8kfME0dPTg696nOeJBWwnVg4Lwk891FM8sXtnAZEqHoI0ERCkRRAh1PSybX5/LLP5zOzM7uxmk91sXs/HgwfZ2SmfnUDmlde7mSRJkkAIIYQQkiSY470AQgghhJBYQnFDCCGEkKSC4oYQQgghSQXFDSGEEEKSCoobQgghhCQVFDeEEEIISSoobgghhBCSVFDcEEIIISSpoLghhBBCSFJBcUMIAQDceOONKCwsjPcyCCGk3lDcEJLgmEwmQ39WrFgR76UGUVRUhEmTJqFz585wOp1o3bo1zjvvPMyYMSOq833++ed46KGHojp28ODBMJlMmDt3blTHE0KaDibOliIksXnrrbcUr//1r39hyZIlePPNNxXbL7roIuTn50d9HbfbDZ/PB4fDEfU5RHbv3o0zzzwTKSkpuOmmm1BYWIhDhw5h48aN+OKLL1BTUxPxOadMmYI5c+Yg0h9bu3btwumnn47CwkK0a9cOq1evjvjahJCmgzXeCyCEhOb3v/+94vW3336LJUuWBG1XU1VVhdTUVMPXsdlsUa1Pj3/84x+oqKjA5s2b0bFjR8V7R44ciem1wvHWW28hLy8Pzz77LK655hoUFRUlZAjO5/PB5XLB6XTGeymENGkYliIkCTj//PPRq1cvbNiwAeeddx5SU1Nx3333AQA++eQTjB49Gm3btoXD4UDnzp3x6KOPwuv1Ks6hzrkpKiqCyWTCM888g5dffhmdO3eGw+HAmWeeie+++y7smvbs2YP27dsHCRsAyMvLC9r2xRdf4Nxzz0VaWhoyMjIwevRobNu2TbG+OXPmAFCG6ozw9ttv45prrsHll1+OrKwsvP3225r7rV27FpdddhlycnKQlpaGPn364LnnnlPss2PHDlx77bVo1aoVUlJS0K1bN9x///2KdWoJp4ceeihovSaTCVOmTMGCBQtwxhlnwOFwYNGiRQCAZ555BsOGDUPLli2RkpKCgQMH4v3339dc91tvvYXBgwcjNTUVOTk5OO+88/Dll18CACZOnIjc3Fy43e6g4y6++GJ069ZN/8YR0kShuCEkSTh+/DguvfRS9OvXD7Nnz8aIESMAAK+//jrS09MxdepUPPfccxg4cCCmT5+Oe++919B53377bTz99NP44x//iMceewxFRUW4+uqrNR+WIh07dsSBAwewbNmysNd48803MXr0aKSnp+PJJ5/Egw8+iO3bt+Occ85BUVERAOCPf/wjLrroosD+8p9wrF27Frt378b48eNht9tx9dVXY8GCBUH7LVmyBOeddx62b9+OO++8E88++yxGjBiBTz/9NLDPli1bMGTIECxbtgy33HILnnvuOYwZMwb//e9/w65Dj2XLluHPf/4zxo0bh+eeey4gjJ577jn0798fjzzyCB5//HFYrVb89re/xWeffaY4/uGHH8YNN9wAm82GRx55BA8//DAKCgoC9/2GG27A8ePHsXjxYsVxhw8fxrJly8I6gIQ0SSRCSJNi8uTJkvq/7vDhwyUA0rx584L2r6qqCtr2xz/+UUpNTZVqamoC2yZOnCh17Ngx8Hrfvn0SAKlly5bSiRMnAts/+eQTCYD03//+N+Q6t27dKqWkpEgApH79+kl33nmn9PHHH0uVlZWK/crLy6Xs7GzplltuUWw/fPiwlJWVpdiu9dnDMWXKFKmgoEDy+XySJEnSl19+KQGQNm3aFNjH4/FInTp1kjp27CidPHlScbx8nCRJ0nnnnSdlZGRIP//8s+4+6vsoM2PGjKC1A5DMZrO0bdu2oP3V3zeXyyX16tVLuuCCCwLbdu3aJZnNZmns2LGS1+vVXJPX65Xat28vjRs3TvH+rFmzJJPJJO3duzfo2oQ0dejcEJIkOBwOTJo0KWh7SkpK4Ovy8nIcO3YM5557LqqqqrBjx46w5x03bhxycnICr88991wAwN69e0Med8YZZ2Dz5s34/e9/j6KiooDLkZ+fj1deeSWw35IlS1BSUoLx48fj2LFjgT8WiwVDhgzB8uXLw65RD4/Hg4ULF2LcuHGBkNAFF1yAvLw8hXuzadMm7Nu3D3fddReys7MV55CPO3r0KFatWoWbbroJHTp00NwnGoYPH46ePXsGbRe/bydPnkRpaSnOPfdcbNy4MbD9448/hs/nw/Tp02E2K3+cy2sym824/vrr8Z///Afl5eWB9xcsWIBhw4ahU6dOUa+dkESF4oaQJKFdu3aw2+1B27dt24axY8ciKysLmZmZaNWqVSAUUVpaGva86ge5LHROnjwZ9tjTTz8db775Jo4dO4YtW7YEwiu33norvvrqKwD+SibALzpatWql+PPll1/WK/n4yy+/xNGjRzF48GDs3r0bu3fvxr59+zBixAj8+9//hs/nA+DPDwKAXr166Z5LFnOh9okGPXHx6aef4qyzzoLT6USLFi3QqlUrzJ07V/E927NnD8xms6Y4EpkwYQKqq6vx0UcfAQB27tyJDRs24IYbbojdByEkgWC1FCFJgvibvkxJSQmGDx+OzMxMPPLII4F+Mxs3bsTf/va3wMM9FBaLRXO7FEE5tsViQe/evdG7d28MHToUI0aMwIIFCzBy5MjAGt588020bt066FirNfofU7I7c+2112q+v3LlykBuUqzQc3HUCdwyWt+3r7/+GldeeSXOO+88vPTSS2jTpg1sNhtee+013WToUPTs2RMDBw7EW2+9hQkTJuCtt96C3W7XvS+ENHUobghJYlasWIHjx4/jww8/xHnnnRfYvm/fvritadCgQQCAQ4cOAQA6d+4MwF9BNXLkyJDHRhL+qaysxCeffIJx48bhmmuuCXr/jjvuwIIFCzBixIjAGrZu3aq7htNOOy2wTyhycnJQUlIStP3nn382vPYPPvgATqcTixcvVvQdeu211xT7de7cGT6fD9u3b0e/fv1CnnPChAmYOnUqDh06hLfffhujR49WhBsJSSYYliIkiZFdF9FlcblceOmllxr82l9//bVmRdXnn38OAIES5FGjRiEzMxOPP/645v5Hjx4NfJ2WlgYAmuJBzUcffYTKykpMnjwZ11xzTdCfyy+/HB988AFqa2sxYMAAdOrUCbNnzw46t3zvWrVqhfPOOw/z58/H/v37NfcB/IKjtLQUW7ZsCWw7dOhQICRkBIvFApPJpHB7ioqK8PHHHyv2GzNmDMxmMx555JEgF07trI0fPx4mkwl33nkn9u7dyyopktTQuSEkiRk2bBhycnIwceJE3HHHHTCZTHjzzTcj7vAbDU8++SQ2bNiAq6++Gn369AEAbNy4Ef/617/QokUL3HXXXQCAzMxMzJ07FzfccAMGDBiA6667Dq1atcL+/fvx2Wef4eyzz8aLL74IABg4cCAAv+syatQoWCwWXHfddZrXX7BgAVq2bIlhw4Zpvn/llVfilVdewWeffYarr74ac+fOxRVXXIF+/fph0qRJaNOmDXbs2IFt27YFyqiff/55nHPOORgwYABuvfVWdOrUCUVFRfjss8+wefNmAMB1112Hv/3tbxg7dizuuOMOVFVVYe7cuTj99NMVycChGD16NGbNmoVLLrkEv/vd73DkyBHMmTMHXbp0UYimLl264P7778ejjz6Kc889F1dffTUcDge+++47tG3bFjNnzgzs26pVK1xyySV47733kJ2djdGjRxtaCyFNkniWahFCIkevFPyMM87Q3P+bb76RzjrrLCklJUVq27atdM8990iLFy+WAEjLly8P7KdXCv70008HnROANGPGjJDr/Oabb6TJkydLvXr1krKysiSbzSZ16NBBuvHGG6U9e/YE7b98+XJp1KhRUlZWluR0OqXOnTtLN954o7R+/frAPh6PR/q///s/qVWrVpLJZNItCy8uLpasVqt0ww036K6vqqpKSk1NlcaOHRvYtnr1aumiiy6SMjIypLS0NKlPnz7SCy+8oDhu69at0tixY6Xs7GzJ6XRK3bp1kx588EHFPl9++aXUq1cvyW63S926dZPeeust3VLwyZMna67vn//8p9S1a1fJ4XBI3bt3l1577TXNc0iSJM2fP1/q37+/5HA4pJycHGn48OHSkiVLgvZ79913JQDSrbfeqntfCEkGOFuKEEKaCZ988gnGjBmDVatWBUr6CUlGKG4IIaSZcPnll+PHH3/E7t2769Wbh5BEhzk3hBCS5LzzzjvYsmULPvvsMzz33HMUNiTpoXNDCCFJjslkQnp6OsaNG4d58+bVq3cQIU0B/gsnhJAkh7/DkuYG+9wQQgghJKmguCGEEEJIUtHswlI+nw+//vorMjIymFRHCCGENBEkSUJ5eTnatm0Lszm0N9PsxM2vv/6KgoKCeC+DEEIIIVFw4MABtG/fPuQ+zU7cZGRkAPDfnMzMzDivhhBCCCFGKCsrQ0FBQeA5HopmJ27kUFRmZibFDSGEENLEMJJSwoRiQgghhCQVFDeEEEIISSoobgghhBCSVFDcEEIIISSpoLghhBBCSFJBcUMIIYSQpILihhBCCCFJBcUNIYQQQpIKihtCCCGEJBUUN4QQQghJKuIqblatWoUrrrgCbdu2hclkwscffxz2mBUrVmDAgAFwOBzo0qULXn/9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\n" + }, + "metadata": {} + } + ], + "source": [ + "# Plot Loss\n", + "fig = plt.figure(facecolor=\"w\")\n", + "plt.plot(acc_hist)\n", + "plt.title(\"Train Set Accuracy\")\n", + "plt.xlabel(\"Iteration\")\n", + "plt.ylabel(\"Accuracy\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hhx12ZJP0eF7" + }, + "source": [ + "## 2.2 Evaluate the Network on the Test Set" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BTjjGQHuhQ7i", + "outputId": "4ce8c530-c92a-4759-926d-bf7fc5a48849" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "The average loss across the testloader is: 0.65\n" + ] + } + ], + "source": [ + "# Make sure your model is in evaluation mode\n", + "scnn_net.eval()\n", + "\n", + "# Initialize variables to store predictions and ground truth labels\n", + "acc_hist = []\n", + "\n", + "# Iterate over batches in the testloader\n", + "with torch.no_grad():\n", + " for data, targets in testloader:\n", + " # Move data and targets to the device (GPU or CPU)\n", + " data = data.to(device)\n", + " targets = targets.to(device)\n", + "\n", + " # Forward pass\n", + " spk_rec = forward_pass(scnn_net, data)\n", + "\n", + " acc = SF.accuracy_rate(spk_rec, targets)\n", + " acc_hist.append(acc)\n", + "\n", + " # if i%10 == 0:\n", + " # print(f\"Accuracy: {acc * 100:.2f}%\\n\")\n", + "\n", + "print(\"The average loss across the testloader is:\", statistics.mean(acc_hist))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1a-oeEzK0Xvt" + }, + "source": [ + "## 2.3 Visualize Spike Recordings\n", + "\n", + "The following visual is a spike count histogram for a single target and single piece of data using the spike recording list." + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "id": "ZJArj6jlXBEs" + }, + "outputs": [], + "source": [ + "spk_rec = forward_pass(scnn_net, data)" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "tJSBM-ctXETI", + "outputId": "e788d7f4-db1e-4438-fd70-3a9e03884ebc" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "The target label is: 3\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "" + ] + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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\n" + }, + "metadata": {} + } + ], + "source": [ + "from IPython.display import HTML\n", + "\n", + "idx = 8\n", + "fig, ax = plt.subplots(facecolor='w', figsize=(12, 7))\n", + "labels=['0', '1', '2', '3', '4', '5', '6', '7', '8','9']\n", + "print(f\"The target label is: {targets[idx]}\")\n", + "\n", + "# Plot spike count histogram\n", + "anim = splt.spike_count(spk_rec[:, idx].detach().cpu(), fig, ax, labels=labels,\n", + " animate=True, interpolate=1)\n", + "\n", + "display(HTML(anim.to_html5_video()))\n", + "# anim.save(\"spike_bar.mp4\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dhkWLN0dYr16" + }, + "source": [ + "# Congratulations!\n", + "You trained a Spiking CNN using `snnTorch` and `Tonic` on ST-MNIST!" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "gpuType": "T4", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "8a99b133e85f4bb695664801a50839c8": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "model_module_version": "1.5.0", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "IntProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fdbee8d3a50947f4ae15bc96922fa93e", + "max": 640, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_65b936fc7fd940db8eab6847ea05d7ca", + "value": 640 + } + }, + "fdbee8d3a50947f4ae15bc96922fa93e": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "model_module_version": "1.2.0", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "65b936fc7fd940db8eab6847ea05d7ca": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "model_module_version": "1.5.0", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "755b25b8bc1943389b5f9cd53f3c7862": { + "model_module": "@jupyter-widgets/controls", + "model_name": "IntProgressModel", + "model_module_version": "1.5.0", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "IntProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_54aed6bf532945ee9c8f756d69714673", + "max": 320, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_156f838174924805b49be2ad66e793b5", + "value": 320 + } + }, + "54aed6bf532945ee9c8f756d69714673": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "model_module_version": "1.2.0", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "156f838174924805b49be2ad66e793b5": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "model_module_version": "1.5.0", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From 90f6ac195f2ddd553a2dc0974dd4b620eb1a8881 Mon Sep 17 00:00:00 2001 From: jeshraghian Date: Fri, 8 Mar 2024 15:41:23 -0800 Subject: [PATCH 13/13] revert table --- docs/tutorials/tutorials.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/tutorials/tutorials.rst b/docs/tutorials/tutorials.rst index b3958f2a..e8f3bc3a 100644 --- a/docs/tutorials/tutorials.rst +++ b/docs/tutorials/tutorials.rst @@ -52,11 +52,6 @@ The tutorial consists of a series of Google Colab notebooks. Static non-editable :alt: Open In Colab :target: https://colab.research.google.com/github/jeshraghian/snntorch/blob/master/examples/tutorial_7_neuromorphic_datasets.ipynb - * - Tutorial 8 - - Training on ST-MNIST with Tonic + snnTorch Tutorial - - .. image:: https://colab.research.google.com/assets/colab-badge.svg - :alt: Open In Colab - :target: https://colab.research.google.com/drive/1P2yQCDmp7TilNrEqj_cBzS7vscIs0L_o?usp=sharing .. list-table:: :widths: 70 32