{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# A simple example of a fully connected deep neural network (FCN)\n", "# The FCN trains on images from ten classes, then takes an image\n", "# and estimates which class it represents" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Import matplotlib to display digit images\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "# Import PyTorch data used in example program\n", "\n", "import torch\n", "import torch.nn as nn\n", "import torchvision.datasets as dsets\n", "import torchvision.transforms as xforms\n", "from torch.autograd import Variable" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "input_size = 3072 # The image size = 32x32x3 = \n", "hidden_size = 500 # Number of nodes in the hidden layer\n", "num_classes = 10 # Number of output classes (0..9)\n", "num_epochs = 5 # Number of times DNN is trained on training dataset\n", "batch_size = 100 # The size of input data for one iteration\n", "learning_rate = 0.001 # The speed of convergence" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Files already downloaded and verified\n" ] } ], "source": [ "# Read om training and test datasets, these are included as part of\n", "# PyTorch's dataset repository\n", "\n", "train_dataset = dsets.CIFAR10( root ='./data', train=True, transform=xforms.ToTensor(), download=True )\n", "test_dataset = dsets.CIFAR10( root='./data', train=False, transform=xforms.ToTensor() )\n", "\n", "classes = [ 'plane','car','bird','cat','deer','dog','frog','horse','ship','truck' ]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "frog deer dog car\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAArkAAACqCAYAAACpg1eoAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJztvWuopVl63/df77vve59r3bqqulo9N0kj5FhjBtlGSSCWBcYQpA8yyB/CBAQCQ0DGSvA4ARtDPsj5oHxIIGZAQpNEWFZig0RQYo8VmWAIksbSaDQX9fRMa6a7urru574v723lQ5W69vN/Vtc5deqcU3vv/H/QdK19We/a7/us9a6z9//5PyHGCCGEEEIIIVaJ7FUPQAghhBBCiLNGm1whhBBCCLFyaJMrhBBCCCFWDm1yhRBCCCHEyqFNrhBCCCGEWDm0yRVCCCGEECuHNrlCCCGEEGLl0CZXCCGEEEKsHC+1yQ0h/I0QwlshhG+HED5/VoMS4rxR7IplRbErlhHFrXgVhNNWPAsh5AC+BeAnANwG8AcA/naM8Rsf9Z61tbV46dLlD9sxNsceJwt2fHkW7POZ3adnwT4PAO4R9xrbTo2LTxMfF7AvSJ1Xfigx1GP7CNmxb+J3PP/18OfMH8P3cWzY8FsSr+eH/vRb334YY7xyTM8vzWlid3NzM964cePDdpbl5vkmeb05jsJzWh81H465fsdf3mQcmecbjt1U/NM8zO3nT807JqP3MHVtjxtj7V8Unz/Pmub55/zJOOzc9fOS54P/LqCqyg//ff/efezv75/gSrw8Lxq76xujeO3a9ofteIKJmdN3HxwOIfD5S8QXHcadU54Lyfiha8vXmgbm1+REjxQfNcV+ahhZ9vyxI/KHTR2YPy89H/gelFowaX4E23bjSnyYjK7dn771zsKuuduXLsVbr9/6sB1drPrPV9d2zeDz6E9Jar9w3FQ+fs/kxnrMupW819N6GCr72fhachgmDpuY/c+fY6lOGjqJdW7beavluuCZyet0VVWmXc6tr/Ojnee9d2+fKHb9aE7OjwL4dozxHQAIIfw6gJ8E8JFBe+nSZfzDf/SPPmxPpxPzfB78Ce7n9rGNQdu0h/2OaQ96tv2kX9oIt2wfoOcn06nrgxfDXq9nu2hsAPJkA/yFbFEwNLAXvqwK10ev17UPUADycUPiy3qeHJ1Oh9r2/GSZD5OKFxO3wNpjpM5HQ7PyL//4f/o996Lz4YVj98aNG/hffu1//bA9GG6a5yczHzOz2cy0eXPQos1WmeiD/6iLfLPkG3vixlYWHEf2NdOZfb4qj1wfNcXuxrr9/N02xUhiwR0MR6ad5fY9e/v7pj2bHro+8saOtSzsOR5P7Dls4DfWw9GaabuNDo2r1++7Ph4+uP/hv3/h7/2Ce/4ceaHYvXZtG7/0P/yXH7arYOd61vh5uRbs2lbNaL1o2zWoKP0NKWb2nHbpPVm016XXpzUZAOgmf0RxPK3t/WMwsOMG/E1+emTjZX9s++j0/XrZ79qxdei2GRvb5nkOAFljH8vbPI/tMarS/6FZVXZe1i0b63nLntOc5ySAXm7n4F/9j356YdfcW6/fwm//63/9YbusaZ5mfm4f7B2YdkX3UP4Cp5X5uON7ZuB9ifurz+9bGt4P0BypaVxVYlOX79r1r/3QfrZBy86pKvElQknjaEf72YrGruvj0t+DeOM7oU3t3rodx9bVy2C6dN+aTMam/fDhPdO+//CuHwfsOfr5v/NfnSh2X0aucBPAe3Pt208fM4QQfi6E8OUQwpcPDw/4aSFeBS8cuzs7Oxc2OCGew7GxOx+3e3v+DwUhXgEvvOY+evzowgYnVpeX2eQe//sSgBjjF2KMn40xfnZE36AI8Yp44djd2tq6gGEJcSzHxu583G5sjBIvF+LCeeE199L2pQsYllh1XkaucBvArbn26wDuPO8NVVXi/tzPfNOx/cq6nxhNGNgHB5F+rm8NTbOI9ucnAABrDoP9Wr8krUtZpn5at32Macq26M+FpklobPjn6haPw34d3yQ0iaGyP53yr9MsC2gnpAYFfd4J/fzSbrOcw/8M4n6So4GUle2Tf74BgJAY2wXxwrGLEJDnz85LWdqfeer6+Ovd7drY5Z/4Y9dLbTr0Gv8T3fH60enEzgmOzQHFTFH4cRQkLeLPQr9gYUYyAiAh38jsOex27c/NiR+wMTl4bNotirsOTcTx1I9jfGg/f6tlP++Ifn4b9v3P4DtzkqfjNXxnygvFbgg5+q31D9udtv1jrSr8N71t1gt27bpURdvubwxcH3W015Z/8m1AseBDDnmwP+muDTdMe6Oxx53M/LWuCpqDdK03evaPgDrRx3Bg11xep2v6ibeKXmY2HNoveHJe++hn9PWB/6O6qu1Ydw7sT7x1Q2NP3IPQ8WO7IF54zd072Mf/9W/+7w/bWWav3Sc/8Qn3ntnE/lp89+77pt0lmeFf+OHPuD421u25d/pZmu5V4+c/a04DzYeqtNcq1l6u0HTXTXtnaj/LYWH7dJsQ+L0OKpIeFHbtP0oJe1m3S892enYP1u37LzMzuj+WYxuHTWbX3FbH/3FezE6nBHiZb3L/AMCnQggfCyF0APwMgN96if6EuCgUu2JZUeyKZURxK14Jp/4qLcZYhRD+CwD/CkAO4FdijF8/s5EJcU4odsWyotgVy4jiVrwqXur34hjjbwP47TMaixAXhmJXLCuKXbGMKG7Fq+BCRZEhAO157REdfXPgh7M5tBoa1kd5/ajXlLB1V9Ww/ZUlZb3ihCiksemSBY6z64TXYTkPO7IuqmvS3ACoSf/TblvNTZssUVoJWxG24nBeefT6lEqnTTZjRUE6tYatzDxFwjJrUWmaBuM5uyG2AiwS14ptUirS8Ua2PErpluna5CzlI41ukbC/m9JjBY+DvSRdBHitd0WWOCxLY/0t4CWCHdLgsp643fHzkONuSpZhbGXHNmWA9+M9HFvrspIGWlT+fMzr+E/nNH5RNED27Fq0yHaKbQwBABTKmx2rsTuY7dmXt73lXBPtcdh6uwW7jh+WPpeioTnVBOtw0icryMMmMQ46To/Wx9GGnT9V7dfLjUtWG3l4QB6fXasvnEy9dnBSUk5HtPOjRZrl7U2rcwSAjS1rzdR8177n4e5tO64iEZnNK9PkvjBZlqO39kyHff3K6/b53Kst79//wLSLgmPCnpNp4h60SXOiphwWTr+ooh9H4zzRbcxM6X45m/jY5bWsuGK1wm3a6+Qdn8WQ0Wfp5FbXfKlt1+BWog+2Ozs8tOtld0B5UY2/F/b7Vj8/IgvK165fN+29xw9dH99660/cYydBZX2FEEIIIcTKoU2uEEIIIYRYObTJFUIIIYQQK4c2uUIIIYQQYuW42MQzAK3wTIDd6dg99qU1XyO+TzW+c0r4KiZWFN4kzIy5Djj7I3d7VM89kawypUQa9tzn+ubFzJs712QizkUoOD2rkxKBUzJG4JroZAjdcJ1t+LFXNI6MktVCoo+6IME+Jeu44hicZQdgWvhEq0UlCxn6vWfxmeVWsN9JZNa1KYGR24FNxhPH5dPGSWJsOl6UCVPxxLk346AEBlfoAz5Zq6Tj9KiQBfcJAEVhExg4saIBJ8Al6rkHO47IxTEoGaWTSE7hxLuMwrCkzJJZIvFs/pFFTjyLDTAbP/uAdbVrnt/qb7v3TBqbWBICG9tTvJR+nXKFThpKLKNFKEvE3KBj5xhHw4wSYiaJxLN+1/Y7HFABHioeNMhtwQkAaFEC5PU3rph2r2OTaJrKJ968/c7XTHtn967t85Kt7tXp+QS4y5x41PkLts/fs8k6nMwGAK3o77GLSqfbwxsf++SH7UHbJi89uneb34Lx2Cb9cd41J0QXpU/E4/WSryavBk0i0SrSPfPwyM6pP/vOt0z70T2bMAcA06kd25TWT3CxqFQBKtrLtLs2SWywZmNqc9vHf5+S6r/+x18x7U9+38dMe5xIfn7jY2+a9o3rN0w7FnZNubzhi6HcG5yueqO+yRVCCCGEECuHNrlCCCGEEGLl0CZXCCGEEEKsHBeuye3NaeTapBfpJszfh10rqmGNKatQQqrsAIlwa9KyZKwPS6jsWGcVyd386IhM6dkxGsCMdIwljaPT6to3VAmNDesWSXflCkqUXi/UzuxxWNbIGt0qUdmCC0hMC3ucaclaUd9HVadKRCwm7XYbr83piOpEsQ+GdVmsp+XoTchYk0U0bJ+23et5zZ3T8XIREor/yFovAPWlK/QaKlKRGjz3wSeN3sMxBSQ021xkhLScgQX3Ca0n65jdGkLv4fUBsOtQv9dzzy8Kecix0ZnTt5FGuZwk9ISw+uq1dVsM4splGwutln09AEQynR9PbSGHnclj2963bQBgj/2CCirsHNo+q8RXNp3c5lJMCrqfNHYtvHLlpuujP7Cfv9uxc2xj3eoY2x1axwH0RvY9uw+sJrfTIo1/15/TyZHVD29escUhvv/TnzbtB3ffcX3UiZyVRSWEgNbcPZGLBz169MC9h29VnAdRUVGb8cTrR7mwDS/1rOuNiSI+s9L2e/vOu6a9d2QLqmSdRNGmqZ2bbdoL8dpfjP1n6QQbRxvbVutaBzo/CT35bGbPwIzO4cHYauHXh76Qyd7OI9O+vG1zAaYzG9ujto//ERWUOCn6JlcIIYQQQqwc2uQKIYQQQoiVQ5tcIYQQQgixclyoJjfPAoa9Z4fs5Fb80mJzVXjNaadlPdu8vi6lObIaErKaRUMak+hUOPCedLD6mKK2etuGhT0ASudxattFSVqXiffwy+h8dOklTRjbY0691+jGwOphhsN10251rbanmpDHJbzn6XRmT+qY2rt7Ce1TQuu42IS5f7E21F9vF4vcdHrRVOw+P2b4sKk55GAtLLejXxa6pDt1anEaV2oUTtvKgz/GExjw8/04KXDKIthfq5dzus1Z1L5A5HmGtbVnWrbR+lXzfL/r9aORdHlVMaPnbeznwWsSByPb76WtT5j2lfKWaT987PWVe48PTXv3sfUSXcutP21v5K/jztiuhw/HVgu5ObT+tHnuA2rYt5rbms5PMbNrYZ7wZt5cs2PdGFqdb0m+6uMj7/k7ndjzMdiy6/jV194w7YO9+66P/dmBe2xRiRFo5nT8s4n1mp1O/DnKM7s/4FwRUM5KWfvYLen6ss6X16C68ffYx3tWY74/s3E42LQxVVCcAkA8oOs9tLruydS+J5WPlNHaVJOvPt+DW5zTAODmDatT767b/QLI735z4HMUPvjgjn2ADIw3KecD7AkMoN+XT64QQgghhBAAtMkVQgghhBAriDa5QgghhBBi5bhQTW6WBawNn2lmuqTL6LQT2janhX2+12iVqEXNWpUB6dDYS2828/qYLr2nIF3a7r59T1H7vx9yGvp6m/04Scea8PCryDwyZ40ujfPWFVsjGgBmByQyIklRj+q71wmdZ0G1plt0LddJkzdMeOcdzrwn3yIzrxFNaT1fFNZ2pWD96HF60pOMi31wx6TtGvT9taoK1sLacbDetk7UUT/J57Uc7+l5/Of1L3jxa/d8rfQZhMK5kedtbG5e+7A9HFg9Xa/X5rc4/fWUNKcz0ouWnOQAYHJg9ZORXtPtWc/L11+zGl0AGOZW18haYOSkHW6sdhgAYtvqGIvMXq2NnvUNbRIG2If7u6Y9m9lx9Pr2/Ewm/raakYa/3bHnOKf1s9tOeFVToNWkL+527TnNB/5+2mktz5qbhYDunAfzzpHVExeFzxXJM3vuG7pfsgf8USLf5IC0sCz8z0hzfZTQTz/as9emojUk0PWeJtbGghaqUY/87QO9Z+pjpkP5NrFt+6hJs9zJvZ42wq4Rww2rBb+0aXXtrdLvW+7cu2fah5Rv1OnZe8609vu45pTfyeqbXCGEEEIIsXJokyuEEEIIIVYObXKFEEIIIcTKoU2uEEIIIYRYOS488azfeSZizmorUM4TxQHaVPyhpoIJTbTi617PJho8wQq4ayrU0DRWfN3udMAcHNnjPt6zSQ7jmR1Hmcix2aBEsx984zXTXl+zx/3GnR3Xx3tkkN5QEhEXiyimXhRfknlzt0vnPR5fpCOnx9qBixbYE7Cxbs3PAaAz8Ykii038iH9/VDLTy6ckpQoivOzr9/dtUsTDRzYp4OaN1917jo7sXB0OrTH3YGCTXhpOijjh2Ogd7pHjij/4JLHjk9dOM45lIQsBg+6zZJLZ2K4f5cSfn7Bpk1UGlPAy7Nt1q0kYyNelndshcrEcGx85fNLM5pZdy/P2NdPmBKGm9uNYG9I8pcSkXscmvMREuDzasYlnDx/a+bO9ZY39W4n86ZoT7yhBeDSy4xh2/UBamT1nDx+8b8dxxSbvrW/4pOPp/Yd+cAtKngVsDJ/F7h7dl8vCF2GgGk3oUIJfj/rotH2i1e6uvd6gRDNexo4ShRwCF4ih90zHNuGtmvp7Id1ScUjJ7RzLa5euuz5GI1uEpKTEyoz2T3nHB2+ra49z9NjGULlnk0zfuOXjbnvTJniOD+2+pEUT74P7vpBJ3D90j50EfZMrhBBCCCFWDm1yhRBCCCHEyqFNrhBCCCGEWDkuVpMbMgz7z3RW5cTqlEJIFB0gDW7FmhLap5cJU2VWN1U1mXl3yCA5oafd2bdG1BPS4EbS4ITMa6q6LSuyGWZWh9Oi87HdtbpHADjo236PSHPLmuUPHj1yfQQy6m/o84OPm7gubCIfow0lvk6oveZoc+iN6BcZoyllmSYLqE7Fy+tHU5pVLtywu2u13juPH9g3JLSz7ZbVR66PrG6zpjnli1acRE977DDcY6nj0DtO0Mfxx2Ve9LO8KuqmweGcdvVoSubvbX8LKCqrSdxYs9e+R/M26/p5nPetBj9UpFus2YQ/dbGtIfwa6VQHHavzqzNfxKTJrOayIu0f68TvP/Dr5Z17dr4UU9KnD+z6OU4UQslbtD7SZysoiWPS89dl1LP3mMeP7XVqde2cvLxtNcwA8OiRP0eLSpZlGA2exd72JVt04NOf/mH3ntHI3ru6PWr3bbuO/mY/mdnrW9Ge4uCQ9gKJYhBVtPOspoIqNRWtijOvL+7kdl71O3bs21esNr5NxUAAoCDdcnlkda2RJLjdgdcoH5JG+cF337V9kr64n/vY7VDxl3FB57iy7ZubPodnvPfYPXYS9E2uEEIIIYRYObTJFUIIIYQQK4c2uUIIIYQQYuW4YJ/cDL3BM01Qr2M1JylN7pT0MQ1pWQLpZWJK20U+d52O/dg1nYYHO16XVdZW29IiM8QWHaPd9jq1Pvkc3nlstTxNbfuoe16TO+zbsQawnthqgXjcAFDSQzXrmBvvWck4yTFdu4w8j5sq0WdC+7zYzH3oU2lwX1w/6l5xzEtSWlF+TyT97JB8UNH4mGm3rZZvn3Rpa+tWD9jpeq9p/njHftqUvtg9cMw5TRifJtcI8xb7fFLnPDeSRZbnVlWDBzvPdHiRzsc089e6lZGHZ2HX3BHpR7sDr5/js9KqbLwMSMcayTMdAOqpfU+gQG5aNuaq3MdcFe1jU/II3yEP3Lv3vO6vpDyHTYr1g0PrE3o0tmswAKxvWi/dft/qnGv6bA/e9z6h1y/b47Kc9O5d63f9Rt97xoeOv6csKhFAMbdWbWxZTe7a+haYmu4zDXnic6rILKGFragP9jg+2rM+yUf73s+e15Ax+1PPbI5KnrgX5sHe6zNq8/WvSn+PDTTfc16tSJM/IP9mALj33m3TnlJ+Uk77OL73A8Dr3/eG7WNCc3tqz8/h977n+ti/81332EnQN7lCCCGEEGLl0CZXCCGEEEKsHMduckMIvxJCuB9C+NrcY9shhC+FEN5++n//u4EQrxjFrlhWFLtiGVHcikXjJJrcXwXwPwL4n+ce+zyA34kx/mII4fNP23//2J5CMNrNkB//RXKrRVpXkP6DNCYp38yaNHgtqlc9PrT6mHLs9WFbpIWtSHbVIg3u5W2rnwKAQG9qSLsyI/1xFvw4Om2rMev37Hqxfclqv3b27rg+Hj6yGrI8Iy0PeTg20V8nrs2d5bbN/pMxUZv+AsxGfxVnFbvHcLxf60n8V4/3lvWers6w1/WRkYB6nTSF+4/vmnbFwQ1gn2qNb1Kd9K3LVi+X/Kjh+R6lTPJ5PgHOF/sUMcXn9ARvaebGdhYOyQl+FWcQuxHAbO5yNoX1q40J/T17urLnd7tv9dmZDxeUtJb1O7TWkX6wJo0eABRHpP0jr82qY/soCu/FPSH9+RF5ke/u2rjmcQHA+obVHOeU9/DgodXx1sH7le4efGDHOrXX4ZOf+pRpP9zx3qtH+1YLev2KvQ7TQ9vnldduuD4+fvNH3GNnzK/ijNbcumlwOHn2mTKa+1kih6emexXnm7C+tt32fWxu2Htqp2Pvba+/Zte6kLi3se6/IJ3vhLxl+doBwJheMybP2zHpievS7xfaLbsvGZAG9+r2ZdO+tOH3LXe+a8/Zp3/o06b98R/8uGkPez7+Dx5a3XJ12+p8H9+xGtyjB1ZfDgCHpGs+KcfuMmOM/w8AVuP/JIAvPv33FwH81KmOLsQ5otgVy4piVywjiluxaJxWk3stxvgBADz9/9WPemEI4edCCF8OIXx5Z3f/o14mxEVxqth9lKgcJ8QFc6LYnY/b3d291EuEuEhOt194rDVXvDznnngWY/xCjPGzMcbPbm36r8KFWFTmY/cSlZQUYlGZj9tNsq4SYpEx+4Vtrbni5TntJvdeCOE6ADz9vzf1E2IxUeyKZUWxK5YRxa14ZZy2GMRvAfgcgF98+v/fPMmbYoyoqjkheMMZC94RuSxtMkFdW/F5QwbJBRWLAIAZ9bG2Yff2sbHv2fS6aWyt2feUFSXzXHrNtHP4bIzJ1IrP2yzQnthjbIy8cfeUxOec8NPtW6F5t2eF5QAwPbLnY0LG1FlORToSYVKTE7UvOGCfT+ZlHZ+JdR6cKnYBm8DFcXiSHKmzybPjREv7bGoc/NhoZBNp+HrfvWeTZABgRMkYVy5x8gX9vZwq9EGDTZVpeM7LASSSTY79M90PpIl2HsaGjsvn+LhDXBwvHLsxRpRziYQ1VYKJ7CgPoJNRsZxg46Oi9WBa+zPUZDa5N1Y2KeZg38o2J/u+CEMxs+tyZ80a1YeeXWMr+MQUyjPDjNZPnhy9TmKtK8jIn+5bG9vX7DiCN9T/7jtvm/bRvi1CcXNq1+A3P/Z9ro+3v/kNO9a2HUeW05pU+4SoXs8XiLgATrXmBtikR1f8wCWdAg195pwS17coIXw48OejS8lorvARrVNZYtHlhxpaRdy0S90K6bg1FZhoaPGra9/J3p6ViLZpUV2jPcgkkUT3Y//Jj5n2OiWmNqVNkHvw7W+5Pr711T8x7UjJmi06IVXt90+HZSLD9QScxELsnwH4fwH8QAjhdgjhZ/EkWH8ihPA2gJ942hZioVDsimVFsSuWEcWtWDSO/SY3xvi3P+KpHz/jsQhxpih2xbKi2BXLiOJWLBqqeCaEEEIIIVaO02pyT00T5jW5pOtMCFNapP/odKw+7GBsdRo7+95Em+oWID+0JuPVkTVi3h7SGwB8/E2rQXx8YHUo3TWrbRkMvJ726MiOrdcj7Wu0x80TosSjsR171rJat6Opff7g0GuUWYPZ69rzzrUAohclIZA2ko37nR71WAXmcsHFH1LaRtZl8Tk7iUb3ONmyvw4pY3ILG6Szti0nA3EAaLdsbJLUzcVqkxg4m7n7AhpkoF742D2a2nlXkJ6cC1mEzI9jfd2a6Pd6th0jjzPxXcDc9V4gza4jxoh6TqdYs/44S3y2YK91RevSuKJ1aprQylX22sXS6lrHe1aTd7jnNbnIbOGbUYfmWG3Xvhq+GIQrOkG6xZz1x2XClP/Ajm00sPGyNrQ6z8cHfhw8CXMqHjQj/fHmur9/fPyT32/ak11b6Gd6+MC0j/a8Bdfm1vI4FoQAtOcKRlVUuCRxW8Iaze3RmtXctjtcUML3kZH2NSNdP78ldW/jxZ2LVtES49YcwBdQcnVwOKgSa+7Wut2XZGBdL88Hv/cZVvSeuzZn4/ZbXzftu2//mesjUnEY/ixcxKNM6PxnjR/bSdA3uUIIIYQQYuXQJlcIIYQQQqwc2uQKIYQQQoiV40I1uSEL6PWe6ayazGpdiiKh7SIN1ZQ0eLt7VuuV0vG1W1bfcUB9jEhvuL7mqwT11jZNOy9I/8J9XLvp+miRFrjVWI1uJG/dIuELN2pbjU3tDGqtjm29bT1RAaDTs3qvYmzP4dGR1T3Wib+FKvYjJB1TKyetW5XSBp9OY7MIeA/c1N+LrNuN1H7x4zakn51M7LXqdOz1B4Bu1/p2TqbkWUrXu9X2mtyS5tX7771r2p/4pNW+lSzsBrC/b+N/PLbxf0DzY29vx/UxJl37jMYV2TszeK302prVUL755idM+/Wb1qO0lftrG8/G9PjcCSFD1np2/TkGWScNAIE0+xXJvKcz6zWbpdZt8pKtJva6HR7Yaz2b+T4CnffskMrCd0ij2fL+tKx1bMi/mz1Oq4p8dOH15ZOJHXubdb9Hvg9Mrda3yx62pDctCztHAWBj3c6xvLZre6gp16T24zg6XJ4yz7GJqObv1bRebl+y92QAGA2tPzMCJ0awJ3YCWkN4BeEpk5D9p4S7z+0kldNxnF+388VN+AYHvudQnAU+qUc+7j74hvW9ffQ163nbats4W8sSJum0iMw6nEtiXz5L5AoUkCZXCCGEEEIIANrkCiGEEEKIFUSbXCGEEEIIsXJcqCY3Ng2KOZ/LrLba2DylkOFS9WRsVxa2j37X6wl7bfsxS6oTPiSP27Vrb7o+7u9bTcmjx7Z9a2T1UtOp9ysdUo3zAKtlqSur2+olnGRn5OkbSWO21qdxJLzltq7Z11Tkrfvu22+Z9v6+947MnE7RtllhVyeubUjUVl9s5uqoOw1VykvYtvlqch950rPRPrhLfqIHB1ZPffPmLddHTXXA7969a9qTidVhbW97j842+VXfu2f7ODgkH9SJj5nd3V3TLgob/6w3Dgk9LXvrso82rw+sQQWAvR3rH/oWrQdrQ6t1vHr1huujnNM7LrLfc0REPacqzNtWs8ie2U8eJD21AApRAAAgAElEQVQ96+XIqzgFa/1mpMEdH9r4YH9jAEBu+6ij1eR2BpQH0E14VcN+PvYJzskTGCltJOkD9/bJfzbauJ4ceC3sJq2IXdKO1kf2s9394LbrY2vdxiWlgWBre5PaPreE149FpihmeO+7zzxXP/OZv2ieX6d7LgBE9rR1fu0n+F7vGL09z/cmtU4d42HL70hp/GNDa1nNz5O+OCGF5ccK0tw+etfmVjz8s+/5cbxv1/pOYdf6/sdtnI2PEvf1sZ0TOfvq0zhLn1qCpuuv90nQN7lCCCGEEGLl0CZXCCGEEEKsHNrkCiGEEEKIlUObXCGEEEIIsXJcaOIZYNNzmpILBCSSd0iiHek1nN81S4ivIxkRr/WsqvnGm2+a9vrl110f3/yjPzLtEZnuBzLe3t/xRvajrSum3Rps00Dt+SjJQB0AWpESFkp73DEZtfeGW66P/sgmKFSFNVEP79rEs5j7pJAYbOjE+hiT6URCRxOX62+sVBLT82joHJAvPVqU0NKU3oj7wcP7pr27Z5Ncrt98w7Tz3E/porKJVa2Ofc0bb9g+hkOfjHR0yIlDNvno/v0PTJuLNABA03AhAvv5W+0OPZ9K5qM+KAEy5wICiTXFJfxRsZiCkllD5vtoyrk+TlPV44KIMaKeK9YQqABLyHyGR6TrwtetbvjaJuY2FX+ZTmwRgpLW/iZxCjud55u/13SdGp5gALI2xQPNj0MqMFHTXAGAVsvOh27PrsETSrqsuAABgIJibEoxWO7a+8XhzM43AKiu2rV8e2No25ftur6+5gsB7R/ec48tKk1d42j/WdwMOvY6tBPzkot/cJpYw/uJVLKWr/TzvC5RJxPVKAGO14iG4jJxKyxpbJEyQAMlM4YjG4cAcEBJY/u7dh5OPrDPR2oDQIeLv1AsV1TYYTr2az/vILKa1lwu9JBIMusNfLGXk7BcuwwhhBBCCCFOgDa5QgghhBBi5dAmVwghhBBCrByvVpNL5u8pE2Y2yI8VC1Vss9/3esJR277n+o1Lpn3lltXgTo68pqTVWL3k1vq6HQbpsEZDW2ACABoae0mC4prOR136v0EirIZu58Bqyu7dv2Pat173xsx9MtGezaz2l/3hB5v+nLJ5dUN6oaayOp7Z2OtNq1nCiH5RCQHZnHCKdYopPbl/yD4wJs31vTvvuS6KmdW+Xn3tummPNqyuO6VzbuVWQ/jJT/2Aaec0ieraX6t3vv22aQfSbfZJp8jaWACoSBvP+rkWBV7k9QFeu8bHaZPeOKW5qxs7js1tew43Nq22MaXFni9esLiKXCAgIMzpUKuGdHzR6+0DxRDnQTRUXASN76MubdyWhY2pitaHkNCSM6y/5iINXo8JFJSzMDuiPAcae7/v1+1Wi4KONMnl1PZ5ectqZQGgDnZ+hNyu470+FelovDY4D/azlHQOuz27rvN8AoB+z49tUQkhoN1+9hkePbJFODY31/ktaJOu3+vvWcOfijsqwnDcDE88fTi28f/4kdVcb1BezMaGL8CTU55LHNsCKrt3bCGHvbff8X08trG5ftXmBWFiY/lo4gu9NKTjr0kLndH0b5WJE0IPFVTJ5BEVg9mf+T1Y3u25x06CvskVQgghhBArhza5QgghhBBi5dAmVwghhBBCrBwXrsmd19mVlRVq5B3v2diQ7ioLVqeyPbI6jVbb67I2N6x259obb5r26PI10757+yuuj40Nq3caXbHvycmPNmt7/UhJ3pEl6U6ODsjD7sjqbQEgkh9vq2sv4WBgtS77B973bjSy54P9itlXGIXXaDYo3WPztFn7NPKelzMWXC8xWcpLla2CSZjEXrLdgdfLvXbjpml3SFNX1FZz5vSD8P6KWUZeqTT0du51ia9dt166s5nVUO3tPbbjDF4PyL64NY29S3raVHTweW637XtYoztJaLvaLeu3eO01e46HaxumXVQ+1jtza5Xz1VwgIoBmbp3lGOQ8AABAQ5+XfUH5fLBGF94n18ua+ZwdP3+amnM4bLtx/r3AuLAaw2lhx3ppy2oje13vxdnU5OnLc65t35OxSBHAWt/G5XDdajDb1Mfk0MdcVdp+R2s2t4S101Xlz8f6mp/bi0pEQD2nD//Kn3zNPN/r+jXm+vUbpr02sue517PnOaW35+nc6fD15XXMdYGjKflEU35Nmwz9+1N/rWryHn/8J9+wfe7YNbc9TdyTK/thbt++bY8xsdpv9pEGgJI9f+m70WLPzrFix2qHASBm9lo9Ii38XfKnrhNL6iCxlp8EfZMrhBBCCCFWDm1yhRBCCCHEyqFNrhBCCCGEWDkuVJMbYHV508JqSBJ2i8YnD/C164cD+/z+gdePbv/gXzTt9aufpFdYvW2d0H70SJczvPSaaReZ7ePB3fddHxV7Ns7sWMekyc0aL/ZhzeXalq1Pfu0S+aamtJGZ1Qt3cnucjDzryr2ENpgEcw1paAoSNrUHXm89WvP1qReVGKPxRm3o2rRafipVpN3juumjkb12o0SteaasWR9lr0PFekoAwWmDSVNFfYTo9dODgdVxb25ZPeB0cmDHkfJKpLFnVK+cZc085wCvuc1J1x2okzKhF83bNu7W1lnbSP6rwc/DxVXhWmKMKOfiluwpvb4WAChOWbbYkAgx2QdpfUNGeuuMYyxxRvm4NOfYizsGry9mP+vh0Grae30bC6nrWlMMRYqxwcjmY8SENpj9iceUb8H+rk3l72MZTWTWm7Zbto+y9NrIwfCSe2xRybIM/bnrxV7LB0fe0/X+V61ut+S8B1pTBgN/D2Jd9htv3DLtS+SrPZkl4p/2LV3yeGVv5aPyvuuiet/64OYPHpr2GunL9+Hj//bMxsADyunZbOw4NxN5Mrz81YU9zuyxPUYDf//Yp0XkYWk1uBP23nU9ICXsPxH6JlcIIYQQQqwc2uQKIYQQQoiVQ5tcIYQQQgixcmiTK4QQQgghVo4LTTyLEajnkiDalESChJF9HjgJwrbbHfueH/jhH3B93PrUx027O7CC/aOdB6adJRIYpoUVSh/tWhH4QWFF0d/90z91fXTo81VkMj4aWnF6N2F2vbNvk9NqGmt/zZqbX7pqzbEBAJRYNJnaJAjyHMe0TBjG099HnGjkUi8KnwB02dfLWFgCgIzjdY4mYarPSWEtNtomjT8nyQBAoAIKucsis2f6YO+R62M2trG7tX3V9tnj5Bu/LHAy2qVLl017b+eeaY9rn4zBhRuqkhKYKMGnbvw4hkM71v7ABhGvDylT8YKK0HBCKF/LVDJSOOb5RWK+WEVF1yWPfvR8Dl1YuuIQPjEvY0f93CZFZS1KIkskCNaUAMvzI3B+S+L+0evZ4gfDoU2g5DnJxwSAvGXX4X5u+8gpaSY2PmEy0ufjoiYx2vPhE/N8ERPOw8kp8YyTtAFgVvhktEWliRHTuaQuXn/rxHq5RevSdGyT1fb3dk27SCSZHxzYJFpOXss+SYUd+v5GdnnbjqOc2jW42LX33M7UJ57F3CbWuVxeWmJvVz4R7x1KPKupSFWR2bjrcAY5gPVI84ruSQU9/yixf9qlx/K+TQBdpzmWtXyieqvtHzsJ+iZXCCGEEEKsHNrkCiGEEEKIlePYTW4I4VYI4XdDCN8MIXw9hPDzTx/fDiF8KYTw9tP/bx3XlxAXiWJXLCOKW7GsKHbFonESTW4F4BdijH8YQlgD8O9DCF8C8J8D+J0Y4y+GED4P4PMA/v7zu4pWe0Tar5DQ2DTweq95MjJ3fu2616Dmmd3LP7j7gWlPD3ZMu0row4qJ1bvsP7Y63gKkKUlUtuhkZBBNupNB336Ww8ND10dDhvqsF9rfsZpdwGt9CnpPK6PCDrnVy4wTGjPWV7Y79rO1SVM2I/NnAGhiSut7ppxZ7MYYUc4VL2mxq35CmZk5XZ09z05TxzrGxHtA16qqWMfq467ds3HWomuVBf5b11+XSIPtkabq6rXrpv3u2Mdut02fjz7arLLHvXT1muvjxk07vwOdM9b1tncfuz7u3LaFWt5566um/Ynv/yHT3rpsNcyA1fLxuTkDzm7NjXY9K0u7jnVaXvffclpx7pLOeULX29A5yWjtCy0qsJAoKMEaXF4vnEQ+oftv56TjpdhuWDue0LG2uSgJvaYu7XoaWHsPAHQPatP6URf2uoQskZ9C/fJ1adE4Wx0/joPDh+6xM+YM9wt2iWCtfGrW7e9brev4kDSpTj/u17o8p3vXzN679g/sMV7bsDk+AFBQsYc27WM6HTv6TmLtH1NcUe0sFDM79vvR75VmXatJ50INZbSdXk7cktdobAXd1/bputzP/DjqDuUb5TZWMyoWE939FUCeeOwEHPtNbozxgxjjHz799wGAbwK4CeAnAXzx6cu+COCnTjUCIc4Jxa5YRhS3YllR7IpF44U0uSGENwF8BsDvAbgWY/wAeBLYAPzXHU/e83MhhC+HEL68u3eQeokQ587Lxu7jx961QIjz5mXjdm+ff9kR4mJ42dhlJwQhTsOJN7khhBGAfwHg78YY9497/Z8TY/xCjPGzMcbPbm6snWaMQrwUZxG729vLU/NdrAZnEbcb6xvnN0AhPoKziN31jc3j3yDEMZzIJzeE0MaTgP21GOO/fPrwvRDC9RjjByGE60iJP5M806LExmo3sjyhyWVdFmloRj2r9fj2W99yffRHdmjDkV3469J66eWZPy0d0juxjpE9f0fk5wkAVWGP0yJty+SI9EO1Px/dFvk6kr720d07pn3w0H8D6XSbudXcNPTZOusJf7oO+Trmts8W6ed68Nq/K1fOP/fgLGN33j+0qlhzmNLQsV6U4p3ek+qDNdiB/DXb5Ht47drrro8Y2cfTtlnXym0AqGJFr7FjvXLlNdO+d+e264N12gikDe/Z2P7Ep37Q9dEiLTifn5y0XDxOAHh4z15u9kadjq2eLiX+25vTy9cJj+SX5azitok1ppNnY2WdeJPQ01asW6TPz6kT7vXwOuU26UMjeWvWCV1zIB0jv6ROeJwyFd3iun27LrMHbp4nNMqsn6X8gkjracpPO9Bj7bY9Tqxsn1ni1twiTSKPy38Wv26zvvQ8OKvYzfMcGxvPPInn4xgAtm9c57fgzh2bb8Ofl9eDVu7jfzCwMdKhHIYhPb8+svkJAEC3aTQzq30tCxvbs6mP/8Mj+5pD8hW/39j4P0xosAONvaG8B5LkokzMwwmJ9NkHd4fmf5Xws83arGun1/C9IfX16ykNyU/irhAA/DKAb8YYf2nuqd8C8Lmn//4cgN883RCEOB8Uu2IZUdyKZUWxKxaNk3yT+2MA/jMAfxJC+MrTx/5rAL8I4DdCCD8L4F0Af+t8hijEqVHsimVEcSuWFcWuWCiO3eTGGP8dPvqL4h8/2+EIcXYodsUyorgVy4piVywaJ9LkniXz+kD2r2W/VgBuusRAWibS5I3H1vMWAAry7GzXpKki1Ua/7/W0vTXymyNPuv0D7wvKsB6ItXwZedilPCxZD+e8hfl81V6DxVaQM/Ljq8nDsrPm/SfLttUXz+h8VIUdyFbX628HCd3yohJCQLf7TP/qPBsTnr+sVWStK/eR0sKCHmN9bRbsFK7KlD7StlstG4d82JTvK3tHMnVDWtjM67L6Q/JfntrM/9desx64HfJ4fHIcmjM0rJLOea/nPSxbpA9rk4djRrrfWcrDdU5TeuYuuWdI0zSYzZ5pjIcjm8xTNYl4Ke3n5XjgXAFeP5+8x16nmo6T0/NNKvbpxHKfFV2X1HXotuy1dZOBNcmJeVyyQSmtdYEW3Szhk9smkSbr73OKuVbi1tzp2bjtUj4K98ke2gAwnS6PY0Erz7G18Sx/ZpfyAh4+eMBvwaBvz8knPvFx0y7pnMwmNg8GgDMgbiiX4t13v2fa4wlp+OFzcrp0L69Jk7u76/Xl93esd/IB7D33Xtu+J6WFbZMGlzW5oNySKiFgfQx7zu7yHOna47YTWvA8sA8u5VbQ/SWRnoKQ8LA+CSrrK4QQQgghVg5tcoUQQgghxMqhTa4QQgghhFg5tMkVQgghhBArxwUnngWE8Exg3CLxcYQX/XPyVZuSUcraiqIHHZ8gk1G/9cwKxWOw7ylznxA1HNqEjUhi9MvX1k37vfE7ro+anJczSlgoKMGh2yUDZfhkPRZjFySs3z2w4nUAmE4pgSPY4w4v2XGt9XyY1JQkNxnbPvKKkujWfRJRWS5yyg4RbIKWz5NJFYOgLlzimY0hLhZxEtjwPQs+WTHwlAg8z7gohU8C4qQWTporOIkukTnASWNszH/9hk08KxPng5OgXEIcDb3d9XO527MJcNyFK9KRMPcfjZ7FM8/JRSI2NSZzJvqcJMYFBJ68h43rbYILF5Bot/05bqhAQixsAmyHzmlIJDs29BgnVZYVJ+v469CiBNmmsuthlVFCXOPvHxUdh2OOC2y0E+e03bHzNNJ9ixPPuLgQAAxGdg3tD2w7p3HcvW8LIwDA/v7UPbao1FWFvcePP2zfuGnXh9HQF2F4/44thnT/oU1O42TFbidR6Iji+2D/wI6Lkt3fvePrWnChjk6Lrj/FdlH66xI5SYyS6qoT1PVo0x6CagfhcM/G9oMTpNHW9FlyameJ+OdkzEhFOLhmT564B6UK+5yExV2dhRBCCCGEOCXa5AohhBBCiJVDm1whhBBCCLFyXHgxiHmtBRu3h5Q+LLNDZA1ullsNSUqTmOX2sZzM4LtkZnx45As7lGtWczvc2DbtgyNrKn3l5huuj+LIant2HlktT1FYXQ5rA5+M1Y49kIbmkPRDe3te6xNIx9kd2fMz6NMxEqbiYWL76E/tWNfIDHu9Z88fADx+cHwBjYUhWh951gumpEzHFX9gAWlK+8nm9XVtNWXTqb2+3Y7XR3JclSTm6pNGlTWGTyAdd/18feRozevl+mRmn7VJx922nz8iocmlE83j4LEnpJ5OpNzt2ViuuOBEQh82X0/jo8o7LQJ1E7F38Oz6H43tXB4OfLx0KK+hmNm1rart8/OFMT58jHS9rDenWjHotFN9kG6RtcE0nbLExY4Ul7OJXR9jQ0b2LFoEkLt5Sfcc0ui2Eqb8HIiBdPEdek+37edgv2/nVK9vNbk8X6aJIgWx9vNyUZnNZnjnne982N7bt4Usrly96t5z65a9716+YmP36NBe//19fw+aTu36uLl92bS5oERV+EIOrP0tas4lIE167uNubc3mATV03MP7d+0bEgtRTgVDOJckUKGsaSIPgvW0bd5PUfyHROEgfsznFoXntp88Jk2uEEIIIYQQALTJFUIIIYQQK4g2uUIIIYQQYuW4UE1ungHDwTOtRT0mrVdM6QnpAfKFZd1qN+GLyZqRkjwbW6x9rf3e/85775n21sRqWVjbk9KUsPdhRnrjNumyisJrYcvSPsZeqx3Sct167ZLro0W63ob0YQ3pPqt91wXCzI59SGO/fsnqpYY9rwW7c7jjO15QIoB6TotXOw/PhG75GE0uaz3ZNzpFRceNpEucTLwG++GO9cscrlmd1qDvPYwZ1qnVjZ2YMZLWc7Tm+rh65TXTfvDgoWnfu2vHefnqNdeHm1fH2DoekVYeAAakQ2VN/nRmP2ueOEg2d61Sc31RiDGimfP1LGt73cYJHWue07WjdaqgWJhVXsfnLhOtU5nT13kdK88X9vid8foY/Ti6he23NbFrWyB9dkae4QBQk1+p0yiST2hVeo0mazDbrONt0fMJTW67xfcLq43c3bHraTsRtx0v/VxYQghmTTw6tBrjJnp/2pK0sDzXN9ZtbsjWpr8/8nzmNXVG8c/3YACoaE6wBrVLWlnWmwPAHl3P/T2rSWbf6MHI32OvXLlij0Nr2yH1mVrLWi3OabJt5yueyOkIGfviUj5KeL5G96MeOwn6JlcIIYQQQqwc2uQKIYQQQoiVQ5tcIYQQQgixclysJjcP2Nh4ptfoBXv4x3teD3U4Jp/Qxr6n07H79KL0BZ2baPUuGRnKTca2nnlRsJ8pUNXkYQvb7pA/6dGh7RMA9klDxoqpEXtWsuASwHRq+22Rp2WP9LapGtAVefaBNDTsRVwX/m+hNtX33t4YmfbayH6WvX3v2Tg58td7WeDa46wxAryGyOsQLewLCnhf2DwjPRTpqR/cs7XbAaDbsXNmfWT9F9n3MSQMFyNdb9aPVyXPBy/+i9HG2cbmlml/8IEd+3vvWh08ANx6/XXTZo9SPoesYwOA0ZqNVdY27h9YL82q9HEa5tau46u9vzoCgtHMtUguxz7DABDpttBiD1vSrdYJH22np6X50iJd63iSWAucrtf2MZvZ47Y6Pm4b0twis+tjTXE9m/n7B8llEemc1aRZTE3zVsvOB84TaeV2HHlS12g7bmgcY/Jhf/f2d10fo97i6seZEALanWfn9tatW+b5y6Q3BYC9vT3T/upXv2ravKb0+z6HhzX6/X6Pnqd2Yq3jfvlaHY3t/XBnx+enzCb2Xj8e+/yCeXhOAcB0Qhr8ie0jJ513Hn3cse8zv4f9a5M+ufSa4zS4SU1u4h57EvRNrhBCCCGEWDm0yRVCCCGEECuHNrlCCCGEEGLl0CZXCCGEEEKsHBeaeBYyoNt7JkquKPGoN0zsuTtW1D8+tMkGnDiR5TaxAABqKu5QUQIDmzlPS5801mnbU8Xm/2VlBd117ZPGokvGoKS5mT0f3a797E8esyJ3Nr8ek1i90/Em6+zUHprnJzelahSwufnmNiUzUR7J9773wPVx75FPRltUYmwwm0v6a5G4PiSSBDkJipNvOBkheVxqtzN7PR89ft+0Z1OfwHBt803Tzsl4P2Z8FD8PuVBFJOP9CRmkDwY2uQsAIsVdu2Pn6k1KLNnbtUkkANDQOWRT/ZIC7zBRDGJj08bqYGhN1PsHtrDLeOzXg7W1jQ//vdCpPAHI57LN2pSEWE+8Cf1kas8ZrzmcZFvX/hxXLhmN11x7nWKRSu6zbU6K4fOeJxJvWjTWFn0WyjtD1fhx5Jx5FrhIBRv/+4jgYgDOQJ9eX1c+AQ5ULGl/557to7Jr7PXLvshLlbi3LSp1U+Pw6NlcvP3+bfP8KFH8YI2SSjMKokcPH5l2v+/3C31KAJ9OKGmQsjczpBKt3COmxevUZOLnECfEl4mCEeb5RAJolws/0V7nkAo9cUIk4BMeXaIZx3Ii85ILRLjiEHh+sYjUa06KvskVQgghhBArhza5QgghhBBi5dAmVwghhBBCrBwXqslFCMjm9E2trtVp9BNm3hnpTLIWGYJPaZ/e+D7aLavdYV1fWVkj+5zNz5HQlASrW23ARSsSxv6RdSj0PBVhaLzExo2DNYkHpMktE9rgXs/qdNhQnzU3ZUJzdDi2mrEJFdAoCvv8O9996PpYploQTdMYs/Uu6UmPjry+mA2tez2r7WL9NKKPGS660BnZuCtLq9PKc6/BbrXtWDkOEaiwRfBaYdZylaRJn5Gmcm3d68kjRTzPw0CxvbW97fsgXTsXamAt6PqG1d8CQE7ntKDPwkUqUtUejua0vlz4YJHIsoDenLafP2u7468Ta/9q0v1npMdvoo+XjIobUPi4wg4ckgCQN/Y4LcoVmFGRn8SSiw7Ffqtlrz1L/7LMn48W3XMy0u3ye3iNfvLY8w30q8ZqMpvGFzHZfWwFlFlt19gYuWCRv71zoZ+FJgQTa4eHViv//vvv8ztw/fp10+5SfK+tWZ0y680Br5fdpQITvB6w7hfwmlLOx6grOyGaRE5HTePgNZjjrKpOoGt393r7glbLxz9XN3EZHKyvzfz+yet2+R7EzURBIj+yE6FvcoUQQgghxMqhTa4QQgghhFg5tMkVQgghhBArx4VqcmMDFMXcvpo8PzstrxfKSSLSIS/EomeVGuw1++Qxq+UpStbHWD1MN/f+gi3SlLDHKetS8oTGLGs93xuu3WH/Od8Ha3fYw7HbsydskvDBnJE+qNsn30uSBz3a9R5+D+9ZfdiI/AaHrMkMXlEz6CY8fBeUAKt/LklzzD7KQEqHZWOzQ36L7YQeKpISKWvb9mjT6laLsb/erTZp0snnE9HOuyLhpXmwf2Da6+v2uFevXrPjTH4WCmiKZY7tkNAos4aM/Ua75At9+eoV1wcLwPg6dUjrltTczb0lpUFbFELIjK9tQ7pN9rsGAFBuRFGw7tmufe2EkXabZKns4ek9w/05Xm+xFtC+pyzpPQnRnvf0tM+3aE2eHNk4B4BHB1aTubFm51O7Y+8XLs4B9Hv2NXVt70m7D+/QO8jAFMARaX+HdP8crlst+XTq74X7h4urH2cCrIa0pnXq/du3wdwhnS7nLPCakwqaPt0PWT9e072fPcOfvMc+VtfUB8VyTHimV7UdO88Ql1tUem/l3T3rmz6dkG6bNbon0dPy+ujylVIet89/wPnkpvpIPHYSFnd1FkIIIYQQ4pRokyuEEEIIIVaOYze5IYReCOH3Qwh/HEL4egjhHz99/GMhhN8LIbwdQvjnIYTl+e1Z/P8Cxa5YRhS3YllR7IpF4ySa3BmAvxZjPAxPzGH/XQjh/wTw9wD89zHGXw8h/FMAPwvgf3peR3UN7M/Jm+qpPXxn4PVCrTbpZWlq9Pt2n16UXofE2qTJ2GpIpiRBDNHv/SN5xXpNGfXhejheT1iRLi0mLA1z0v80pDmK9PljQmMzJY0dyYUwIV3z7mOv0ZyS1rcuSCvatTXEr2ysuT5m52/ZeGaxCwTj88o6JNZ1AkBNnpSR9GBt0o+mvJVZp8paYPZj7Pa9nrysKSZID9aiz1IkL4yNo5zek7dZg+tngPOTTZwze4zUPKRRkR6Ur0PyEM6jkbSfrA1OaMHyufecViv2HM4wboFs7lqwfjZ4S1eXo8Bes+PaavQD/LrNa1vOvrlOk+dvRR3yKz8qed2i65TQNdakjeQrNSusRvHu/fuuj71dq8mN8bJpj9Y27Bsy/1n6QzsvHz38wLTv3PueabfcfAKGXauD774Br5UAAAf8SURBVIysdnR2ZIOdPVGfjNX7Rp8xZxa7IQTk83kLPLcT/tQV+UCztyyvfeMjq41OHMZ5HGeBNagJTW7k/YHtlHN6Uh63PPbcee/a19e172N35zE9Yvvo961PMGvYgdRcprhi3fsJfIMzPs6JltDTOeUe+01ufMKfR0L76X8RwF8D8L8/ffyLAH7qVCMQ4pxQ7IplRHErlhXFrlg0TqTJDSHkIYSvALgP4EsAvgNgN8YPv2u8DeDmR7z350IIXw4hfHln12eMCnGenFXsPnZ/EQtxfpxV3HKVKCHOm7OK3f197RfEy3OiTW6MsY4x/giA1wH8KIBPp172Ee/9QozxszHGz25trp9+pEKcgrOK3e0tX2JWiPPirOJ2NBqlXiLEuXFWsbu+rv2CeHleyF0hxrgL4N8C+CsANkMIfy5WeR0AG/0JsTAodsUyorgVy4piVywCxyaehRCuAChjjLshhD6Avw7gnwD4XQA/DeDXAXwOwG8ee7SQIWbPBPh1fsM8XSdMlUNjkxxaNgcCvaH9CD02ugfQp+IP/YkV9U/HVvVcFomEl4ZF/CQCp6QhFsADXrDNJstFRebOhe8jgz1H3WBPSAw2Mamu/WdpdexxWiSs7+X2GFuw4nQAuHbNJk1dumaLAWxu228+b76eMCY/8IULzpKzjN2IaBLDOIkqmXxE4vos5wQn+3I2zAd88tXujk2CmUzs/NhYpyQYAI8f2cRBNt7vdm0Cy3qiD8qb8YkU1fHngx/h1/C42Owc8Mkm/JoWzbE8TxTpoLnK15ILu6S+czJFOo5JoHtRzjRuY0TZPJt7DZ3jLFEbgBNrati4HA7telAkTOi5KA8nmvDal9c+Xo4omXXqEgKffx0BoKQk24ND+xP43q41y9/bO3J9UO0L7B/YOVcVlIjXpAoS2TlYlvY9gw17znuJgkQ13Q/yvl2Dy8J+/kmiqEv7nAvwnOl+ATBraEZzuZVcc11G43PbdWK/wElhsbHnvYp0fV2BCV/Ex61bLlb9GsLJzQ29hgtO1Yn7x5SKv4zW7LfjvD6mikG44g+8pvLcdj3AXZdIbU68axJJ2KlEypNwEneF6wC+GELI8eSb39+IMf4fIYRvAPj1EMJ/C+CPAPzyqUYgxPmh2BXLiOJWLCuKXbFQHLvJjTF+FcBnEo+/gyd6GyEWEsWuWEYUt2JZUeyKRUMVz4QQQgghxMoRUib253awEB4A+B6AywAeXtiBT8+yjBNYnrE+b5zfF2O8cpGDOSmK3XNlWcb6UeNU3J4tyzLWZRknoNi9CJZlnMDyjPWl9wsXusn98KAhfDnG+NkLP/ALsizjBJZnrMsyzo9iWca/LOMElmesyzLOFMs09mUZ67KME1iusTLLMvZlGSewPGM9i3FKriCEEEIIIVYObXKFEEIIIcTK8ao2uV94Rcd9UZZlnMDyjHVZxvlRLMv4l2WcwPKMdVnGmWKZxr4sY12WcQLLNVZmWca+LOMElmesLz3OV6LJFUIIIYQQ4jyRXEEIIYQQQqwc2uQKIYQQQoiV40I3uSGEvxFCeCuE8O0Qwucv8tjHEUL4lRDC/RDC1+Ye2w4hfCmE8PbT/2+9yjE+HdOtEMLvhhC+GUL4egjh5xd4rL0Qwu+HEP746Vj/8dPHPxZC+L2nY/3nIYTzLah+Bih2Xx7F7qtBsfvyLEvsKm4vBsXtuYz1fGI3xngh/wHIAXwHwMcBdAD8MYAfuqjjn2B8/zGAvwTga3OP/XcAPv/0358H8E8WYJzXAfylp/9eA/AtAD+0oGMNAEZP/90G8HsA/gqA3wDwM08f/6cA/s6rHusxn0OxezbjVOxe/OdQ7J7NOJcidhW3FzY+xe3Zj/VcYvciP8BfBfCv5tr/AMA/eNUnlsb4JgXtWwCuzwXLW696jIkx/yaAn1j0sQIYAPhDAH8ZTyqYtFJxsYj/KXbPbcyK3fMfu2L3fMa88LGruD33MSpuz2+cZxa7FylXuAngvbn27aePLTLXYowfAMDT/199xeMxhBDeBPAZPPmLZyHHGkLIQwhfAXAfwJfw5K/z3Rhj9fQlyxAHit0zRrF7YSh2z5hFj13F7Stj4WJhnkWPW+B8YvciN7kh8Zj8y05JCGEE4F8A+Lsxxv1XPZ6PIsZYxxh/BMDrAH4UwKdTL7vYUb0wit0zRLF7oSh2z5BliF3FrWCWIW6B84ndi9zk3gZwa679OoA7F3j803AvhHAdAJ7+//4rHg8AIITQxpOA/bUY4798+vBCjvXPiTHuAvi3eKKx2QwhtJ4+tQxxoNg9IxS7F45i94xYtthV3F44CxkLyxa3wNnG7kVucv8AwKeeZsp1APwMgN+6wOOfht8C8Lmn//4cnuhZXikhhADglwF8M8b4S3NPLeJYr4QQNp/+uw/grwP4JoDfBfDTT1+2EGM9BsXuGaDYfSUods+AZYldxe0rZaFiAVieuAXOMXYvWEz8N/Eku+87AP6bVy1uprH9MwAfACjx5K/InwVwCcDvAHj76f+3F2Cc/yGefF3/VQBfefrf31zQsf4HAP7o6Vi/BuAfPn384wB+H8C3AfxvALqveqwn+CyK3Zcfp2L31XwWxe7Lj3MpYldxe2FjU9ye/VjPJXZV1lcIIYQQQqwcqngmhBBCCCFWDm1yhRBCCCHEyqFNrhBCCCGEWDm0yRVCCCGEECuHNrlCCCGEEGLl0CZXCCGEEEKsHNrkCiGEEEKIleP/A9rypAhlQtecAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Let's look at four of the images in the training dataset, and the\n", "# corresponding label (which defines the object the image represents)\n", "\n", "# Grab the first four images and corresponding objects they represent\n", "# from the training set\n", "\n", "img = []\n", "val = []\n", "\n", "for i in range( 4 ):\n", " im, v = train_dataset[ 20 * i ]\n", " img.append( im )\n", " val.append( v )\n", " \n", " img[ i ] = img[ i ] / 2 + 0.5\n", " img[ i ] = img[ i ].numpy()\n", " img[ i ] = img[ i ].transpose( 1, 2, 0 )\n", " \n", "# Print out what objects the four images are meant to represent\n", " \n", "print( ' '.join( classes[ val[ i ] ] for i in range( 4 ) ) )\n", " \n", "# Create a single row of four images\n", " \n", "fig, axes = plt.subplots( 1, 4, figsize=( 12, 2.5 ) )\n", "for i in range( 4 ):\n", " axes[ i ].imshow( img[ i ] )" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# Create training and test dataloaders, these will load and cache data of batch_size during\n", "# looping, training data is shuffled randomly, test data is not\n", "\n", "train_loader = torch.utils.data.DataLoader( dataset=train_dataset, batch_size=batch_size, shuffle=True )\n", "test_loader = torch.utils.data.DataLoader( dataset=test_dataset, batch_size=batch_size, shuffle=False )" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "net = nn.Sequential(\n", " nn.Linear( input_size, hidden_size ), # fully connected layer, 784 (input data) -> 500 (hidden layer)\n", " nn.ReLU(), # Rectified liner unit filter, max( 0, x )\n", " nn.Linear( hidden_size, num_classes ) # output layer, 500 (hidden layer) -> 10 (output classes)\n", ")\n", "\n", "#net.cuda() # Uncomment to enable GPU computation" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Choose a cross-entropy loss function to use during evaluation of DNN performance, and an\n", "# Adam optimizer (Adam, see https://arxiv.org/abs/1412.6980) to update DNN weights\n", "\n", "criterion = nn.CrossEntropyLoss()\n", "optimizer = torch.optim.Adam( net.parameters(), lr=learning_rate )" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch [1/5], Step [100/500], Loss: 1.7935\n", "Epoch [1/5], Step [200/500], Loss: 1.8810\n", "Epoch [1/5], Step [300/500], Loss: 1.7973\n", "Epoch [1/5], Step [400/500], Loss: 1.8349\n", "Epoch [1/5], Step [500/500], Loss: 1.7606\n", "Epoch [2/5], Step [100/500], Loss: 1.8202\n", "Epoch [2/5], Step [200/500], Loss: 1.5356\n", "Epoch [2/5], Step [300/500], Loss: 1.6673\n", "Epoch [2/5], Step [400/500], Loss: 1.7702\n", "Epoch [2/5], Step [500/500], Loss: 1.6312\n", "Epoch [3/5], Step [100/500], Loss: 1.6856\n", "Epoch [3/5], Step [200/500], Loss: 1.5715\n", "Epoch [3/5], Step [300/500], Loss: 1.5455\n", "Epoch [3/5], Step [400/500], Loss: 1.8162\n", "Epoch [3/5], Step [500/500], Loss: 1.9575\n", "Epoch [4/5], Step [100/500], Loss: 1.3813\n", "Epoch [4/5], Step [200/500], Loss: 1.4239\n", "Epoch [4/5], Step [300/500], Loss: 1.6099\n", "Epoch [4/5], Step [400/500], Loss: 1.4577\n", "Epoch [4/5], Step [500/500], Loss: 1.6722\n", "Epoch [5/5], Step [100/500], Loss: 1.5722\n", "Epoch [5/5], Step [200/500], Loss: 1.6129\n", "Epoch [5/5], Step [300/500], Loss: 1.5547\n", "Epoch [5/5], Step [400/500], Loss: 1.6038\n", "Epoch [5/5], Step [500/500], Loss: 1.6430\n" ] } ], "source": [ "# Train the DNN\n", "\n", "for epoch in range( 0, num_epochs ): # For each of the five epochs\n", " \n", " for i, (images, labels) in enumerate( train_loader ): # For each of the 100-image batches\n", " \n", " images = Variable( images.view( -1, 32 * 32 * 3 )) # Convert torch tensor to Variable, from 784-pix image to 28x28 matrix\n", " labels = Variable( labels ) # Grab pre-assigned labels for each of the 100 images\n", " \n", " optimizer.zero_grad() # Zero gradients for current pass\n", " outputs = net( images ) # Forward pass, compute output class for given image\n", " loss = criterion( outputs, labels ) # Compute loss, difference between estimated label and actual label\n", " loss.backward() # Backpropegation, compute improved weights\n", " optimizer.step() # Update weights of hidden nodes\n", " \n", " if ( i + 1 ) % 100 == 0: # Log message\n", " print( 'Epoch [%d/%d], Step [%d/%d], Loss: %.4f' % ( epoch + 1, num_epochs, i + 1, len( train_dataset ) // batch_size, loss.data ) )" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy on 10K test images: 45 %\n" ] } ], "source": [ "# Test performance on test images\n", "\n", "correct = 0\n", "total = 0\n", "\n", "for images, labels in test_loader: # For each image the the test dataset\n", " \n", " images = Variable( images.view( -1, 32 * 32 * 3 ) ) # Convert torch tensor to Variable, from 784-pix image to 28x28 matrix\n", " outputs = net( images ) # Get correct lables for each image\n", " \n", " _, predicted = torch.max( outputs.data, 1 ) # Choose best class from DNN output\n", " total += labels.size( 0 ) # Increment total count\n", " correct += ( predicted == labels ).sum() # Increment correct prediction count\n", " \n", "# Print overall accuracy of labeling\n", " \n", "print( 'Accuracy on 10K test images: %d %%' % ( 100 * correct / total ) )" ] }, { "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.7.1" } }, "nbformat": 4, "nbformat_minor": 2 }