{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Imports"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch","execution_count":1,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"np.random.seed(2)\ntorch.manual_seed(2)","execution_count":2,"outputs":[{"output_type":"execute_result","execution_count":2,"data":{"text/plain":"<torch._C.Generator at 0x7f4b4e208f90>"},"metadata":{}}]},{"metadata":{"trusted":true,"_uuid":"235c5900d1049bca329ba23de65ded75533d0a5a"},"cell_type":"code","source":"from torchvision import datasets\nimport torchvision.transforms as transforms\nimport torch.nn.functional as F\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image, ImageOps, ImageEnhance\nimport math\nimport random\nimport matplotlib.pyplot as plt\n%matplotlib inline","execution_count":3,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Creating a Dataset to get images and labels from the csv to get images and labels with some transforms"},{"metadata":{"trusted":true,"_uuid":"788758e45eda228003a315930b02edf907f3cdae"},"cell_type":"code","source":"class dataset(Dataset):\n    def __init__(self, file_path, transform=transforms.Compose([transforms.ToPILImage(), \n                                                                transforms.ToTensor(), \n                                                                transforms.Normalize(mean=(0.5,), \n                                                                                     std=(0.5,))])):\n        df = pd.read_csv(file_path)\n        if len(df.columns)==n_pixels:\n            self.X = df.values.reshape((-1, 28, 28)).astype(np.uint8)[:, :, :, None]\n            self.y = None\n        else:\n            self.X = df.iloc[:, 1:].values.reshape((-1, 28, 28)).astype(np.uint8)[:, :, :, None]\n            self.y = torch.from_numpy(df.iloc[:, 0].values)\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, idx):\n        if self.y is not None:\n            return self.transform(self.X[idx]), self.y[idx]\n        return self.transform(self.X[idx])","execution_count":4,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"03d712cf417d6444b1ab9576657527e0a1848987"},"cell_type":"code","source":"test_df = pd.read_csv('../input/test.csv')\ntest_df.head()","execution_count":5,"outputs":[{"output_type":"execute_result","execution_count":5,"data":{"text/plain":"   pixel0  pixel1  pixel2    ...     pixel781  pixel782  pixel783\n0       0       0       0    ...            0         0         0\n1       0       0       0    ...            0         0         0\n2       0       0       0    ...            0         0         0\n3       0       0       0    ...            0         0         0\n4       0       0       0    ...            0         0         0\n\n[5 rows x 784 columns]","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>pixel0</th>\n      <th>pixel1</th>\n      <th>pixel2</th>\n      <th>pixel3</th>\n      <th>pixel4</th>\n      <th>pixel5</th>\n      <th>pixel6</th>\n      <th>pixel7</th>\n      <th>pixel8</th>\n      <th>pixel9</th>\n      <th>pixel10</th>\n      <th>pixel11</th>\n      <th>pixel12</th>\n      <th>pixel13</th>\n      <th>pixel14</th>\n      <th>pixel15</th>\n      <th>pixel16</th>\n      <th>pixel17</th>\n      <th>pixel18</th>\n      <th>pixel19</th>\n      <th>pixel20</th>\n      <th>pixel21</th>\n      <th>pixel22</th>\n      <th>pixel23</th>\n      <th>pixel24</th>\n      <th>pixel25</th>\n      <th>pixel26</th>\n      <th>pixel27</th>\n      <th>pixel28</th>\n      <th>pixel29</th>\n      <th>pixel30</th>\n      <th>pixel31</th>\n      <th>pixel32</th>\n      <th>pixel33</th>\n      <th>pixel34</th>\n      <th>pixel35</th>\n      <th>pixel36</th>\n      <th>pixel37</th>\n      <th>pixel38</th>\n      <th>pixel39</th>\n      <th>...</th>\n      <th>pixel744</th>\n      <th>pixel745</th>\n      <th>pixel746</th>\n      <th>pixel747</th>\n      <th>pixel748</th>\n      <th>pixel749</th>\n      <th>pixel750</th>\n      <th>pixel751</th>\n      <th>pixel752</th>\n      <th>pixel753</th>\n      <th>pixel754</th>\n      <th>pixel755</th>\n      <th>pixel756</th>\n      <th>pixel757</th>\n      <th>pixel758</th>\n      <th>pixel759</th>\n      <th>pixel760</th>\n      <th>pixel761</th>\n      <th>pixel762</th>\n      <th>pixel763</th>\n      <th>pixel764</th>\n      <th>pixel765</th>\n      <th>pixel766</th>\n      <th>pixel767</th>\n      <th>pixel768</th>\n      <th>pixel769</th>\n      <th>pixel770</th>\n      <th>pixel771</th>\n      <th>pixel772</th>\n      <th>pixel773</th>\n      <th>pixel774</th>\n      <th>pixel775</th>\n      <th>pixel776</th>\n      <th>pixel777</th>\n      <th>pixel778</th>\n      <th>pixel779</th>\n      <th>pixel780</th>\n      <th>pixel781</th>\n      <th>pixel782</th>\n      <th>pixel783</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>...</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>...</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>...</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>...</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>...</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n      <td>0</td>\n    </tr>\n  </tbody>\n</table>\n</div>"},"metadata":{}}]},{"metadata":{"trusted":true,"_uuid":"e8294470265f0837ee00a38f7baa312a3be8536f"},"cell_type":"code","source":"n_pixels = len(test_df.columns)\nn_pixels","execution_count":6,"outputs":[{"output_type":"execute_result","execution_count":6,"data":{"text/plain":"784"},"metadata":{}}]},{"metadata":{},"cell_type":"markdown","source":"For training, we use the data augmentations of random rotation. For testing, we just create normal tensors"},{"metadata":{"trusted":true,"_uuid":"9c0257ed7cf2929152b35df876bada88d3ad6c59"},"cell_type":"code","source":"num_workers = 0\nbatch_size = 64\ntransform = transforms.Compose([transforms.ToPILImage(), transforms.RandomRotation(degrees=20),\n                                transforms.ToTensor(), transforms.Normalize(mean=(0.5,), std=(0.5,))])\n\ntrain_dataset = dataset('../input/train.csv', transform=transform)\ntest_dataset = dataset('../input/test.csv')\ntrain_dl = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\ntest_dl = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)","execution_count":7,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Plot one batch of images"},{"metadata":{"trusted":true,"_uuid":"b4a2e4d9a99bc19a86d760f0c386a97ba907f48f"},"cell_type":"code","source":"dataiter = iter(train_dl)\nimages, labels = dataiter.next()\nimages = images.numpy()\n\nfig = plt.figure(figsize=(25, 4))\nfor idx in np.arange(batch_size):\n    ax = fig.add_subplot(2, batch_size/2, idx+1, xticks=[], yticks=[])\n    ax.imshow(np.squeeze(images[idx]), cmap='gray')\n    ax.set_title(str(labels[idx].item()))","execution_count":8,"outputs":[{"output_type":"display_data","data":{"text/plain":"<Figure size 1800x288 with 64 Axes>","image/png":"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zJSYoqKinP4t96ERI0aoY9mLL74Y8rhOnz5NRET/8z//Q2vXrlX7Urdu3WjHjh2lnkuTk5Np2rRp6m8TQhAzq7x64oknghy9Z3FxcU7Hqby8PNNika5du0ZERJ999hkJIeirr75S37tw4YJZYXnt008/JSL757xy5Uoi+uWcl5eXR//85z9Ni23hwoUql19//XXKycmhAwcOEBHR119/TQ0aNKD//u//phYtWhARUdOmTYmIVJ+3UaNGdOjQIRMi986RI0eoTZs2tHXrVrNDISKi2bNnExHR0aNHiYgoOjpaXS+kpqZSREQE1ahRg4iIioqKQh7bhAkTiIioVq1aXv3M3bt3aeTIkUREtGfPHjp+/HjQ4vPHrFmzqHfv3kRk79fIPl2obNu2jYiI/vjHP5IQQn3WL7zwQolzm6uYmBhau3YttW3bloh+6eekp6cTEVFKSoo6NlsOShQAACAASURBVBpl0KBBRES0b98++vWvf01//vOficjev9m5cyf961//IiKiKVOmEBFRfn6+Ol/88MMP1KBBA3WsiI2NpfHjx6tz4/z58+n8+fOGxhso1z55KN2+fdvp3576i1bWt29fIiL6z3/+QxkZGSZHUzYZ4yOPPEJCCNWvl/18syUkJBAR0W9/+1vKyckxNZY7d+4Qkf2YMWjQIBo/fjwR/XLtWZpr166RzWajL7/8koiIPvzww+AFSkRnz55V/79jxw7at28fffbZZ0RE1KtXL3XeKywsJCKiRYsW0ahRo6hdu3ZEZB//+/e//+107WeG6OhomjRpEtWtW9fUOFzJ/owvx1N5TR/MczJqEAMAAAAAAAAAAACUV95MM/Znavfw4cOdHrcuLi7mixcvcl5eHl+7do2vXbvG06dP54sXLzrVJtU0jRs0aOD1I/GhfKTGtbVq1YpbtWrlUx1iI2IdN24c67quas7Kepx169blq1ev8tWrV1nXdb8eaXJphjzy8f3336saw8XFxWyz2fx65MDoeOXqzPIRGFk30rW+sONKrJ4eE/SjPpRh29ddq1atGlerVk3Ft2nTJn9WuvQqd8uKNyoqil977TXV5P4ua7N6enRl165dvHLlSl65ciUzM2dnZ/Po0aN59OjRvHjxYu7YsaNh+5qsdbh06VLOzc31WMpCHsNKK5uxdu1a03PB9fMfOnSoegRPNtccHjBgAA8YMIAjIyMNj1e+d35+Pm/ZskWVm9m/f7/HR2kOHjzIBw8e5LfffpvT09O5YsWKqpm9fV3bpk2b1PFNbs86depwnTp1Qrqvyda/f3/u37+/2zxlZsNLCwQSb0JCgnqEXdd13rhxIz/66KP86KOPcsWKFblRo0Y8cuRI3rNnD+/Zs0fVGZbH582bN/PmzZu5bt26XLdu3YDi9edvT05O5uTkZHUM6N+/P//jH//gf/zjH0Zt34By17EO4LPPPmvo5x6MeD011zITmqbx008/HVbxuusb6LrOR44c4SNHjvC8efO4ffv2HBkZyZGRkV7nqze5G4w+77Jly1jTNJ4+fTpPnz7dr/cIJFbXEhNJSUmclJSkYvvpp59Uk6+RNVLNyIX4+HiOj4/ndevWeewrypXnx48f77H0nhm566498sgj6viRn5/PcXFxIY1XCMFCCG7UqJHTNiwsLOQTJ06oPuW0adP4ypUrPHv2bP7oo4/4o48+4oKCAtY0TZUcGTp0KH/yySfq0e5Acteb7RsbG6v6Ob179+ajR486HRMc/6tpGmdlZfHZs2edjteO3w92vL629PR01nVdXXN6UzrM23h9eY+PP/7Yp9JzocrdQFurVq2c+kWLFi0KabwZGRmckZFR6rFUHmv79u3Lu3fvdsrdXbt2qWvscNm+58+f5/PnzzMzB3KOKDV3fY134cKFTuU4vP25n3/+2emcF6p4XZun68U6derw3Llzee7cuVxUVMSPPvqoIdvX9XVRUVGqnGO7du1UTjpuk0GDBvGgQYP42LFjapvJNYNat25tRG4FlLuy5N6RI0f47t27bq+H5fjUxo0b/Vnvyut4nWL35kX+JFFMTAwPGTKE58yZw3PmzPFYu8T14lXWHvam/nAwk97b5rpQXVkfnBGxjhgxosRAyjfffMO5ubnqaxs3bvRngQ5Dkj46OrrEANSZM2e4e/fu3L17d1/qq4Uk3sGDB/P8+fN53LhxPG7cON66datT0zT74hgTJkxQO+nJkyfVQlCOC0KFIl6zmlH72muvvcYvvPCC+vdHH33Effr04YSEBNWhdi0Yn5yc7PPFtL+xxsXF8YIFC3jBggXq4sKxyZtasnZgdnY2L1iwgHv27Mk9e/b0dyA+KLkwZMgQjxeqEydO5IkTJ/KZM2dC1vmMj48vs8aSruu8bds2NWj/9ttve31BF+rtO3DgQJ40aRJv2rSpxPb1ZcDS29z1Nl6Zm57Os+E0QExE6pzvTW7ous7fffedWruAiHxeCMPIXEhLS+O0tDSnAWIjt20guRsXF6e2WXFxMcfHxxsdm6HxltYcB4gzMzM5MzPT636iGfEGq4Wyz7t8+XLWdV0t6GJkvL68h+MgsaZpfOHChRLHW7lWQXnKhWDHu379enX8WL58uWnxCiG4YsWK/Nxzz5W45iqtLVmyxGnhqQoVKhiSu/5u39jYWI6NjeXhw4fz5s2b1aDw2bNn+fLly6zrulp8PD09XS3QbFa8pbVWrVo5nZMzMzN9fg8jYo2MjOTRo0erBQxtNhvv3bvX0L81kNz1tz3wwANq2+7cuZNr1aoV0ngdB3szMjLUelLy/zMyMlTuuk6g8mWgM5Tbd/Xq1bx69WpmZl69enVA72XUviaE4ObNm6vrsRs3bqgmXzN48GBevHixqsnuOllt6tSpIYvXn+bPGkjexjpy5EinhSodxxkTEhJ48eLFTn0Em83Gf/vb37h169ZGDQ4bmrsDBgwosf7OunXr1KC3ARM/S43XKXZvXmREEm3fvp01zb5Cr+sF6+uvv86vv/46d+vWzbAkClWHbtKkSWqmmzd3eY2ItVatWjx27Fhes2YNr1mzxukkLe/YuK7YGMqklwXN5U7p54zKkMVbVps4caIaUBk8eDAPHjxYfa927dpcu3btsIo3WM3sfc2oeAN93/bt2/OoUaPUXUmD4g1KLkRERPDw4cOdBoRlMyvezp0789ixY3ns2LG8ePFiXrx4MXfr1o27devGJ06c4ISEBI6IiDA6H4Kyfdu0acOFhYUlbogtWLAgKLnrbbyHDh3iQ4cOhWRw2Ih4ZRs6dCgfP36cT506VaItXLiQFy5cyE8++aRXqzb7E68/7+U4QHzy5Mlg3AD1K3cbNmzIGzZsUG3jxo2Gf+5GxltW69evn9q/5AKb4RxvsFooz8NmzyCWrV27dpybm+t2EFAOXKSkpJS7XAh2vI0bN3aaQex4cVqjRg2nG/2hjHf27Nluc2H58uWqfxMTE8NCiID+/lDsa3IF++bNm3PHjh3Vv8M1XtkiIiLULGJd17mgoMDnc18wYrXZbH4/uRWK3HXXGjVqxO3atVML78XHx/P+/ft5xYoVvGLFCn8GhwOO13GwVy4S7mn2u+NAclmzjs3Yvg75phjwXkHZ15YuXaq2qxwolgPCjk81p6WlccOGDb1eCDmUxwaDPiuvYo2JieH169fz+vXrPU5EldszLy+PJ02aFPD1Q6hy9/r16zx27NiAZ7v7Eq9jQw1iAAAAAAAAAAAAgPLKm1Fko+8yyLIT48aN4zZt2qgZxP68l9l3RXr27KlmEAcSbyhi9aP5dVfkwIEDbLPZ+NKlS3zp0qVg3c01LF6rbV+zmtn7mlHxmh1XqHNB1vCzQrwGlMUJabwdOnRQd6dlndF+/fqZPnNJPj516tQppzvp169fD0YulNtjQ1pamjrPffPNN8GK11LnCcQb3BbKfW3+/PlhMYOYyD6LOC8vj/Py8nyqy3o/50Io4pVPo8iZok2aNOEmTZrwjz/+yAUFBWEXr5HtfjmvBSvewYMHOz3B6muNaittWwpi7iYmJvLHH3+s1mcqLCxkXdfDIt6UlBSnNR8cy0nIr/Xp08eXWsMh376yuatP628Lxb7m+HSEfEpd0zQeMmQIV65cWdVoD5d4jWxGxCrLSaSmpnJqaio/8MADwYrXUue10uJ1it2bF4XzH3q/xGt2XL4mkTc/Lx9ttUq8Vtu+oW7Y15ALiNe5VahQgVNTUw0frAjWvuZnrXTT4g1WMyrWtLQ0TkxM5MTERO7Ro0ew4sW+hnhVC/W+1q5dO7WgrD+DxFbatlbLhVDEO2vWLJ41axbrus6fffYZS3KBsnCL18h2v5zXghmvv4PDpcVr9nb00IKau4mJiapc1blz5/jQoUNhE++MGTMsv32NbqHe13r37u3TgLDZ8QZr+5odl4dmqdwtLV7HJu79AV65l5hhhZmFp+9ZKd5wjJWIfmDmOHffQLyGsFS82NeCylK5QIg3qO6XfY3IWvH6E2tiYiIREf3rX/8KMCqPLJW7hHiDqjzvayFgqVwgE+J9++23iYjo66+/pu+//97XH7fU9r1f9jUia8UbjrFSkHO3fv36dOXKlUDfxpGl9jWyWLz3y75GZK14wzFWsljuUinxOkINYgAAAAAAAAAAAIByKtLsAAAAAACsKIgzhwEAwspf/vIXs0MAuO8YPHsYACAgvg4QXyGic8EIxE8tyvi+leINt1iJEG+wWSle7GvBhXiDy0rx3k/7GpG14g23WIkQb7BZKV7sa8GFeIPLSvHeT/sakbXiDbdYiRBvsFkp3vtpXyOyVrzhFivR/RWv4lMNYgAAAAAAAAAAAAC4f6AGMQAAAAAAAAAAAEA5hQFiAAAAAAAAAAAAgHIKA8QAAAAAAAAAAAAA5RQGiAEAAAAAAAAAAADKKQwQAwAAAAAAAAAAAJRTGCAGAAAAAAAAAAAAKKcwQAwAAAAAAAAAAABQTmGAGAAAAAAAAAAAAKCcwgAxAAAAAAAAAAAAQDmFAWIAAAAAAAAAAACAcgoDxAAAAAAAAAAAAADlFAaIAQAAAAAAAAAAAMopDBADAAAAAAAAAAAAlFMYIAYAAAAAAAAAAAAopzBADAAAAAAAAAAAAFBOYYAYAAAAAAAAAAAAoJzCADEAAAAAAAAAAABAOYUBYgAAAAAAAAAAAIByCgPEAAAAAAAAAAAAAOUUBogBAAAAAAAAAAAAyikMEAMAAAAAAAAAAACUUxggBgAAAAAAAAAAACinMEAMAAAAAAAAAAAAUE5hgBgAAAAAAAAAAACgnMIAMQAAAAAAAAAAAEA5hQFiAAAAAAAAAAAAgHIKA8QAAAAAAAAAAAAA5RQGiAEAAAAAAAAAAADKKQwQAwAAAAAAAAAAAJRTGCAGAAAAAAAAAAAAKKcwQAwAAAAAAAAAAABQTmGAGAAAAAAAAAAAAKCcwgAxAAAAAAAAAAAAQDmFAWIAAAAAAAAAAACAcgoDxAAAAAAAAAAAAADlFAaIAQAAAAAAAAAAAMopDBADAAAAAAAAAAAAlFMYIAYAAAAAAAAAAAAopzBADAAAAAAAAAAAAFBOYYAYAAAAAAAAAAAAoJzCADEAAAAAAAAAAABAOYUBYgAAAAAAAAAAAIByCgPEAAAAAAAAAAAAAOUUBogBAAAAAAAAAAAAyikMEAMAAAAAAAAAAACUUxggBgAAAAAAAAAAACinMEAMAAAAAAAAAAAAUE5hgBgAAAAAAAAAAACgnMIAMQAAAAAAAAAAAEA5hQFiAAAAAAAAAAAAgHIKA8QAAAAAAAAAAAAA5RQGiAEAAAAAAAAAAADKKQwQAwAAAAAAAAAAAJRTGCAGAAAAAAAAAAAAKKcwQAwAAAAAAAAAAABQTmGAGAAAAAAAAAAAAKCcwgAxAAAAAAAAAAAAQDmFAWIAAAAAAAAAAACAcgoDxAAAAAAAAAAAAADlFAaIAQAAAAAAAAAAAMopDBADAAAAAAAAAAAAlFMYIAYAAAAAAAAAAAAopzBADAAAAAAAAAAAAFBOYYAYAAAAAAAAAAAAoJzCADEAAAAAAAAAAABAORWyAWIhxH9cmiaEmBOq3+8PIcSvhRDbhBAFQoiTQojeZsdUFiFEfyFEthCiSAhxSgjxf8yOyR2r5QNyIbistH2tlrtEREKIb4QQtxxiPm52TKWxWO7+XQiRK4S4IYQ4IYR42eyYSiOEGCWEyBJC3BZCfGJ2PKWxUqySEKKuEOLze7l7TgjxP2bHVBYhxK/uHR/+bnYspbHaviZZYftadF+LEUJ8KYS4JoS4KIT4qxAi0uy4SmORXKgshFh87/hVKIQ4KIRIMjuu0lipD0lkrdy1Yp+XyDr9SKttX6vFS2SdXCCy1rGByHp9XqudK4jMyd+QDRAzcw3ZiKgRERUT0aeh+v2+urczrieifxJRXSIaTkR/F0K0NjWwUgghniCi6UQ0lIiiiKgzEZ02NSgPrJQPyIXgstr2tVLuuhjlEPtDZgfjiZVy956pRBTDzDWJ6Fki+osQopPJMZXmZyL6CxEtMTsQL1gpVimNiO78v/bOPD7Ga//jn0lCLEnETiqksRZVFddeSSqooqRKaa3Xmiqq9qsIftarrXKV6g3Cldppc221JJUiJbXErS2WhEpSCUEq68x8f3+M53RmMpPMTJ5lHs779TovZuZ5nvnMyfec5zznfM/3C6AmgA8BrNVoNM2UlVQiawCcVVqEDaitrQmooX7V2Na+BnAfQG0ALQEEAvhIUUUlowZbcANwF4b6rATgMwA7NBqNn4KarKK2MeQzVGO7ahzzqmkcqbb6VZteNdnCM1TTNzxDNWNeNd4rlLJfpUJM9IPB+OMU+n5baALAB8CXRKQjouMATgIYoqysYpkPYAERxRORnojuEdE9pUXZgLPbA7cFaVFj/Qo4u+2qETXZLojoNyLKF14+K/UVlFQsRLSHiPYBeKC0lpJQk1YA0Gg0FWHoE+YQ0Z9E9DOAH+DEfZlGoxkI4BGAY0prKQm1tTVAPfWrtrb2jJcB7CCiPCJKB3AIgFM+mAKqsoWnRBRORMnP7sH/BXAbgLMuxqhxDKkq2zVCLWNeVY0jjVBL/QqoQa/abEE1fYMKx7xqvFcoYr9KTRAPA7CZiEih73cUDYDmSouwhEajcQXQGkD1Zy7zvz/bllBeaW02oEZ74LYgLU5bv2aoyXaXaDSaTI1Gc1Kj0QQpLcYSarVdjUbztUajyQFwFUAagAMKS+IoQyMAWiK6bvTeRTjv4N4LwAIAnyqtxVbU1NbUWL8qYyWAgRqNpoJGo3kJQA8YHqadDjXbgkajqQlD3/ab0lrswNnHkKqxXTOcfsyr1nHkM5y+fs1war0qtQU19Q2qGvNawWnvFUrar+wTxBqNph4M7vKRcn+3nVyDYVVsmkajKaPRaLrBoLuCsrKsUhNAGQDvAXgDhm0Jr8OwNcxpUYk9cFuQFrXVLwDV2K7ADAD+AF4CsB5AtEajcUbPO7XZLgCAiD6CYevPGwD2AMgv/gzOc4oHgCdm7z2GwTackYUAIojod6WF2IrK2prq6ldlnIDhQfQJgN8BJADYp6gi66jSFjQaTRkAWwFEEtFVpfVYQY1jSDXZLgBVjXlVOY5UUf0CUI1eNdqCmvoGtY151XavUMx+lfAgHgLgZyK6rcB32wwRFQLoC6AngHQAUwDsgKGxOiO5z/5dTURpRJQJ4AsAbyuoyRac3h64LUiLCutXwOltV4CIfiGibCLKJ6JIGLbUOKM9qMp2jXm2XelnAHUAhCmth6MIfwLwMnvPC0C2AlqKRaPRtAQQAuBLpbXYixramprrVw1oNBoXGLyq9gCoCKAagMowxOpzKtRqC8/qeAsM8SU/VliOVdQ2hlST7ZqhljGvWseRaqlfATXoVZUtqLBvUM2YF1DfvQIK2q8SE8RD4dyrTQwiSiSiQCKqSkTdYfDAO6O0LksQURYMBm68zcMpt3yYoQp74LYgLWqqXyNUYbtWIBi21TgVarRdC7jByeOiciTjOgA3jUbT0Oi91+CcW7ODAPgBuKPRaNIBTAXQT6PRnFNSlJ04c1sLgvrr15mpAqAugH89W/h8AGAjnPPBPwgqswWNRqMBEAGDB1O/Zw/WTovKxpBqsl1jVDHmVfE4UhX1a4TT61WhLaitb1DTmBeAuu4VStqvrBPEGo2mAwxbnJ0226UxGo2mhUajKfcsDsxUGDJKblJYVnFsBDBBo9HU0Gg0lQFMhiFTo1OiJnvgtiAtaqtfldmut0aj6f6sft00Gs2HMGRBddaYVqqx3WcaB2o0Gg+NRuOq0Wi6AxgEJ05C9MwGygFwBeAq2IXSuiyhJq2AIbkTDJ4fCzQaTUWNRtMRQB8YvPCcjfUwTK62fFbWAdgPoLuSoqyhwramtvpVW1vLhCFxWtgz7d4wxMNMVFaZRVRlC89YC+AVAL2JKLekg5VGTWNIldkuAHWNeZ+hmnEkoL76VZle1diC2voGlY15AajrXvEMRexXbg/iYQD2EJFTup5bYAgMSVDuA+gCoKtRBm1nZCGAszCs6FwBcB7AIkUVFY+a7IHbgrSorX7VZLtlAPwfgAwAmQAmAOhrllTAmVCT7RIMW9x/B5AFYAWAT4joB0VVFc9nMGxbmglg8LP/O2s8NjVpFfgIQHkY+rLvAIQRkdN5UxBRDhGlCwWGrYJ5RJShtDYrqKqtqbB+1djW3gXwFgz3thsACmF4eHIq1GYLz2KLjoVhMjtdo9H8+ax8qLC04lDbGFIVtmuEmsa8gLrGkYD66ldNetVmC2rrG1Qx5jVCbfcKRexX46SJJzkcDofD4XA4HA6Hw+FwOBwOhyMxSsQg5nA4HA6Hw+FwOBwOh8PhcDgcjhPAJ4g5HA6Hw+FwOBwOh8PhcDgcDucFhU8QczgcDofD4XA4HA6Hw+FwOBzOCwqfIOZwOBwOh8PhcDgcDofD4XA4nBcUPkHM4XA4HA6Hw+FwOBwOh8PhcDgvKG72HKzRaEgqIY5CRBprn6lJrzNqBZBJRNUtfcD1ioKq9PK2JimqsgVwvZLyvLQ1QF16nVErVGa74Holhbc1SVGVLYDrlZTnpa0B6tLrjFqhMtsF1yspz0tbA9Sl1xm1QmW2i2L0GsM9iDnFkaK0ADvhejlqRW22wPVyOPKgNtvlejlqRW22wPVyOPKgNtvlejkceVCb7dqkl08QP6dcuHABXbt2VVoGh8PhcFTGyZMnlZbA4XA4HA6HIypr1qzB+fPnWeG8WLRq1UppCRxOieh0OixevFix7+cTxM8ZPj4+8PHxQa1atdCvXz+l5XAUhohARAgPD1daCofDcVKaNm2K5ORkJCcng4jw559/Ki2JwynC5MmTERcXp7QMjgqoWbOm0hKeO9zd3bF48WJFH1o5nNIybtw4EBFef/11vP7660rL4chA1apVsWrVKqxatQoJCQlITEyEu7s73N3dlZbG4ZjQu3dv9O7dm83fKIVdMYg5BmrUqAEAuH//vsJKirJz504AQPXq1XH79m2F1TjOtWvXAACurq4AgPr160OjsRpCh2NGUFAQgoKC2Ot58+YhMDAQwcHByonicCwQEBCAPXv2AADq1aunsJqiVK9eHenp6QCAQ4cOYcmSJfD19TU5Jisri02q/vLLL9DpdNDr9bJrdQQXFxf069eP/Sa16Oa8WKSmpqJmzZo4deoUmyTu1KkTiAguLtzX4UUlNTUVAFif++uvvwIAGy+GhoYqpk3A3d0d+fn5SssoFR4eHnj33Xcxc+ZMk/eN74WfffYZUlLUttuW8yIwY8YM6HQ69jo5OVk5MRxZCQ0NxZ49e0wm2xo2bIi2bdsCAE6cOKGUNNWh0WhQq1YtfPTRRwCA2rVrY+TIkSbHbNy4EeHh4fj9998B8GcKewgNDUVUVJTSMgBwD2IOh8PhcDgcDofD4XA4HA6Hw3lh4R7ExdCgQQN06tQJmzZtAgB069YNH330ES5fvgwA+Mc//qGguqL079+fxdbJycnB/v37FVZkOwsXLkR+fj6ysrIAAI0bN4aLiwtWrFgBwLC1lGMb4eHhmDdvXpH3g4KCEBMTAwDck5ijKG3atAEAzJkzB2+//TZ7v3bt2khLS1NKlkUyMjLw6quvAgAWLFiAH3/8kX3m5uYGN7eit9Hjx4+jT58+AICnT5/KI9RBhgwZYhKCJj4+Hh988IFieg4ePIjKlSsDAL744gvs2LFDMS3PE0FBQZg3bx7mz58PAIiNjXX4Oo6eWxpCQkLQp08fTJkyBUuWLAEA7Nu3D6+++irLt3DkyBHZdXGUo2XLlvjpp58AAAMHDgQA1K1bl33+3//+VxFd5mzfvh19+/ZVWoZD+Pv7AwC2bt2Kdu3aMS88c09iAPDy8mL3PQ5HaYRdlIcOHTJ5Py4urojXI+f5ZMCAAfjPf/5j8l5+fj6mTZvmlJ7DXl5eaN++PbufAYa5qBs3brDXP/zwA/bu3QsPDw8AkCUkXLly5QAAw4YNw9q1a00+Mw+DMHz4cAwfPhxTpkwBAHz11Vfci9hG+vTpgzJlyrDXM2bMAADMnj1bfjFCjAtbCgAqqVSpUoWqVKlCzZo1o2bNmpV4fGlLafWaF1dXV3J1daURI0ZQZmYmHThwwOTz8ePH08GDB+ngwYOi6i1tPfj4+JBer2dl1apVYtRvghR6586dS7GxsZSYmEjffPMNffPNN1Zt6cKFC3ThwgUaO3asYnqF0rx5c1q/fj2tX7+evvnmG6pWrZqJ3dSoUcMp6jcmJoYsERMTU6rfL3Zbs6Xk5eVRXl4ehYSEiKZXCp3BwcH01Vdf0VdffUWVK1d25BqS2EJgYCCNGDGCdDodswOdTkc6na60v7lUetu0aUNt2rQhrVZLf/zxB9WoUcOR9qN4/TZo0IB69uxZpEybNo31xVu2bBHNdqWw36ysLNLpdKythYWFKabX09OTtFotK9nZ2TRr1izR7UHufqyUpVS2Gx4eTuHh4az9BwUFUVBQkF0azK8hpd6SSps2bUxelylThp4+fUpPnz516D4htV5LpW3bttS2bVt68OABRUZG2nWuEvdh89K6dWtWSrIHKbTu2bOHsrOzKT8/v8g4R6Bt27ZUtmxZRW1BoFWrVlL9LSS13bS0NHYfIyK6c+eOyXOGpeLm5kZubm6y6vXy8qKPP/6YPZtZKu3atXPk7ydJW7t//z4REcXFxZGXlxd5eXmJYg9y9g0ZGRlUs2ZNSfSWVluZMmWoQYMGdOvWLbp16xbpdDqKjo6mwMBACgwMdPS6ktju1KlTqWrVqqL+baTUK2GRRG9ubi7rv4Q+qnPnzqXWK2Zbc3V1pZEjR9LIkSMpJSWFtFotnThxgs6cOUNnzpyhqKgo2rBhA925c4fu3LlDmZmZdOLECapUqRJVqlRJFr0VK1akihUr0sWLF0u8B1gqSOrkaQAAIABJREFU48ePF6V+ncBOJbVdT09POnbsGB07dow9B9WpU0c2vcZFNA/iZs2a4ZNPPsEbb7wBwBDfpUWLFmjWrBk7pnnz5ujUqRN7PWjQIHz33XfMO+vSpUuYMGGCWJIcQpilnz9/PtauXctm741xxtjDU6dOBfCXt9q//vUvJeUUoWrVqswW7t+/j3HjxuHmzZsoLCy0evyBAwfw/fffAwA2bNggm1Zz3N3dsWrVKgwePNgkjpyHhwfzxjp8+DCioqKUWeV5hrBabhx7WGD+/PmKeH3ZSqdOnRAQEICOHTuy97p27coSCGzdutWpk87s3bsXlSpVAgD8+OOPinvvC/2sEJOciNgK7rObFs6ePQvgr/hb3333HQDgwoULKF++PLKzsyXT9/7777P/C17tauTGjRsmK/sCjx49Yv/Pzc2VU5LdxMTEmKxaf/TRR0U8BORC2DEiUL58eSxcuJB5jDoTo0aNwvjx402S3Hh6eqJ9+/bFnmfsgS41gtewgCP3AUvXUJIzZ86YvHZzc8OFCxcAGMZBR48eVUIWAMM4WNgFJcTGtYSQQNjb25v1x2pCsIe3334bWq0Wd+/eBQCMGTMGCQkJyMjIkOR7hTGkpbjC6enpqFWrFhuf//LLL5JocISXX34Z586dK/G46dOnY+vWrQCAe/fuSS3LKsHBwfD392c7OQAgLy8Pb7zxBvO8TExMhK+vLxYsWAAAqFixIt544w1otVrZdLZu3RoAsH//fpYbxhodOnTA22+/jZMnT8ohzYR69erhgw8+wN/+9jcAhrj/qampaNu2LYYNGwYA+Pbbb5GXlye7NlvQ6/XQaDQmfRURYebMmU65u3PRokVo0qQJ203w8OFDDBs2DA8fPlRYmWHM6Obmxu7Dw4YNw9SpUxEbG8ueHwsLC3Hnzh0FVaqfQYMGATA8vwv3p82bNwNwvpjDNWrUwIEDBwAY+oGDBw9i2bJlxer08/Mz8TSVmmrVqgEAm6+zlwkTJqCgoACAYT7HOB64XAi734xzNAUGBiIoKMhpclwFBgYiMDCQvY6IiGCxnOWGxyDmcDgcDofD4XA4HA6Hw+FwOJwXFNE8iPfv3486deqw13/++ScuXrxY5DjzVciwsDD2/zfeeAO3bt1iK+hKeOp+9tlnAAzeQRs2bLDo3fHxxx/LLatY6tSpg7///e8ADB4cAHD9+nUlJZlw9uxZ6HQ6lt3Y2HvQGuXLl4e3tzdb8bXmaSwH69atw7BhwxAbG4tRo0YBAN555x0EBwfjlVdeAWDwEJDKa8ZWzD2HY2NjnTrWcJUqVQAY4tBOmjTJ4gqeEI82Pz8fzZs3x//+9z9ZNZpz5MgRi57MV69eRaNGjQCAebMpQaNGjdCzZ08WU7ZixYpWjxU8H1u1agUiwqRJkwAABw4cQExMDL788ktJNCYkJKBly5YAgF27dgFwzl0ZpWH48OGsz3LWGLrm3gd//PEHAGDixIlKyAFgiEG9ZMkSfPrppwDAdhB0794dhw8fVkyXJTQaDX788UecP3+evXZ3d0fDhg2LHGc8jjCOuQ0AT548QXx8vCQajb3zY2NjTWJN24p5PHtHriEllSpVYrH4pNz1UBLt2rXDTz/9xHYUGO+eM0cYNwBQfLeJPZQtWxYTJkxA586dTd6vVasWAENsxF69eoneVtu0aYOpU6eiS5cu7L2UlBQ8fvwYP/zwAwCD93heXh5+/vlnq9cJCAjAr7/+Kqo2S3h6egIAeway1XPx8uXLbPfP9u3bpRFnA9WqVcPq1atRtmxZ9t6cOXOQkpKCuXPnmhz77rvvAgA6duyIv//977J46Hp5eWHNmjVszGvsPbx48WIAQHR0NIC/8m3MnTsX//73v9GjRw8AQHJysuQ6BX7++We89NJL7HXlypXx+PFj5uUIAGvXrsV///tf7N69GwDQtGlTDBw4sEh9S4kQPzokJARVq1Zl7wtbjo3vZY8ePcLEiRPx5ptvAgBee+012XQWh06nYxofPHgAwPDMqaT3cM2aNfHvf/8bAFC/fn0AYJ7jn3zyCaZOnYr333+feZj7+/vjhx9+UDSet9D/dOjQochnLi4uRWLK/vzzzyb2rDTGO4n0ej26du1qcbefM5CWlobatWuz1//9739L9HLOz89nNvT5559Lqq9mzZpW4/kXFhZi+/btLHoAYBgPCGN3gUaNGuGbb74BYPDgbt26NZvrkxLjHXCWdlcLmM/1CR7+P/30k2xj3iZNmuDbb79lr3Nzc0v821aoUAE5OTmS6Cn1BLGwvejEiRP44Ycf2MPSzZs3kZaWxgaKt27dgkajwb59+4psvUtPTwdg+AN5enoqNlnQs2dPNmiIiIiweIwzbgFav349G5AeP35cYTUG3N3dWaMSBmj2BlJftGgR2xKiBML2tcGDB+M///kPGyADwKpVq7B69Wps3LgRgKGTFB5UlMDSQobSW4FLQugbWrdujezsbKxbtw6nT58GYNh6u2HDBpZ0MSsryyS8h5RMmjSJJTvq2LEjKlSowD5zcXEpshBw6dIlvPzyy2jcuDEAwNXVVRadxjRv3hyAoU5r1aoFFxfD5hC9Xm/3Fua3334bBQUFkk0Qp6ammmzLN07G8DzQqlUrDBkyhPXFSm55Lw4huZ7wECIk8lAy5Mfu3bsRGRnJxgRfffUVAMOC3DvvvAMAGD9+vGL6jPnPf/6DXbt2oUWLFgAs98ECQugsFxcXtpUQMEwe5+TkYNmyZQAMdS/WBIv5oFZI5mUvxoNqZwtT9PHHH2PVqlXo1q0bAGXbmpeXF9zc3Ey25VvCx8eHTQJmZWU5zZjNFiZMmIClS5fK/r2zZs0C8NeiMmBYeJszZw4bFyxYsAANGzZkSaTNqVChAk6dOoW2bdsCkHYh980330RUVBRzhrCnTxUcUJScIAb+SkokhHczD/+jBOXLlwdgCDnWq1cv9n56ejqbgNu3bx8AsIUAYfEtPT0daWlpsk4MC1y4cAHe3t4srNebb76JvXv3srBegGECxcvLCyNGjABgCBM4YMAAWXXevHkTALBnzx6T9wWbvHPnDgvdcvXqVQC2L35IjbGzWUZGBqKioliSLKXp0KEDs9fNmzfDxcWFPWPcu3cPvr6+8Pf3Z5ND/v7+ePPNN+Ht7Q3ANGSZHFy+fBm+vr4AYPL8I2C+6A0AvXr1Mul779+/X+yEnJS0a9eOPZsDhoVLZ50cFhAWDopD6JP/8Y9/YMyYMWxhVmo+/fTTIgvewhh97NixbDFOoFu3blizZo3V3ySEDhUmwYUQIGITFBTk8POMccjO8PBwNp6WcrJYSPJ66tQpAIb7XXx8vMm4x8vLy+QcrVaL+vXrs75bVGwJVCx1cGghaZJWq6W5c+fada5Yeps2bUpNmzala9eu0bVr18jDw8PicZUqVaIpU6bQlClTaPr06eTv7y+KXkfqLSwsjMLCwlgQ8MWLF1s9NigoyJHg/KUKvC0ENbfnOwMCAiggIIDu3r3riC2JFijcw8ODoqKiKCoqim7cuGExGUODBg1YcpynT58qqtc4gZAxxsmFwsPDHdFYou06ordKlSpMY3x8vMUEZVWqVGFB2o8dOyaaXvPjhg4dSufOnaNz587RpEmTLAbYT0pKoqSkJIvf4+LiQnq9nu7du0f37t1ztH5LZQvbt2+n7du3s/oy7lOF/wu/xfgz4XPjxGBarZZ27dpFs2bNolmzZllLoOGw3s8//5x9z7Zt20plk3LVry1FuIccP36c8vLyqGvXrtS1a1eHriX1fbhFixb05Zdf0pdffsnsYfny5bR8+XKn0tunTx96+vQpabVaioyMpMjISEcST9ms15ZzPT09ydPTk/bs2UNarZb1YzqdjrKzsyk2Npbd+4iIBg8ebHL+kydPaMCAATRgwABatmwZ3bx5k7Kzsyk7O5t69Oghmu2a3xMcqaegoKAi9xMbzpO8rdWtW5fq1q1LFy9epDNnzpT2eqLoHTZsGOn1ekpNTaXU1NQSj9Pr9bRz507RbFfM+jUuPXr0YGPNx48fU2FhISs6nc7kdWFhIXXv3t0mvfbqOHbsmIktrly5kpo0aVLsOeb3tSFDhlDZsmWL60NEsYU+ffpQZmYmvfTSS/TSSy/ZdI6npyelp6eTh4cHK3LZrnkpV64c6fV6unTpEtWqVYtq1apl9di4uDiKi4sjvV5PERERkumtUqUK7dy5k3bu3MlsIC0tjdLS0qhDhw6i231xtmtv/d66dcta385KmTJlKDw8nG7cuEE3btygvLw82fU2b96cmjdvTjdv3qScnBw6fPgwHT582GLi2szMTNLpdNS7d2/q3bu3qPVr73UCAgLYPVS45zZo0EBse5D8viYk0ROoWrVqaRLYOaR3//79bExorRg/R1greXl5dPz4cTp+/Ljs9Tt58mR2j7127Rr5+fmJbQui34fd3d3J3d2dzp49S7GxsUWSz1WsWJF+/fVX+vXXX0mv19MXX3whm94rV64UeSYW+n1r54wbN45SUlIoJSXFauI6Yb7NUlLT0tStkIjZFswTMFs7Ri7bXb58ucmY5dtvvzWxD/MxzY0bN2j+/Pn22ptNSep4DGIOh8PhcDgcDofD4XA4HA6Hw3lRsWUWuTSrIiWV5s2bO4UHMQCKiIigVatW0apVq6weM3r0aFq7di2tXbuWiIi2bNkiil57tXp6etKdO3fozp07rP7Mj/H396cFCxbQggULmHdHSb/PrEi+YmpcAgIC2Op5x44dHbmGaHpr167NVrmsrfy/88477BilPYhjYmJsWi2LiYmhmJgYdo4YtuuoPaxevZpWr15NRGRxtb9t27ZMtyOeubZqHTduHD148IAePHjAPPEFj6n69etT/fr1ydvbm7y9va1+V4UKFejmzZt08+ZNevLkCTVu3Fg2WzD2HLbmEWztPWNvgP3799P+/ftp7969Jse3a9dONL2C97DQLy1YsMDuv6unpycBoC5dulCXLl2of//+srY181K5cmWaOXMm5ebmsmLv6r6ttitW3ztnzhwTb4+HDx+y0rp1a6fR27JlS0pOTjax1+bNm5f69zuq1dPTk3bt2kW7du0irVZLN2/epPz8fMrPz6fDhw9Tq1atqHLlyuz4wYMHl+i9MnXqVHaNZcuWiWa7lvp8e4v5fcXG8yQdN/j4+NDly5fp8uXL9PDhQ5o8eXJprymK3sjISNLpdBQdHU3R0dElHqfT6az9vR2yXbHq17js27eP9u3bZ9VLjIhk8yAWxtzG3LlzhypVqkSVKlWit956i8LCwmjz5s20efNm+vHHH4scb9w2pbCFPn36sPLgwQO76/vevXvUo0ePEr1NxbZdS6V27do2HSeXB/HgwYOL/D0XLlxICxcutElnWFiY3Z6uYrW1tWvX0pIl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\n"},"metadata":{}}]},{"metadata":{"trusted":true,"_uuid":"a4b9ed25363b033fa543a4158dfd288b82fd8899"},"cell_type":"code","source":"import torch.nn as nn","execution_count":9,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# A Capsule net has 3 main parts - \n1. A conv layer\n2. A primary capsule\n3. A digit capsule"},{"metadata":{},"cell_type":"markdown","source":"The conv layer applies a normal convolution with kernel size of 9 and output channels of 256. The output thus produced is of size 20x20x256"},{"metadata":{"trusted":true,"_uuid":"a30049b6a2aa69e256af14263fc9a6df18ad27a7"},"cell_type":"code","source":"class ConvLayer(nn.Module):\n    def __init__(self, in_channels=1, out_channels=256):\n        super(ConvLayer, self).__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=9, stride=1, padding=0)\n    def forward(self, x):\n        x = F.relu(self.conv(x))\n        return x","execution_count":11,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The primary capsule is just 8 stacked convolutions, whose output is then squashed."},{"metadata":{"trusted":true,"_uuid":"1cdb6c8a20cabe8ae785ea4bceea1422e81afcbf"},"cell_type":"code","source":"class PrimaryCaps(nn.Module):\n    def __init__(self, num_capsules=8, in_channels=256, out_channels=32):\n        super(PrimaryCaps, self).__init__()\n        self.capsules = nn.ModuleList([\n            nn.Conv2d(in_channels, out_channels, kernel_size=9, stride=2, padding=0)\n            for _ in range(num_capsules)\n        ])\n    def forward(self, x):\n        batch_size = x.size(0)\n        u = [capsule(x).view(batch_size, 32*6*6, 1) for capsule in self.capsules]\n        u = torch.cat(u, dim=-1)\n        u_squashed = self.squash(u)\n        return u_squashed\n    \n    def squash(self, x):\n        squared_norm = (x**2).sum(dim=-1, keepdim=True)\n        scale = squared_norm/(1+squared_norm)\n        output = scale * x/torch.sqrt(squared_norm)\n        return output","execution_count":14,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3303b04fded4d9a75900e7cd9576b08ad214af5b"},"cell_type":"code","source":"def softmax(x, dim=1):\n    transposed_inp = x.transpose(dim, len(x.size())-1)\n    softmaxed = F.softmax(transposed_inp.contiguous().view(-1, transposed_inp.size(-1)), dim=-1)\n    return softmaxed.view(*transposed_inp.size()).transpose(dim, len(x.size())-1)","execution_count":15,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6cf5fe335649261c5b64e625872a3b6521290a88"},"cell_type":"code","source":"def dynamic_routing(b_ij, u_hat, squash, routing_iterations=3):\n    for iterations in range(routing_iterations):\n        c_ij = softmax(b_ij, dim=2)\n        s_j = (c_ij*u_hat).sum(dim=2, keepdim=True)\n        v_j = squash(s_j)\n        if iterations < routing_iterations-1:\n            a_ij = (u_hat * v_j).sum(dim=-1, keepdim=True)\n            b_ij = b_ij + a_ij\n    return v_j","execution_count":16,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"93f2c2a737ebe238037ef6e544c7534546fc5472"},"cell_type":"code","source":"TRAIN_ON_GPU = torch.cuda.is_available()\nif TRAIN_ON_GPU: print('training on gpu')","execution_count":17,"outputs":[{"output_type":"stream","text":"training on gpu\n","name":"stdout"}]},{"metadata":{},"cell_type":"markdown","source":"The digit capusle takes the 8 primary capsules and produces 10 capsules as output. These 10 capsules correspond to the 10 classes of MNIST. The digit capsules apply dynamic routing on the primary capsules to select the children which corresponds the maximum to each capsule."},{"metadata":{"trusted":true,"_uuid":"7dc394aa7ea00415c98fceb762f0f88453d70308"},"cell_type":"code","source":"class DigitCaps(nn.Module):\n    def __init__(self, num_caps=10, previous_layer_nodes=32*6*6,\n                 in_channels=8, out_channels=16):\n        super(DigitCaps, self).__init__()\n        self.num_caps = num_caps\n        self.previous_layer_nodes = previous_layer_nodes\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.W = nn.Parameter(torch.randn(num_caps, previous_layer_nodes,\n                                          in_channels, out_channels))\n    \n    def forward(self, x):\n        x = x[None, :, :, None, :]\n        W = self.W[:, None, :, :, :]\n        x_hat = torch.matmul(x, W)\n        b_ij = torch.zeros(*x_hat.size())\n        if TRAIN_ON_GPU: b_ij = b_ij.cuda()\n        v_j = dynamic_routing(b_ij, x_hat, self.squash, routing_iterations=3)\n        return v_j\n    \n    def squash(self, x):\n        squared_norm = (x**2).sum(dim=-1, keepdim=True)\n        scale = squared_norm/(1+squared_norm)\n        out = scale * x/torch.sqrt(squared_norm)\n        return out","execution_count":18,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"For getting reconstructed images, we also create a decoder, which takes the 10 digit capsules and after a series of linear and relu operations, convert the capsules again into a 28x28 image"},{"metadata":{"trusted":true,"_uuid":"a029fe6c71e9280538fd20a8021fa26611f6a331"},"cell_type":"code","source":"class Decoder(nn.Module):\n    def __init__(self, input_vector_length=16, input_capsules=10, hidden_dim=512):\n        super(Decoder, self).__init__()\n        input_dim = input_vector_length*input_capsules\n        self.lin_layers = nn.Sequential(\n            nn.Linear(input_dim, hidden_dim),\n            nn.ReLU(inplace=True),\n            nn.Linear(hidden_dim, hidden_dim*2),\n            nn.ReLU(inplace=True),\n            nn.Linear(hidden_dim*2, 28*28),\n            nn.Sigmoid()\n        )\n    def forward(self, x):\n        classes = (x**2).sum(dim=-1)**0.5\n        classes = F.softmax(classes, dim=-1)\n        _, max_length_indices = classes.max(dim=1)\n        sparse_matrix = torch.eye(10)\n        if TRAIN_ON_GPU: sparse_matrix = sparse_matrix.cuda()\n        y = sparse_matrix.index_select(dim=0, index=max_length_indices.data)\n        x = x*y[:, :, None]\n        flattened_x = x.view(x.size(0), -1)\n        reconstructed = self.lin_layers(flattened_x)\n        return reconstructed, y","execution_count":19,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We apply all these layers to create capsule network"},{"metadata":{"trusted":true,"_uuid":"f6798b1acb1b4513ec0ad8d22c2ff3d15643dfe6"},"cell_type":"code","source":"class CapsuleNetwork(nn.Module):\n    def __init__(self):\n        super(CapsuleNetwork, self).__init__()\n        self.conv_layer = ConvLayer()\n        self.primary_capsule = PrimaryCaps()\n        self.digit_capsule = DigitCaps()\n        self.decoder = Decoder()\n    def forward(self, x):\n        primary_caps_out = self.primary_capsule(self.conv_layer(x))\n        caps_out = self.digit_capsule(primary_caps_out).squeeze().transpose(0, 1)\n        reconstructed, y = self.decoder(caps_out)\n        return caps_out, reconstructed, y","execution_count":20,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"aa71d20627bcaef9f908cf8da2ce663a48845c6c"},"cell_type":"code","source":"capsule_net = CapsuleNetwork()\n\nprint(capsule_net)\n\nif TRAIN_ON_GPU: capsule_net = capsule_net.cuda()","execution_count":21,"outputs":[{"output_type":"stream","text":"CapsuleNetwork(\n  (conv_layer): ConvLayer(\n    (conv): Conv2d(1, 256, kernel_size=(9, 9), stride=(1, 1))\n  )\n  (primary_capsule): PrimaryCaps(\n    (capsules): ModuleList(\n      (0): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (1): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (2): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (3): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (4): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (5): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (6): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n      (7): Conv2d(256, 32, kernel_size=(9, 9), stride=(2, 2))\n    )\n  )\n  (digit_capsule): DigitCaps()\n  (decoder): Decoder(\n    (lin_layers): Sequential(\n      (0): Linear(in_features=160, out_features=512, bias=True)\n      (1): ReLU(inplace)\n      (2): Linear(in_features=512, out_features=1024, bias=True)\n      (3): ReLU(inplace)\n      (4): Linear(in_features=1024, out_features=784, bias=True)\n      (5): Sigmoid()\n    )\n  )\n)\n","name":"stdout"}]},{"metadata":{},"cell_type":"markdown","source":"For the loss function of our network, we use the CapsuleLoss module defined below. "},{"metadata":{"trusted":true,"_uuid":"00b2237913c40550e25e2c15c6cc54d06dda52f8"},"cell_type":"code","source":"class CapsuleLoss(nn.Module):\n    def __init__(self):\n        super(CapsuleLoss, self).__init__()\n        self.reconstruction_loss = nn.MSELoss(size_average=False)\n    \n    def forward(self, x, labels, images, reconstructions):\n        batch_size = x.size(0)\n        v_c = torch.sqrt((x**2).sum(dim=2, keepdim=True))\n        left = F.relu(0.9-v_c).view(batch_size, -1)\n        right = F.relu(v_c-0.1).view(batch_size, -1)\n        margin_loss = labels * left + 0.5 * (1.-labels) * right\n        margin_loss = margin_loss.sum()\n        images = images.view(reconstructions.size()[0], -1)\n        reconstruction_loss = self.reconstruction_loss(reconstructions, images)\n        return (margin_loss + 0.0005 * reconstruction_loss)/images.size(0)","execution_count":22,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"90e4dd28ac16df35dd220772c7703db818bf97cf"},"cell_type":"code","source":"import torch.optim as optim\ncriterion = CapsuleLoss()\noptimizer = optim.Adam(capsule_net.parameters())","execution_count":23,"outputs":[{"output_type":"stream","text":"/opt/conda/lib/python3.6/site-packages/torch/nn/_reduction.py:49: UserWarning: size_average and reduce args will be deprecated, please use reduction='sum' instead.\n  warnings.warn(warning.format(ret))\n","name":"stderr"}]},{"metadata":{"trusted":true,"_uuid":"46a6963df16722a6b467bbbcb6d9525781684e61"},"cell_type":"code","source":"def train(capsule_net, criterion, optimizer, n_epochs, print_every=300):\n    losses = []\n    for epoch in range(1, n_epochs+1):\n        train_loss = 0.0\n        capsule_net.train() \n        for batch_i, (images, target) in enumerate(train_dl):\n            target = torch.eye(10).index_select(dim=0, index=target)\n            if TRAIN_ON_GPU: images, target = images.cuda(), target.cuda()\n            optimizer.zero_grad()\n            caps_output, reconstructions, y = capsule_net(images)\n            loss = criterion(caps_output, target, images, reconstructions)\n            loss.backward()\n            optimizer.step()\n            train_loss += loss.item()\n            if batch_i != 0 and batch_i % print_every == 0:\n                avg_train_loss = train_loss/print_every\n                losses.append(avg_train_loss)\n                print('Epoch: {} \\tTraining Loss: {:.8f}'.format(epoch, avg_train_loss))\n                train_loss = 0 \n    return losses","execution_count":24,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3a12c81728eb48683380e5c9519e7557f045c788"},"cell_type":"code","source":"n_epochs = 10","execution_count":25,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training the model and plotting the losses"},{"metadata":{"trusted":true,"_uuid":"c714b512a5adc59654d23281f92508638e60d2b8"},"cell_type":"code","source":"losses = train(capsule_net, criterion, optimizer, n_epochs=n_epochs)","execution_count":26,"outputs":[{"output_type":"stream","text":"Epoch: 1 \tTraining Loss: 0.60580754\nEpoch: 1 \tTraining Loss: 0.44441782\nEpoch: 2 \tTraining Loss: 0.42060483\nEpoch: 2 \tTraining Loss: 0.40943055\nEpoch: 3 \tTraining Loss: 0.40253513\nEpoch: 3 \tTraining Loss: 0.39926065\nEpoch: 4 \tTraining Loss: 0.39777637\nEpoch: 4 \tTraining Loss: 0.39197787\nEpoch: 5 \tTraining Loss: 0.38960765\nEpoch: 5 \tTraining Loss: 0.38881000\nEpoch: 6 \tTraining Loss: 0.38686105\nEpoch: 6 \tTraining Loss: 0.38332668\nEpoch: 7 \tTraining Loss: 0.38401642\nEpoch: 7 \tTraining Loss: 0.38160509\nEpoch: 8 \tTraining Loss: 0.38153522\nEpoch: 8 \tTraining Loss: 0.37940489\nEpoch: 9 \tTraining Loss: 0.37909753\nEpoch: 9 \tTraining Loss: 0.37760976\nEpoch: 10 \tTraining Loss: 0.37761336\nEpoch: 10 \tTraining Loss: 0.37684563\n","name":"stdout"}]},{"metadata":{"trusted":true,"_uuid":"ef442969ca2ee287c19f507096299e9bd04ba7fe"},"cell_type":"code","source":"plt.plot(losses)\nplt.title('Training Loss')\nplt.show()","execution_count":27,"outputs":[{"output_type":"display_data","data":{"text/plain":"<Figure size 432x288 with 1 Axes>","image/png":"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\n"},"metadata":{}}]},{"metadata":{"trusted":true,"_uuid":"97dd7a6067435c943c11d640ca8eed49845aad72"},"cell_type":"code","source":"out = []","execution_count":60,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ec305877f548c583897fab41e8d944cdcfce5b65"},"cell_type":"code","source":"capsule_net.eval()\nfor image in test_dl:\n    if TRAIN_ON_GPU: image = image.cuda()\n    caps_out, reconstructed, y = capsule_net(image)\n    _, pred = torch.max(y.data.cpu(), 1)\n    out.extend(pred.numpy().tolist())","execution_count":61,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"695e4c26379887a442fb3c0951e0fe49a40c4093"},"cell_type":"code","source":"len(out)","execution_count":62,"outputs":[{"output_type":"execute_result","execution_count":62,"data":{"text/plain":"28000"},"metadata":{}}]},{"metadata":{"trusted":true,"_uuid":"c851ee288a9ea951aecb6055469e5a4f1f6376d5"},"cell_type":"code","source":"sub = pd.read_csv('../input/sample_submission.csv')","execution_count":63,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8800718c0f82f074b4fd823d7e1b5177f5ab5f03"},"cell_type":"code","source":"sub['Label'] = out","execution_count":64,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6812de553fe0b076c98c3cc27803a2f93bd84b90"},"cell_type":"code","source":"sub.to_csv('capsule.csv', index=False)","execution_count":65,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This model gives 98.8% accuracy on public LB. This can further be improved by training more and adding more data augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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"}},"nbformat":4,"nbformat_minor":1}