{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# pailab Specific Setup\n", "This example is taken from [autoencoder](https://github.com/udacity/deep-learning-v2-pytorch/tree/master/autoencoder/convolutional-autoencoder) notebook from the udacity [repository](https://github.com/udacity/deep-learning-v2-pytorch/) and then adapted to work with pailab. It has he same functionality as the [Convolutional_Autoencoder.ipynb](./Convolutional_Autoencoder.ipynb) except that it shows how to use disk and hdf storages to persist all ml objects on disk.\n", "To run it, please make sure that\n", "\n", "- PyTorch is installed,\n", "- the path to the file autoenc_conv_pytorch.py (in pailab's example/custom_models directory) is either included in PYTHONPATH environment variable or just set it locally by uncommenting and editingthe following lines" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import sys\n", "custom_model_dir = 'C:\\\\Users\\\\Anwender\\\\development\\\\pailab_oeltz\\\\examples\\\\custom_models' # set path to the implemented pytorch autoencoder\n", "if custom_model_dir not in sys.path:\n", " sys.path.append(custom_model_dir)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We instantiate the repository. Here, we use a disk handler to store all objects except their big data part on disk and a hdf store to store the big data in hdf5 files on disk. \n", "\n", "**Please adjust the *workspace* variable below to select the directory to store the respective files.**" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "code_folding": [] }, "outputs": [], "source": [ "from pailab import RepoInfoKey, MeasureConfiguration, MLRepo, DataSet, MLObjectType, FIRST_VERSION, LAST_VERSION\n", "workspace = 'c:/temp'\n", "# setting up the repository\n", "config = {'user': 'test_user',\n", " 'workspace': workspace,\n", " 'repo_store': \n", " {\n", " 'type': 'disk_handler', \n", " 'config': {\n", " 'folder': workspace + '/objects', \n", " 'file_format': 'json'\n", " }\n", " },\n", " 'numpy_store':\n", " {\n", " 'type': 'hdf_handler',\n", " 'config':{\n", " 'folder': workspace + '/numpy',\n", " 'version_files': True\n", " }\n", " },\n", " 'job_runner':\n", " {\n", " 'type': 'simple',\n", " 'config': {\n", " 'throw_job_error': True\n", " }\n", " }\n", " }\n", "ml_repo = MLRepo( user = 'test_user', config=config)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-------\n", "# Convolutional Autoencoder\n", "\n", "Sticking with the MNIST dataset, let's improve our autoencoder's performance using convolutional layers. We'll build a convolutional autoencoder to compress the MNIST dataset. \n", "\n", ">The encoder portion will be made of convolutional and pooling layers and the decoder will be made of **transpose convolutional layers** that learn to \"upsample\" a compressed representation.\n", "\n", "\n", "\n", "### Compressed Representation\n", "\n", "A compressed representation can be great for saving and sharing any kind of data in a way that is more efficient than storing raw data. In practice, the compressed representation often holds key information about an input image and we can use it for denoising images or oher kinds of reconstruction and transformation!\n", "\n", "\n", "\n", "Let's get started by importing our libraries and getting the dataset." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import torch\n", "import numpy as np\n", "from torchvision import datasets\n", "import torchvision.transforms as transforms\n", "\n", "import logging\n", "logging.basicConfig(level=logging.ERROR)\n", "\n", "# convert data to torch.FloatTensor\n", "transform = transforms.ToTensor()\n", "\n", "# load the training and test datasets\n", "train_data = datasets.MNIST(root='data', train=True,\n", " download=True, transform=transform)\n", "test_data = datasets.MNIST(root='data', train=False,\n", " download=True, transform=transform)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Create training and test dataloaders\n", "\n", "num_workers = 0\n", "# how many samples per batch to load\n", "batch_size = 20\n", "\n", "# prepare data loaders\n", "train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=num_workers)\n", "test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, num_workers=num_workers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualize the Data" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", " \n", "# obtain one batch of training images\n", "dataiter = iter(train_loader)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nMZv/AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "images, labels = dataiter.next()\n", "images = images.numpy()\n", "\n", "# get one image from the batch\n", "img = np.squeeze(images[0])\n", "fig = plt.figure(figsize = (5,5)) \n", "ax = fig.add_subplot(111)\n", "ax.imshow(img, cmap='gray')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Convolutional Autoencoder\n", "\n", "#### Encoder\n", "The encoder part of the network will be a typical convolutional pyramid. Each convolutional layer will be followed by a max-pooling layer to reduce the dimensions of the layers. \n", "\n", "#### Decoder\n", "\n", "The decoder though might be something new to you. The decoder needs to convert from a narrow representation to a wide, reconstructed image. For example, the representation could be a 7x7x4 max-pool layer. This is the output of the encoder, but also the input to the decoder. We want to get a 28x28x1 image out from the decoder so we need to work our way back up from the compressed representation. A schematic of the network is shown below.\n", "\n", "\n", "\n", "Here our final encoder layer has size 7x7x4 = 196. The original images have size 28x28 = 784, so the encoded vector is 25% the size of the original image. These are just suggested sizes for each of the layers. Feel free to change the depths and sizes, in fact, you're encouraged to add additional layers to make this representation even smaller! Remember our goal here is to find a small representation of the input data.\n", "\n", "### Transpose Convolutions, Decoder\n", "\n", "This decoder uses **transposed convolutional** layers to increase the width and height of the input layers. They work almost exactly the same as convolutional layers, but in reverse. A stride in the input layer results in a larger stride in the transposed convolution layer. For example, if you have a 3x3 kernel, a 3x3 patch in the input layer will be reduced to one unit in a convolutional layer. Comparatively, one unit in the input layer will be expanded to a 3x3 path in a transposed convolution layer. PyTorch provides us with an easy way to create the layers, [`nn.ConvTranspose2d`](https://pytorch.org/docs/stable/nn.html#convtranspose2d). \n", "\n", "It is important to note that transpose convolution layers can lead to artifacts in the final images, such as checkerboard patterns. This is due to overlap in the kernels which can be avoided by setting the stride and kernel size equal. In [this Distill article](http://distill.pub/2016/deconv-checkerboard/) from Augustus Odena, *et al*, the authors show that these checkerboard artifacts can be avoided by resizing the layers using nearest neighbor or bilinear interpolation (upsampling) followed by a convolutional layer. \n", "\n", "> We'll show this approach in another notebook, so you can experiment with it and see the difference.\n", "\n", "\n", "#### TODO: Build the network shown above. \n", "> Build the encoder out of a series of convolutional and pooling layers. \n", "> When building the decoder, recall that transpose convolutional layers can upsample an input by a factor of 2 using a stride and kernel_size of 2. \n", "\n", " \n", "**In contrast to the original notebook we have defined the autoencoder outside the notebook in a separate source file: autoenc_conv_pytorch.py which is located in examples/custom_models.**\n", "Also note that we need to transform the data into numpy data to add it to the repo. To add a PyTorch DataSet directly to the repo is subject of future work." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "code_folding": [], "collapsed": true }, "outputs": [], "source": [ "from autoenc_conv_pytorch import ConvAutoencoder\n", "model = ConvAutoencoder()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'test_data': '0aa71bfa-8360-11e9-98fc-fc084a6691eb',\n", " 'train_data': '0aa71bfa-8360-11e9-98fc-fc084a6691eb'}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# transform the pytorch datasets into numpy arrays and add the data to the MLRepo\n", "tuple(train_data[0][0].shape)\n", "train_tmp = np.empty((len(train_data), ) + tuple(train_data[0][0].shape))\n", "for i in range(len(train_data)):\n", " train_tmp[i] = train_data[i][0]\n", "tuple(test_data[0][0].shape)\n", "test_tmp = np.empty((len(test_data), ) + tuple(test_data[0][0].shape))\n", "for i in range(len(test_data)):\n", " test_tmp[i] = test_data[i][0]\n", "#now add th raw data as well as the trainign and test data sets to the MLRepo\n", "from pailab import RawData, DataSet\n", "train_raw = RawData(train_tmp, x_coord_names=['image'], repo_info={RepoInfoKey.NAME: 'train_raw'})\n", "test_raw = RawData(test_tmp, x_coord_names=['image'], repo_info={RepoInfoKey.NAME: 'test_raw'})\n", "ml_repo.add([train_raw, test_raw])\n", "train_data_repo = DataSet('train_raw', repo_info={RepoInfoKey.NAME: 'train_data', RepoInfoKey.CATEGORY: MLObjectType.TRAINING_DATA})\n", "test_data_repo = DataSet('test_raw', repo_info={RepoInfoKey.NAME: 'test_data', RepoInfoKey.CATEGORY: MLObjectType.TEST_DATA})\n", "ml_repo.add([train_data_repo, test_data_repo])" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "code_folding": [ 3 ] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:pailab.ml_repo.repo_objects:Used module does not define a version which may lead to irreproducable results.\n", "WARNING:pailab.ml_repo.repo_objects:Used module does not define a version which may lead to irreproducable results.\n" ] } ], "source": [ "# Add model to the MLRepo.\n", "# The method add_model is a convenience method doign all the work you would need to define a model in pailab:\n", "# adding the training and model parameter, the model definition, the functions for training and evaluation of the model.\n", "import pailab.externals.pytorch_interface as pytorch_interface\n", "from pailab.ml_repo.repo_objects import get_object_from_classname\n", "pytorch_interface.add_model(ml_repo, model, {}, 'conv_autoencoder', batch_size=20, epochs=3,\n", " loss='MSE', optimizer='Adam', optim_param={})\n", "\n", "# We can check what objects the method added by listing all objects of the repo before and after calling add_model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Training\n", "\n", " \n", "**Since we have defined the model outside of the notebook and the training method is implemented in pailab's PyTorch interface, in contrast to the original notebook we can simply call run_training to start the training.** " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('conv_autoencoder/jobs/training', '0b239dd2-8360-11e9-aded-fc084a6691eb')" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ml_repo.run_training()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Checking out the results\n", "\n", "Below I've plotted some of the test images along with their reconstructions. These look a little rough around the edges, likely due to the checkerboard effect we mentioned above that tends to happen with transpose layers." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('conv_autoencoder/model/jobs/eval_job/train_data',\n", " '7c5f90d0-8360-11e9-ac25-fc084a6691eb'),\n", " ('conv_autoencoder/model/jobs/eval_job/test_data',\n", " 'a18ebd78-8360-11e9-af3b-fc084a6691eb')]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ml_repo.run_evaluation()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eval_train = ml_repo.get('conv_autoencoder/eval/train_data', full_object = True)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nvZGDDz44xFdffbXJdenSJcT9+vUzuRkzZqxxP5HdUUcdZdq77LJLiH0tRV0Hq9Louji+3+PGjavv\n7lQtXZvXv4933HFHiC+99NLMz7nTTjuF2NcaWrFiRYiXLl1qcu+++26I77nnHpMbO3asaesa13Pm\nzDG56dOnh7h58+Ym9/7770f7jsqz6aabhvixxx7LvN2HH35o2n6coDItX77ctD/55JMQb7jhhib3\n0UcfhdjPXzG6puuiRYtMrlOnTqY9b968EA8ZMiTzPlA5mjRpYtq77rpriP2coj9/fXwUsePmtdde\nM7nvfOc7pu1rFWu6HuBxxx1ncv379w+x/1sAUH30ebA/J86qmJrlnr7uO+KII0zu6aefztUfVCf/\n+wqoTr179w7x3XffbXL6XNjPE5MmTQrxHnvsYXK63aNHD5PbeOONTVufJ+lzdBGRH/7wh9G+VyK+\nKQwAAAAAAAAANYSbwgAAAAAAAABQQ7gpDAAAAAAAAAA1hJrCRXrnnXdMu1evXqb9ve99L8SDBg0y\nuZ/85Cch7tq1q8kdeuihpeoiMvA1Vtddd90Qz5071+T++te/1kufCmnatGmI+/btW/BxL7zwgmlf\ncskl5epSo3P22WeHeMqUKSa377775nrOqVOnhviJJ54wuffeey/Eo0ePzvX8Xp8+fUxb1x31dWVR\nfS666KIQF1NH79prry1Hd1Bmn376qWkfc8wxIf773/9ucm3btg3x5MmTTe7JJ58M8b333mtyCxYs\nCPHDDz9scr6msM+jOuhzG1/v9/HHHy+43RVXXBFif27xyiuvhFiPvdU9docddii4D32Muuaaa0wu\ndvxctmxZwedE5dL1YOs6hh1wwAEhvu2228rWJ5SPv14+8MADQ3zyySeb3LPPPhviL7/8Mvc+zzzz\nzBCfe+65uZ8H1e/FF18Msf8dIVSnH/zgB6at77N99dVXJqfPoU888USTW7hwYYhvvPFGk+vevXuI\nfb1hXwtd1y1u3769yU2bNi3Eeu4TWfU8vVLwTWEAAAAAAAAAqCHcFAYAAAAAAACAGkL5iDXkl3g+\n8MADIb777rtNbp11/vd266VRIvar5SNGjChdB1E0vzRx1qxZ9bp/XS5CROSyyy4L8YUXXmhy06dP\nD7FfAvH555+XoXeN3+9///uG7kIuBx98cMHcY489Vo89QSnssssupn3YYYdl2k6XCxARmTBhQsn6\n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\nAAAAAACghnBTGAAAAAAAAABqSL3XFC5U42dNagiVIufrhMT6pvl6H7qGVqy+TNOmTU1u6dKlIfa1\njvR2zZo1M7lFixYV7KduN9a6R+V4XXXV5CyUK2Z8NWnSxLR1DR2fi33+8+fPL7jPvO9NLYwbL2vd\nw7rqUtW3rOPPzylZa5gXUz+tFPWMKlkl/S0Uc5zzn2HW8dy8eXOT08eaYsZ9LY8ZkcoaN9WEcVMd\n5zZ1zTdZay6uu+66JqfPiYvpG+Om/PNNrFamvibyn40+t/Xnua1atTLt6dOnh7iYa5u8v5dRK+Om\nPq/Bi5lv9LiJ1Vv1482fp+h5I3bu07JlS5NbuHBhpu2Yb6z6OE7FcnrcxGrmx+Ypkew1fkv1ezyM\nm8Z3Xpx1fhOJ3/PRj/X3fPQ9Rj9OSnHvhm8KAwAAAAAAAEAN4aYwAAAAAAAAANSQei8foemvPseW\na3ixr/nr5/RfydZLC/xXq/V2/mve+rH+69q+L3qfsSVPsaUM/jk333zzEM+dO9fk2rZtG+IFCxYU\n3F9jknXcFLOMUediY8PTz+O300v2/f5at25t2g888ECIN9poI5MbNmxYiJ999lmTGzFiRIiXL19e\nsJ+efm/864v97VXbmCr02RWzPCk23+ilHLHlIbHxFssVU77B9zM2NvVS3WXLlhXch1+OpbeLLdWq\ntnFSSNa5Ju9nmHc7n8t6TPSP9WVFdH86duxocltuuWWI33jjjYL7i82Dvi/6dcSOl9Wm3McoL/b5\n6+fx50TFHDP055h1qaXfv99Ov/5i5q9Y+ZJqXnqZddwUU7asmGNGoZzfXzHnS7pUmj9m6H77vujx\nph9X1/5jc0qtj5v6OE7pz/uRRx4xuc8++2y1jxMRufjii027TZs2IS7m2kb3tZjjTez5a33c5D1O\nxeYi/x7rv/FYKQs/F/i56Rvf+EaIfQmaL7/8MsR+/OkyFEuWLCm4f983fUz1fWtM11Jaueeb2Hvj\nt4tdk2Q9TojYz/+LL74o2Df/GceupZlvrHKPGy/rNbh/jth2/jwlaykjPzZjx9e+ffuG+LjjjjO5\nffbZJ8SffvppwefMi28KAwAAAAAAAEAN4aYwAAAAAAAAANQQbgoDAAAAAAAAQA1p0JrCsdpPeetT\nZq3v4Wt46LpErVq1Kvicvgajrl8kYusw7rfffian68h+85vfNLn77rsvxHvssUfB7fTjRETef//9\nEMfqFzUmWcdNbLtS1XPKWttsp512Mrk77rjDtLt06RJiX7OoZ8+eIfa1iD/44IMQz5gxw+Sy1uiK\n1Qur5rpXIvn+Jpo1a2bauhZQrD5r7D3OOk58u676UbG6RLF97r777iH240bXYZs/f37B54yNm8ai\nFHNNMe9L1u2KyRVT107PU/fff7/JvfTSSyGeN2+eyekx5GtnaXnryFWbvONGy7udp9/XvLWARey5\nTzH1n2P18bLOi8XUpqxmlTRuYs+p+XNiXZtRRKRHjx4h9uc2+rPzdRz1bynk/Z0Hxk1pjlOx5/Sf\nqT5/6Natm8ktXLgwxBtssIHJHXvssaY9YMCAEBdTQ79QP0UYN15Dzjd+3th4441D7Ov9HnTQQSH2\nNTZ322030540aVKI9W/uiIi0bNkyxH7c6vE2ZMgQk9PjdubMmVJIY76W0so938Supfzfvv5NlBYt\nWpic/rx17WERO95ERN55550Q5/0cmW/iGvJ6qpjPrVRi1+ft2rUL8Q033GBy3//+90Mcux9Rjn7z\nTWEAAAAAAAAAqCHcFAYAAAAAAACAGlIx5SOK+Rp0bDu9JMUvJdAlG0455RSTO/LII0O8YMECk9tx\nxx1D3KRJE5PzS970V739/vXX3idMmGByeumKX347fPjwgtvppRONcfn26mQdN6Vash/bh15m4rfb\neeedQ/z444+bXPv27U37888/D7Ff8rRo0aIQd+rUyeT69esX4p///Ocmp8dxMcuGtWJKElQi/flk\nXcasl7uKiLzyyish9svm/d9/IXnnN99n/zz6c42Naf88gwYNCvFzzz1ncg888ECI9bI5kca7rKmQ\nvHNN1s/Q/11m3S7rsrTVPY/eZ+fOnU3uoYceCrEvcbTeeuuF+KmnnjK52bNnh9gfv2JLuPKWP6l0\npRg35ThG+bGgz5f0UksRke7du5v2v/71rxAvWbIk8/4XL14cYj/e9RLevMeoxiTruMn795933Pil\n3rpM2i9+8QuTO/roo01bl1jzS3j1XKGX74rY464+PxKpnXPdrOr7OFXocb7tS4noOWby5Mkm98wz\nz5h2rGxXVrG/hWKWejdW5Z5v/LjR4+HEE080ucsvvzzEvoSjLpvn96evgUVs+UU/b+n+6OsqEZGL\nL744xP7Yd80114R41qxZJldr58QilTXfaOeff75p77333iHWJUJFbOlFEZFf//rXIS6mPFasb8w3\n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\niT0HAAAAAAAAAKAyZCkfca+IfMf928UiMjxN064iMnxlGwAAAAAAAABQ4eosH5Gm6cgkSTZ1/9xD\nRA5cGd8nIiNE5KJidx77+nxW/qvV+mv+EyZMMLlLLrkkxPfff7/J3XjjjSHefPPNTU6Xj/DLX/1S\nc10W4JNPPjG52DI+Levyi7pyseWm1bwkIeu4KWZZi14u4peKbLbZZiH246Zt27Yh/uKLL0zu3Xff\nDfHJJ59scn7JnV5KMGrUKJOLLdvW5SM6d+5scnoJhF8arN8bPxaqeWzE6M/Y/x3rJSL+81+yZEnB\nnObHW9ZlH8Us+Sjmb3yjjTYKca9evUzuyy+/DLFfuqJzXmMdG4VknWtiy7n9UjSdi5UO8fvLuvTK\nL7X2ZZQ0/3cwceLEED/44IMmp8dFqZZFNtbxlPfcJradHke6XISIyDnnnBPiE0880eQmT54cYl8S\nZPz48SH25ydvvvmmaetlmrEx/cYbb5icLifgl/031s8/r1KcE/vPJlY+Rpeq8qVk9Ha69JmIPZce\nPHiwyfnSIk2aNAnxPvvsY3L6nMXPKfp5/NhsrMuy8yr3cSp23uOPYQsWLAjx1KlTTU6XCPFL+z/7\n7DPT3nnnnUP88ssvR/dZSGwOLcfS22pTimup2Husz539Y2PXHf4cNLZE249bXQpSX5+J2Ov1WJmd\n4cOHm5wvS1Cob7VyLdWQ840XKwOgr519eSQ/pnVZkrxzAfNNXN75ptBz+HZsvPlrHV3OwZeI2G67\n7UKsz19E4mVa/bmPPr854ogjTE6fT//5z382uazzTTnk/aG5DmmazhIRWfnfjep4PAAAAAAAAACg\nApT9h+aSJOkjIn3KvR80Lowb5MG4QbEYM8iDcYM8GDfIg3GDPBg3yINxgzwYN9Ut703hOUmSdErT\ndFaSJJ1EZG6hB6ZpOlBEBoqIJEnSONdSoOQYN8iDcYNiMWaQB+MGeTBukAfjBnkwbpAH4wZ5MG6q\nW96bwk+JyGkicu3K/z5Zsh6tlLcWT6y+j67x62u66hppDzzwgMnNmDEjxEcffbTJ+bp7b7/9doiz\n1r2qSzE1e7LmGqtYjdVYPRtdN6ZZs2Ym99BDD4XY16jS+zv++ONNTtdqjdUF9s9TjFg9ndNOOy3E\nkyZNMjld66sxjxNd/0fXDfK1f3R9IV8bWn+OsfqMXtaakMXUCff713OMH7e6XuSee+5pclOmTAnx\n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\nvTFrmVqRtV68j8OpavGUo9TH/MPXSU15iZelpkCVzk1q+l+X6XceLZp21GU65KrXS2lb7+rVq7P7\n8bEwnC4TtkeRpHv37mWPGQp/xvh4ExpzbvpkJiU1hTGesh9u09T+vHPnTmNZuL3b6kpNxcud0ras\n96jQmDMjlT3WxHKnYsavEbbYCo8l0qNTKMOpmBcvXlz4Ol3q5D2qKXc/ps4fUucoXaY+LnpeXGeX\nc0uON8sz5LlNbiuTVLuY+HewuP1auH/aWiItWpaa+svxJv94k9r+cWuPjY2N2f3jx483lj148GB2\nP279GJ6TPnz4MFV2UrjvUq0lUut1+R2M482w5zfhevG5drhsc3OzsSxsoSc1cxzvq9S+63s+PZXj\nzbJzk3r9+P0mXC9uAxseY1LX/Nq2v6drfqG+ueGTwgAAAAAAAAAwIVwUBgAAAAAAAIAJ4aIwAAAA\nAAAAAExI0Z7C0uIeG6meRbdu3WosC3tqxD1kwr53qV6O8bK+PdJWYVX9R3ej3N5isbC3lZTuUxwu\n67teCcva/2PvYbRI3x7bq14vlZu28cK+SPExLezZl9uTqYspHG+WsQ9TfRXjvvfhforX27t37+x+\nlx6LKaXfa6aQGan8sWYZzp4923h86dKlxuMzZ87M7q+vrzeWxf1AQ6mfqe97zW59j8qVykbqvLf0\nOUmM481qeD3epF4z/jsyuX2KdzJm3/F2a25CfX/m+O9ThOedW1tbC9eLe3yG/TH7nmu1rZtaL/e5\nXWrbrblZ9fFmFe9T8d/hOH/+fONx+Hel+p5f8Dt4Wunz23CMnfQpD60im57Ob/ikMAAAAAAAAABM\nCBeFAQAAAAAAAGBC3LSPSE0r7PKR6HB6f5f1wvF28vHwvh/77vvc1DSD3TR1JTc3fV5jiGV9n7uK\nn3c3T3laRm5Kr9f3uV2OBeFUvZT4WDiF403JY02X6fThdMs9e5pv3V3es5Z1zMpdbwqZkcoea7pM\nmU0tC1uUxNO5L1++3Hi8trY2ux+39Oqb95Sp56bL85axPZa1TVf1Xpe73tRzU/rcpsvr7KQtwDKQ\nm+XkJrWtUu1rUuJ2Wbn65mZZ/07Ijd/jTZipOBdhm5Od1LOM4x2/g+/89ZY5xipecyzX/PikMAAA\nAAAAAABMCBeFAQAAAAAAAGBCuCgMAAAAAAAAABNiJXuXmNmfkn6V9LSkO8UGTptqLS9WVfVMobF2\npM7N3/KznyRy4x65aVWqlrFlhveoNHITITdZyE2E3GQhNxFy04pz4jnITStyMwe5aUVu5uB38Fbu\nzm2KXhSeDWr2Y1VVrxYfeA5qGQdv28ZTPZ5q8cbbtvFUj6davPG0bTzVIvmrxxNP28ZTLZK/ejzx\ntG081SL5q8cTT9uGWsbD0/ahlvHwtH2oZRy8bRtP9Xiq5X+0jwAAAAAAAACACeGiMAAAAAAAAABM\nyFAXhT8daNx5qGUcvG0bT/V4qsUbb9vGUz2eavHG07bxVIvkrx5PPG0bT7VI/urxxNO28VSL5K8e\nTzxtG2oZD0/bh1rGw9P2oZZx8LZtPNXjqRZJA/UUBgAAAAAAAAAMg/YRAAAAAAAAADAhRS8Km9lR\nM7tuZptmdqrk2PX4n5vZlpldCb6338zWzexG/fXJQrUcNLPvzOyamV01s/eHrMczcjMbk8x0MGRu\nvGSmHpfcdEBuZuOSmw7IzWxccpOJc5tGLeQmE7lp1EJuMpGbRi3kJhO5adRCbjJxTjwbdzSZKXZR\n2Mwek/SJpLckHZH0jpkdKTV+bU3S0eh7pyRdqKrqsKQL9eMS/pX0YVVVL0t6TdJ79fYYqh6XyE0D\nmcnkIDdr8pEZidxkIzcN5CYTuWkgNxkcZEYiN6NDbh5BbjKQm0eQmwzk5hHkJoOD3KyJzHRXVVWR\nm6TXJX0bPD4t6XSp8YNxD0m6Ejy+LulAff+ApOula6rH/kbSm17q8XIjN2RmrLnxmBlyQ27IDbkh\nN8PfPGSG3IzvRm7IDbkhN+TGx34iN35zQ2a630q2j3he0m/B45v194b2XFVVtyWp/vps6QLM7JCk\nVyR976EeZ8jNHGSmlcfcDL6fyE0rcjMHuWlFbuYgN0keMyM52E/kJoncLEBuksjNAuQmidwsQG6S\nPOZm8H3kPTMlLwrbnO9VBcd3ycyekPSVpA+qqvpr6HocIjcRMpOF3ETITRZyEyE3WchNhNy0IjNz\nkJtW5GYOctOK3MxBblqRmznITStyExlDZkpeFL4p6WDw+AVJvxccf5E/zOyAJNVft0oNbGZ7tR2Q\nL6qq+nroepwiNwEyk81jbjjW+EduAuQmG7kJkJssHjMjkRvvyE2E3GQhNxFyk4XcRMhNFo+5ITMt\nSl4U/kHSYTN7ycwel/S2pHMFx1/knKQT9f0T2u71sXJmZpI+k3StqqqPh67HMXJTIzOdeMwNxxr/\nyE2N3HRCbmrkJpvHzEjkxjtyEyA32chNgNxkIzcBcpPNY27ITJuSDYwlHZO0IekXSR+VbqAs6UtJ\ntyX9o+3/xXhX0lPa/qt/N+qv+wvV8oa2P0r/s6Sf6tuxoerxfCM3ZGZsufGSGXJDbsgNuSE3Pm+c\n25AbckNuyA25P5NPnwAAAHpJREFU8XwjN+RmbLkhM/1uVhcMAAAAAAAAAJiAku0jAAAAAAAAAAAD\n46IwAAAAAAAAAEwIF4UBAAAAAAAAYEK4KAwAAAAAAAAAE8JFYQAAAAAAAACYEC4KAwAAAAAAAMCE\ncFEYAAAAAAAAACaEi8IAAAAAAAAAMCH/AeVk93skCl7nAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#compare original and autoencoded image\n", "fig, axes = plt.subplots(nrows=2, ncols=10, sharex=True, sharey=True, figsize=(25,4))\n", "\n", "for i in range(10):\n", " train_data = ml_repo.get('train_data', full_object = True)\n", " axes[0,i].imshow(np.squeeze(train_data.x_data[i]), cmap='gray')\n", " axes[1,i].imshow(np.squeeze(eval_train.x_data[i]), cmap='gray')\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Copyright\n", "The main parts of the above notebook are taken from the [repository](https://github.com/udacity/deep-learning-v2-pytorch/). The notebook is under the MIT license and we therefore attach the respective license terms of the notebook.\n", "\n", "\n", "MIT License\n", "\n", "Copyright (c) 2018 Udacity\n", "\n", "Permission is hereby granted, free of charge, to any person obtaining a copy\n", "of this software and associated documentation files (the \"Software\"), to deal\n", "in the Software without restriction, including without limitation the rights\n", "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n", "copies of the Software, and to permit persons to whom the Software is\n", "furnished to do so, subject to the following conditions:\n", "\n", "The above copyright notice and this permission notice shall be included in all\n", "copies or substantial portions of the Software.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "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.1" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "209px", "width": "252px" }, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }