├── .gitignore ├── README.md ├── mnist └── __init__.py ├── mnist_conv_autoencode.ipynb ├── mnist_conv_autoencode.py ├── network └── __init__.py ├── requirements.txt └── shape.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | *.np 60 | *.pkl 61 | *.gz -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # convolutional_autoencoder 2 | 3 | The original author is no longer making changes to this repo, but will review/accept pull requests... 4 | 5 | Code for a convolutional autoencoder written on python, theano, lasagne, nolearn 6 | 7 | I highly recommend you use the ipython notebook to run this, if you just need code to read, look at the python file. 8 | 9 | Due to the fact that the newest versions of theano, nolearn and lasagne are sometimes in conflict, it is recommended that you work in a virtualenv (see http://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/). Then you can install a set of modules that are compatible using pip install -r https://github.com/mikesj-public/convolutional_autoencoder/blob/master/requirements.txt 10 | 11 | The newest version of lasagne makes use of cudNN. If you have a decent graphics card you should follow the instructions at https://developer.nvidia.com/cudnn to take advantage of this (the code checks for it). 12 | -------------------------------------------------------------------------------- /mnist/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesj-public/convolutional_autoencoder/a9eaa23b051fde3ed0b1d63dd5959f516e0955b7/mnist/__init__.py -------------------------------------------------------------------------------- /mnist_conv_autoencode.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import os, sys, urllib, gzip\n", 12 | "from __future__ import print_function\n", 13 | "try:\n", 14 | " import cPickle as pickle\n", 15 | "except:\n", 16 | " import pickle\n", 17 | "sys.setrecursionlimit(10000)" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 2, 23 | "metadata": { 24 | "collapsed": false 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "import matplotlib\n", 29 | "matplotlib.use('Agg') # Change matplotlib backend, in case we have no X server running..\n", 30 | "import matplotlib.pyplot as plt\n", 31 | "%matplotlib inline\n", 32 | "import numpy as np\n", 33 | "from IPython.display import Image as IPImage\n", 34 | "from PIL import Image" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 3, 40 | "metadata": { 41 | "collapsed": false 42 | }, 43 | "outputs": [ 44 | { 45 | "name": "stderr", 46 | "output_type": "stream", 47 | "text": [ 48 | "Using gpu device 0: GeForce GTX TITAN X (CNMeM is disabled)\n" 49 | ] 50 | } 51 | ], 52 | "source": [ 53 | "from lasagne.layers import get_output, InputLayer, DenseLayer, Upscale2DLayer, ReshapeLayer\n", 54 | "from lasagne.nonlinearities import rectify, leaky_rectify, tanh\n", 55 | "from lasagne.updates import nesterov_momentum\n", 56 | "from lasagne.objectives import categorical_crossentropy\n", 57 | "from nolearn.lasagne import NeuralNet, BatchIterator, PrintLayerInfo" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 4, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [ 67 | { 68 | "name": "stdout", 69 | "output_type": "stream", 70 | "text": [ 71 | "Using cuda_convnet (faster)\n" 72 | ] 73 | } 74 | ], 75 | "source": [ 76 | "from lasagne.layers import Conv2DLayer as Conv2DLayerSlow\n", 77 | "from lasagne.layers import MaxPool2DLayer as MaxPool2DLayerSlow\n", 78 | "try:\n", 79 | " from lasagne.layers.cuda_convnet import Conv2DCCLayer as Conv2DLayerFast\n", 80 | " from lasagne.layers.cuda_convnet import MaxPool2DCCLayer as MaxPool2DLayerFast\n", 81 | " print('Using cuda_convnet (faster)')\n", 82 | "except ImportError:\n", 83 | " from lasagne.layers import Conv2DLayer as Conv2DLayerFast\n", 84 | " from lasagne.layers import MaxPool2DLayer as MaxPool2DLayerFast\n", 85 | " print('Using lasagne.layers (slower)')" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 5, 91 | "metadata": { 92 | "collapsed": false 93 | }, 94 | "outputs": [], 95 | "source": [ 96 | "fname = 'mnist/mnist.pkl.gz'\n", 97 | "if not os.path.isfile(fname):\n", 98 | " try:\n", 99 | " testfile = urllib.request.URLopener()\n", 100 | " except:\n", 101 | " testfile = urllib.URLopener()\n", 102 | " testfile.retrieve(\"http://deeplearning.net/data/mnist/mnist.pkl.gz\", fname)\n", 103 | "f = gzip.open(fname, 'rb')\n", 104 | "try:\n", 105 | " train_set, valid_set, test_set = pickle.load(f, encoding='latin1')\n", 106 | "except:\n", 107 | " train_set, valid_set, test_set = pickle.load(f)\n", 108 | "f.close()\n", 109 | "X, y = train_set" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 6, 115 | "metadata": { 116 | "collapsed": false 117 | }, 118 | "outputs": [ 119 | { 120 | "name": "stdout", 121 | "output_type": "stream", 122 | "text": [ 123 | "X type and shape: float32 (50000, 1, 28, 28)\n", 124 | "X.min(): 0.0\n", 125 | "X.max(): 0.996094\n" 126 | ] 127 | } 128 | ], 129 | "source": [ 130 | "# reshape from (50000, 784) to 4D tensor (50000, 1, 28, 28)\n", 131 | "X = np.reshape(X, (-1, 1, 28, 28))\n", 132 | "print('X type and shape:', X.dtype, X.shape)\n", 133 | "print('X.min():', X.min())\n", 134 | "print('X.max():', X.max())" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 7, 140 | "metadata": { 141 | "collapsed": false 142 | }, 143 | "outputs": [ 144 | { 145 | "name": "stdout", 146 | "output_type": "stream", 147 | "text": [ 148 | "X_out: float32 (50000, 784)\n" 149 | ] 150 | } 151 | ], 152 | "source": [ 153 | "# we need our target to be 1 dimensional\n", 154 | "X_out = X.reshape((X.shape[0], -1))\n", 155 | "print('X_out:', X_out.dtype, X_out.shape)" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 72, 161 | "metadata": { 162 | "collapsed": false 163 | }, 164 | "outputs": [], 165 | "source": [ 166 | "conv_num_filters = 16\n", 167 | "filter_size = 3\n", 168 | "pool_size = 2\n", 169 | "encode_size = 16\n", 170 | "dense_mid_size = 128\n", 171 | "pad_in = 'valid'\n", 172 | "pad_out = 'full'\n", 173 | "layers = [\n", 174 | " (InputLayer, {'shape': (None, X.shape[1], X.shape[2], X.shape[3])}), \n", 175 | " (Conv2DLayerFast, {'num_filters': conv_num_filters, 'filter_size': filter_size, 'pad': pad_in}),\n", 176 | " (Conv2DLayerFast, {'num_filters': conv_num_filters, 'filter_size': filter_size, 'pad': pad_in}),\n", 177 | " (MaxPool2DLayerFast, {'pool_size': pool_size}),\n", 178 | " (Conv2DLayerFast, {'num_filters': 2*conv_num_filters, 'filter_size': filter_size, 'pad': pad_in}),\n", 179 | " (MaxPool2DLayerFast, {'pool_size': pool_size}),\n", 180 | " (ReshapeLayer, {'shape': (([0], -1))}),\n", 181 | " (DenseLayer, {'num_units': dense_mid_size}),\n", 182 | " (DenseLayer, {'name': 'encode', 'num_units': encode_size}),\n", 183 | " (DenseLayer, {'num_units': dense_mid_size}),\n", 184 | " (DenseLayer, {'num_units': 800}),\n", 185 | " (ReshapeLayer, {'shape': (([0], 2*conv_num_filters, 5, 5))}),\n", 186 | " (Upscale2DLayer, {'scale_factor': pool_size}),\n", 187 | " (Conv2DLayerFast, {'num_filters': conv_num_filters, 'filter_size': filter_size, 'pad': pad_out}),\n", 188 | " (Upscale2DLayer, {'scale_factor': pool_size}),\n", 189 | " (Conv2DLayerSlow, {'num_filters': conv_num_filters, 'filter_size': filter_size, 'pad': pad_out}),\n", 190 | " (Conv2DLayerSlow, {'num_filters': 1, 'filter_size': filter_size, 'pad': pad_out}),\n", 191 | " (ReshapeLayer, {'shape': (([0], -1))}),\n", 192 | "]" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 73, 198 | "metadata": { 199 | "collapsed": false 200 | }, 201 | "outputs": [], 202 | "source": [ 203 | "ae = NeuralNet(\n", 204 | " layers=layers,\n", 205 | " max_epochs=20,\n", 206 | " \n", 207 | " update=nesterov_momentum,\n", 208 | " update_learning_rate=0.01,\n", 209 | " update_momentum=0.975,\n", 210 | " \n", 211 | " regression=True,\n", 212 | " verbose=1\n", 213 | ")\n", 214 | "# ae.initialize()\n", 215 | "# PrintLayerInfo()(ae)" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 74, 221 | "metadata": { 222 | "collapsed": false 223 | }, 224 | "outputs": [ 225 | { 226 | "name": "stdout", 227 | "output_type": "stream", 228 | "text": [ 229 | "# Neural Network with 224177 learnable parameters\n", 230 | "\n", 231 | "## Layer information\n", 232 | "\n", 233 | " # name size\n", 234 | "--- ------------ --------\n", 235 | " 0 input0 1x28x28\n", 236 | " 1 conv2dcc1 16x26x26\n", 237 | " 2 conv2dcc2 16x24x24\n", 238 | " 3 maxpool2dcc3 16x12x12\n", 239 | " 4 conv2dcc4 32x10x10\n", 240 | " 5 maxpool2dcc5 32x5x5\n", 241 | " 6 reshape6 800\n", 242 | " 7 dense7 128\n", 243 | " 8 encode 16\n", 244 | " 9 dense9 128\n", 245 | " 10 dense10 800\n", 246 | " 11 reshape11 32x5x5\n", 247 | " 12 upscale2d12 32x10x10\n", 248 | " 13 conv2dcc13 16x12x12\n", 249 | " 14 upscale2d14 16x24x24\n", 250 | " 15 conv2d15 16x26x26\n", 251 | " 16 conv2d16 1x28x28\n", 252 | " 17 reshape17 784\n", 253 | "\n", 254 | " epoch train loss valid loss train/val dur\n", 255 | "------- ------------ ------------ ----------- -----\n", 256 | " 1 \u001b[36m0.06895\u001b[0m \u001b[32m0.05581\u001b[0m 1.23542 6.37s\n", 257 | " 2 \u001b[36m0.04507\u001b[0m \u001b[32m0.03644\u001b[0m 1.23680 6.30s\n", 258 | " 3 \u001b[36m0.03320\u001b[0m \u001b[32m0.03009\u001b[0m 1.10341 6.36s\n", 259 | " 4 \u001b[36m0.02873\u001b[0m \u001b[32m0.02703\u001b[0m 1.06266 6.36s\n", 260 | " 5 \u001b[36m0.02637\u001b[0m \u001b[32m0.02511\u001b[0m 1.05001 6.30s\n", 261 | " 6 \u001b[36m0.02464\u001b[0m \u001b[32m0.02363\u001b[0m 1.04285 6.37s\n", 262 | " 7 \u001b[36m0.02339\u001b[0m \u001b[32m0.02263\u001b[0m 1.03326 6.37s\n", 263 | " 8 \u001b[36m0.02248\u001b[0m \u001b[32m0.02189\u001b[0m 1.02676 6.31s\n", 264 | " 9 \u001b[36m0.02175\u001b[0m \u001b[32m0.02123\u001b[0m 1.02464 6.36s\n", 265 | " 10 \u001b[36m0.02116\u001b[0m \u001b[32m0.02069\u001b[0m 1.02274 6.42s\n", 266 | " 11 \u001b[36m0.02065\u001b[0m \u001b[32m0.02024\u001b[0m 1.02054 6.33s\n", 267 | " 12 \u001b[36m0.02022\u001b[0m \u001b[32m0.01984\u001b[0m 1.01911 6.35s\n", 268 | " 13 \u001b[36m0.01985\u001b[0m \u001b[32m0.01951\u001b[0m 1.01749 6.28s\n", 269 | " 14 \u001b[36m0.01952\u001b[0m \u001b[32m0.01920\u001b[0m 1.01644 6.37s\n", 270 | " 15 \u001b[36m0.01922\u001b[0m \u001b[32m0.01892\u001b[0m 1.01587 6.38s\n", 271 | " 16 \u001b[36m0.01895\u001b[0m \u001b[32m0.01867\u001b[0m 1.01484 6.30s\n", 272 | " 17 \u001b[36m0.01871\u001b[0m \u001b[32m0.01844\u001b[0m 1.01444 6.37s\n", 273 | " 18 \u001b[36m0.01848\u001b[0m \u001b[32m0.01823\u001b[0m 1.01371 6.39s\n", 274 | " 19 \u001b[36m0.01827\u001b[0m \u001b[32m0.01803\u001b[0m 1.01290 6.29s\n", 275 | " 20 \u001b[36m0.01808\u001b[0m \u001b[32m0.01784\u001b[0m 1.01313 6.36s\n" 276 | ] 277 | }, 278 | { 279 | "data": { 280 | "text/plain": [ 281 | "NeuralNet(X_tensor_type=None,\n", 282 | " batch_iterator_test=,\n", 283 | " batch_iterator_train=,\n", 284 | " custom_score=None,\n", 285 | " layers=[(, {'shape': (None, 1, 28, 28)}), (, {'filter_size': 3, 'pad': 'valid', 'num_filters': 16}), (, {'filter_size': 3, 'pad': 'valid', 'num_filters': 16}...d': 'full', 'num_filters': 1}), (, {'shape': ([0], -1)})],\n", 286 | " loss=None, max_epochs=20, more_params={},\n", 287 | " objective=,\n", 288 | " objective_loss_function=,\n", 289 | " on_epoch_finished=[],\n", 290 | " on_training_finished=[],\n", 291 | " on_training_started=[],\n", 292 | " regression=True,\n", 293 | " train_split=,\n", 294 | " update=,\n", 295 | " update_learning_rate=0.01, update_momentum=0.975,\n", 296 | " use_label_encoder=False, verbose=1,\n", 297 | " y_tensor_type=TensorType(float32, matrix))" 298 | ] 299 | }, 300 | "execution_count": 74, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "ae.fit(X, X_out)" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": 75, 312 | "metadata": { 313 | "collapsed": false 314 | }, 315 | "outputs": [ 316 | { 317 | "data": { 318 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEPCAYAAABcA4N7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xt8VNW99/HPLzcgNwKBBAiEi4AKogQVQVDTRw9FtGJV\nUEQQ6FNtj1hPj/Wx2qro8dTj0aMteoraWsUrFHu01hsonlSrAqKIyk1AuYRLCIHcE3Jbzx97EkJI\nJhPIJJnh+3699mtm7732zMow5Ju11t5rm3MOERGRpkS0dwVERKRjU1CIiIhfCgoREfFLQSEiIn4p\nKERExC8FhYiI+BXUoDCziWa20cw2m9ntTZSZ79u/1swyfNtONrM19ZYCM/tZMOsqIiKNs2BdR2Fm\nkcAm4CJgF/ApMM05t6FemUnAXOfcJDM7B/idc25Mg9eJ8B0/2jm3MyiVFRGRJgWzRTEa2OKc2+ac\nqwQWAZMblLkMWAjgnFsJJJlZaoMyFwFbFRIiIu0jmEGRBtT/5Z7t29Zcmb4NylwDvNTqtRMRkYAE\nMygC7dOypo4zsxjgB8CS1qqUiIi0TFQQX3sX0K/eej+8FoO/Mn1922pdDHzmnMtt7A3MTBNViYgc\nA+dcwz/SmxTMFsVqYIiZDfC1DK4GXm9Q5nVgJoCZjQHynXM59fZPA1729ybOOS2ttNxzzz3tXodw\nWvR56rPsqEtLBa1F4ZyrMrO5wFIgEnjaObfBzG707X/SOfeWmU0ysy1ACTC79ngzi8MbyP5xsOoo\nIiLNC2bXE865t4G3G2x7ssH63CaOLQF6BK92IiISiJC/MrusrL1rED4yMzPbuwphRZ9n69Fn2b6C\ndsFdWzAzt3KlY/To9q6JiEjoMDNcCwazg9r11Ba++AIFhUgHYhbw7x9pA63RGAiLoBCRjiWUeyrC\nSWuFdsiPUSgoRESCK+THKOLiHAUFEBnZ3rUREajr/27vaghN/1u0dIwi5FsUKSmwZUt710JEJHyF\nfFBkZKj7SUTa1k9/+lPuv//+Yzo2MzOTp59+upVrFFwhHxQjRyooRCRwAwYM4P333z+u11iwYAG/\n/vWvj+lYMwu5M8PCIijWrGnvWohIqGhuDKWqqqoNaxMawiIo1KIQkUDMmDGDHTt28IMf/ICEhAQe\nfvhhtm3bRkREBH/605/o378/F110EQBTpkyhd+/eJCUlccEFF7B+/fq615k1axZ33XUXAFlZWfTt\n25dHHnmE1NRU+vTpw7PPPhtQfZxz3H///QwYMIDU1FSuv/56CgsLASgvL+e6666jR48edOvWjdGj\nR7Nv3z4Ann32WU466SQSExMZNGgQL70U3Fv2hHxQ9O0LVVWwd29710REOrrnn3+e9PR03njjDYqK\nivjFL35Rt++DDz5g48aNLF26FIBLLrmELVu2kJuby6hRo5g+fXpd2YbdRzk5ORQWFrJ7926efvpp\nbrrpJgoKCpqtzzPPPMPChQvJysri22+/pbi4mLlzvenvFi5cSGFhIdnZ2Rw4cIAnn3ySLl26UFJS\nwi233MI777xDYWEhn3zyCSNHjmytj6hRIR8UZmpViIQas9ZZWtO8efPo0qULnTp1ArxWQ1xcHNHR\n0dxzzz2sXbuWoqKiuvL1u6+io6O5++67iYyM5OKLLyY+Pp5NmzY1+54vvvgit956KwMGDCAuLo4H\nHniARYsWUV1dTUxMDHl5eWzevBkzIyMjg4SEBAAiIiL46quvKCsrIzU1lWHDhrXuh9FAyAcFaJxC\nJNQ41zpLa+rX7/A91GpqavjlL3/J4MGD6dq1KwMHDgRg//79jR6bnJxMRMThX6exsbEUFxc3+557\n9uyhf//+devp6elUVVWxb98+ZsyYwfe//32uueYa0tLSuP3226mqqiIuLo7FixfzxBNP0KdPHy69\n9NKAQul4hE1QqEUhIoFo6oyj+ttffPFFXn/9dZYvX05BQQHfffcdcGQrojXOXOrTpw/btm2rW9+x\nYwdRUVGkpqYSFRXF3Xffzbp16/j444954403eO655wCYMGECy5YtY+/evZxyyin8+MfBvW1PWASF\nrqUQkUClpqaydetWv2WKi4vp1KkT3bt3p6SkhDvvvPOI/cd6p7iGpk2bxqOPPsq2bdsoLi7mzjvv\n5JprriEiIoKsrCy++uorqqurSUhIIDo6msjISPbt28df//pXSkpKiI6OJi4ujsggT00RFkFx8smQ\nnQ0BtPRE5AR3xx13cP/999OtWzceeeQR4OjWwcyZM+nfvz9paWmcdtppjB079ogyDQezj7V1MWfO\nHGbMmMH555/PoEGDiI2N5bHHHgNg7969TJkyha5duzJs2DAyMzOZMWMGNTU1PProo6SlpZGcnMyH\nH37IggULjun9AxXycz3V1v/ss2H+fBg7tp0rJXKC01xPHYfmempAA9oiIsERNkGhcQoRkeAIm6DQ\nmU8iIsERNmMURUXQqxcUFEBUyN+3TyR0aYyi49AYRQMJCZCWBkG+7kRE5IQTNkEB6n4SEQmGsAoK\nDWiLiLS+sAoKtShERFpf2AXFmjWtP1mYiEhWVtYREweedtppfPDBBwGVbSgiIoJvv/221esYLGF1\nflCvXhAZCbt2efepEBEJlq+//rq9q9BmgtqiMLOJZrbRzDab2e1NlJnv27/WzDLqbU8ys1fMbIOZ\nrTezMc2/n8YpRERaW9CCwswigceBicAwYJqZndqgzCRgsHNuCHADUH9mq98BbznnTgVOBzYE8r4a\npxCRpjz44INMmTLliG233HILt9xyC+DdcW7YsGEkJiZy0kkn8dRTTzX5WgMGDGD58uUAlJWVMWvW\nLLp3787w4cP59NNPA65TQUEBM2fOJCUlhQEDBvDv//7vddc+bNmyhQsuuICkpCR69uzJNddcA3iz\n1/785z8nNTWVrl27cvrpp7Nu3boWfRYtEcyup9HAFufcNgAzWwRM5shf+JcBCwGccyt9rYhUoBw4\nzzl3vW9fFdD8fQXxguKVV1rtZxCRMDJt2jTuu+8+iouLiY+Pp7q6miVLlvDaa68B3hTkb775JgMH\nDuSDDz7g4osv5uyzzyYjI+Oo16o/g+y9997Ld999V3c704kTJwY8o+zNN99MUVER3333Hfv372fC\nhAn07t2bOXPmcNdddzFx4kT+/ve/U1FRwerVqwFYtmwZH374IZs3byYxMZFNmzbRtWvXVvqUjhbM\noEgDdtZbzwbOCaBMX6AayDWzZ4AzgM+AW5xzpc296ciR8KtfHU+1RSTY7N7WuY+pu6dlZ66kp6cz\natQoXn31VWbMmMH7779PbGwso0ePBmDSpEl1Zc8//3wmTJjAhx9+2GhQ1LdkyRIWLFhAUlISSUlJ\n3HLLLdx3333N1qe6uprFixezdu1a4uLiiIuL49Zbb+X5559nzpw5xMTEsG3bNnbt2kVaWhrnnnsu\nADExMRQVFbFhwwbOPvtsTj755BZ9Di0VzKAI9F+w4TfG4dVrFDDXOfepmf0W+CVwd3MvNmQI5OR4\nU3kEMWBF5Di09Bd8a7r22mt5+eWXmTFjBi+99BLTp0+v2/f2229z7733snnzZmpqaigtLeX0009v\n9jV37959xFlO6enpAdVl//79VFZWHnU71F27dgHwn//5n9x1112MHj2abt26ceuttzJ79my+973v\n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\nCBmdatLRAAAAAElFTkSuQmCC\n", 319 | "text/plain": [ 320 | "" 321 | ] 322 | }, 323 | "metadata": {}, 324 | "output_type": "display_data" 325 | } 326 | ], 327 | "source": [ 328 | "from nolearn.lasagne.visualize import plot_loss\n", 329 | "plot_loss(ae)" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 76, 335 | "metadata": { 336 | "collapsed": false 337 | }, 338 | "outputs": [], 339 | "source": [ 340 | "# ae.save_params_to('mnist/conv_ae.np')\n", 341 | "pickle.dump(ae, open('mnist/conv_ae.pkl','wb'))\n", 342 | "# ae = pickle.load(open('mnist/conv_ae.pkl','rb'))\n", 343 | "# ae.layers" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": 77, 349 | "metadata": { 350 | "collapsed": false 351 | }, 352 | "outputs": [ 353 | { 354 | "name": "stdout", 355 | "output_type": "stream", 356 | "text": [ 357 | "(50000, 28, 28) (50000, 1, 28, 28)\n" 358 | ] 359 | } 360 | ], 361 | "source": [ 362 | "X_pred = ae.predict(X).reshape(-1, 28, 28)\n", 363 | "X_pred = np.rint(256. * X_pred).astype(int)\n", 364 | "X_pred = np.clip(X_pred, a_min = 0, a_max = 255)\n", 365 | "X_pred = X_pred.astype('uint8')\n", 366 | "print(X_pred.shape , X.shape)" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": 78, 372 | "metadata": { 373 | "collapsed": false 374 | }, 375 | "outputs": [], 376 | "source": [ 377 | "!mkdir -p data\n", 378 | "!mkdir -p montage" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": 79, 384 | "metadata": { 385 | "collapsed": false 386 | }, 387 | "outputs": [ 388 | { 389 | "name": "stdout", 390 | "output_type": "stream", 391 | "text": [ 392 | "2\n" 393 | ] 394 | }, 395 | { 396 | "data": { 397 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOAAAABwCAAAAAAiICN+AAADfElEQVR4nO3ay4tcVRDH8c/EyWMM\nMRpjNCZGfBEfZHDjImKMMSAiuHSluMvK/8CtO/EPcCGCoEshunEhLkTUxAcKasCJRsyDGKMmUToT\nzWi7qAtOd9/c6b5eR+5NfWE4M6dP1e3qmh+nTp0mSZIkSZIkSZIkSZIkWW6mmnb4MF7Dbsw17bwG\nK/7vN/BfkwG2nenhiV24FvtrOrwPn9Swux0P4nxh/82YdrO4FT0cwG9Dr3c+gxlg2xnR4EO4Qz0N\nTuEWbDP5Bns/7hXa601gtxv34FucxJdDr3c+gxlg2xnR4NP4sKazzdiHV/H1BHZ34m5ch/eFlsZh\nj9i3b8QJHCtZ0/kMZoBtZ0SD/ybil4rx8IR2N+N6LOCnCex2YStOi/3vXMmazmcwA2w7AxrcIbRQ\nl/XF+PYENiuwCTeIs9zvY9o9LvbOtfgAH1f47zQZYNsZ0OBjmKnpaJM4CxJ14bhsxE24UpwD+2PY\nrBO9mLU4jkPFWEbnM5gBtp0BDW4vxq9qOHpB7KFzRnuTVdxVPPcqnMLqMWz2iL4P5X2YxXQ+gxlg\n2xk5D3Lpum6YdXgUT+GRYu455eeyMlaLe4VtYh88L/bhDfilWLPZPz2a9eLuY0fxex+/4mzFMzqf\nwQyw7ZRqcMPQ37Pik9greiCr8GQxN4+D4hw3jU8nePgMtoiasoc/hbYeEPq8TdS3nwud9Yv128We\nu1L0cU5XPKPzGcwA286ABufF//mLeHbR/Ky471sQe9UhvCzu0t8VNeRxoalJ7iTO4gexz12NP4S+\nt+AKXFOMF4v5vqhZtwrdrsJfOFPxjM5nMANsOwMafAbfi/vyxRzFG0J7B0uc7BN3e0dqvIF3hL43\ninPoF0JjJ4XGesV7IrQ5I3S3ppir0h+XQQYzwLYzUos+X8PJ3mJ8vYbtd3hT7G+HF82VcQIfYafo\nw87jxyX8dz6DGWDbKT0P1mV/TbtTxc84fCZ0tyD6Nkvdg3Q+gxlg22lUg8vFnOiPHsPPS6ztfAYz\nwLbTmAanxHe9DzTlsIJp0ac5J3qpVXQ+gxlg22lMg33L92mtFL2aC6I/WkXnM5gBtp1Ga9GdeKVJ\nh5fgojg/9sRdSRWdz2AG2HYarUWXgzWiBj0i7iSPLrG+8xnMANtOIxp8C0804WgMLuA9UY+eUf09\nNS6DDGaASZIkSZIkSZLU429VA486ufvJswAAAABJRU5ErkJggg==\n", 398 | "text/plain": [ 399 | "" 400 | ] 401 | }, 402 | "execution_count": 79, 403 | "metadata": {}, 404 | "output_type": "execute_result" 405 | } 406 | ], 407 | "source": [ 408 | "### show random inputs / outputs side by side\n", 409 | "\n", 410 | "def get_picture_array(X, rescale=4):\n", 411 | " array = X.reshape(28,28)\n", 412 | " array = np.clip(array, a_min = 0, a_max = 255)\n", 413 | " return array.repeat(rescale, axis = 0).repeat(rescale, axis = 1).astype(np.uint8())\n", 414 | "\n", 415 | "def compare_images(index):\n", 416 | " print(index)\n", 417 | " original_image = Image.fromarray(get_picture_array(255 * X[index]))\n", 418 | " new_size = (original_image.size[0] * 2, original_image.size[1])\n", 419 | " new_im = Image.new('L', new_size)\n", 420 | " new_im.paste(original_image, (0,0))\n", 421 | " rec_image = Image.fromarray(get_picture_array(X_pred[index]))\n", 422 | " new_im.paste(rec_image, (original_image.size[0],0))\n", 423 | " new_im.save('data/test.png', format=\"PNG\")\n", 424 | " return IPImage('data/test.png')\n", 425 | "\n", 426 | "compare_images(2)\n", 427 | "# compare_images(np.random.randint(50000))" 428 | ] 429 | }, 430 | { 431 | "cell_type": "code", 432 | "execution_count": 82, 433 | "metadata": { 434 | "collapsed": false 435 | }, 436 | "outputs": [], 437 | "source": [ 438 | "## we find the encode layer from our ae, and use it to define an encoding function\n", 439 | "\n", 440 | "def get_layer_by_name(net, name):\n", 441 | " for i, layer in enumerate(net.get_all_layers()):\n", 442 | " if layer.name == name:\n", 443 | " return layer, i\n", 444 | " return None, None\n", 445 | "encode_layer, encode_layer_index = get_layer_by_name(ae, 'encode')\n", 446 | "\n", 447 | "def encode_input(encode_layer, X):\n", 448 | " return get_output(encode_layer, inputs=X).eval()\n", 449 | "\n", 450 | "X_encoded = encode_input(encode_layer, X)" 451 | ] 452 | }, 453 | { 454 | "cell_type": "code", 455 | "execution_count": 83, 456 | "metadata": { 457 | "collapsed": false 458 | }, 459 | "outputs": [], 460 | "source": [ 461 | "next_layer = ae.get_all_layers()[encode_layer_index + 1]\n", 462 | "final_layer = ae.get_all_layers()[-1]\n", 463 | "new_layer = InputLayer(shape=(None, encode_layer.num_units))\n", 464 | "\n", 465 | "# N.B after we do this, we won't be able to use the original autoencoder , as the layers are broken up\n", 466 | "next_layer.input_layer = new_layer" 467 | ] 468 | }, 469 | { 470 | "cell_type": "code", 471 | "execution_count": 84, 472 | "metadata": { 473 | "collapsed": false 474 | }, 475 | "outputs": [ 476 | { 477 | "name": "stdout", 478 | "output_type": "stream", 479 | "text": [ 480 | "(1, 784)\n" 481 | ] 482 | }, 483 | { 484 | "data": { 485 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAACHUlEQVR4nO3ZSWtUQRSG4ceY0eBI\nHBMjDhAHFDcuFKPkB/hn3btURAUFh4UjGkOMUZMoHYfEtItzwRA6t7sJ5KYr9W7upepwTvN9VNW5\n1WQymUwmk8lkMtWzY72JM7iBRTzC6xYTXsIp1HAfP9bMd7X/GzdG+gW715u4hsvCu1obCW/iAt5g\nGs/WzKcv6dbw8CzO4yDuCi9aYQLjOIYpTDaISV/SreHhCRzGMr60kWwcI5gV62+hQUz6klbvYRcO\n4Yg4y363mOiWWLuDuIeH68SlL2n1Hg7hOHaJc7DeQpLdopcZxEe8KJ6NSF/S6j08hzHswQz6Wkgy\ngdHivVEfs5r0Ja3Wwz7xXTAq1uEiBnAA34qYo/73OHtxBReL9zq+Y76kYPqSVuvhAIbFnljDX+HN\ndeHvaZzEE+FTvYgfEz1Qj+iDZksKpi9ptR7O45NYZ/vwB73Cp53YXzyXivG62HNHhO+9WMFcScH0\nJa3+PLwjLm+G8BxPhUfTwqMa3hexw2LtrqC/GCvzj+0gafUevsNtsb5erRprxBQe4Kr4HvmJz00K\npi9p9R4S/ehMiwkeC9+WRd8z1SQ+fUm3hoft8lL0p5P42iQ2fUk708Nu0ecsiF62jPQl7UwPe0Sv\n80v0p2WkL2lnergkzs+auBcoI31JO8/DfrGHvhV3pB+axKcv6aYXXPd//HYYEfvpnPJ7NraDpJte\nMJPJZDIb5x/4kV8I1LXQnAAAAABJRU5ErkJggg==\n", 486 | "text/plain": [ 487 | "" 488 | ] 489 | }, 490 | "execution_count": 84, 491 | "metadata": {}, 492 | "output_type": "execute_result" 493 | } 494 | ], 495 | "source": [ 496 | "def get_output_from_nn(last_layer, X):\n", 497 | " return get_output(last_layer,X).eval()\n", 498 | "\n", 499 | "def decode_encoded_input(X):\n", 500 | " return get_output_from_nn(final_layer, X)\n", 501 | "\n", 502 | "X_decoded = 256 * decode_encoded_input(X_encoded[2])\n", 503 | "\n", 504 | "X_decoded = np.rint(X_decoded).astype(int)\n", 505 | "X_decoded = np.clip(X_decoded, a_min = 0, a_max = 255)\n", 506 | "X_decoded = X_decoded.astype('uint8')\n", 507 | "print(X_decoded.shape)\n", 508 | "\n", 509 | "pic_array = get_picture_array(X_decoded)\n", 510 | "image = Image.fromarray(pic_array)\n", 511 | "image.save('data/test.png', format=\"PNG\") \n", 512 | "IPImage('data/test.png')" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "execution_count": 85, 518 | "metadata": { 519 | "collapsed": false 520 | }, 521 | "outputs": [], 522 | "source": [ 523 | "enc_std = X_encoded.std(axis=0)\n", 524 | "enc_mean = X_encoded.mean(axis=0)\n", 525 | "enc_min = X_encoded.min(axis=0)\n", 526 | "enc_max = X_encoded.max(axis=0)\n", 527 | "m = X_encoded.shape[1]" 528 | ] 529 | }, 530 | { 531 | "cell_type": "code", 532 | "execution_count": 89, 533 | "metadata": { 534 | "collapsed": false 535 | }, 536 | "outputs": [], 537 | "source": [ 538 | "n = 256\n", 539 | "generated = np.random.normal(0, 1, (n, m)) * enc_std + enc_mean\n", 540 | "generated = generated.astype(np.float32).clip(enc_min, enc_max)\n", 541 | "X_decoded = decode_encoded_input(generated) * 256.\n", 542 | "X_decoded = np.rint(X_decoded ).astype(int)\n", 543 | "X_decoded = np.clip(X_decoded, a_min = 0, a_max = 255)\n", 544 | "X_decoded = X_decoded.astype('uint8')\n", 545 | "!mkdir -p montage\n", 546 | "for i in range(n):\n", 547 | " pic_array = get_picture_array(X_decoded[i], rescale=1)\n", 548 | " image = Image.fromarray(pic_array)\n", 549 | " image.save('montage/{0:03d}.png'.format(i), format='png')" 550 | ] 551 | }, 552 | { 553 | "cell_type": "code", 554 | "execution_count": 90, 555 | "metadata": { 556 | "collapsed": false 557 | }, 558 | "outputs": [ 559 | { 560 | "data": { 561 | "image/png": "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\ngg==\n", 562 | "text/plain": [ 563 | "" 564 | ] 565 | }, 566 | "execution_count": 90, 567 | "metadata": {}, 568 | "output_type": "execute_result" 569 | } 570 | ], 571 | "source": [ 572 | "!montage -mode concatenate -tile 16x montage/*.png montage.png\n", 573 | "IPImage('montage.png')" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": null, 579 | "metadata": { 580 | "collapsed": true 581 | }, 582 | "outputs": [], 583 | "source": [] 584 | } 585 | ], 586 | "metadata": { 587 | "kernelspec": { 588 | "display_name": "Python 2", 589 | "language": "python", 590 | "name": "python2" 591 | }, 592 | "language_info": { 593 | "codemirror_mode": { 594 | "name": "ipython", 595 | "version": 2 596 | }, 597 | "file_extension": ".py", 598 | "mimetype": "text/x-python", 599 | "name": "python", 600 | "nbconvert_exporter": "python", 601 | "pygments_lexer": "ipython2", 602 | "version": "2.7.6" 603 | } 604 | }, 605 | "nbformat": 4, 606 | "nbformat_minor": 0 607 | } 608 | -------------------------------------------------------------------------------- /mnist_conv_autoencode.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3.0 3 | 4 | # 5 | 6 | # add to kfkd.py 7 | from lasagne import layers 8 | from lasagne.updates import nesterov_momentum 9 | from nolearn.lasagne import NeuralNet 10 | import numpy as np 11 | import theano.tensor as T 12 | from nolearn.lasagne import BatchIterator 13 | from theano.sandbox.neighbours import neibs2images 14 | from lasagne.objectives import squared_error 15 | 16 | ### this is really dumb, current nolearn doesnt play well with lasagne, 17 | ### so had to manually copy the file I wanted to this folder 18 | from shape import ReshapeLayer 19 | 20 | from lasagne.nonlinearities import tanh 21 | import pickle 22 | import sys 23 | from sklearn.metrics import mean_squared_error as mse 24 | from sklearn.metrics import precision_score 25 | import os 26 | import urllib 27 | import gzip 28 | import cPickle 29 | from IPython.display import Image as IPImage 30 | from PIL import Image 31 | 32 | 33 | # 34 | 35 | class Unpool2DLayer(layers.Layer): 36 | """ 37 | This layer performs unpooling over the last two dimensions 38 | of a 4D tensor. 39 | """ 40 | def __init__(self, incoming, ds, **kwargs): 41 | 42 | super(Unpool2DLayer, self).__init__(incoming, **kwargs) 43 | 44 | if (isinstance(ds, int)): 45 | ds = (ds, ds) 46 | else: 47 | ds = tuple(ds) 48 | if len(ds) != 2: 49 | raise ValueError('ds must be an int or pair of int') 50 | self.ds = ds 51 | 52 | def get_output_shape_for(self, input_shape): 53 | output_shape = list(input_shape) 54 | 55 | output_shape[2] = input_shape[2] * self.ds[0] 56 | output_shape[3] = input_shape[3] * self.ds[1] 57 | 58 | return tuple(output_shape) 59 | 60 | def get_output_for(self, input, **kwargs): 61 | ds = self.ds 62 | input_shape = input.shape 63 | output_shape = self.get_output_shape_for(input_shape) 64 | return input.repeat(ds[0], axis=2).repeat(ds[1], axis=3) 65 | 66 | 67 | # 68 | 69 | ### when we load the batches to input to the neural network, we randomly / flip 70 | ### rotate the images, to artificially increase the size of the training set 71 | 72 | class FlipBatchIterator(BatchIterator): 73 | 74 | def transform(self, X1, X2): 75 | X1b, X2b = super(FlipBatchIterator, self).transform(X1, X2) 76 | X2b = X2b.reshape(X1b.shape) 77 | 78 | bs = X1b.shape[0] 79 | h_indices = np.random.choice(bs, bs / 2, replace=False) # horizontal flip 80 | v_indices = np.random.choice(bs, bs / 2, replace=False) # vertical flip 81 | 82 | ### uncomment these lines if you want to include rotations (images must be square) ### 83 | #r_indices = np.random.choice(bs, bs / 2, replace=False) # 90 degree rotation 84 | for X in (X1b, X2b): 85 | X[h_indices] = X[h_indices, :, :, ::-1] 86 | X[v_indices] = X[v_indices, :, ::-1, :] 87 | #X[r_indices] = np.swapaxes(X[r_indices, :, :, :], 2, 3) 88 | shape = X2b.shape 89 | X2b = X2b.reshape((shape[0], -1)) 90 | 91 | return X1b, X2b 92 | 93 | # 94 | 95 | fname = 'mnist/mnist.pkl.gz' 96 | if not os.path.isfile(fname): 97 | testfile = urllib.URLopener() 98 | testfile.retrieve("http://deeplearning.net/data/mnist/mnist.pkl.gz", fname) 99 | f = gzip.open(fname, 'rb') 100 | train_set, valid_set, test_set = cPickle.load(f) 101 | f.close() 102 | X, y = train_set 103 | X = np.rint(X * 256).astype(np.int).reshape((-1, 1, 28, 28)) # convert to (0,255) int range (we'll do our own scaling) 104 | mu, sigma = np.mean(X.flatten()), np.std(X.flatten()) 105 | 106 | # 107 | 108 | X_train = X.astype(np.float64) 109 | X_train = (X_train - mu) / sigma 110 | X_train = X_train.astype(np.float32) 111 | 112 | # we need our target to be 1 dimensional 113 | X_out = X_train.reshape((X_train.shape[0], -1)) 114 | 115 | # 116 | 117 | conv_filters = 32 118 | deconv_filters = 32 119 | filter_sizes = 7 120 | epochs = 20 121 | encode_size = 40 122 | ae = NeuralNet( 123 | layers=[ 124 | ('input', layers.InputLayer), 125 | ('conv', layers.Conv2DLayer), 126 | ('pool', layers.MaxPool2DLayer), 127 | ('flatten', ReshapeLayer), # output_dense 128 | ('encode_layer', layers.DenseLayer), 129 | ('hidden', layers.DenseLayer), # output_dense 130 | ('unflatten', ReshapeLayer), 131 | ('unpool', Unpool2DLayer), 132 | ('deconv', layers.Conv2DLayer), 133 | ('output_layer', ReshapeLayer), 134 | ], 135 | input_shape=(None, 1, 28, 28), 136 | conv_num_filters=conv_filters, conv_filter_size = (filter_sizes, filter_sizes), 137 | # conv_border_mode="valid", removed from latest version 138 | conv_nonlinearity=None, 139 | pool_pool_size=(2, 2), 140 | flatten_shape=(([0], -1)), # not sure if necessary? 141 | encode_layer_num_units = encode_size, 142 | hidden_num_units= deconv_filters * (28 + filter_sizes - 1) ** 2 / 4, 143 | unflatten_shape=(([0], deconv_filters, (28 + filter_sizes - 1) / 2, (28 + filter_sizes - 1) / 2 )), 144 | unpool_ds=(2, 2), 145 | deconv_num_filters=1, deconv_filter_size = (filter_sizes, filter_sizes), 146 | # deconv_border_mode="valid", 147 | deconv_nonlinearity=None, 148 | output_layer_shape = (([0], -1)), 149 | update_learning_rate = 0.01, 150 | update_momentum = 0.975, 151 | batch_iterator_train=FlipBatchIterator(batch_size=128), 152 | regression=True, 153 | max_epochs= epochs, 154 | verbose=1, 155 | ) 156 | ae.fit(X_train, X_out) 157 | print 158 | ### expect training / val error of about 0.087 with these parameters 159 | ### if your GPU not fast enough, reduce the number of filters in the conv/deconv step 160 | 161 | # 162 | 163 | import pickle 164 | import sys 165 | sys.setrecursionlimit(10000) 166 | 167 | pickle.dump(ae, open('mnist/conv_ae.pkl','w')) 168 | #ae = pickle.load(open('mnist/conv_ae.pkl','r')) 169 | ae.save_weights_to('mnist/conv_ae.np') 170 | 171 | # 172 | 173 | X_train_pred = ae.predict(X_train).reshape(-1, 28, 28) * sigma + mu 174 | X_pred = np.rint(X_train_pred).astype(int) 175 | X_pred = np.clip(X_pred, a_min = 0, a_max = 255) 176 | X_pred = X_pred.astype('uint8') 177 | print X_pred.shape , X.shape 178 | 179 | # 180 | 181 | ### show random inputs / outputs side by side 182 | 183 | def get_picture_array(X, index): 184 | array = X[index].reshape(28,28) 185 | array = np.clip(array, a_min = 0, a_max = 255) 186 | return array.repeat(4, axis = 0).repeat(4, axis = 1).astype(np.uint8()) 187 | 188 | def get_random_images(): 189 | index = np.random.randint(5000) 190 | print index 191 | original_image = Image.fromarray(get_picture_array(X, index)) 192 | new_size = (original_image.size[0] * 2, original_image.size[1]) 193 | new_im = Image.new('L', new_size) 194 | new_im.paste(original_image, (0,0)) 195 | rec_image = Image.fromarray(get_picture_array(X_pred, index)) 196 | new_im.paste(rec_image, (original_image.size[0],0)) 197 | new_im.save('data/test.png', format="PNG") 198 | 199 | get_random_images() 200 | IPImage('data/test.png') 201 | 202 | # 203 | 204 | ## we find the encode layer from our ae, and use it to define an encoding function 205 | 206 | encode_layer_index = map(lambda pair : pair[0], ae.layers).index('encode_layer') 207 | encode_layer = ae.get_all_layers()[encode_layer_index] 208 | 209 | def get_output_from_nn(last_layer, X): 210 | indices = np.arange(128, X.shape[0], 128) 211 | sys.stdout.flush() 212 | 213 | # not splitting into batches can cause a memory error 214 | X_batches = np.split(X, indices) 215 | out = [] 216 | for count, X_batch in enumerate(X_batches): 217 | out.append(layers.helper.get_output(last_layer, X_batch).eval()) 218 | sys.stdout.flush() 219 | return np.vstack(out) 220 | 221 | 222 | def encode_input(X): 223 | return get_output_from_nn(encode_layer, X) 224 | 225 | X_encoded = encode_input(X_train) 226 | 227 | # 228 | 229 | next_layer = ae.get_all_layers()[encode_layer_index + 1] 230 | final_layer = ae.get_all_layers()[-1] 231 | new_layer = layers.InputLayer(shape = (None, encode_layer.num_units)) 232 | 233 | # N.B after we do this, we won't be able to use the original autoencoder , as the layers are broken up 234 | next_layer.input_layer = new_layer 235 | 236 | def decode_encoded_input(X): 237 | return get_output_from_nn(final_layer, X) 238 | 239 | X_decoded = decode_encoded_input(X_encoded) * sigma + mu 240 | 241 | X_decoded = np.rint(X_decoded ).astype(int) 242 | X_decoded = np.clip(X_decoded, a_min = 0, a_max = 255) 243 | X_decoded = X_decoded.astype('uint8') 244 | print X_decoded.shape 245 | 246 | ### check it worked : 247 | 248 | pic_array = get_picture_array(X_decoded, np.random.randint(len(X_decoded))) 249 | image = Image.fromarray(pic_array) 250 | image.save('data/test.png', format="PNG") 251 | IPImage('data/test.png') 252 | 253 | # 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /network/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesj-public/convolutional_autoencoder/a9eaa23b051fde3ed0b1d63dd5959f516e0955b7/network/__init__.py -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | funcsigs==0.4 2 | joblib==0.8.4 3 | Lasagne==0.2.dev1 4 | matplotlib==1.4.3 5 | mock==1.3.0 6 | nolearn==0.6a0.dev0 7 | nose==1.3.7 8 | numpy==1.9.3 9 | pbr==1.8.0 10 | pyparsing==2.0.3 11 | python-dateutil==2.4.2 12 | pytz==2015.6 13 | scikit-learn==0.16.1 14 | scipy==0.16.0 15 | six==1.9.0 16 | tabulate==0.7.5 17 | Theano==0.7.0 18 | -------------------------------------------------------------------------------- /shape.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from lasagne.theano_extensions import padding 4 | 5 | from lasagne.layers import Layer 6 | 7 | 8 | __all__ = [ 9 | "FlattenLayer", 10 | "flatten", 11 | "ReshapeLayer", 12 | "reshape", 13 | "DimshuffleLayer", 14 | "dimshuffle", 15 | "PadLayer", 16 | "pad", 17 | ] 18 | 19 | 20 | class FlattenLayer(Layer): 21 | def get_output_shape_for(self, input_shape): 22 | return (input_shape[0], int(np.prod(input_shape[1:]))) 23 | 24 | def get_output_for(self, input, **kwargs): 25 | return input.flatten(2) 26 | 27 | flatten = FlattenLayer # shortcut 28 | 29 | 30 | class ReshapeLayer(Layer): 31 | """ 32 | A layer reshaping its input tensor to another tensor of the same total 33 | number of elements. 34 | 35 | :parameters: 36 | - incoming : a :class:`Layer` instance or a tuple 37 | the layer feeding into this layer, or the expected input shape 38 | 39 | - shape : tuple 40 | The target shape specification. Any of its elements can be `[i]`, 41 | a single-element list of int, denoting to use the size of the ith 42 | input dimension. At most one element can be `-1`, denoting to 43 | infer the size for this dimension to match the total number of 44 | elements of the input tensor. Any remaining elements must be 45 | positive integers directly giving the size of the corresponding 46 | dimension. 47 | 48 | :usage: 49 | >>> from lasagne.layers import InputLayer, ReshapeLayer 50 | >>> l_in = InputLayer((None, 100, 20)) 51 | >>> l1 = ReshapeLayer(l_in, ([0], [1], 2, 10)) 52 | >>> l1.get_output_shape() 53 | (None, 100, 2, 10) 54 | >>> l2 = ReshapeLayer(l_in, ([0], 1, 2, 5, -1)) 55 | >>> l2.get_output_shape() 56 | (None, 1, 2, 5, 200) 57 | 58 | :note: 59 | The tensor elements will be fetched and placed in C-like order. That 60 | is, reshaping `[1,2,3,4,5,6]` to shape `(2,3)` will result in a matrix 61 | `[[1,2,3],[4,5,6]]`, not in `[[1,3,5],[2,4,6]]` (Fortran-like order), 62 | regardless of the memory layout of the input tensor. For C-contiguous 63 | input, reshaping is cheap, for others it may require copying the data. 64 | """ 65 | 66 | def __init__(self, incoming, shape, **kwargs): 67 | super(ReshapeLayer, self).__init__(incoming, **kwargs) 68 | shape = tuple(shape) 69 | for s in shape: 70 | if isinstance(s, int): 71 | if s == 0 or s < - 1: 72 | raise ValueError("`shape` integers must be positive or -1") 73 | elif isinstance(s, list): 74 | if len(s) != 1 or not isinstance(s[0], int) or s[0] < 0: 75 | raise ValueError("`shape` input references must be " 76 | "single-element lists of int >= 0") 77 | else: 78 | raise ValueError("`shape` must be a tuple of int and/or [int]") 79 | if sum(s == -1 for s in shape) > 1: 80 | raise ValueError("`shape` cannot contain multiple -1") 81 | self.shape = shape 82 | 83 | def get_output_shape_for(self, input_shape, **kwargs): 84 | # Initialize output shape from shape specification 85 | output_shape = list(self.shape) 86 | # First, replace all `[i]` with the corresponding input dimension, and 87 | # mask parts of the shapes thus becoming irrelevant for -1 inference 88 | masked_input_shape = list(input_shape) 89 | masked_output_shape = list(output_shape) 90 | for dim, o in enumerate(output_shape): 91 | if isinstance(o, list): 92 | if o[0] >= len(input_shape): 93 | raise ValueError("specification contains [%d], but input " 94 | "shape has %d dimensions only" % 95 | (o[0], len(input_shape))) 96 | output_shape[dim] = input_shape[o[0]] 97 | masked_output_shape[dim] = input_shape[o[0]] 98 | if (input_shape[o[0]] is None) \ 99 | and (masked_input_shape[o[0]] is None): 100 | # first time we copied this unknown input size: mask 101 | # it, we have a 1:1 correspondence between out[dim] and 102 | # in[o[0]] and can ignore it for -1 inference even if 103 | # it is unknown. 104 | masked_input_shape[o[0]] = 1 105 | masked_output_shape[dim] = 1 106 | # From the shapes, compute the sizes of the input and output tensor 107 | input_size = (None if any(x is None for x in masked_input_shape) 108 | else np.prod(masked_input_shape)) 109 | output_size = (None if any(x is None for x in masked_output_shape) 110 | else np.prod(masked_output_shape)) 111 | del masked_input_shape, masked_output_shape 112 | # Finally, infer value for -1 if needed 113 | if -1 in output_shape: 114 | dim = output_shape.index(-1) 115 | if (input_size is None) or (output_size is None): 116 | output_shape[dim] = None 117 | output_size = None 118 | else: 119 | output_size *= -1 120 | output_shape[dim] = input_size // output_size 121 | output_size *= output_shape[dim] 122 | # Sanity check 123 | if (input_size is not None) and (output_size is not None) \ 124 | and (input_size != output_size): 125 | raise ValueError("%s cannot be reshaped to specification %s. " 126 | "The total size mismatches." % 127 | (input_shape, self.shape)) 128 | return tuple(output_shape) 129 | 130 | def get_output_for(self, input, **kwargs): 131 | # Replace all `[i]` with the corresponding input dimension 132 | output_shape = list(self.shape) 133 | for dim, o in enumerate(output_shape): 134 | if isinstance(o, list): 135 | output_shape[dim] = input.shape[o[0]] 136 | # Everything else is handled by Theano 137 | return input.reshape(tuple(output_shape)) 138 | 139 | reshape = ReshapeLayer # shortcut 140 | 141 | 142 | class DimshuffleLayer(Layer): 143 | """ 144 | A layer that rearranges the dimension of its input tensor, maintaining 145 | the same same total number of elements. 146 | 147 | :parameters: 148 | - incoming : a :class:`Layer` instance or a tuple 149 | the layer feeding into this layer, or the expected input shape 150 | 151 | - pattern : tuple 152 | The new dimension order, with each element giving the index 153 | of the dimension in the input tensor or `'x'` to broadcast it. 154 | For example `(3,2,1,0)` will reverse the order of a 4-dimensional 155 | tensor. Use `'x'` to broadcast, e.g. `(3,2,1,'x',0)` will 156 | take a 4 tensor of shape `(2,3,5,7)` as input and produce a 157 | tensor of shape `(7,5,3,1,2)` with the 4th dimension being 158 | broadcast-able. In general, all dimensions in the input tensor 159 | must be used to generate the output tensor. Omitting a dimension 160 | attempts to collapse it; this can only be done to broadcast-able 161 | dimensions, e.g. a 5-tensor of shape `(7,5,3,1,2)` with the 4th 162 | being broadcast-able can be shuffled with the pattern `(4,2,1,0)` 163 | collapsing the 4th dimension resulting in a tensor of shape 164 | `(2,3,5,7)`. 165 | 166 | :usage: 167 | >>> from lasagne.layers import InputLayer, DimshuffleLayer 168 | >>> l_in = InputLayer((2, 3, 5, 7)) 169 | >>> l1 = DimshuffleLayer(l_in, (3, 2, 1, 'x', 0)) 170 | >>> l1.get_output_shape() 171 | (7, 5, 3, 1, 2) 172 | >>> l2 = DimshuffleLayer(l1, (4, 2, 1, 0)) 173 | >>> l2.get_output_shape() 174 | (2, 3, 5, 7) 175 | """ 176 | def __init__(self, incoming, pattern, **kwargs): 177 | super(DimshuffleLayer, self).__init__(incoming, **kwargs) 178 | 179 | # Sanity check the pattern 180 | used_dims = set() 181 | for p in pattern: 182 | if isinstance(p, int): 183 | # Dimension p 184 | if p in used_dims: 185 | raise ValueError("pattern contains dimension {0} more " 186 | "than once".format(p)) 187 | used_dims.add(p) 188 | elif p == 'x': 189 | # Broadcast 190 | pass 191 | else: 192 | raise ValueError("pattern should only contain dimension" 193 | "indices or 'x', not {0}".format(p)) 194 | 195 | self.pattern = pattern 196 | 197 | def get_output_shape_for(self, input_shape): 198 | # Build output shape while keeping track of the dimensions that we are 199 | # attempting to collapse, so we can ensure that they are broadcastable 200 | output_shape = [] 201 | dims_used = [False] * len(input_shape) 202 | for p in self.pattern: 203 | if isinstance(p, int): 204 | if p < 0 or p >= len(input_shape): 205 | raise ValueError("pattern contains {0}, but input shape " 206 | "has {1} dimensions " 207 | "only".format(p, len(input_shape))) 208 | # Dimension p 209 | o = input_shape[p] 210 | dims_used[p] = True 211 | elif p == 'x': 212 | # Broadcast; will be of size 1 213 | o = 1 214 | else: 215 | raise RuntimeError("invalid pattern entry, should have " 216 | "caught in the constructor") 217 | output_shape.append(o) 218 | 219 | for i, (dim_size, used) in enumerate(zip(input_shape, dims_used)): 220 | if not used and dim_size != 1 and dim_size is not None: 221 | raise ValueError( 222 | "pattern attempted to collapse dimension " 223 | "{0} of size {1}; dimensions with size != 1/None are not" 224 | "broadcastable and cannot be " 225 | "collapsed".format(i, dim_size)) 226 | 227 | return tuple(output_shape) 228 | 229 | def get_output_for(self, input, **kwargs): 230 | return input.dimshuffle(self.pattern) 231 | 232 | dimshuffle = DimshuffleLayer # shortcut 233 | 234 | 235 | class PadLayer(Layer): 236 | def __init__(self, incoming, width, val=0, batch_ndim=2, **kwargs): 237 | super(PadLayer, self).__init__(incoming, **kwargs) 238 | self.width = width 239 | self.val = val 240 | self.batch_ndim = batch_ndim 241 | 242 | def get_output_shape_for(self, input_shape): 243 | output_shape = () 244 | for k, s in enumerate(input_shape): 245 | if k < self.batch_ndim: 246 | output_shape += (s,) 247 | else: 248 | output_shape += (s + 2 * self.width,) 249 | 250 | return output_shape 251 | 252 | def get_output_for(self, input, **kwargs): 253 | return padding.pad(input, self.width, self.val, self.batch_ndim) 254 | 255 | pad = PadLayer # shortcut --------------------------------------------------------------------------------