From 23a0591630c4bfb95ae3c82abb92cb95cbbcc6f2 Mon Sep 17 00:00:00 2001 From: Nigel Barink Date: Thu, 30 Mar 2023 19:41:46 +0200 Subject: [PATCH] Dataloaders and datasets --- .gitignore | 2 +- data.ipynb | 267 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 +- 3 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 data.ipynb diff --git a/.gitignore b/.gitignore index 2603ec8..a712188 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ data -venv +.venv .vscode diff --git a/data.ipynb b/data.ipynb new file mode 100644 index 0000000..40614f8 --- /dev/null +++ b/data.ipynb @@ -0,0 +1,267 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Code for processing data samples can get messy and hard to maintain; we ideally want our dataset code to be decoupled from our model training code for better readability and modularity. PyTorch provides two data primitives: torch.utils.data.DataLoader and torch.utils.data.Dataset that allow you to use pre-loaded datasets as well as your own data. Dataset stores the samples and their corresponding labels, and DataLoader wraps an iterable around the Dataset to enable easy access to the samples." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch.utils.data import Dataset\n", + "from torchvision import datasets\n", + "from torchvision.transforms import ToTensor\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Using FashionMNIST dataset as an example again!\n", + "\n", + "training_data = datasets.FashionMNIST(\n", + " root=\"data\", # Path where the data will be / is stored \n", + " train=True, # Specify wheter this is for training or test\n", + " download=True, # Should we download the data if its not available in previously specified `root` path\n", + " transform=ToTensor() # Feature and label Transformations \n", + ")\n", + "\n", + "test_data = datasets.FashionMNIST(\n", + " root=\"data\",\n", + " train=False,\n", + " download=True,\n", + " transform=ToTensor()\n", + ")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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220iItKpU6cLOl6gIiQlJcmnn34qW7ZskY4dO1ofu3r1apk/f778/Oc/l+joaHnxxRfl9ttvl3379kmDBg2suTt27JC7775bxo4dK/fff79ccsklMmvWLBk9erRcccUVMmbMGBERSU1NrbDXBlQ377//vrRs2VJ69ux53seOHj1aZs6cKUOHDpVJkybJf/7zH3n22Wdl27ZtsmDBgtLHvf766xIVFSUTJ06UqKgoWbFihfzmN7+R48ePy3PPPSciIr/61a8kNzdXDhw4IC+88IKIyAU1U+ICeI7YsGGDJyLe8uXLPc/zvJKSEq9Zs2behAkTyjwuPT3dExGvQYMG3tGjR0vjCxcu9ETEe//990tjw4cP9yIjIz3P87zVq1d7MTEx3qBBg7xTp06Vec4+ffp4ffr0Kf33WbNmeXXq1PH+/e9/l3ncK6+84omIt2bNGutrGT58uCci5f5p2rSp9/nnn5d57MMPP+yJSJl95eXleSkpKV5ycrJXXFzseZ7nTZ061RMR74033ih9XGFhoXfVVVd5UVFR3vHjxz3P87zDhw97IuI99dRT1mMEKsuHH37oBQcHe8HBwd5VV13lPfroo96yZcu8wsLCMo8TES80NNTbvXt3aWzz5s2eiHjTp08vjb322mueiHjp6emlsaSkJE9EvKVLl5bbf2RkpDd8+PAKf11AdZObm+uJiHfzzTef97GbNm3yRMQbPXp0mfgjjzziiYi3YsWK0lhBQUG5/LFjx3oRERFl7p+DBg3ykpKSAj5+mDnzq97Zs2dL48aN5dprrxWR70Y93HXXXTJ37twyXy+fddddd0m9evVK//2aa64Rke9+bXqulStXyoABA+T666+X+fPnn/ePxN966y1p166dtG3bVrKzs0v/ue6660qf73zCwsJk+fLlsnz5clm2bJm8+uqrEhUVJQMHDpSdO3eWPm7x4sVyxRVXyNVXX10ai4qKkjFjxsjevXtLu4AXL14sCQkJcvfdd5c+LiQkRB566CHJz8+Xjz/++LzHBFSFG264QT799FO56aabZPPmzTJlyhQZMGCANG3aVN57770yj+3Xr1+Zb+Q6deokMTExxuv4XCkpKTJgwIAKP36gpjh+/LiIiERHR5/3sYsXLxYRkYkTJ5aJT5o0SUSkzJ8Xff+3YXl5eZKdnS3XXHONFBQUyPbt23/wccPOiV/1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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Iterating and Visulalizing the Dataset\n", + "\"\"\"\n", + "We can index Datasets manually like a list: training_data[index].\n", + "We use matplotlib to visualize some samples in our training data.\n", + "\"\"\"\n", + "labels_map = {\n", + " 0: \"T-Shirt\",\n", + " 1: \"Trouser\",\n", + " 2: \"Pullover\",\n", + " 3: \"Dress\",\n", + " 4: \"Coat\",\n", + " 5: \"Sandal\",\n", + " 6: \"Shirt\",\n", + " 7: \"Sneaker\",\n", + " 8: \"Bag\",\n", + " 9: \"Ankle Boot\",\n", + "}\n", + "\n", + "figure = plt.figure(figsize=(8,8))\n", + "cols, rows = 3, 3\n", + "for i in range(1, cols * rows + 1):\n", + " sample_idx = torch.randint(len(training_data), size=(1,)).item()\n", + " img, label = training_data[sample_idx]\n", + " figure.add_subplot(rows, cols, i)\n", + " plt.title(labels_map[label])\n", + " plt.axis(\"off\")\n", + " plt.imshow(img.squeeze(), cmap=\"gray\")\n", + "\n", + "plt.show()\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A custom Dataset class must implement three functions: __init__, __len__, and __getitem__. Take a look at this implementation; the FashionMNIST images are stored in a directory img_dir, and their labels are stored separately in a CSV file annotations_file." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import pandas as pd\n", + "from torchvision.io import read_image\n", + "\n", + "class CustomImageDataset(Dataset):\n", + " def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):\n", + " self.img_labels = pd.read_csv(annotations_file)\n", + " self.img_dir = img_dir\n", + " self.transform = transform\n", + " self.target_transform = target_transform\n", + "\n", + "\n", + " def __len__(self):\n", + " return len(self.img_labels)\n", + " \n", + " def __getitem__(self, idx):\n", + " img_path = os.path.joi(self.img_dir, self.img_labels.iloc[idx,0])\n", + " image = read_image(img_path)\n", + " label = self.img_labels.iloc[idx,1]\n", + " if self.transform:\n", + " image = self.transform(image)\n", + " if self.target_transform:\n", + " label = self.target_transform(label)\n", + " return image, label\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The __init__ function is run once when instantiating the Dataset object. We initialize the directory containing the images, the annotations file, and both transforms\n", + "\n", + "The labels.csv file looks like:\n", + "\n", + "```csv\n", + "\n", + "tshirt1.jpg, 0\n", + "tshirt2.jpg, 0\n", + "......\n", + "ankleboot999.jpg, 9\n", + "\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The __len__ function returns the number of samples in our dataset." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The __getitem__ function loads and returns a sample from the dataset at the given index idx. Based on the index, it identifies the image’s location on disk, converts that to a tensor using read_image, retrieves the corresponding label from the csv data in self.img_labels, calls the transform functions on them (if applicable), and returns the tensor image and corresponding label in a tuple." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preparing data for training with DataLoaders\n", + "\n", + "The Dataset retrieves our dataset’s features and labels one sample at a time. While training a model, we typically want to pass samples in “minibatches”, reshuffle the data at every epoch to reduce model overfitting, and use Python’s multiprocessing to speed up data retrieval.\n", + "\n", + "DataLoader is an iterable that abstracts this complexity for us in an easy API." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from torch.utils.data import DataLoader\n", + "\n", + "train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)\n", + "test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have loaded that dataset into the DataLoader and can iterate through the dataset as needed. Each iteration below returns a batch of train_features and train_labels (containing batch_size=64 features and labels respectively). Because we specified shuffle=True, after we iterate over all batches the data is shuffled (for finer-grained control over the data loading order, take a look at Samplers)." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feature batch shape; torch.Size([64, 1, 28, 28])\n", + "Labels batch shape: torch.Size([64])\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAikklEQVR4nO3deWxVdf7/8VcL7YVCe0tbuklZZV+qIFTC8kWpLE6MKJlR9A8wBqJTzAA6mjoq6kzSGc2o0TCYSRzQRNxmWKJjcBSkRC2MIFgLWmkttkgXBLvTFuj5/UHs/Cogvg9tP215PpKT0Hvvq/fD6SkvTu+574Z4nucJAIAOFup6AQCAyxMFBABwggICADhBAQEAnKCAAABOUEAAACcoIACAExQQAMCJnq4X8FPNzc06evSoIiMjFRIS4no5AAAjz/NUU1Oj5ORkhYZe+Dyn0xXQ0aNHlZKS4noZAIBLVFJSogEDBlzw/k5XQJGRka6XgMvYyy+/bM4cP37cnPn666/NmRtuuKFDnkeSMjMzfeWs/PyUw0+mubnZnMGlu9i/5+1WQGvWrNHTTz+tsrIypaam6oUXXtCUKVMumuPHbh2vI/d5Zx89GBERYc7U19ebM4FAwJzp06ePOdOrVy9zpiN1VAH5PcY7+/Ha2V1sv7fLRQhvvPGGVq1apdWrV+uzzz5Tamqq5s6dq4qKivZ4OgBAF9QuBfTMM89o6dKluuuuuzRmzBi9+OKLioiI0D/+8Y/2eDoAQBfU5gXU1NSkvXv3Kj09/X9PEhqq9PR05eTknPP4xsZGVVdXt9oAAN1fmxfQ999/rzNnzighIaHV7QkJCSorKzvn8VlZWQoGgy0bV8ABwOXB+RtRMzMzVVVV1bKVlJS4XhIAoAO0+VVwcXFx6tGjh8rLy1vdXl5ersTExHMeHwgEfF0RBADo2tr8DCg8PFyTJk3Stm3bWm5rbm7Wtm3bNHXq1LZ+OgBAF9Uu7wNatWqVFi9erGuuuUZTpkzRc889p7q6Ot11113t8XQAgC6oXQrotttu07Fjx/TYY4+prKxMV111lbZu3XrOhQkAgMtXiNfJ3upbXV2tYDDoehldlp93fHeyQ6BNxMTE+Mr9/e9/b+OVnF9ycrI54+e10ry8PHNGkl566SVzZufOnb6eqzPj++nSVFVVKSoq6oL3O78KDgBweaKAAABOUEAAACcoIACAExQQAMAJCggA4AQFBABwggICADhBAQEAnKCAAABOUEAAACcoIACAEwwjhW9XXXWVOTN69GhzZuLEiebMmDFjzBlJys7ONmdOnDhhzsydO7dDnqempsackaTa2toOea7Y2Fhz5uWXXzZn8vPzzRm/GGD6PwwjBQB0ShQQAMAJCggA4AQFBABwggICADhBAQEAnKCAAABOUEAAACcoIACAExQQAMAJCggA4AQFBABwggICADjBNOwO0pkn5N5///2+cn4mTh89etSc8TMF+syZM+aMJP3www/mzMyZM82Z48ePmzN++Jk2LUm5ubnmTEREhDkTFhZmziQlJZkzx44dM2ck6fHHH/eVswoNtZ8LNDc3t8NK2hbTsAEAnRIFBABwggICADhBAQEAnKCAAABOUEAAACcoIACAExQQAMAJCggA4AQFBABwggICADhBAQEAnOjpegGXi44aLPqHP/zBnKmrq/P1XDk5OeZM//79zZmCggJzxq+mpiZzxs8gST+Zfv36mTPXXHONOSNJ9fX15kxJSYk5U1paas7U1taaM3369DFnJGnlypXmzLPPPmvOdIXBou2BMyAAgBMUEADACQoIAOAEBQQAcIICAgA4QQEBAJyggAAATlBAAAAnKCAAgBMUEADACQoIAOAEBQQAcIJhpJ1Y3759zZmwsDBzxs+AUElKTU01Z44cOWLODBw40JzxO9xx0KBB5oyfYa4//PCDOeNncOenn35qzkhS7969zZmUlBRzprKy0pzZv3+/OTN27FhzRpJGjBhhzlxxxRXmzHfffWfOdAecAQEAnKCAAABOtHkBPf744woJCWm1jRo1qq2fBgDQxbXLa0Bjx47VBx988L8n6clLTQCA1tqlGXr27KnExMT2+NQAgG6iXV4DOnTokJKTkzV06FDdeeedKi4uvuBjGxsbVV1d3WoDAHR/bV5AaWlpWr9+vbZu3aq1a9eqqKhIM2bMUE1NzXkfn5WVpWAw2LL5uZQTAND1tHkBzZ8/X7/+9a81YcIEzZ07V++++64qKyv15ptvnvfxmZmZqqqqatlKSkraekkAgE6o3a8OiI6O1ogRI1RQUHDe+wOBgAKBQHsvAwDQybT7+4Bqa2tVWFiopKSk9n4qAEAX0uYF9MADDyg7O1uHDx/WJ598oltuuUU9evTQokWL2vqpAABdWJv/CO7I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Fw0A6PpMBZSdna2MjAzt2rVL77//vk6dOqU5c+aorq6u1eOWLl2q0tLSlu2pp55q00UDALo+00UIW7dubfXx+vXrFR8fr71792rmzJktt0dERCgxMbFtVggA6JYu6TWgqqoqSVJMTEyr21999VXFxcVp3LhxyszMVH19/QU/R2Njo6qrq1ttAIDuz/dl2M3NzVqxYoWmTZumcePGtdx+xx13aNCgQUpOTlZubq4eeugh5efna+PGjef9PFlZWXriiSf8LgMA0EX5LqCMjAzl5eXpo48+anX7smXLWv48fvx4JSUlafbs2SosLNSwYcPO+TyZmZlatWpVy8fV1dVKSUnxuywAQBfhq4CWL1+ud955Rzt37tSAAQN+9rFpaWmSpIKCgvMWUCAQUCAQ8LMMAEAXZiogz/N03333adOmTdqxY8cverf5j+9aTkpK8rVAAED3ZCqgjIwMbdiwQVu2bFFkZKTKysoknR3B0bt3bxUWFmrDhg268cYbFRsbq9zcXK1cuVIzZ87UhAkT2uUvAADomkwFtHbtWkln32z6/1u3bp2WLFmi8PBwffDBB3ruuedUV1enlJQULVy4UI888kibLRgA0D2YfwT3c1JSUpSdnX1JCwIAXB6Yht1BevToYc74mfp7zTXXmDPjx483ZyR/63vwwQfNmcjISHPmYv9ZupA+ffqYMz9eaGPhZ2KyH19//bWv3BdffGHOFBQU+HqujpCamuor5+fY8zNR3c+k8+6AYaQAACcoIACAExQQAMAJCggA4AQFBABwggICADhBAQEAnKCAAABOUEAAACcoIACAExQQAMAJCggA4ATDSDvI4cOHzZmePe1fns8//9ycycnJMWf8OnnyZIdk/Dp27Jg54+dri47l5+sqSd9++605s3PnTnMmLCzMnOkOOAMCADhBAQEAnKCAAABOUEAAACcoIACAExQQAMAJCggA4AQFBABwggICADhBAQEAnKCAAABOdLpZcJ7nuV5Cuzhz5ow5ExISYs40NjaaM83NzeYM0JX4+f6TpIaGBnPm9OnT5oyf7/Wu4GL/nod4nexf/CNHjiglJcX1MgAAl6ikpEQDBgy44P2droCam5t19OhRRUZGnvO/gurqaqWkpKikpERRUVGOVuge++Es9sNZ7Iez2A9ndYb94HmeampqlJycrNDQC7/S0+l+BBcaGvqzjSlJ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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Label: 6\n" + ] + } + ], + "source": [ + "# Display image and label\n", + "train_features, train_labels = next(iter(train_dataloader))\n", + "print(f\"Feature batch shape; {train_features.size()}\")\n", + "print(f\"Labels batch shape: {train_labels.size()}\")\n", + "img = train_features[0].squeeze()\n", + "label = train_labels[0]\n", + "plt.imshow(img, cmap=\"gray\")\n", + "plt.show()\n", + "print(f\"Label: {label}\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "4944a85e4459d92b06dc1c94852b4e8e8e6d0531f16bd543c843a0ca37cdfcdb" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/requirements.txt b/requirements.txt index 1579240..b68e154 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ torch torchvision --index-url https://download.pytorch.org/whl/cu117 torchaudio -numpy \ No newline at end of file +numpy +pandas \ No newline at end of file