{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":7586,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# PyTorch Dataset and DataLoader\n\n* **1. Introduction**\n* **2. Version Check**\n* **3. Dataset and DataLoader tutorials**\n    * 3.1 Cumtom Dataset\n    * 3.2 transform is None\n    * 3.3 take a look at the dataset\n    * 3.4 transform is ToTensor()\n    * 3.5 transform is [ToTensor(), some augmentations]\n","metadata":{"_uuid":"a566099498dd6d93c0c1e0d8a5048170c3392aee"}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision\nfrom torchvision import transforms","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-09T02:40:54.039349Z","iopub.execute_input":"2024-07-09T02:40:54.039677Z","iopub.status.idle":"2024-07-09T02:40:54.163196Z","shell.execute_reply.started":"2024-07-09T02:40:54.039621Z","shell.execute_reply":"2024-07-09T02:40:54.162147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Version check\n\nThe behaviour of ToTensor() method in torchvision was changed from 0.3.0 to 0.4.0.\n\nIn 0.4.0 version, only **torch.ByteTensor** can be divided by 255 although other tensor types are not divided automatically.\n\nso you have to convert data type of input data to **np.uint8** of ndarray.\n\n**BE CAREFULL!!** (because pytorch official source code don't refer to this)\n\nofficial code : \n\n```python\nclass ToTensor(object):\n    \"\"\"Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.\n    Converts a PIL Image or numpy.ndarray (H x W x C) in the range\n    [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].\n    \"\"\"\n\n    def __call__(self, pic):\n        \"\"\"\n        Args:\n            pic (PIL Image or numpy.ndarray): Image to be converted to tensor.\n        Returns:\n            Tensor: Converted image.\n        \"\"\"\n        return F.to_tensor(pic)\n\n    def __repr__(self):\n        return self.__class__.__name__ + '()'\n```","metadata":{"_uuid":"df5b3532bcf4e4b9dbb5bd0251c6f08f621e3ac0"}},{"cell_type":"code","source":"print(torch.__version__)","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2024-07-09T02:41:02.990610Z","iopub.execute_input":"2024-07-09T02:41:02.990962Z","iopub.status.idle":"2024-07-09T02:41:02.996829Z","shell.execute_reply.started":"2024-07-09T02:41:02.990911Z","shell.execute_reply":"2024-07-09T02:41:02.995967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Dataset and DataLoader Tutorial","metadata":{"_uuid":"d17c80c953b357e3bcfc60753b9f9dc21076cddb"}},{"cell_type":"markdown","source":"### 3.1 Custom Dataset\n\nyou have to overwrite **__len__()** and **__getitem__()** functions.\n\nofficial code : \n\n```python\nclass Dataset(object):\n    \"\"\"An abstract class representing a Dataset.\n    All other datasets should subclass it. All subclasses should override\n    ``__len__``, that provides the size of the dataset, and ``__getitem__``,\n    supporting integer indexing in range from 0 to len(self) exclusive.\n    \"\"\"\n\n    def __getitem__(self, index):\n        raise NotImplementedError\n\n    def __len__(self):\n        raise NotImplementedError\n\n    def __add__(self, other):\n        return ConcatDataset([self, other])\n```\n\n- **__init__()** : initial processes like reading a csv file, assigning transforms, ... \n- **__len__()** : return the size of input data\n- **__getitem__()** : return data and label at orbitary index","metadata":{"_uuid":"930e8a15afb30bb9f4a3cd9a5d871fcaba2c1bbd"}},{"cell_type":"code","source":"class DatasetMNIST(Dataset):\n    \n    def __init__(self, file_path, transform=None):\n        self.data = pd.read_csv(file_path)\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        # load image as ndarray type (Height * Width * Channels)\n        # be carefull for converting dtype to np.uint8 [Unsigned integer (0 to 255)]\n        # in this example, i don't use ToTensor() method of torchvision.transforms\n        # so you can convert numpy ndarray shape to tensor in PyTorch (H, W, C) --> (C, H, W)\n        image = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((1, 28, 28))\n        label = self.data.iloc[index, 0]\n        \n        if self.transform is not None:\n            image = self.transform(image)\n            \n        return image, label","metadata":{"_uuid":"c295de919b46641c6e3140ebc4d8aedb5f24b8b6","execution":{"iopub.status.busy":"2024-07-09T02:41:14.456788Z","iopub.execute_input":"2024-07-09T02:41:14.457096Z","iopub.status.idle":"2024-07-09T02:41:14.479695Z","shell.execute_reply.started":"2024-07-09T02:41:14.457056Z","shell.execute_reply":"2024-07-09T02:41:14.478529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"let's create dataset for loading handwritten-digits data","metadata":{"_uuid":"ff6acc52a3ead7e5e1255af4ad1707b0a3424228"}},{"cell_type":"markdown","source":"### 3.2 transform is None","metadata":{"_uuid":"db7f266b37ae2ff132ae86d023912d842fb7e5d5"}},{"cell_type":"code","source":"train_dataset = DatasetMNIST('../input/train.csv', transform=None)","metadata":{"_uuid":"4aed0da9376721e50f8f2eede99e1eef06fa74aa","execution":{"iopub.status.busy":"2024-07-09T02:41:24.401741Z","iopub.execute_input":"2024-07-09T02:41:24.402111Z","iopub.status.idle":"2024-07-09T02:41:28.653829Z","shell.execute_reply.started":"2024-07-09T02:41:24.402060Z","shell.execute_reply":"2024-07-09T02:41:28.652932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# we can access and get data with index by __getitem__(index)\nimg, lab = train_dataset.__getitem__(0)","metadata":{"_uuid":"75fcc80925f474d8868ed73b5a1200a9d619d592","execution":{"iopub.status.busy":"2024-07-09T02:41:40.989161Z","iopub.execute_input":"2024-07-09T02:41:40.989501Z","iopub.status.idle":"2024-07-09T02:41:40.997972Z","shell.execute_reply.started":"2024-07-09T02:41:40.989437Z","shell.execute_reply":"2024-07-09T02:41:40.996918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset.data","metadata":{"execution":{"iopub.status.busy":"2024-07-09T02:42:56.165872Z","iopub.execute_input":"2024-07-09T02:42:56.166195Z","iopub.status.idle":"2024-07-09T02:42:56.430185Z","shell.execute_reply.started":"2024-07-09T02:42:56.166150Z","shell.execute_reply":"2024-07-09T02:42:56.429237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\ndata = pd.read_csv('../input/train.csv')\ndata.shape\ndata.iloc[0]","metadata":{"execution":{"iopub.status.busy":"2024-07-09T02:44:13.644749Z","iopub.execute_input":"2024-07-09T02:44:13.645082Z","iopub.status.idle":"2024-07-09T02:44:16.884244Z","shell.execute_reply.started":"2024-07-09T02:44:13.645035Z","shell.execute_reply":"2024-07-09T02:44:16.883350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset[0]","metadata":{"execution":{"iopub.status.busy":"2024-07-09T02:42:22.928285Z","iopub.execute_input":"2024-07-09T02:42:22.928577Z","iopub.status.idle":"2024-07-09T02:42:22.941154Z","shell.execute_reply.started":"2024-07-09T02:42:22.928538Z","shell.execute_reply":"2024-07-09T02:42:22.938722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"we now didn't convert numpy array.","metadata":{"_uuid":"04e2321de7c9ae835dae907496ac9b052e51c087"}},{"cell_type":"code","source":"print(img.shape)\nprint(type(img))","metadata":{"_uuid":"348347d88fc85e8fca7c52d5064c6ee7f23a8e89","execution":{"iopub.status.busy":"2024-07-09T02:41:45.210392Z","iopub.execute_input":"2024-07-09T02:41:45.210727Z","iopub.status.idle":"2024-07-09T02:41:45.217178Z","shell.execute_reply.started":"2024-07-09T02:41:45.210652Z","shell.execute_reply":"2024-07-09T02:41:45.216195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.3 take a look at the dataset\n\nyou have to use data loader in PyTorch that will accutually read the data within batch size and put into memory.","metadata":{"_uuid":"32dc1dda90f65a2707f1f960cc6a2fbd31a29bda"}},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)","metadata":{"_uuid":"3165aea4a62c4bc2d9dffbd3cfe337815ef3d69c","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"we can use dataloader as iterator by using iter() function.","metadata":{"_uuid":"f68bef521c18b117b16b866a4844dd199ca6a3f5"}},{"cell_type":"code","source":"train_iter = iter(train_loader)\nprint(type(train_iter))","metadata":{"_uuid":"2f4984286c3e01e3824ea46466e540a8dc9754f5","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"we can look at images and labels of batch size by extracting data .next() method.","metadata":{"_uuid":"bc46c85a6f9220d37c3e2c7577247564d58a996b"}},{"cell_type":"code","source":"images, labels = train_iter.next()\n\nprint('images shape on batch size = {}'.format(images.size()))\nprint('labels shape on batch size = {}'.format(labels.size()))","metadata":{"_uuid":"21c91736a6006ad843b7f4fac8875432ff56f513","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# make grid takes tensor as arg\n# tensor : (batchsize, channels, height, width)\ngrid = torchvision.utils.make_grid(images)\n\nplt.imshow(grid.numpy().transpose((1, 2, 0)))\nplt.axis('off')\nplt.title(labels.numpy());","metadata":{"_uuid":"2183b838b564ab2f2d30d3c0838ac707642c8843","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.4 transform is ToTensor()**","metadata":{"_uuid":"f3ecb333d6d81467511b7da7d04f3862ac5970ac"}},{"cell_type":"code","source":"class DatasetMNIST2(Dataset):\n    \n    def __init__(self, file_path, transform=None):\n        self.data = pd.read_csv(file_path)\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        # load image as ndarray type (Height * Width * Channels)\n        # be carefull for converting dtype to np.uint8 [Unsigned integer (0 to 255)]\n        # in this example, we use ToTensor(), so we define the numpy array like (H, W, C)\n        image = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((28, 28, 1))\n        label = self.data.iloc[index, 0]\n        \n        if self.transform is not None:\n            image = self.transform(image)\n            \n        return image, label","metadata":{"_uuid":"dd81d3b6cd86c48c1495c7a241c1eb55fcdbb34e","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset2 = DatasetMNIST2('../input/train.csv', transform=torchvision.transforms.ToTensor())","metadata":{"_uuid":"d3ab2e2d763c99047d62e029e5bd3b32dd85c4d1","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img, lab = train_dataset2.__getitem__(0)\n\nprint('image shape at the first row : {}'.format(img.size()))","metadata":{"_uuid":"a642e46e7ce2318fa2746541ca2f7b0a6deb5815","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"_uuid":"e464778146b50984564f4e93e36ce8b00becb877","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader2 = DataLoader(train_dataset2, batch_size=8, shuffle=True)\n\ntrain_iter2 = iter(train_loader2)\nprint(type(train_iter2))\n\nimages, labels = train_iter2.next()\n\nprint('images shape on batch size = {}'.format(images.size()))\nprint('labels shape on batch size = {}'.format(labels.size()))","metadata":{"_uuid":"39cda01e607caf788f8255ff41f9ceec28a2c468","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"grid = torchvision.utils.make_grid(images)\n\nplt.imshow(grid.numpy().transpose((1, 2, 0)))\nplt.axis('off')\nplt.title(labels.numpy());","metadata":{"_uuid":"793e0eb4ee138e5cc21950a6cb2f357bbb5f7cb7","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.5 transform is [ToTensor(), some augmentations]\n\ntransforms.* methods use some type of input data like (tensor only), (tensor or numpy), (PILimage only), so you have to consider the order of transform","metadata":{"_uuid":"18f1b0604aad676ebe27111f4c14fa587648f32c"}},{"cell_type":"markdown","source":"**ToTensor()**\n\n```python\n    \"\"\"Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.\n    Converts a PIL Image or numpy.ndarray (H x W x C) in the range\n    [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].\n    (this is only for np.uint8 type)\n    \"\"\"\n```\n\nToTensor() takes **PIL image** or **numpy ndarray** (both shapes are (Height, Width, Channels))\n\n**ToPILImage**\n\n```python\n    \"\"\"Convert a tensor or an ndarray to PIL Image.\n    Converts a torch.*Tensor of shape C x H x W or a numpy ndarray of shape\n    H x W x C to a PIL Image while preserving the value range.\n    Args:\n        mode (`PIL.Image mode`_): color space and pixel depth of input data (optional).\n            If ``mode`` is ``None`` (default) there are some assumptions made about the input data:\n            1. If the input has 3 channels, the ``mode`` is assumed to be ``RGB``.\n            2. If the input has 4 channels, the ``mode`` is assumed to be ``RGBA``.\n            3. If the input has 1 channel, the ``mode`` is determined by the data type (i,e,\n            ``int``, ``float``, ``short``).\n    .. _PIL.Image mode: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#concept-modes\n    \"\"\"\n```\n\nToPILImage() takes **torch.*Tensor ( C, H, W )** or **numpy ndarray ( H, W, C )**\n\n**RandomHorizontalFlip**\n\n```python\n    \"\"\"Horizontally flip the given PIL Image randomly with a given probability.\n    Args:\n        p (float): probability of the image being flipped. Default value is 0.5\n    \"\"\"\n```\n\nRandomHorizontalFlip() takes **PIL Image** only","metadata":{"_uuid":"8bf0d4be5aa4ed229eaa704344c515ea0fef3fb2"}},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.ToPILImage(), # because the input dtype is numpy.ndarray\n    transforms.RandomHorizontalFlip(0.5), # because this method is used for PIL Image dtype\n    transforms.ToTensor(), # because inpus dtype is PIL Image\n])","metadata":{"_uuid":"d47e8f4ad2c122fa3c9f5c1e99c849ec5c3176d3","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"if you want to take data augmentation, you have to make List using **torchvision.transforms.Compose**\n\nthis function can convert some image by order within **\\__call__** method.\n\n```python\nclass Compose(object):\n    \"\"\"Composes several transforms together.\n    Args:\n        transforms (list of ``Transform`` objects): list of transforms to compose.\n    Example:\n        >>> transforms.Compose([\n        >>>     transforms.CenterCrop(10),\n        >>>     transforms.ToTensor(),\n        >>> ])\n    \"\"\"\n\n    def __init__(self, transforms):\n        self.transforms = transforms\n\n    def __call__(self, img):\n        for t in self.transforms:\n            img = t(img)\n        return img\n\n    def __repr__(self):\n        format_string = self.__class__.__name__ + '('\n        for t in self.transforms:\n            format_string += '\\n'\n            format_string += '    {0}'.format(t)\n        format_string += '\\n)'\n        return format_string\n    ```","metadata":{"_uuid":"64e68ac03d9511adc1306103cbf53b453b9fff08"}},{"cell_type":"code","source":"train_dataset3 = DatasetMNIST2('../input/train.csv', transform=transform)","metadata":{"_uuid":"b820608335db63cadd489914b8525645e3a179e3","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader3 = DataLoader(train_dataset3, batch_size=8, shuffle=True)\n\ntrain_iter3 = iter(train_loader3)\nprint(type(train_iter3))\n\nimages, labels = train_iter3.next()\n\nprint('images shape on batch size = {}'.format(images.size()))\nprint('labels shape on batch size = {}'.format(labels.size()))","metadata":{"_uuid":"f6e156e614874984de3346dd1b62586dde00f47d","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"grid = torchvision.utils.make_grid(images)\n\nplt.imshow(grid.numpy().transpose((1, 2, 0)))\nplt.axis('off')\nplt.title(labels.numpy());","metadata":{"_uuid":"43ed17bbece07e4fc83fe28299bf6a8536973001","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"you can notice that the first image is horizontally flipped.","metadata":{"_uuid":"e3bebf55d821193efb017154a96cef384e3373f1"}},{"cell_type":"code","source":"","metadata":{"_uuid":"626c99ec04de9f9ad542da631da275b62c32df77","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I haven't  understood the concepts of both dataset and DataLoader yet ...","metadata":{"_uuid":"4abfb5f096e35f1bc120b9edb3b1d5e4b1360686"}},{"cell_type":"code","source":"","metadata":{"_uuid":"749d5a20cf50b9bcbb8fefbec0e539846fa2dc1b","collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]}]}