{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms\n",
    "\n",
    "from utils import mnist, plot_graphs, plot_mnist\n",
    "import numpy as np\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_loader, valid_loader, test_loader = mnist(valid=10000, transform=transforms.ToTensor())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ConvLayer(nn.Module):\n",
    "    def __init__(self, size, padding=1, pool_layer=nn.MaxPool2d(2, stride=2),\n",
    "                 bn=False, dropout=False, activation_fn=nn.ReLU()):\n",
    "        super(ConvLayer, self).__init__()\n",
    "        layers = []\n",
    "        layers.append(nn.Conv2d(size[0], size[1], size[2], padding=padding))\n",
    "        if pool_layer is not None:\n",
    "            layers.append(pool_layer)\n",
    "        if bn:\n",
    "            layers.append(nn.BatchNorm2d(size[1]))\n",
    "        if dropout:\n",
    "            layers.append(nn.Dropout2d())\n",
    "        layers.append(activation_fn)\n",
    "        \n",
    "        self.model = nn.Sequential(*layers)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        return self.model(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class FullyConnected(nn.Module):\n",
    "    def __init__(self, sizes, dropout=False, activation_fn=nn.Tanh):\n",
    "        super(FullyConnected, self).__init__()\n",
    "        layers = []\n",
    "        \n",
    "        for i in range(len(sizes) - 2):\n",
    "            layers.append(nn.Linear(sizes[i], sizes[i+1]))\n",
    "            if dropout:\n",
    "                layers.append(nn.Dropout())\n",
    "            layers.append(activation_fn())\n",
    "        else: # нам не нужен дропаут и фнкция активации в последнем слое\n",
    "            layers.append(nn.Linear(sizes[-2], sizes[-1]))\n",
    "        \n",
    "        self.model = nn.Sequential(*layers)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.model(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self, batchnorm=False, dropout=False, optim_type='SGD', **optim_params):\n",
    "        super(Net, self).__init__()\n",
    "        \n",
    "        self._conv1 = ConvLayer([1, 16, 3], bn=batchnorm)\n",
    "        self._conv2 = ConvLayer([16, 32, 3], bn=batchnorm, activation_fn=nn.Sigmoid())\n",
    "        \n",
    "        self.fc = FullyConnected([32*7*7, 10], dropout=dropout)\n",
    "        \n",
    "        self._loss = None\n",
    "        if optim_type == 'SGD':\n",
    "            self.optim = optim.SGD(self.parameters(), **optim_params)\n",
    "        elif optim_type == 'Adadelta':\n",
    "            self.optim = optim.Adadelta(self.parameters(), **optim_params)\n",
    "        elif optim_type == 'RMSProp':\n",
    "            self.optim = optim.RMSprop(self.parameters(), **optim_params)\n",
    "        elif optim_type == 'Adam':\n",
    "            self.optim = optim.Adam(self.parameters(), **optim_params)\n",
    "    \n",
    "    def conv(self, x):\n",
    "        x = self._conv1(x)\n",
    "        x = self._conv2(x)\n",
    "        return x\n",
    "        \n",
    "    def forward(self, x):\n",
    "        x = self.conv(x)\n",
    "        x = x.view(-1, 32*7*7)\n",
    "        x = self.fc(x)\n",
    "        return x\n",
    "    \n",
    "    def loss(self, output, target, **kwargs):\n",
    "        self._loss = F.cross_entropy(output, target, **kwargs)\n",
    "        self._correct = output.data.max(1, keepdim=True)[1]\n",
    "        self._correct = self._correct.eq(target.data.view_as(self._correct)).to(torch.float).cpu().mean()\n",
    "        return self._loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "models = {'SGD': Net(False, False, 'SGD', lr=1e-3),\n",
    "          'momentum': Net(False, False, 'SGD', lr=1e-3, momentum=0.9),\n",
    "          'Adadelta': Net(False, False, 'Adadelta', lr=1.),\n",
    "          'RMSProp': Net(False, False, 'RMSProp', lr=1e-2),\n",
    "          'Adam': Net(False, False, 'Adam', lr=1e-3), \n",
    "         }\n",
    "train_log = {k: [] for k in models}\n",
    "test_log = {k: [] for k in models}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(epoch, models, log=None):\n",
    "    train_size = len(train_loader.sampler)\n",
    "    for batch_idx, (data, target) in enumerate(train_loader):\n",
    "        for model in models.values():\n",
    "            model.optim.zero_grad()\n",
    "            output = model(data)\n",
    "            loss = model.loss(output, target)\n",
    "            loss.backward()\n",
    "            model.optim.step()\n",
    "            \n",
    "        if batch_idx % 200 == 0:\n",
    "            line = 'Train Epoch: {} [{}/{} ({:.0f}%)]\\tLosses '.format(\n",
    "                epoch, batch_idx * len(data), train_size, 100. * batch_idx / len(train_loader))\n",
    "            losses = ' '.join(['{}: {:.4f}'.format(k, m._loss.item()) for k, m in models.items()])\n",
    "            print(line + losses)\n",
    "            \n",
    "    else:\n",
    "        batch_idx += 1\n",
    "        line = 'Train Epoch: {} [{}/{} ({:.0f}%)]\\tLosses '.format(\n",
    "            epoch, batch_idx * len(data), train_size, 100. * batch_idx / len(train_loader))\n",
    "        losses = ' '.join(['{}: {:.4f}'.format(k, m._loss.item()) for k, m in models.items()])\n",
    "        if log is not None:\n",
    "            for k in models:\n",
    "                log[k].append((models[k]._loss, models[k]._correct))\n",
    "        print(line + losses)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(models, loader, log=None):\n",
    "    test_size = len(loader.sampler)\n",
    "    avg_lambda = lambda l: 'Loss: {:.4f}'.format(l)\n",
    "    acc_lambda = lambda c, p: 'Accuracy: {}/{} ({:.0f}%)'.format(c, test_size, p)\n",
    "    line = lambda i, l, c, p: '{}: '.format(i) + avg_lambda(l) + '\\t' + acc_lambda(c, p)\n",
    "\n",
    "    test_loss = {k: 0. for k in models}\n",
    "    correct = {k: 0. for k in models}\n",
    "    with torch.no_grad():\n",
    "        for data, target in loader:\n",
    "            output = {k: m(data) for k, m in models.items()}\n",
    "            for k, m in models.items():\n",
    "                test_loss[k] += m.loss(output[k], target, reduction='sum').item() # sum up batch loss\n",
    "                pred = output[k].data.max(1, keepdim=True)[1] # get the index of the max log-probability\n",
    "                correct[k] += pred.eq(target.data.view_as(pred)).cpu().sum().item()\n",
    "    \n",
    "    for k in models:\n",
    "        test_loss[k] /= test_size\n",
    "    correct_pct = {k: c / test_size for k, c in correct.items()}\n",
    "    lines = '\\n'.join([line(k, test_loss[k], correct[k], 100*correct_pct[k]) for k in models]) + '\\n'\n",
    "    report = 'Test set:\\n' + lines\n",
    "    if log is not None:\n",
    "        for k in models:\n",
    "            log[k].append((test_loss[k], correct_pct[k]))\n",
    "    print(report)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch: 1 [0/50000 (0%)]\tLosses SGD: 2.3290 momentum: 2.3675 Adadelta: 2.2857 RMSProp: 2.3930 Adam: 2.3024\n",
      "Train Epoch: 1 [10000/50000 (20%)]\tLosses SGD: 2.3140 momentum: 2.3285 Adadelta: 0.4463 RMSProp: 0.5349 Adam: 0.5101\n",
      "Train Epoch: 1 [20000/50000 (40%)]\tLosses SGD: 2.3033 momentum: 2.2751 Adadelta: 0.2352 RMSProp: 0.4357 Adam: 0.2310\n",
      "Train Epoch: 1 [30000/50000 (60%)]\tLosses SGD: 2.3089 momentum: 2.2037 Adadelta: 0.1256 RMSProp: 0.3194 Adam: 0.2328\n",
      "Train Epoch: 1 [40000/50000 (80%)]\tLosses SGD: 2.2960 momentum: 1.8090 Adadelta: 0.1447 RMSProp: 0.3828 Adam: 0.1596\n",
      "Train Epoch: 1 [50000/50000 (100%)]\tLosses SGD: 2.2919 momentum: 1.4106 Adadelta: 0.0980 RMSProp: 0.3228 Adam: 0.2125\n",
      "Test set:\n",
      "SGD: Loss: 2.3010\tAccuracy: 1108.0/10000 (11%)\n",
      "momentum: Loss: 1.3665\tAccuracy: 7059.0/10000 (71%)\n",
      "Adadelta: Loss: 0.1170\tAccuracy: 9641.0/10000 (96%)\n",
      "RMSProp: Loss: 0.2003\tAccuracy: 9401.0/10000 (94%)\n",
      "Adam: Loss: 0.1581\tAccuracy: 9566.0/10000 (96%)\n",
      "\n",
      "Train Epoch: 2 [0/50000 (0%)]\tLosses SGD: 2.3077 momentum: 1.4557 Adadelta: 0.2397 RMSProp: 0.2623 Adam: 0.3407\n",
      "Train Epoch: 2 [10000/50000 (20%)]\tLosses SGD: 2.3063 momentum: 1.0407 Adadelta: 0.0881 RMSProp: 0.2817 Adam: 0.1200\n",
      "Train Epoch: 2 [20000/50000 (40%)]\tLosses SGD: 2.3024 momentum: 0.9372 Adadelta: 0.1034 RMSProp: 0.3283 Adam: 0.1301\n",
      "Train Epoch: 2 [30000/50000 (60%)]\tLosses SGD: 2.3248 momentum: 0.8127 Adadelta: 0.0739 RMSProp: 0.1890 Adam: 0.1328\n",
      "Train Epoch: 2 [40000/50000 (80%)]\tLosses SGD: 2.3034 momentum: 0.7151 Adadelta: 0.1338 RMSProp: 0.1648 Adam: 0.1291\n",
      "Train Epoch: 2 [50000/50000 (100%)]\tLosses SGD: 2.2887 momentum: 0.4787 Adadelta: 0.0319 RMSProp: 0.0878 Adam: 0.0602\n",
      "Test set:\n",
      "SGD: Loss: 2.2959\tAccuracy: 1108.0/10000 (11%)\n",
      "momentum: Loss: 0.5333\tAccuracy: 8560.0/10000 (86%)\n",
      "Adadelta: Loss: 0.0972\tAccuracy: 9683.0/10000 (97%)\n",
      "RMSProp: Loss: 0.1885\tAccuracy: 9401.0/10000 (94%)\n",
      "Adam: Loss: 0.1006\tAccuracy: 9707.0/10000 (97%)\n",
      "\n",
      "Train Epoch: 3 [0/50000 (0%)]\tLosses SGD: 2.3044 momentum: 0.6067 Adadelta: 0.0548 RMSProp: 0.2307 Adam: 0.0458\n",
      "Train Epoch: 3 [10000/50000 (20%)]\tLosses SGD: 2.2805 momentum: 0.6814 Adadelta: 0.1182 RMSProp: 0.1120 Adam: 0.1385\n",
      "Train Epoch: 3 [20000/50000 (40%)]\tLosses SGD: 2.2895 momentum: 0.4060 Adadelta: 0.0389 RMSProp: 0.1193 Adam: 0.0836\n",
      "Train Epoch: 3 [30000/50000 (60%)]\tLosses SGD: 2.3066 momentum: 0.4778 Adadelta: 0.0401 RMSProp: 0.0210 Adam: 0.0784\n",
      "Train Epoch: 3 [40000/50000 (80%)]\tLosses SGD: 2.3008 momentum: 0.3588 Adadelta: 0.0364 RMSProp: 0.0902 Adam: 0.0437\n",
      "Train Epoch: 3 [50000/50000 (100%)]\tLosses SGD: 2.2876 momentum: 0.5758 Adadelta: 0.1150 RMSProp: 0.1495 Adam: 0.0967\n",
      "Test set:\n",
      "SGD: Loss: 2.2888\tAccuracy: 1280.0/10000 (13%)\n",
      "momentum: Loss: 0.3925\tAccuracy: 8930.0/10000 (89%)\n",
      "Adadelta: Loss: 0.0740\tAccuracy: 9774.0/10000 (98%)\n",
      "RMSProp: Loss: 0.1255\tAccuracy: 9637.0/10000 (96%)\n",
      "Adam: Loss: 0.0709\tAccuracy: 9793.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 4 [0/50000 (0%)]\tLosses SGD: 2.2888 momentum: 0.4456 Adadelta: 0.1138 RMSProp: 0.1418 Adam: 0.1133\n",
      "Train Epoch: 4 [10000/50000 (20%)]\tLosses SGD: 2.2773 momentum: 0.2510 Adadelta: 0.0584 RMSProp: 0.0792 Adam: 0.0548\n",
      "Train Epoch: 4 [20000/50000 (40%)]\tLosses SGD: 2.3029 momentum: 0.5469 Adadelta: 0.2221 RMSProp: 0.2862 Adam: 0.2500\n",
      "Train Epoch: 4 [30000/50000 (60%)]\tLosses SGD: 2.2656 momentum: 0.4090 Adadelta: 0.0878 RMSProp: 0.1248 Adam: 0.1023\n",
      "Train Epoch: 4 [40000/50000 (80%)]\tLosses SGD: 2.2904 momentum: 0.3794 Adadelta: 0.0479 RMSProp: 0.0759 Adam: 0.0360\n",
      "Train Epoch: 4 [50000/50000 (100%)]\tLosses SGD: 2.2886 momentum: 0.3349 Adadelta: 0.0584 RMSProp: 0.1397 Adam: 0.0569\n",
      "Test set:\n",
      "SGD: Loss: 2.2810\tAccuracy: 1372.0/10000 (14%)\n",
      "momentum: Loss: 0.3303\tAccuracy: 9066.0/10000 (91%)\n",
      "Adadelta: Loss: 0.0804\tAccuracy: 9737.0/10000 (97%)\n",
      "RMSProp: Loss: 0.1324\tAccuracy: 9593.0/10000 (96%)\n",
      "Adam: Loss: 0.0666\tAccuracy: 9808.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 5 [0/50000 (0%)]\tLosses SGD: 2.2810 momentum: 0.3006 Adadelta: 0.0847 RMSProp: 0.1458 Adam: 0.0800\n",
      "Train Epoch: 5 [10000/50000 (20%)]\tLosses SGD: 2.2960 momentum: 0.2347 Adadelta: 0.0889 RMSProp: 0.0943 Adam: 0.0688\n",
      "Train Epoch: 5 [20000/50000 (40%)]\tLosses SGD: 2.2746 momentum: 0.4371 Adadelta: 0.1469 RMSProp: 0.1157 Adam: 0.1675\n",
      "Train Epoch: 5 [30000/50000 (60%)]\tLosses SGD: 2.2794 momentum: 0.3212 Adadelta: 0.0389 RMSProp: 0.1210 Adam: 0.0474\n",
      "Train Epoch: 5 [40000/50000 (80%)]\tLosses SGD: 2.2727 momentum: 0.2381 Adadelta: 0.0416 RMSProp: 0.0534 Adam: 0.0535\n",
      "Train Epoch: 5 [50000/50000 (100%)]\tLosses SGD: 2.2598 momentum: 0.2454 Adadelta: 0.0030 RMSProp: 0.0233 Adam: 0.0066\n",
      "Test set:\n",
      "SGD: Loss: 2.2674\tAccuracy: 2622.0/10000 (26%)\n",
      "momentum: Loss: 0.2884\tAccuracy: 9223.0/10000 (92%)\n",
      "Adadelta: Loss: 0.0577\tAccuracy: 9826.0/10000 (98%)\n",
      "RMSProp: Loss: 0.1017\tAccuracy: 9686.0/10000 (97%)\n",
      "Adam: Loss: 0.0549\tAccuracy: 9834.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 6 [0/50000 (0%)]\tLosses SGD: 2.2625 momentum: 0.3003 Adadelta: 0.0435 RMSProp: 0.0658 Adam: 0.0405\n",
      "Train Epoch: 6 [10000/50000 (20%)]\tLosses SGD: 2.2433 momentum: 0.2332 Adadelta: 0.0046 RMSProp: 0.0786 Adam: 0.0104\n",
      "Train Epoch: 6 [20000/50000 (40%)]\tLosses SGD: 2.2381 momentum: 0.1586 Adadelta: 0.0109 RMSProp: 0.0384 Adam: 0.0152\n",
      "Train Epoch: 6 [30000/50000 (60%)]\tLosses SGD: 2.2679 momentum: 0.3471 Adadelta: 0.0137 RMSProp: 0.0482 Adam: 0.0121\n",
      "Train Epoch: 6 [40000/50000 (80%)]\tLosses SGD: 2.2530 momentum: 0.2196 Adadelta: 0.0148 RMSProp: 0.1191 Adam: 0.0466\n",
      "Train Epoch: 6 [50000/50000 (100%)]\tLosses SGD: 2.2618 momentum: 0.2701 Adadelta: 0.0503 RMSProp: 0.0589 Adam: 0.0318\n",
      "Test set:\n",
      "SGD: Loss: 2.2471\tAccuracy: 2091.0/10000 (21%)\n",
      "momentum: Loss: 0.2580\tAccuracy: 9290.0/10000 (93%)\n",
      "Adadelta: Loss: 0.0580\tAccuracy: 9813.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0912\tAccuracy: 9727.0/10000 (97%)\n",
      "Adam: Loss: 0.0529\tAccuracy: 9829.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 7 [0/50000 (0%)]\tLosses SGD: 2.2502 momentum: 0.3182 Adadelta: 0.0064 RMSProp: 0.0680 Adam: 0.0086\n",
      "Train Epoch: 7 [10000/50000 (20%)]\tLosses SGD: 2.2444 momentum: 0.3233 Adadelta: 0.0173 RMSProp: 0.0272 Adam: 0.0281\n",
      "Train Epoch: 7 [20000/50000 (40%)]\tLosses SGD: 2.2495 momentum: 0.2716 Adadelta: 0.0338 RMSProp: 0.1467 Adam: 0.0166\n",
      "Train Epoch: 7 [30000/50000 (60%)]\tLosses SGD: 2.2355 momentum: 0.2908 Adadelta: 0.0144 RMSProp: 0.0996 Adam: 0.0176\n",
      "Train Epoch: 7 [40000/50000 (80%)]\tLosses SGD: 2.2315 momentum: 0.1809 Adadelta: 0.0262 RMSProp: 0.0201 Adam: 0.0674\n",
      "Train Epoch: 7 [50000/50000 (100%)]\tLosses SGD: 2.1942 momentum: 0.1046 Adadelta: 0.0045 RMSProp: 0.0041 Adam: 0.0015\n",
      "Test set:\n",
      "SGD: Loss: 2.2092\tAccuracy: 4610.0/10000 (46%)\n",
      "momentum: Loss: 0.2354\tAccuracy: 9342.0/10000 (93%)\n",
      "Adadelta: Loss: 0.0630\tAccuracy: 9813.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0974\tAccuracy: 9709.0/10000 (97%)\n",
      "Adam: Loss: 0.0538\tAccuracy: 9837.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 8 [0/50000 (0%)]\tLosses SGD: 2.2057 momentum: 0.2635 Adadelta: 0.0086 RMSProp: 0.0457 Adam: 0.0059\n",
      "Train Epoch: 8 [10000/50000 (20%)]\tLosses SGD: 2.2058 momentum: 0.2410 Adadelta: 0.0241 RMSProp: 0.0153 Adam: 0.0223\n",
      "Train Epoch: 8 [20000/50000 (40%)]\tLosses SGD: 2.1716 momentum: 0.1898 Adadelta: 0.0341 RMSProp: 0.0352 Adam: 0.0532\n",
      "Train Epoch: 8 [30000/50000 (60%)]\tLosses SGD: 2.1549 momentum: 0.2593 Adadelta: 0.0474 RMSProp: 0.0987 Adam: 0.0342\n",
      "Train Epoch: 8 [40000/50000 (80%)]\tLosses SGD: 2.1610 momentum: 0.1133 Adadelta: 0.0566 RMSProp: 0.0509 Adam: 0.0243\n",
      "Train Epoch: 8 [50000/50000 (100%)]\tLosses SGD: 2.1153 momentum: 0.1621 Adadelta: 0.0125 RMSProp: 0.1119 Adam: 0.0586\n",
      "Test set:\n",
      "SGD: Loss: 2.1431\tAccuracy: 4168.0/10000 (42%)\n",
      "momentum: Loss: 0.2182\tAccuracy: 9404.0/10000 (94%)\n",
      "Adadelta: Loss: 0.0544\tAccuracy: 9841.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0948\tAccuracy: 9717.0/10000 (97%)\n",
      "Adam: Loss: 0.0487\tAccuracy: 9863.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 9 [0/50000 (0%)]\tLosses SGD: 2.1511 momentum: 0.1071 Adadelta: 0.0247 RMSProp: 0.0137 Adam: 0.0070\n",
      "Train Epoch: 9 [10000/50000 (20%)]\tLosses SGD: 2.1514 momentum: 0.1605 Adadelta: 0.0582 RMSProp: 0.1231 Adam: 0.0225\n",
      "Train Epoch: 9 [20000/50000 (40%)]\tLosses SGD: 2.1012 momentum: 0.4684 Adadelta: 0.1117 RMSProp: 0.3062 Adam: 0.1213\n",
      "Train Epoch: 9 [30000/50000 (60%)]\tLosses SGD: 2.0702 momentum: 0.2625 Adadelta: 0.0269 RMSProp: 0.0977 Adam: 0.0611\n",
      "Train Epoch: 9 [40000/50000 (80%)]\tLosses SGD: 2.0486 momentum: 0.0907 Adadelta: 0.0009 RMSProp: 0.0375 Adam: 0.0008\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch: 9 [50000/50000 (100%)]\tLosses SGD: 2.0295 momentum: 0.2734 Adadelta: 0.0226 RMSProp: 0.0576 Adam: 0.0468\n",
      "Test set:\n",
      "SGD: Loss: 2.0242\tAccuracy: 5300.0/10000 (53%)\n",
      "momentum: Loss: 0.2010\tAccuracy: 9452.0/10000 (95%)\n",
      "Adadelta: Loss: 0.0511\tAccuracy: 9853.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0792\tAccuracy: 9767.0/10000 (98%)\n",
      "Adam: Loss: 0.0479\tAccuracy: 9860.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 10 [0/50000 (0%)]\tLosses SGD: 2.0267 momentum: 0.1886 Adadelta: 0.0064 RMSProp: 0.0159 Adam: 0.0079\n",
      "Train Epoch: 10 [10000/50000 (20%)]\tLosses SGD: 2.0161 momentum: 0.3075 Adadelta: 0.1056 RMSProp: 0.1914 Adam: 0.0984\n",
      "Train Epoch: 10 [20000/50000 (40%)]\tLosses SGD: 2.0007 momentum: 0.2481 Adadelta: 0.0329 RMSProp: 0.1228 Adam: 0.0345\n",
      "Train Epoch: 10 [30000/50000 (60%)]\tLosses SGD: 1.9824 momentum: 0.2798 Adadelta: 0.0118 RMSProp: 0.0342 Adam: 0.0190\n",
      "Train Epoch: 10 [40000/50000 (80%)]\tLosses SGD: 1.9385 momentum: 0.1670 Adadelta: 0.0414 RMSProp: 0.0905 Adam: 0.0059\n",
      "Train Epoch: 10 [50000/50000 (100%)]\tLosses SGD: 1.8318 momentum: 0.1291 Adadelta: 0.0232 RMSProp: 0.0049 Adam: 0.0112\n",
      "Test set:\n",
      "SGD: Loss: 1.8519\tAccuracy: 6274.0/10000 (63%)\n",
      "momentum: Loss: 0.1884\tAccuracy: 9450.0/10000 (94%)\n",
      "Adadelta: Loss: 0.0490\tAccuracy: 9854.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0871\tAccuracy: 9729.0/10000 (97%)\n",
      "Adam: Loss: 0.0475\tAccuracy: 9862.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 11 [0/50000 (0%)]\tLosses SGD: 1.8732 momentum: 0.3498 Adadelta: 0.0086 RMSProp: 0.1314 Adam: 0.0173\n",
      "Train Epoch: 11 [10000/50000 (20%)]\tLosses SGD: 1.8177 momentum: 0.1003 Adadelta: 0.0027 RMSProp: 0.0242 Adam: 0.0047\n",
      "Train Epoch: 11 [20000/50000 (40%)]\tLosses SGD: 1.6775 momentum: 0.0981 Adadelta: 0.0161 RMSProp: 0.0197 Adam: 0.0202\n",
      "Train Epoch: 11 [30000/50000 (60%)]\tLosses SGD: 1.7550 momentum: 0.2379 Adadelta: 0.0406 RMSProp: 0.0218 Adam: 0.0244\n",
      "Train Epoch: 11 [40000/50000 (80%)]\tLosses SGD: 1.6180 momentum: 0.0768 Adadelta: 0.1180 RMSProp: 0.0716 Adam: 0.0461\n",
      "Train Epoch: 11 [50000/50000 (100%)]\tLosses SGD: 1.7226 momentum: 0.3150 Adadelta: 0.1958 RMSProp: 0.0650 Adam: 0.1015\n",
      "Test set:\n",
      "SGD: Loss: 1.6390\tAccuracy: 6972.0/10000 (70%)\n",
      "momentum: Loss: 0.1768\tAccuracy: 9492.0/10000 (95%)\n",
      "Adadelta: Loss: 0.0578\tAccuracy: 9829.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0768\tAccuracy: 9777.0/10000 (98%)\n",
      "Adam: Loss: 0.0461\tAccuracy: 9856.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 12 [0/50000 (0%)]\tLosses SGD: 1.6218 momentum: 0.1006 Adadelta: 0.0019 RMSProp: 0.0031 Adam: 0.0015\n",
      "Train Epoch: 12 [10000/50000 (20%)]\tLosses SGD: 1.6575 momentum: 0.3089 Adadelta: 0.0488 RMSProp: 0.1030 Adam: 0.0219\n",
      "Train Epoch: 12 [20000/50000 (40%)]\tLosses SGD: 1.5848 momentum: 0.2765 Adadelta: 0.0265 RMSProp: 0.1815 Adam: 0.0207\n",
      "Train Epoch: 12 [30000/50000 (60%)]\tLosses SGD: 1.4475 momentum: 0.0918 Adadelta: 0.0141 RMSProp: 0.0529 Adam: 0.0025\n",
      "Train Epoch: 12 [40000/50000 (80%)]\tLosses SGD: 1.4904 momentum: 0.3509 Adadelta: 0.0183 RMSProp: 0.1717 Adam: 0.0740\n",
      "Train Epoch: 12 [50000/50000 (100%)]\tLosses SGD: 1.3712 momentum: 0.0748 Adadelta: 0.0061 RMSProp: 0.0146 Adam: 0.0100\n",
      "Test set:\n",
      "SGD: Loss: 1.4286\tAccuracy: 7235.0/10000 (72%)\n",
      "momentum: Loss: 0.1662\tAccuracy: 9512.0/10000 (95%)\n",
      "Adadelta: Loss: 0.0512\tAccuracy: 9861.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0779\tAccuracy: 9762.0/10000 (98%)\n",
      "Adam: Loss: 0.0594\tAccuracy: 9821.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 13 [0/50000 (0%)]\tLosses SGD: 1.4711 momentum: 0.1646 Adadelta: 0.0090 RMSProp: 0.0464 Adam: 0.0272\n",
      "Train Epoch: 13 [10000/50000 (20%)]\tLosses SGD: 1.3948 momentum: 0.1252 Adadelta: 0.0563 RMSProp: 0.0316 Adam: 0.0192\n",
      "Train Epoch: 13 [20000/50000 (40%)]\tLosses SGD: 1.4908 momentum: 0.2784 Adadelta: 0.0835 RMSProp: 0.1229 Adam: 0.0325\n",
      "Train Epoch: 13 [30000/50000 (60%)]\tLosses SGD: 1.2886 momentum: 0.1040 Adadelta: 0.0041 RMSProp: 0.0312 Adam: 0.0078\n",
      "Train Epoch: 13 [40000/50000 (80%)]\tLosses SGD: 1.2166 momentum: 0.1860 Adadelta: 0.0298 RMSProp: 0.1094 Adam: 0.0070\n",
      "Train Epoch: 13 [50000/50000 (100%)]\tLosses SGD: 1.1036 momentum: 0.1894 Adadelta: 0.0872 RMSProp: 0.0165 Adam: 0.0689\n",
      "Test set:\n",
      "SGD: Loss: 1.2428\tAccuracy: 7510.0/10000 (75%)\n",
      "momentum: Loss: 0.1598\tAccuracy: 9538.0/10000 (95%)\n",
      "Adadelta: Loss: 0.0554\tAccuracy: 9839.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0844\tAccuracy: 9750.0/10000 (98%)\n",
      "Adam: Loss: 0.0505\tAccuracy: 9845.0/10000 (98%)\n",
      "\n",
      "Train Epoch: 14 [0/50000 (0%)]\tLosses SGD: 1.2891 momentum: 0.1764 Adadelta: 0.0403 RMSProp: 0.1448 Adam: 0.0252\n",
      "Train Epoch: 14 [10000/50000 (20%)]\tLosses SGD: 1.2228 momentum: 0.1801 Adadelta: 0.0286 RMSProp: 0.0282 Adam: 0.0393\n",
      "Train Epoch: 14 [20000/50000 (40%)]\tLosses SGD: 1.1186 momentum: 0.0893 Adadelta: 0.0016 RMSProp: 0.0126 Adam: 0.0026\n",
      "Train Epoch: 14 [30000/50000 (60%)]\tLosses SGD: 1.0216 momentum: 0.0577 Adadelta: 0.0148 RMSProp: 0.0228 Adam: 0.0245\n",
      "Train Epoch: 14 [40000/50000 (80%)]\tLosses SGD: 1.0780 momentum: 0.2194 Adadelta: 0.1806 RMSProp: 0.2429 Adam: 0.1397\n",
      "Train Epoch: 14 [50000/50000 (100%)]\tLosses SGD: 1.1312 momentum: 0.1450 Adadelta: 0.0132 RMSProp: 0.0930 Adam: 0.0107\n",
      "Test set:\n",
      "SGD: Loss: 1.0885\tAccuracy: 7711.0/10000 (77%)\n",
      "momentum: Loss: 0.1519\tAccuracy: 9565.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0485\tAccuracy: 9870.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0801\tAccuracy: 9761.0/10000 (98%)\n",
      "Adam: Loss: 0.0481\tAccuracy: 9865.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 15 [0/50000 (0%)]\tLosses SGD: 1.1588 momentum: 0.2621 Adadelta: 0.1603 RMSProp: 0.0574 Adam: 0.1378\n",
      "Train Epoch: 15 [10000/50000 (20%)]\tLosses SGD: 1.1441 momentum: 0.3539 Adadelta: 0.0633 RMSProp: 0.1565 Adam: 0.0371\n",
      "Train Epoch: 15 [20000/50000 (40%)]\tLosses SGD: 1.0197 momentum: 0.2554 Adadelta: 0.0105 RMSProp: 0.0883 Adam: 0.0137\n",
      "Train Epoch: 15 [30000/50000 (60%)]\tLosses SGD: 1.2132 momentum: 0.3101 Adadelta: 0.0291 RMSProp: 0.1600 Adam: 0.0244\n",
      "Train Epoch: 15 [40000/50000 (80%)]\tLosses SGD: 0.9071 momentum: 0.0781 Adadelta: 0.0028 RMSProp: 0.0056 Adam: 0.0080\n",
      "Train Epoch: 15 [50000/50000 (100%)]\tLosses SGD: 1.0040 momentum: 0.1091 Adadelta: 0.0485 RMSProp: 0.0539 Adam: 0.0177\n",
      "Test set:\n",
      "SGD: Loss: 0.9656\tAccuracy: 7866.0/10000 (79%)\n",
      "momentum: Loss: 0.1438\tAccuracy: 9569.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0477\tAccuracy: 9860.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0790\tAccuracy: 9770.0/10000 (98%)\n",
      "Adam: Loss: 0.0455\tAccuracy: 9869.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 16 [0/50000 (0%)]\tLosses SGD: 0.8332 momentum: 0.1011 Adadelta: 0.0018 RMSProp: 0.0018 Adam: 0.0014\n",
      "Train Epoch: 16 [10000/50000 (20%)]\tLosses SGD: 0.9349 momentum: 0.0660 Adadelta: 0.0057 RMSProp: 0.0102 Adam: 0.0023\n",
      "Train Epoch: 16 [20000/50000 (40%)]\tLosses SGD: 0.8991 momentum: 0.1297 Adadelta: 0.0046 RMSProp: 0.0683 Adam: 0.0079\n",
      "Train Epoch: 16 [30000/50000 (60%)]\tLosses SGD: 0.7444 momentum: 0.2204 Adadelta: 0.1930 RMSProp: 0.2542 Adam: 0.0486\n",
      "Train Epoch: 16 [40000/50000 (80%)]\tLosses SGD: 0.8917 momentum: 0.1312 Adadelta: 0.0226 RMSProp: 0.0659 Adam: 0.0281\n",
      "Train Epoch: 16 [50000/50000 (100%)]\tLosses SGD: 0.7455 momentum: 0.0753 Adadelta: 0.0100 RMSProp: 0.1089 Adam: 0.0169\n",
      "Test set:\n",
      "SGD: Loss: 0.8655\tAccuracy: 8023.0/10000 (80%)\n",
      "momentum: Loss: 0.1390\tAccuracy: 9594.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0485\tAccuracy: 9862.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0749\tAccuracy: 9784.0/10000 (98%)\n",
      "Adam: Loss: 0.0502\tAccuracy: 9857.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 17 [0/50000 (0%)]\tLosses SGD: 0.7299 momentum: 0.0415 Adadelta: 0.0019 RMSProp: 0.0075 Adam: 0.0037\n",
      "Train Epoch: 17 [10000/50000 (20%)]\tLosses SGD: 0.8957 momentum: 0.0796 Adadelta: 0.0048 RMSProp: 0.0120 Adam: 0.0019\n",
      "Train Epoch: 17 [20000/50000 (40%)]\tLosses SGD: 0.7635 momentum: 0.0877 Adadelta: 0.0067 RMSProp: 0.0039 Adam: 0.0022\n",
      "Train Epoch: 17 [30000/50000 (60%)]\tLosses SGD: 0.7872 momentum: 0.1051 Adadelta: 0.0149 RMSProp: 0.0386 Adam: 0.0112\n",
      "Train Epoch: 17 [40000/50000 (80%)]\tLosses SGD: 0.8631 momentum: 0.1662 Adadelta: 0.0100 RMSProp: 0.0360 Adam: 0.0370\n",
      "Train Epoch: 17 [50000/50000 (100%)]\tLosses SGD: 0.6845 momentum: 0.0895 Adadelta: 0.0046 RMSProp: 0.0079 Adam: 0.0075\n",
      "Test set:\n",
      "SGD: Loss: 0.7839\tAccuracy: 8131.0/10000 (81%)\n",
      "momentum: Loss: 0.1333\tAccuracy: 9608.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0493\tAccuracy: 9864.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0846\tAccuracy: 9754.0/10000 (98%)\n",
      "Adam: Loss: 0.0446\tAccuracy: 9873.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 18 [0/50000 (0%)]\tLosses SGD: 0.8799 momentum: 0.0847 Adadelta: 0.0034 RMSProp: 0.0230 Adam: 0.0030\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch: 18 [10000/50000 (20%)]\tLosses SGD: 0.9637 momentum: 0.1177 Adadelta: 0.0012 RMSProp: 0.0100 Adam: 0.0018\n",
      "Train Epoch: 18 [20000/50000 (40%)]\tLosses SGD: 0.9276 momentum: 0.1625 Adadelta: 0.0329 RMSProp: 0.0685 Adam: 0.0124\n",
      "Train Epoch: 18 [30000/50000 (60%)]\tLosses SGD: 0.9665 momentum: 0.3093 Adadelta: 0.0225 RMSProp: 0.0847 Adam: 0.0227\n",
      "Train Epoch: 18 [40000/50000 (80%)]\tLosses SGD: 0.5513 momentum: 0.0514 Adadelta: 0.0151 RMSProp: 0.0107 Adam: 0.0145\n",
      "Train Epoch: 18 [50000/50000 (100%)]\tLosses SGD: 0.7531 momentum: 0.0885 Adadelta: 0.0590 RMSProp: 0.1376 Adam: 0.0158\n",
      "Test set:\n",
      "SGD: Loss: 0.7198\tAccuracy: 8246.0/10000 (82%)\n",
      "momentum: Loss: 0.1288\tAccuracy: 9613.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0463\tAccuracy: 9871.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0843\tAccuracy: 9764.0/10000 (98%)\n",
      "Adam: Loss: 0.0468\tAccuracy: 9862.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 19 [0/50000 (0%)]\tLosses SGD: 0.7803 momentum: 0.2883 Adadelta: 0.0436 RMSProp: 0.0704 Adam: 0.0149\n",
      "Train Epoch: 19 [10000/50000 (20%)]\tLosses SGD: 0.7111 momentum: 0.1070 Adadelta: 0.0188 RMSProp: 0.0379 Adam: 0.0033\n",
      "Train Epoch: 19 [20000/50000 (40%)]\tLosses SGD: 0.7322 momentum: 0.1013 Adadelta: 0.0012 RMSProp: 0.0064 Adam: 0.0013\n",
      "Train Epoch: 19 [30000/50000 (60%)]\tLosses SGD: 0.8782 momentum: 0.1492 Adadelta: 0.0192 RMSProp: 0.1087 Adam: 0.0192\n",
      "Train Epoch: 19 [40000/50000 (80%)]\tLosses SGD: 0.6235 momentum: 0.0701 Adadelta: 0.0042 RMSProp: 0.0220 Adam: 0.0235\n",
      "Train Epoch: 19 [50000/50000 (100%)]\tLosses SGD: 0.7410 momentum: 0.1310 Adadelta: 0.0157 RMSProp: 0.1297 Adam: 0.0343\n",
      "Test set:\n",
      "SGD: Loss: 0.6665\tAccuracy: 8334.0/10000 (83%)\n",
      "momentum: Loss: 0.1248\tAccuracy: 9640.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0520\tAccuracy: 9848.0/10000 (98%)\n",
      "RMSProp: Loss: 0.0775\tAccuracy: 9775.0/10000 (98%)\n",
      "Adam: Loss: 0.0453\tAccuracy: 9868.0/10000 (99%)\n",
      "\n",
      "Train Epoch: 20 [0/50000 (0%)]\tLosses SGD: 0.6762 momentum: 0.1211 Adadelta: 0.0039 RMSProp: 0.0212 Adam: 0.0020\n",
      "Train Epoch: 20 [10000/50000 (20%)]\tLosses SGD: 0.5095 momentum: 0.0797 Adadelta: 0.0036 RMSProp: 0.0065 Adam: 0.0031\n",
      "Train Epoch: 20 [20000/50000 (40%)]\tLosses SGD: 0.5597 momentum: 0.0703 Adadelta: 0.0053 RMSProp: 0.0260 Adam: 0.0028\n",
      "Train Epoch: 20 [30000/50000 (60%)]\tLosses SGD: 0.5705 momentum: 0.0807 Adadelta: 0.0085 RMSProp: 0.0952 Adam: 0.0069\n",
      "Train Epoch: 20 [40000/50000 (80%)]\tLosses SGD: 0.5922 momentum: 0.1140 Adadelta: 0.0101 RMSProp: 0.1888 Adam: 0.0026\n",
      "Train Epoch: 20 [50000/50000 (100%)]\tLosses SGD: 0.6552 momentum: 0.0763 Adadelta: 0.0430 RMSProp: 0.0388 Adam: 0.0063\n",
      "Test set:\n",
      "SGD: Loss: 0.6225\tAccuracy: 8408.0/10000 (84%)\n",
      "momentum: Loss: 0.1202\tAccuracy: 9644.0/10000 (96%)\n",
      "Adadelta: Loss: 0.0501\tAccuracy: 9863.0/10000 (99%)\n",
      "RMSProp: Loss: 0.0815\tAccuracy: 9782.0/10000 (98%)\n",
      "Adam: Loss: 0.0477\tAccuracy: 9874.0/10000 (99%)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(1, 21):\n",
    "    for model in models.values():\n",
    "        model.train()\n",
    "    train(epoch, models, train_log)\n",
    "    for model in models.values():\n",
    "        model.eval()\n",
    "    test(models, valid_loader, test_log)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_graphs(test_log, 'loss')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEWCAYAAACJ0YulAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzs3XecFPX9+PHXZ2b3euO44+AKcPR2cEixUsSoGKNGTUT9xZpoEgVbmhoLmqiJscREv37VJGryTUCDvTeKYKUXgaPDHe0a13dvd2c+vz9mb7k7TjiOW/bK+/l4DNNn3rvcft4zn5n5jNJaI4QQQgAYkQ5ACCFExyFJQQghRIgkBSGEECGSFIQQQoRIUhBCCBEiSUEIIUSIJAUhhBAhkhSEEEKESFIQIoyUQ35notOQP1bRLSilbldKbVVKVSul1iulLmw07zql1IZG804ITs9RSr2qlCpRSpUppZ4MTp+tlPq/Ruv3V0pppZQrOL5QKfWAUuozoA4YoJS6ptE+timlftosvguUUquUUlXBOKcrpX6olFrebLlfKKVeD983Jbo7SQqiu9gKTAKSgfuA/1NK9VFK/RCYDVwJJAHnA2VKKRN4G9gJ9AeygLlHsb8rgOuBxOA2ioHvBfdxDfB4o+QzEfgn8CsgBZgM7ADeBHKVUsMbbfdHwL+O6pMLcRQkKYhuQWv9X631Hq21rbV+CdgMTAR+AjystV6qHVu01juD8zKBX2mta7XWXq31kqPY5Qta62+01gGttV9r/Y7WemtwH4uAD3GSFMCPgX9orT8Kxrdba71Ra10PvISTCFBKjcRJUG+3w1ciRIskKYhuQSl1ZbB6pkIpVQGMAtKAHJyziOZygJ1a60Abd1nYbP/nKKW+VEqVB/f/3eD+G/bVUgwALwKXK6UUztnHy8FkIURYSFIQXZ5Sqh/wHDAT6Km1TgHWAQqn8B7YwmqFQN+G6wTN1AJxjcZ7t7BMqPlhpVQ08ArwCJAR3P+7wf037KulGNBafwn4cM4qLkeqjkSYSVIQ3UE8TiFdAqCUugbnTAHgb8AvlVLjgncKDQomka+BvcAflFLxSqkYpdSpwXVWAZOVUn2VUsnAHUfYfxQQHdx/QCl1DnBWo/l/B65RSp2hlDKUUllKqWGN5v8TeBIIHGUVlhBHTZKC6PK01uuBR4EvgP1AHvBZcN5/gQeA/wDVwOtAqtbaAs4DBgG7gCJgRnCdj3Dq+tcAyzlCHb/Wuhq4CXgZOIBzxP9mo/lfE7z4DFQCi4B+jTbxL5wkJmcJIuyUvGRHiI5NKRWLc/fSCVrrzZGOR3RtcqYgRMf3c2CpJARxPLR0EU0I0UEopXbgXJD+foRDEd2EVB8JIYQIkeojIYQQIZ2u+igtLU33798/0mEIIUSnsnz58lKtdfqRlut0SaF///4sW7Ys0mEIIUSnopTa2ZrlpPpICCFEiCQFIYQQIWFLCkqpfyilipVS675lvlJK/UUptUUptaahGWEhhBCRE84zhReA6YeZfw4wONhdDzwdxliEEEK0QtiSgtb6U6D8MItcAPwz2L78l0CKUqpPuOIRQghxZJG8ppBF0zbni4LTDqGUul4ptUwptaykpOS4BCeEEN1RJJOCamFai49Xa62f1VqP11qPT08/4m22Qggh2iiSzykU4bxxqkE2sCdCsYgOQtuagN8m4LMO9n02Ab+N5bechZRyjigUqOCAUsHpDYcaCpTzD6CxsLC1HTrs0Fqjg31nmg5OD87Hmd7QDIzWoJTCbbpxGSaGYaAMZ5oTh7NvZQT7Sh0y3zAU7mgTV7SJYbR0TNToe9Aar+XFE/BQ56/DE/BQb9XjMlxEmVFEm9FEm9Gh4SgjytnX0X7fWmMFbLz19dTW11Hr9VDrrcNT76XO68Hjq8dbX0+9rx6fz4/CQKEwMDCV6QwpA0MbKGVgNJpvYDqfWzvTlFIYSoHp/L8p0/m+MDQYON+XASjtfI8mYOiDyyiwLRttgW1rpx/QaEtj2xrb0tgBguOgAxrbcsa1DbblbEMrO7g9jVZO3zbs4Lgd7DTasNE4fTs43a3cuJQLtxHlDBvu0DRX4z4mpnLhVm4MjODfUvDvznb6tm1j2TYBy8KyLQJ2AMuysWzrYGfZweUsLNtm2NhsRgzPPer/56MRyaTwJjBTKTUXOBGo1FrvjWA8HZq2NZZlE/DZWH6bgD9YWPoaFaChaQcL1FqPh4q6Sqpqa/D6vIDCMAwMFewbyvlRG0az6QZmo+mm4fz4tSb0R43txKUb/uDtg3/wOjiPRsvbtsbvC+D3WVihgl5j+zU6ANqvwD76gq0zsk0L2+3HMv0EXD78Rj0+00u94aFeefCoWnymF79ZH+oChg9Dm5i2G5ftDvUbhqN0NFE6GreOxq2jcNlRuLUzz7TdGLaJsgyns00M28S0W1MEuGh9UWEH+xbgb9N3c3woWq6sOFqBYHd8VLvWdt6koJSaA0wF0pRSRcC9gBtAa/2/OK8j/C6wBajDeclIl6BtTW2lj+pyL9XlHipKa9m3v5yaCo/zY9QGyjZQtkLbKniEY2NbTsHvjGtsq2GadgrYNvIbPizDj6WcP16FQmnnR6G0co6oGw07fSM4Lbh8o5pGGwuttHP0RPDICueoSwen2Y2GG468bGwsw0/A9BEw/E7n8mNFNRo3/GjTQrk1hlthuhWmy8CMMnC5DVzK5SQxZeJSJiYmhjIxlYmB0zeViaGMptMCGpffRrtNdJTzZx86ikcBmtDpR5Azv9H3rsFv+/FZfvyWn4AVwBfwE7D9+K0A/kCAgB1w5gUCUO/HrA9gegO46i1cfnCpOKczgn1iMHQscXY0CYEUDLsXynKjLBMCJuhWFFxKg6nRLhttWmjTwjYsLNPCNv1Y7gD1hpeA4ccwwXAFv1O3gctt4nKZuKNcRLlduN1uoqPcREdFERMdRUx0NDFR0cRGxxAbHeMcreMcudp2wOksp9M6gG35sYLTdcN0O4BtW9gBH/g1OmCjAhr8Nlg22q/BsoPzNFhO1zCsg0f72BrlNjCiXBBlYkS7ULFuVLQbFetCxUZhxERhxEWj4qIwYtzOQY8JylQYpgqeyTi/PbRC2c5ZDhqUNsEGpY3gPGcZbQEBGyxNwPJhWT58AS8By0cgUE/AX0/AqicQ8BGwfViB4LBV78y3fNgBZ7qhwVQKNwpTGZhaYSqFCbi0ialw5qEwtcIFGI2GM4Z+p83lQGuFLSlorS87wnwN3Biu/YeTFbCpOeClusxLdbmXytI6iosrqCitoe6An0C188fWmNdVS627EssIYCvL6QwLW9koU2OYzg/ViFGYpvNDbejcLufHapiKal1JRaCcskAppb4SanU1AcMpVC3DjzvaRXpCT9KT0umT3Is+SX3ITswiM6Ef6XHpaK0J2AEC2inAAnYAS1uhYb/tbzJueb1YtdXYVTXYHi/KbaJdJtrtCvZNtMuFdptgmjiFqtni96aUIsaMIcYVQ6wrllhXbGi8YVq0GY3LaPnPUmuN9niwKiudriLYr6zAqqjErqzEqixtNP1gpz2egxsyDIyEBIz4eMyEeIx4Z9hISMBIiMcMzjPiE0LLGQnxGDEx2DU1WJVVWFVVWJUe7KoqZ7yyEquqyomhypmPZR3T35kGbMONZcYQMKOx3bEYhsZUNqahnU5pDJeBMk2UywUuE2W6DhlWLhMME2wbbVloKwAB65BhAoHgtGbDloXdMM22MSyr4z/56nZjxMZixMRgxMaiYmNBa+fzWnboc4W+g4Zpwc+og/3G/49msIuK0EeKSRsEY04K6z46XdtHx1PAZ7G3qJzd28sp3llJxV4PdQf8WDVNTz01NnXuKqqjD1AdXU5tnwqMRIu4Hm5S0uLo1SuVIamZ9IwdgDfgpdZf22JX0zAcqKXWF+wHp9naOS2Pj4ons2cmWfFZnJA4iMz4TLISsshMyCQzIZOkqKRD6pZtjwf/7t3412/Erq7CVVODXV2DVVONXV3jFHQNw9XVWLU1oWHtP4oqAMNAud2oqKiW+y6XUygFf2gNfa+28Vo2B2zL+WEG+6FlguvoQAAOE4+KisJMScFMTsZMTsadk03MqJGYyc40Iz4e7fVg1dRg19Zh1zif3a51Pr9/377geC12be3BCwyH+bxmUhJGchJmUjJmUhJR2dkHx5OTMZOTMJKSnOGEBKeKze9zCh6/3yl4AgG0Lzjs96MDfud7bxj3B0LzsALogOWMNxTmjYctZzxUoAeHbY8fbVkowziYLKKiGyUOE0xXMLkcHMY0Ds43zIP90Lxm48bBdZqPK9MAlwvlcqPcDcnK9S3TGo03/O2YJrq+Htvjwa6rQ3u9wWEPtqcO7fFge7wHh+s8znyvB13nwfZ6wVCo5p/DZTpxNnwXphH8/AaYZpPPotyu0DTne2o0v/E0V8P350xzhk3n+zdNUIazfcNwphmNhk3nWkxLy6m4uNb/Htuo2ySFfbX72Fa5jRpfDTX+Gqp91VT7qkPDtZ46rDIXRmk8MQdSSKxMJ6k2HVM7X1G9WUdZ/G6qYsupSSmHhIBT6KfH07tXTwYnZ5GZMIqshCwy4jNwG+4m+9eBAP7duzHi4jAykjCio1sde8NFx4AdIMGdcEihry2LwP79+LYWUFlYhH93Eb7CIvxFRfiKCrFKSlvesFLOkXBiAmZ8AkZiImZ6GlG5uc60hASMhERnODHROdJqKKh8viZ9u9n4wb7/4HjAj1INPzQj+KN0+g0/1iYFidHwQ1LBAsnlFLLBQt9JACmYKc64ERNzdH8Uh/vObdspVGqDSaLGOVMyEuKDSSYJIz7e+RGL4yc6GjMpKdJRHJ5tQ8ALfg8EPE7fXwd+L05dWPBC28ELbk7f0s7liZbmNVyp7p0HqZ30mkJH8+72d3l8+eMAmJabnnWZpNfm0Kcul/TaUfSuTcPQTrWHFeXDTquDgeW4emuSMt0kpcWREjMqdEQebR65UNeBAHVff03Ve+9T/fHHWAcOhOapqCjnCDIxESMpETMh2E9MwkxKxGjcT0zASEzC5XZRvXsP/qJCfEVF+BsK/j17mh5BGwbu3r1xZ2eTMHkyUdnZuLNzcGf2cY5sExOdZBAXJ4Xat1CGgZngVC+JCLD8wUK1Pliwep2+5Xc6u6EfaDQeaDS9+XhwOecOiINd6LagZtMPmRYcbyjs/XXNCv1GBX/Ac8SP12bnPgapPw7f9ulGSWGcfzJ3e4bg2aepLfYTrI0hJsFNr76JpPVNpFffRNL7JpLYM6ZNt/eBkwhqv/qK6vc/CCUCFRdH4tSpxJ9yMtrvx6quwa6uwqqqDvWt6ir8e/ZgVVc71Tb19Yfdj5mSgjs7m+gRw0k860yn0M/OIionB3fv3qioSNV6ig7Ptg4WZE2OZD1Nu+bzAl5nXa1pUpi2eFRrN1tOO0fJAe/BgrNJ33twH36Ps2w4OPfBBjvVaDg4TvNpzZZ1xYA71umi4iA+LTgt7uD0UBec5moYj2m0f9Vw/20L+1aHjjcMJ2WG53tppNskBaMyhpqtmvS+SQwdm0Cvvkmk90skoUd0mxNAA+33U/vV11R/8D7VH32MVVGBERdHwumnkzj9bBImTTrqqg27vt6p32+UOLTfhzszE3d2NmZCwjHFLDoA2war3ikIA77gsM8Zbxi26oNHy/Vg+ZoV2F6nwA54mx6l+j3Nhj1Nl7EOf8DxrcxoMFzNCiyOULgZTZd1xTQtWONSD463pm9GgekCww2mO9hvPO5qNL3ZuGE2PNgiDqPbJIWRkzIZNSXrmBNAA+33U/vlV1R98D41H32MVVnpJIJp00iafjbxp512THXcRnQ0RnQ0rrS0dolXtBMrAPVVTudt1PdWNppW2XRefcP8mmACqHcKZrsd7m83o4JHojHNjkpjISYFEvs0LVibHNHGNZoX12has/GGglyqGruFbpMUDPPY/6BDieD996j5+BMnEcTHN00ER3EBWbSB1lBfDd4K8FSA50Drh+urGx5NDm6s0Wk6NDrK/Zb5aOdo+0hcsRCTBNFJTj8mGZKyIDoxWMBGO50ZDa6oZv2Yw09rKLAbCnmj5dt/hWirbpMUKubNo+wfzx/TNgKlpdhVVQcTwTnTiT/1VEkEx0Jr8NVCbTHUlkJtCdQ0Gm48vbbUKeAPV99suJwj5NgUiO0B8emQNtiZFpNEkwI+dMtpa4aDohOdQr6hwG/STwkW/HI9R3Re3SYpmKmpRA8dckzbiBt3Agmnny6J4HCsgHNUXlcOnvJg/8DB4dqSpl1NybffrRGdDAnpBwv2vic7ddANhX5MsOBvPBwVL/XGQhyDbpMUEqdNI3HatEiH0blo7RToNcVQs88pwFsq6EPDB5z69G9juCAu7WBB33OQ049Ph4ReweE0iO8VvKtDEq8Qx1u3SQqiEb8HavYHC/v9B4er9zWaFuzb3/IEcXQyxPWA2FTnCL3nQGc4Ljgem9p0flyqU8UiR/FCdGiSFLqygA/2rYGipVD4Nexf5xT89VUtLKyCR+wZzlF7+jCn3zDe0I/r6VTVmPKnI0RXJL/srqRyt5MAGpLA3tUH70lPyobMfBg4rVEh36jAj0uTgl4IIUmh0/J7nbOAwq+h6GsoWgZVu515ZjRkjoUTr4fsCU53HJ6EFEJ0fpIUOgPbhgPbYe8qKAyeCexb4zzhCpDS17kzJ3sC5EyAjDy5LVII0SaSFDoayw8lG2HvGqfg37sG9q0FX7Uz3xXrnAWc9HPInugkgsSMyMYshOgyJClEkq8W9q0LFv6rnX7xhoNnAO44yBgFY2ZA79HQZwxkjHTachFCiDCQpHC8WH7YseRg4b93DZRtIfQm+dhU6DMaTvyZU/j3Hu3c5inNGAghjiNJCuFmW7D2v7DgQajY6UxLznEK/bwfBM8ARjtt48g9/EKICJOkEC5aw4Y3nWRQstEp/C/5F/Q/zXmQSwghOiBJCu1Na9jyCcz/nXO3UNoQ+OGLMPx8aXpYCNHhSVJoTzs/h09+B7s+d24T/f7TMHqGXBcQQnQakhTaw56VTjLY+gkk9IbvPgInXCXPCgghOh1JCseieAMseAA2vOU0+nbm72DCT5x3twohRCckSaEtyrfDwj/AmpcgKgGm3gEn3RB8iYsQQnRekhSORtUeWPQwrPyX8yLwU2+CU2+Ru4mEEF2GJIXW2vwxzL0ctA3jroHJv4TE3pGOSggh2pUkhdbQGj6+F5Kz4YrXoEe/SEckhBBhITfOt8bmD50X1Ez+pSQEIUSXJmcKrbH4MadpirwfRjoSIUQ3UR+wKK6qZ3+Vl31VXvZVejl1UBrD+4T3hhZJCkey83Mo/BLOeVhaJxVCHDPb1pTX+dhf5XUK/Mp69lV5KW5U+BdX11Ne6ztk3XvPGyFJIeIWP+a8qnLsFZGORAjRCXj9FrsrPOw+4KHogIeiA3XsrnCGnQLfi9/STdZRCtISoslIiia7Ryzj+vUgIymG3kkxZCTHkJEUTe+kGJJjw39gKknhcPaugS0fwbS75IE0IQQAHp/F7oo6CoOF/u5gwV90wMPuCg8l1fVNlncZisyUWLJSYjkxN9Up5BOj6Z0cQ0aS06UnRuM2O8YlXkkKh7PkcYhKhAnXRToSIcRxZNmawvI6NhfXsKW4hs3F1WwtqaWovI6yZtU6blORlRJLVo9Ypg3tRXaPWLJTY8lKiSO7RywZSTGYRudpFl+Swrcp2wrrX4dTboLYlEhHI4QIA1/AZkdZLZv3Hyz8txTXsK20Fl/ADi2XkRTNwPQEzhqZQXYPp7DPSoklu0ccvRKjMTpRoX8kkhS+zWd/dp5aPumGSEcihDhGNfUBtpfUsqXEKfQ3769hS0kNO8vqsGynfl8pyO4Ry+BeiUweks6g9AQGZSQwMD3huNTldxRhTQpKqenAE4AJ/E1r/Ydm8/sCLwIpwWVu11q/G86YWqVqD6yaAydcCYkZkY5GCNEKlq3ZfcDD1tIatpXUsq0k2C+tYX/VwXp+l6HonxbPkF6JfHdUHwYHC/6B6QnERkkz92FLCkopE3gKOBMoApYqpd7UWq9vtNhdwMta66eVUiOAd4H+4Yqp1b54ymnO4tSbIh2JEKKZijofWxsK/dKDhf/Osjp81sEqn+RYNwPS4zltUDoD0uMZmB7PoF4J9OsZ32Eu6nZE4TxTmAhs0VpvA1BKzQUuABonBQ003HSbDOwJYzytU1cOy5533p/co3+koxGiW9tX6WXFrgOs2HmANUWVbCmpaXL/vstQ9O0Zx4C0BKYN68WA9HgGpCcwIC2e1PgolLz3/KiFMylkAYWNxouAE5stMxv4UCk1C4gHvhPGeFrn62fBXwun3RrpSIToVuoDFut2V7Fy1wFW7qpgxa4D7K30AhDlMhiVmcRZIzKcgj8tgQHp8eSkxslRfzsLZ1JoKUXrZuOXAS9orR9VSp0M/EspNUprbTdeSCl1PXA9QN++fcMSLAD1NfDl0zD0u9BrePj2I0Q3p7VmT6WXFTsPJoD1e6pC1T9ZKbGM75/K2JwUTujXgxF9kohySeF/PIQzKRQBOY3Gszm0eujHwHQArfUXSqkYIA0obryQ1vpZ4FmA8ePHN08s7Wf5C+CtgNNuC9suhOiOvH6LtbsrWbnrACt2VrCy8EDo4m+0y2BMdgrXnNqfsX17cELfFHolxUQ44u4rnElhKTBYKZUL7AYuBS5vtswu4AzgBaXUcCAGKAljTN8uUA9fPAn9J0HOhIiEIERXoLVmZ1kdKwuds4CVuyrYsLeKQPDWz76pcZw0oCcn9O3BCX17MKxPolQBdSBhSwpa64BSaibwAc7tpv/QWn+jlLofWKa1fhP4BfCcUupWnKqlq7XW4TsTOJzVc6F6L1zwVER2L0RnVeX1s7rQKfxXFVawctcBDtT5AYiPMhmdncL1kweQn5PC2L49SE+MjnDE4nDC+pxC8JmDd5tNu6fR8Hrg1HDG0Cq2BZ89AX3yYeC0SEcjRIdl2ZrNxdXBMwDnTGBLSQ1aOw9/DUpP4MwRGYzt24OxfVMY3CuxUzXxIOSJZsf6N6B8K1zyT+cvWwgBOFVBG/ZWs3BTMUs2l7K6sIJanwVAjzg3Y/v24PwxmYzt24PROckkxXSfJ3+7KkkKWjvNY/ccDMPOi3Q0QkRcZZ2fxVtKWFhQwqebSigOtvo5vE8SPxiXzdi+PcjPSaFfzzh5DqALkqSw5WPYv9a5lmDIxS7R/di2Zt2eShYWlLBoUwkrdx3A1s4TwZMGpzFlSDpThqTLHUHdhCSFxY9BUhbkXRLpSIQ4bspq6lm8uZSFBcV8urmU8lofSsHorGRmnj6IKUN7MSY7GZfcFdTtdO+ksOtL2PU5TP8DuKIiHY0QYaO1ZsWuChYVFLNwUwlrd1eiNaTGRzF5cBpTh/Zi0uA0eibInUHdXfdOCosfg7ieTmuoQnRB+6u8zFtexMvLCtlZVoehID8nhVu/M4QpQ9LJy0ruUu8CEMeu+yaFfWth8wdw+l0QFR/paIRoN37LZv7GYl5eWsiCgmJsDRNzU5k1bTDfGd6LlDg5KxbfrvsmhSWPQ1QCTPxJpCMRol1sLanh5aWFvLJiN6U19fRKjOanUwZyyfgcctPkwEe0TvdMCmVb4ZvX4OSZENsj0tEI0WZ1vgBvr9nLy0sLWbbzAKahmDasFzPG5zB1aLpcKBZHrXsmhc//4rxq8+QbIx2JEEdNa83KwgpeXlrIW6v3UOuzGJAWz+3nDOOiE7LolSi3joq2635JoWovrPoPjP0RJPaOdDRCtFp5rY9XVzgXjTftryHWbXLu6D7MmJDD+H495EEy0S66X1L48imwA3CKvGpTdHy+gM3CgmJeWVHE/I3F+C1Nfk4KD12Ux/dG9yFRmpUQ7ax7JYWGV22OuhhScyMdjRAt0lqzbncVr6wo4s3Veyiv9ZGWEM2VJ/fnkvE5DO2dGOkQRRfWvZLC18+Br0ZetSk6pP1VXl5fuZtXVhSxaX8NUabBmSMyuHhcFpMHy0VjcXx0n6Tgq4Wv/heGTIeMkZGORgjAeSPZB9/s45UVu1myuQRbwwl9U3jgwlF8Ly+T5DipHhLHV/dJCstfBE+5vGpTRJzWmqU7DvDqiiLeWbOX6voAWSmx3DB1EBedkMWA9IRIhyi6se6TFAZMhdN/C31PjHQkopsqLK/jlRVFvLpiN7vK64iLMjlnVB8uHpfFSbk9pbkJ0SF0n6SQMcLphIiAf325k3veWAfAKQN7cvMZg5k+qjfx0d3nJyg6B/mLFCLMXvhsO7PfWs8Zw3px//dHkZUSG+mQhPhWkhSECKO/Ld7G79/ZwFkjMnjy8hOIcskdRKJjk6QgRJj876Kt/OG9jXw3rzdPXDoWt9xSKjoBSQpChMFTC7bwpw8KOG9MJo9fMkaeMRCdhiQFIdrZEx9v5vGPN/H9/Ewe+aEkBNG5SFIQop1orXn8o038Zf4WLj4hm4d/MBpTbjMVnYwkBSHagdaahz8o4OmFW5kxPoeHLsqT5w5EpyRJQYhjpLXmofc28uyn27j8xL78/oJRkhBEpyVJQYhjoLXm/rfX8/xnO7jy5H7cd/5Iea+B6NQkKQjRRlpr7n3zG/75xU6uPTWXu783XBKC6PQkKQjRBratueuNdfznq11cP3kAd5wzTBKC6BIkKQhxlGxbc8era3lpWSE3TB3Ir84eKglBdBmSFIQ4Cpat+fW8Nbyyooibpg3i1jOHSEIQXUqrnqpRSr2ilDpXKSVP4YhuK2DZ/OLlVbyyoohbvzOE286SMwTR9bS2kH8auBzYrJT6g1JqWBhjEqLDCVg2t768mtdX7eFXZw/l5u8MjnRIQoRFq5KC1vpjrfX/A04AdgAfKaU+V0pdo5SS9wWKLu+xjzbx1uo93H7OMG48fVCkwxEibFpdHaSU6glcDfwEWAk8gZMkPgpLZEJ0EJ9tKeXpRVu5dEIOP5syMNLhCBFWrbrQrJR6FRgG/As4T2u9NzjrJaXUsnAFJ0SkldXUc8tLqxiQFs8958mb+0TX19ozhSe11iO01g81SggAaK3Hf9tKSqnpSqkCpdQWpdTt37LMJUqp9Uqpb5RS/zmK2IUIK9vW/PK/q6n0+Hny8hOIi5Kb9UQ2MahVAAAgAElEQVTX19qkMFwpldIwopTqoZS64XArKKVM4CngHGAEcJlSakSzZQYDdwCnaq1HArccTfBChNM/PtvOgoIS7jp3OMP7JEU6HCGOi9Ymheu01hUNI1rrA8B1R1hnIrBFa71Na+0D5gIXNN8u8FRwe2iti1sZjxBhtW53JX98fyNnjsjgipP6RTocIY6b1iYFQzW6ITt4FhB1hHWygMJG40XBaY0NAYYopT5TSn2plJreyniECJua+gCz5qwkLSGahy8eLc8iiG6ltZWkHwAvK6X+F9DAz4D3j7BOS78k3cL+BwNTgWxgsVJqVOOzEgCl1PXA9QB9+/ZtZchCtM09b6xjZ1ktc647iR7xRzr2EaJrae2Zwm+A+cDPgRuBT4BfH2GdIiCn0Xg2sKeFZd7QWvu11tuBApwk0YTW+lmt9Xit9fj09PRWhizE0XttZRGvrtjNrGmDOXFAz0iHI8Rx16ozBa21jfNU89NHse2lwGClVC6wG7gU56noxl4HLgNeUEql4VQnbTuKfQjRbnaU1nLXa+uY2D+VWdPkATXRPbX2OYXBwEM4dxHFNEzXWg/4tnW01gGl1EycqicT+IfW+hul1P3AMq31m8F5Zyml1gMW8CutdVmbP40QbeQL2Nw0dyUu0+DPl+bjMqWZL9E9tfaawvPAvcDjwOnANbR8zaAJrfW7wLvNpt3TaFgDtwU7ISLmTx9sZE1RJf/7o3FkpsRGOhwhIqa1h0OxWutPAKW13qm1ng1MC19YQhw/CwqKeW7xdn50Ul+mj+od6XCEiKjWnil4g81mbw5WCe0GeoUvLCGOj+JqL798eTXDeidy17nSjIUQrT1TuAWIA24CxgE/Aq4KV1BCHA+2rbntpdXU+gL89bKxxLjNSIckRMQd8Uwh+KDaJVrrXwE1ONcThOj0nvl0G0u2lPLQRXkMzkiMdDhCdAhHPFPQWlvAOCWPdYouZOWuAzz6YQHn5vXh0gk5R15BiG6itdcUVgJvKKX+C9Q2TNRavxqWqIQIoyqvn5vmriQjKYYHL8qTZiyEaKS1SSEVKKPpHUcakKQgOhWtNb99bR17Kry8/NOTSI6VFwcK0Vhrn2iW6wiiS/jvsiLeWr2HX541hHH9UiMdjhAdTmufaH6eQxuzQ2t9bbtHJESYbCmu4d43v+HkAT35+VRpxkKIlrS2+ujtRsMxwIUc2ridEB2W128xa85KYqNM/nxpPqYh1xGEaElrq49eaTyulJoDfByWiIQIgyfnb2HD3ir+ftV4MpJijryCEN1UW1v9GgzIiw1Ep7BpfzXPfLqVi8ZmccbwjEiHI0SH1tprCtU0vaawD+cdC0J0aLatufPVtSREu/jtucMjHY4QHV5rq4/kcU/RKc1dWsiynQf40w9G0zMhOtLhCNHhtar6SCl1oVIqudF4ilLq++ELS4hjV1zt5Q/vbeCkAan8YFx2pMMRolNo7TWFe7XWlQ0jwXco3xuekIRoH797ewNev80DF8pTy0K0VmuTQkvLtfZ2ViGOu4UFxby1eg83nD6QgekJkQ5HiE6jtUlhmVLqMaXUQKXUAKXU48DycAYmRFt5fBZ3vb6Ogenx/HzqwEiHI0Sn0tqkMAvwAS8BLwMe4MZwBSXEsfjzJ5soOuDhwQvziHbJOxKEOBqtvfuoFrg9zLEIcczW76nib4u3c8n4bE4c0DPS4QjR6bT27qOPlFIpjcZ7KKU+CF9YQhw9y9bc+dpaUmLd3PldeSZBiLZobfVRWvCOIwC01geQdzSLDubfX+1kVWEFd39vBClxUZEOR4hOqbVJwVZKhZq1UEr1p4VWU4WIlH2VXh5+v4BJg9O4ID8z0uEI0Wm19rbS3wJLlFKLguOTgevDE5IQR+++t77Bb9n8/vuj5JkEIY5Bq84UtNbvA+OBApw7kH6BcweSEBH38fr9vLduHzedMZh+PeMjHY4QnVprLzT/BPgEJxn8AvgXMDt8YYmuZntpLT9+YSmfbSlt1+3W1ge45411DMlI4LpJA9p120J0R629pnAzMAHYqbU+HRgLlIQtKtHlvLyskE82FvP//vYVt760itKa+nbZ7mMfbWJPpZeHLsojytXWluCFEA1a+yvyaq29AEqpaK31RmBo+MISXc2ighLG9evBTdMG8faaPZzx6CLmfL0L2277/Qpriyp5/rPt/L8T+8r7loVoJ61NCkXB5xReBz5SSr2BvI5TtFJxlZf1e6v4zvAMbjtrKO/dPImhvRO549W1XPLMFxTsqz7qbQYsmzteW0PPhGh+PX1YGKIWontq7YXmC7XWFVrr2cDdwN8BaTpbtMqiTU5N45Qh6QAM6pXIS9efxJ9+MJqtJTWc+5fF/PH9jXh8Vqu3+eIXO1m3u4p7zxtBcqw7LHEL0R0ddSWs1nqR1vpNrbUvHAGJrmfRphLSE6MZ3ufgu5qUUvxwfA6f/GIq3x+bxdMLt3LWnxexsKD4iNvbXeHh0Q8LmDo0nXPz+oQzdCG6HbkyJ8LKsjWLN5cyZUh6i88PpMZH8cgPxzDnupNwmwZXP7+UG/+zguIqb4vb01pz7xvr0Bp+d4E8kyBEe5N3IoiwWl1UQaXHz9Sh6Ydd7uSBPXnv5kk8s2gbTy7YwqcFJfx6+lAuP7EfpnGw4P/gm318vKGYO787jJzUuHCHL46R3++nqKgIr7flJC/aX0xMDNnZ2bjdbatWlaQgwmphQQmGgtMGpR1x2WiXyU1nDOa8MZnc/fo67n7jG+at2M2DF45iZGYyVV4/9775DcP7JHHNqbnHIXpxrIqKikhMTKR///5yVnccaK0pKyujqKiI3Ny2/UYkKYiwWrSphPyclKNqoC43LZ5//Xgib6zaw+/fWc/5T37Gtaf2p9oboLi6nmeuGI/blJrPzsDr9UpCOI6UUvTs2ZOSkrY/RiZJQYRNea2PNUUV3HLGkKNeVynF98dmcfrQXvzh/Y08t3g7AFef0p/8nJQjrC06EkkIx9exft+SFETYLN5cgtYw5QjXEw4nOc7NQxflcfEJWby7dh+3njm4HSMUQjQX1nNwpdR0pVSBUmqLUupb39ymlPqBUkorpcaHMx5xfC3aVEJqfBSjs5KPeVvj+6dyz3kjSIyRZxLE0XvggQcYOXIko0ePJj8/n6+++opAIMCdd97J4MGDyc/PJz8/nwceeCC0jmma5OfnM3LkSMaMGcNjjz2GbdsR/BTHR9jOFJRSJvAUcCZQBCxVSr2ptV7fbLlE4Cbgq3DFIo4/29Z8uqmESYPTMAypPhCR88UXX/D222+zYsUKoqOjKS0txefzcdddd7Fv3z7Wrl1LTEwM1dXVPProo6H1YmNjWbVqFQDFxcVcfvnlVFZWct9990XqoxwX4aw+mghs0VpvA1BKzQUuANY3W+53wMPAL8MYizjO1u+torTGF3qKWYj73vqG9Xuq2nWbIzKTuPe8kYddZu/evaSlpREdHQ1AWloadXV1PPfcc+zYsYOYmBgAEhMTmT17dovb6NWrF88++ywTJkxg9uzZXfo6STirj7KAwkbjRcFpIUqpsUCO1vrtw21IKXW9UmqZUmrZsVxVF8dPQ9MWkwZLUhCRddZZZ1FYWMiQIUO44YYbWLRoEVu2bKFv374kJiYeeQNBAwYMwLZtiouP/NR9ZxbOM4WWUmmoSUyllAE8Dlx9pA1prZ8FngUYP368vAa0E1hUUMKorCTSE6MjHYroII50RB8uCQkJLF++nMWLF7NgwQJmzJjBnXfe2WSZ559/nieeeIKysjI+//xzcnJyWtyW1l2/+AnnmUIR0PibzaZpy6qJwChgoVJqB3AS8KZcbO78qrx+lu86wNQhvSIdihCAc9F46tSp3HfffTz55JO89dZb7Nq1i+pqp4Xea665hlWrVpGcnIxltdww47Zt2zBNk169uvbfdTiTwlJgsFIqVykVBVwKvNkwU2tdqbVO01r311r3B74EztdaLwtjTOI4+GxzKZatj+lWVCHaS0FBAZs3bw6Nr1q1iqFDh/LjH/+YmTNnhprgsCwLn6/ldj5LSkr42c9+xsyZM7v09QQIY/WR1jqglJoJfACYwD+01t8ope4Hlmmt3zz8FkRntWhTCYkxLsbKQ2aiA6ipqWHWrFlUVFTgcrkYNGgQzz77LMnJydx9992MGjWKxMREYmNjueqqq8jMzATA4/GQn5+P3+/H5XJxxRVXcNttt0X404Sf6mx1ZOPHj9fLlsnJREelteaUP8wnPyeFp380LtLhiAjbsGEDw4cPj3QY3U5L37tSarnW+ojV89KAjGhXm4tr2FvplVtRheikJCmIdrWoIPiWNbmeIESnJElBtKuFm4oZmpFIn+TYSIcihGgDSQqi3dTWB1i6/YCcJQjRiUlSEO3my21l+CxbricI0YlJUhDtZtGmEuKiTMb37xHpUIQQbSRJQbSbRZtKOGVgT6JdZqRDEaJDW7VqFe+++26kw2iRJAXRLnaU1rKzrE6qjoRohY6cFOTNa6JdLCxwWo6cIu0diW/z3u2wb237brN3Hpzzh8MusmPHDqZPn85pp53Gl19+yZgxY7jmmmu49957KS4u5t///jeDBg3i2muvZdu2bcTFxfHss88yevRoZs+ezfbt29m7dy+bNm3iscce48svv+S9994jKyuLt956C7fbzfLly7ntttuoqakhLS2NF154gT59+jB16lROPPFEFixYQEVFBX//+9858cQTueeee/B4PCxZsoQ77riDDRs2kJCQwC9/6bxBYNSoUbz9ttN49JFinzhxYrt+pXKmINrFok0l5KbF07dnXKRDEeIQW7Zs4eabb2bNmjVs3LiR//znPyxZsoRHHnmEBx98kHvvvZexY8eyZs0aHnzwQa688srQulu3buWdd97hjTfe4Ec/+hGnn346a9euJTY2lnfeeQe/38+sWbOYN28ey5cv59prr+W3v/1taP1AIMDXX3/Nn//8Z+677z6ioqK4//77mTFjBqtWrWLGjBnHFHt7kzMFccy8fosvtpVx6YS+kQ5FdGRHOKIPp9zcXPLy8gAYOXIkZ5xxBkop8vLy2LFjBzt37uSVV14BYNq0aZSVlVFZWemEfc45uN1u8vLysCyL6dOnA4TWLSgoYN26dZx55pmA07Benz59Qvu+6KKLABg3bhw7duxo99jbmyQFccyW7ijH67fl+QTRYTW8dQ3AMIzQuGEYBAIBXK5Di8KG1lAbL+t2u0PTG9bVWjNy5Ei++OKLw+7bNE0CgUCLy7hcribvf25oubU1sbc3qT4Sx2xRQQlRLoOTcntGOhQh2mTy5Mn8+9//BmDhwoWkpaWRlJTUqnWHDh1KSUlJKCn4/X6++eabw66TmJgYepcDQP/+/VmxYgUAK1asYPv27W35GO1CkoI4Zgs3lXBibiqxUXIrquicZs+ezbJlyxg9ejS33347L774YqvXjYqKYt68efzmN79hzJgx5Ofn8/nnnx92ndNPP53169eTn5/PSy+9xMUXX0x5eTn5+fk8/fTTDBky5Fg/UptJ09nimBQdqOO0Py7grnOH85NJAyIdjuhgpOnsyJCms0XEfLqpFICpcj1BiC5BkoI4Jos2FZOVEsvA9IRIhyKEaAeSFESb+S2bz7aUMWVoepd/b60Q3YUkBdFmy3ceoKY+IE1bCNGFSFIQbbZoUwkuQ3HKQLkV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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_graphs(test_log, 'accuracy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "?optim.ASGD"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
