From d723f37a8751c57aa08e9d4c75c49163f36b72ee Mon Sep 17 00:00:00 2001 From: Laurent Perrinet Date: Tue, 5 Dec 2023 18:35:46 +0100 Subject: [PATCH 1/2] using `tonic` in place of `spikedata` * adapted notebooks to use tonic instead of the deprecated `spikedata` module * added a `DATADIR` variable to let user choose their data directory (`/tmp` has the nice property of getting easily flushed..) * fixed an error to a call of a deprecated torch function: `AttributeError: module 'torch' has no attribute '_six'` * removed all outputs to reduce size of notebooks --- examples/dataloaders/DVS_Gesture.ipynb | 246 +++++++++-------- examples/dataloaders/NMNIST.ipynb | 191 ++++++++++---- .../spiking_heidelberg_digits_dataset.ipynb | 249 +++++------------- snntorch/spikeplot.py | 2 +- snntorch/spikevision/neuromorphic_dataset.py | 6 +- 5 files changed, 353 insertions(+), 341 deletions(-) diff --git a/examples/dataloaders/DVS_Gesture.ipynb b/examples/dataloaders/DVS_Gesture.ipynb index 89b24156..c8110818 100644 --- a/examples/dataloaders/DVS_Gesture.ipynb +++ b/examples/dataloaders/DVS_Gesture.ipynb @@ -1,69 +1,92 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "DVS_Gesture.ipynb", - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "code", + "execution_count": null, "metadata": { "id": "K7t_qlnTVWWS" }, + "outputs": [], "source": [ - "!pip install snntorch" - ], - "execution_count": null, - "outputs": [] + "# have you installed snn torch?\n", + "# %pip install snntorch" + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "YpJrTa3XVaSQ" }, + "outputs": [], "source": [ - "import snntorch as snn\n", - "from snntorch.spikevision import spikedata \n", - "from torch.utils.data import DataLoader" - ], + "import snntorch as snn\n" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "DATADIR = \"/tmp/data\"" + ] }, { "cell_type": "markdown", - "metadata": { - "id": "N7kYJ5reVeDA" - }, + "metadata": {}, "source": [ - "## Download Dataset" + "## Download Dataset using `spikedata` (deprecated)" ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "kbHJ827iVcYY" }, + "outputs": [], "source": [ - "# note that a default transform is already applied to keep things easy\n", + "# from snntorch.spikevision import spikedata \n", + "# # note that a default transform is already applied to keep things easy\n", "\n", - "dvs_train = spikedata.DVSGesture(\"data/dvsgesture\", train=True, dt=1000, num_steps=500, ds=1) # ds: spatial compression; dt: temporal compressiondvs_test\n", - "dvs_test = spikedata.DVSGesture(\"data/dvsgesture\", train=False, dt=1000, num_steps=1800, ds=1)" - ], + "# train_ds = spikedata.DVSGesture(\"/tmp/data/dvsgesture\", train=True, dt=1000, num_steps=500, ds=1) # ds: spatial compression; dt: temporal compressiondvs_test\n", + "# test_ds = spikedata.DVSGesture(\"/tmp/data/dvsgesture\", train=False, dt=1000, num_steps=1800, ds=1)\n", + "# test_ds" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Download Dataset using `tonic`" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "import tonic\n", + "import tonic.transforms as transforms\n", + "\n", + "sensor_size = tonic.datasets.DVSGesture.sensor_size\n", + "\n", + "# Denoise removes isolated, one-off events\n", + "# time_window\n", + "frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n", + " transforms.ToFrame(sensor_size=sensor_size,\n", + " time_window=1000)\n", + " ])\n", + "\n", + "train_ds = tonic.datasets.DVSGesture(save_to=DATADIR, transform=frame_transform, train=True)\n", + "test_ds = tonic.datasets.DVSGesture(save_to=DATADIR, transform=frame_transform, train=False)" + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -72,22 +95,9 @@ "id": "AWQTG9lhVmKY", "outputId": "3d607d3e-b416-4a47-e61e-4d562ed52dba" }, + "outputs": [], "source": [ - "dvs_test" - ], - "execution_count": 1, - "outputs": [ - { - "output_type": "error", - "ename": "NameError", - "evalue": "ignored", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdvs_test\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'dvs_test' is not defined" - ] - } + "test_ds" ] }, { @@ -101,93 +111,123 @@ }, { "cell_type": "code", - "metadata": { - "id": "TWhGAeVLVws5" - }, + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "dvs_train_dl = DataLoader(dvs_train, shuffle=True, batch_size=64)\n", - "dvs_test_dl = DataLoader(dvs_test, shuffle=False, batch_size=64)" - ], + "from torch.utils.data import DataLoader\n", + "\n", + "train_dl = DataLoader(train_ds, shuffle=True, batch_size=64)\n", + "test_dl = DataLoader(test_ds, shuffle=False, batch_size=64)" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "print('the number of items in the dataset is', len(train_dl.dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Play with Data" + ] }, { "cell_type": "code", - "metadata": { - "id": "MhwnXKs_VxgZ" - }, + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# get a feel for the data\n", - "dvs_train_dl.dataset[0][0].size()" - ], + "i_item = 42 # random index into a sample\n", + "data, label = train_dl.dataset[i_item]\n", + "import torch\n", + "data = torch.Tensor(data)\n", + "\n", + "print('The data sample has size', data.shape)\n", + "print(f\"in case you're blind AF, the target is: {label} ({train_ds.classes[label]})\")" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "train_ds.classes" + ] }, { "cell_type": "markdown", - "metadata": { - "id": "i8mEmv8PV9qK" - }, + "metadata": {}, "source": [ - "## Visualization" + "## Visualize" ] }, { "cell_type": "code", - "metadata": { - "id": "iTt_4BlqV3vP" - }, + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "n = 3 # random index into a sample\n", + "import matplotlib.pyplot as plt\n", + "import snntorch.spikeplot as splt\n", + "from IPython.display import HTML, display\n", + "import numpy as np\n", "\n", "# flatten on-spikes and off-spikes into one channel\n", - "a = (dvs_train_dl.dataset[n][0][:, 0] + dvs_train_dl.dataset[n][0][:, 1])\n", - "print(f\"in case you're blind AF, the target is: {spikedata.dvs_gesture.mapping[dvs_train_dl.dataset[n][1]]}\")\n", - "\n", + "# a = (train_dl.dataset[n][0][:, 0] + train_dl.dataset[n][0][:, 1])\n", + "a = (data[:300, 0, :, :] - data[:300, 1, :, :])\n", + "# a = np.swapaxes(a, 0, -1)\n", "# Plot\n", "fig, ax = plt.subplots()\n", - "anim = splt.animator(a, fig, ax, interval=10)\n", + "anim = splt.animator(a, fig, ax, interval=200)\n", "HTML(anim.to_html5_video())\n", - "\n", "# anim.save('nmnist_animation.mp4', writer = 'ffmpeg', fps=50) " - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "iDDqdJ1YWBns" }, + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", - "import torch" - ], - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "id": "JpiRF7pqV9AJ" - }, - "source": [ - "plt.imshow(torch.sum(dvs_train_dl.dataset[4][0][:300,0,:,:], axis=0), cmap='hot')\n", + "import torch\n", + "plt.imshow(torch.sum(data[:300, 0,:,:], axis=0), cmap='hot')\n", "plt.colorbar()" - ], - "execution_count": null, - "outputs": [] + ] + } + ], + "metadata": { + "colab": { + "name": "DVS_Gesture.ipynb", + "provenance": [] }, - { - "cell_type": "code", - "metadata": { - "id": "7gZariHNWH-X" + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 }, - "source": [ - "spikedata.dvs_gesture.mapping" - ], - "execution_count": null, - "outputs": [] + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/examples/dataloaders/NMNIST.ipynb b/examples/dataloaders/NMNIST.ipynb index 2d6ef830..f5f1976e 100644 --- a/examples/dataloaders/NMNIST.ipynb +++ b/examples/dataloaders/NMNIST.ipynb @@ -1,42 +1,36 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "NMNIST.ipynb", - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "code", + "execution_count": null, "metadata": { "id": "lRuXm7d4UpIT" }, + "outputs": [], "source": [ - "!pip install snntorch" - ], - "execution_count": null, - "outputs": [] + "# have you installed snn torch?\n", + "# %pip install snntorch" + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "qtbidebHU1PP" }, + "outputs": [], "source": [ - "import snntorch as snn\n", - "from snntorch.spikevision import spikedata " - ], + "import snntorch as snn\n" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "DATADIR = \"/tmp/data\"" + ] }, { "cell_type": "markdown", @@ -44,33 +38,82 @@ "id": "Yr8wE2ybU4RQ" }, "source": [ - "## Download Dataset" + "## Download Dataset using `spikedata` (deprecated)" ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "rhskczZfU3Wo" }, + "outputs": [], "source": [ + "from snntorch.spikevision import spikedata \n", "# note that a default transform is already applied\n", - "\n", - "train_ds = spikedata.NMNIST(\"data/nmnist\", train=True, num_steps=300, dt=1000) # dt is the # of microseconds integrated\n", - "test_ds = spikedata.NMNIST(\"data/nmnist\", train=False, num_steps=300, dt=1000)\n" - ], - "execution_count": null, - "outputs": [] + "train_ds = spikedata.NMNIST(f\"{DATADIR}/nmnist\", train=True, num_steps=300, dt=1000) # dt is the # of microseconds integrated\n", + "test_ds = spikedata.NMNIST(f\"{DATADIR}/nmnist\", train=False, num_steps=300, dt=1000)" + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "IUoggS_uVAB3" }, + "outputs": [], "source": [ "train_ds " - ], + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Download Dataset using `tonic`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tonic\n", + "train_ds = tonic.datasets.NMNIST(save_to=DATADIR, train=True)\n", + "test_ds = tonic.datasets.NMNIST(save_to=DATADIR, train=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tonic\n", + "import tonic.transforms as transforms\n", + "\n", + "sensor_size = tonic.datasets.NMNIST.sensor_size\n", + "\n", + "# Denoise removes isolated, one-off events\n", + "# time_window\n", + "frame_transform = transforms.Compose([transforms.Denoise(filter_time=10000),\n", + " transforms.ToFrame(sensor_size=sensor_size,\n", + " time_window=1000),\n", + " ])\n", + "\n", + "train_ds = tonic.datasets.NMNIST(save_to=DATADIR, transform=frame_transform, train=True)\n", + "test_ds = tonic.datasets.NMNIST(save_to=DATADIR, transform=frame_transform, train=False)" + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "train_ds" + ] }, { "cell_type": "markdown", @@ -83,29 +126,49 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "aC1cno26VEu8" }, + "outputs": [], "source": [ "from torch.utils.data import DataLoader\n", "\n", "train_dl = DataLoader(train_ds, shuffle=True, batch_size=64)\n", "test_dl = DataLoader(test_ds, shuffle=False, batch_size=64)" - ], + ] + }, + { + "cell_type": "code", "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": [ + "print('the number of items in the dataset is', len(train_dl.dataset))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Play with Data" + ] }, { "cell_type": "code", - "metadata": { - "id": "B535MTroVFMO" - }, + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# get a feel for the data\n", - "train_dl.dataset[0][0].size() # index into one sample" - ], - "execution_count": null, - "outputs": [] + "i_item = 20000 # random index into a sample\n", + "data, label = train_dl.dataset[i_item]\n", + "import torch\n", + "data = torch.Tensor(data)\n", + "\n", + "print('The data sample has size', data.shape)\n", + "print(f\"in case you're blind AF, the target is: {label}\")" + ] }, { "cell_type": "markdown", @@ -118,29 +181,51 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "-zNTZOC3VIKg" }, + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import snntorch.spikeplot as splt\n", - "from IPython.display import HTML\n", - "\n", - "n = 20000 # random index into a sample\n", + "from IPython.display import HTML, display\n", + "import numpy as np\n", "\n", "# flatten on-spikes and off-spikes into one channel\n", - "a = (train_dl.dataset[n][0][:, 0] + train_dl.dataset[n][0][:, 1])\n", - "print(f\"in case you're blind AF, the target is: {train_dl.dataset[n][1]}\")\n", - "\n", + "# a = (train_dl.dataset[n][0][:, 0] + train_dl.dataset[n][0][:, 1])\n", + "a = (data[:, 0, :, :] - data[:, 1, :, :])\n", + "# a = np.swapaxes(a, 0, -1)\n", "# Plot\n", "fig, ax = plt.subplots()\n", "anim = splt.animator(a, fig, ax, interval=30)\n", "HTML(anim.to_html5_video())\n", - "\n", "# anim.save('nmnist_animation.mp4', writer = 'ffmpeg', fps=50) " - ], - "execution_count": null, - "outputs": [] + ] + } + ], + "metadata": { + "colab": { + "name": "NMNIST.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/examples/dataloaders/spiking_heidelberg_digits_dataset.ipynb b/examples/dataloaders/spiking_heidelberg_digits_dataset.ipynb index 7b3eeff9..ececff68 100644 --- a/examples/dataloaders/spiking_heidelberg_digits_dataset.ipynb +++ b/examples/dataloaders/spiking_heidelberg_digits_dataset.ipynb @@ -1,14 +1,5 @@ { "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "TPblP70RZoQD" - }, - "source": [ - "# SpikeVision Test" - ] - }, { "cell_type": "code", "execution_count": null, @@ -19,50 +10,37 @@ "id": "j1HOtQ93l4qa", "outputId": "3f407944-6e49-4b30-824f-a89645798007" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fatal: destination path 'snntorch' already exists and is not an empty directory.\n" - ] - } - ], + "outputs": [], "source": [ - "!pip install snntorch" + "# have you installed snn torch?\n", + "# %pip install snntorch" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "id": "WZth_wmDYx5l" }, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'snntorch'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0msnntorch\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0msnn\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0msnntorch\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mspikevision\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mspikedata\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'snntorch'" - ] - } - ], + "outputs": [], "source": [ - "import snntorch as snn\n", - "from snntorch.spikevision import spikedata" + "import snntorch as snn\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "DATADIR = \"/tmp/data\"" ] }, { "cell_type": "markdown", - "metadata": { - "id": "SRk6IlX3UB3t" - }, + "metadata": {}, "source": [ - "## Downlaod Dataset" + "## Download Dataset using `spikedata` (deprecated)" ] }, { @@ -94,71 +72,12 @@ "id": "W3vKlBvha59s", "outputId": "ed492df0-e2fb-49fe-b521-50c64c2a0eec" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The following files do not exist, will attempt download:\n", - "dataset/shd/shd_train.hdf5\n", - "dataset/shd/shd_test.hdf5\n", - "Downloading https://compneuro.net/datasets/shd_test.h5.gz to dataset/shd/shd_test.h5.gz\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c154e80dcd7b4060bd7010b57eb555a2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))" - ] - }, - "metadata": { - "tags": [] - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Extracting dataset/shd/shd_test.h5.gz to dataset/shd\n", - "Downloading https://compneuro.net/datasets/shd_train.h5.gz to dataset/shd/shd_train.h5.gz\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f0527c7b6fa24f3db1c91819d31c4950", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))" - ] - }, - "metadata": { - "tags": [] - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Extracting dataset/shd/shd_train.h5.gz to dataset/shd\n", - "Creating shd.hdf5...\n", - "shd.hdf5 was created successfully.\n" - ] - } - ], + "outputs": [], "source": [ + "from snntorch.spikevision import spikedata\n", "# note that a default transform is already applied to keep things easy\n", - "train_ds = spikedata.SHD(\"dataset/shd\", train=True)\n", - "test_ds = spikedata.SHD(\"dataset/shd\", train=False)" + "train_ds = spikedata.SHD(\"/tmp/dataset/shd\", train=True)\n", + "test_ds = spikedata.SHD(\"/tmp/dataset/shd\", train=False)" ] }, { @@ -171,35 +90,29 @@ "id": "0T3EgUtkk1iH", "outputId": "4d19117c-e616-470a-837d-c3a414745961" }, - "outputs": [ - { - "data": { - "text/plain": [ - "Dataset SHD\n", - " Number of datapoints: 8156\n", - " Root location: dataset/shd/shd.hdf5\n", - " StandardTransform\n", - "Transform: Compose(\n", - " Downsample(dt = {0}, dp = {1}, dx = {2}, dy = {3})\n", - " ToChannelHeightWidth()\n", - " ToCountFrame(T=1000)\n", - " ToTensor(device:cpu)\n", - " hflip()\n", - " )\n", - "Target transform: " - ] - }, - "execution_count": 10, - "metadata": { - "tags": [] - }, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "train_ds" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Download Dataset using `tonic`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import tonic\n", + "train_ds = tonic.datasets.SHD(save_to=DATADIR, train=True)\n", + "test_ds = tonic.datasets.SHD(save_to=DATADIR, train=False)" + ] + }, { "cell_type": "markdown", "metadata": { @@ -223,6 +136,15 @@ "test_dl = DataLoader(test_ds, shuffle=False, batch_size=64)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print('the number of items in the dataset is', len(train_dl.dataset))" + ] + }, { "cell_type": "markdown", "metadata": { @@ -242,24 +164,24 @@ "id": "ZmOAoGogk7CV", "outputId": "5204b9a8-978f-44cf-e14f-db60c31d3da9" }, - "outputs": [ - { - "data": { - "text/plain": [ - "torch.Size([1000, 700])" - ] - }, - "execution_count": 12, - "metadata": { - "tags": [] - }, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# get a feel for the data\n", + "i_item = 4242 # random index into a sample\n", + "data, label = train_dl.dataset[i_item]\n", "\n", - "test_dl.dataset[0][0].size() #index into sample 0" + "print('The data sample has size', data.shape)\n", + "print(f\"in case you're blind AF, the target is: {label}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "train_dl.dataset[i_item]" ] }, { @@ -282,51 +204,16 @@ "id": "TzpeG8Shedze", "outputId": "22f0ad69-a013-444f-9b46-7147891057b2" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "torch.Size([1000, 700])\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 14, - "metadata": { - "tags": [] - }, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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6NixY0REVCwWQ/9/9atfpccee4y++tWvEhHRN7/5TXrsscfom9/8JhERTUxMBPfhk8SYiIhGRkbo85//fHCP119/nYiIzjrrLDp27BgdPnyYvvSlL9Hjjz9OH/zgBxvKosslOHz4MB09epQOHz6ccis1wleGKEj9S6USHTx4sOEaH/rQh2jXrl30oQ99iIhO9s0999wTnPv5z3+eJiYmqFgs0rFjx2hsbIyIiDZt2kQ7d+6k8fFxIqLg/zPPPDP4/9ixY/T4448TEdFzzz0X6ps//OEPoXKOjo6G/v/Hf/xHevPNN2lsbIz+/Oc/B78dPHgwdN6ePXto3bqTj+lZZ51Fk5OTREQ0OTkZ3OM3v/kN7dy5kzZu3EhERH/+85/pySefJCKiJ598kl5++WUiInr55Zfp4MGDtLCwQJOTk/Sxj32MSqUSveMd7yCiU2NrYmKCzjrrrOCeN998Mz322GP08Y9/nObm5oLvv/e979Hvf/97KhaLdP3119Pk5CS98cYbdN9999HmzZuJiGjz5s10ww030O9//3uanJwMritlJSKam5ujXbt2ERHRO97xDrr55puJmWl4eJh27NhBRKeeD42dO3fSkSNHiIhC/X7w4EGqVqt08ODBYIzI/y4cPnyY7rrrLrrzzjvphhtuCP2GY+q6666jqakpuu666xqu8cEPfpB+/vOf0znnnENERLOzs8Fv5513XvB5YmIi1NY33ngjVatVuvHGG4NyHz58mEqlEl188cV03333Bc/gDTfcQEePHqUbbriBbrvtNnrsscfotttuC5X1scceIyKi+fn5oA10m/z93/897dq1i6699lo6cuQI7dy5M1SXlZWVoM//8z//kxYXF+m6666jkZEReuWVV6her1O1WqUPfehDwf0mJiZCbVWv14mIqF6v0//+7/8SEdGJEyeIiGjr1q10880308TEBL3//e+n97///TQ1NUX/8A//QIuLi1Qqlei8886jV199lYgoGHdEJ5/pUqlEi4uLdOONN9JXvvKVUF3uu+8+euWVV2hycpIuvfRS+q//+i+688476ZlnnqGpqSnas2dP0P7ve9/7gnv84Q9/oIWFBXrHO97hHDMf/ehHnWNKxqBuQz12Wpnfoq5nyDA6zeqSoN8UK3yr1aZAraDo1ABJTIeYBwj9tuSavshCrei4fCd0JvQ4vxbXZx/i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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [] - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import snntorch.spikeplot as splt\n", "\n", - "n = 2000\n", - "\n", - "print(test_dl.dataset[n][0].size())\n", - "\n", "fig = plt.figure(facecolor=\"w\", figsize=(10, 5))\n", "ax = fig.add_subplot(111)\n", "\n", - "splt.raster(test_dl.dataset[n][0], ax, s=1.5, c=\"black\")" + "# splt.raster(test_dl.dataset[n][0], ax, s=1.5, c=\"black\")\n", + "tonic.utils.plot_event_grid(data)" ] } ], @@ -350,7 +237,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.11.6" }, "widgets": { "application/vnd.jupyter.widget-state+json": { diff --git a/snntorch/spikeplot.py b/snntorch/spikeplot.py index 81f1fe50..e0b945cc 100644 --- a/snntorch/spikeplot.py +++ b/snntorch/spikeplot.py @@ -78,7 +78,7 @@ def animator(data, fig, ax, num_steps=False, interval=40, cmap="plasma"): for step in range( num_steps ): # im appears unused but is required by camera.snap() - im = ax.imshow(data[step], cmap=cmap) # noqa: F841 + im = ax.imshow(data[step], cmap=cmap, vmin=data.min(), vmax=data.max()) # noqa: F841 camera.snap() anim = camera.animate(interval=interval) diff --git a/snntorch/spikevision/neuromorphic_dataset.py b/snntorch/spikevision/neuromorphic_dataset.py index 7108762e..749fd4e5 100644 --- a/snntorch/spikevision/neuromorphic_dataset.py +++ b/snntorch/spikevision/neuromorphic_dataset.py @@ -12,7 +12,7 @@ # Adapted from https://github.com/nmi-lab/torchneuromorphic # by Emre Neftci and Clemens Schaefer -DEFAULT_ROOT = "data/" +# DEFAULT_ROOT = "data/" def download_url(url, root, filename=None, md5=None, total_size=None): @@ -142,8 +142,8 @@ def __init__( target_transform_train=None, target_transform_test=None, ): - if isinstance(root, torch._six.string_classes): - root = os.path.expanduser(root) + # if isinstance(root, torch._six.string_classes): + # root = os.path.expanduser(root) self.root = root if root is not None: From 44779a9075c7d7e2659ac3469629d997508c5fdc Mon Sep 17 00:00:00 2001 From: Laurent Perrinet Date: Wed, 6 Dec 2023 17:29:12 +0100 Subject: [PATCH 2/2] Update NMNIST.ipynb --- examples/dataloaders/NMNIST.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/dataloaders/NMNIST.ipynb b/examples/dataloaders/NMNIST.ipynb index f5f1976e..c4955dff 100644 --- a/examples/dataloaders/NMNIST.ipynb +++ b/examples/dataloaders/NMNIST.ipynb @@ -194,11 +194,12 @@ "\n", "# flatten on-spikes and off-spikes into one channel\n", "# a = (train_dl.dataset[n][0][:, 0] + train_dl.dataset[n][0][:, 1])\n", + "data = (data>=1).float() # some spikes are equal to 2...\n", "a = (data[:, 0, :, :] - data[:, 1, :, :])\n", "# a = np.swapaxes(a, 0, -1)\n", "# Plot\n", "fig, ax = plt.subplots()\n", - "anim = splt.animator(a, fig, ax, interval=30)\n", + "anim = splt.animator(a, fig, ax, interval=30, cmap='seismic')\n", "HTML(anim.to_html5_video())\n", "# anim.save('nmnist_animation.mp4', writer = 'ffmpeg', fps=50) " ]