├── .DS_Store ├── .gitignore ├── .ipynb_checkpoints ├── Audio VAE Mag & Phase-checkpoint.ipynb ├── DCT Tricks-checkpoint.ipynb ├── GAN Tutorial-checkpoint.ipynb ├── RecoNet Model 4-checkpoint.ipynb ├── RecoNet Model2-checkpoint.ipynb ├── RecoNet Model3-checkpoint.ipynb ├── RecoNet-checkpoint.ipynb ├── Robustness of DNN Activations-checkpoint.ipynb ├── Seq2Seq Tutorial-checkpoint.ipynb ├── Spoken Digits VAE-checkpoint.ipynb └── keras_mnist-checkpoint.ipynb ├── Audio VAE Mag & Phase.ipynb ├── DCT Tricks.ipynb ├── GAN Tutorial.ipynb ├── README.md ├── RecoNet Model 4.ipynb ├── RecoNet Model2.ipynb ├── RecoNet Model3.ipynb ├── RecoNet.ipynb ├── RecoNet.py ├── Robustness of DNN Activations.ipynb ├── Seq2Seq Tutorial.ipynb ├── Spoken Digits VAE.ipynb ├── SpokenDigitDB.pkl.gz ├── VAE Audio 1.png ├── VAE Audio 2.png ├── VAE Audio 3.png ├── VAE Audio 4.png ├── attention.py ├── custom_layer.py ├── discovery_submit.sh ├── fra.txt ├── handel.wav ├── keras_mnist.ipynb ├── logs ├── events.out.tfevents.1496080787.Cyrus ├── events.out.tfevents.1496080839.Cyrus ├── events.out.tfevents.1496081175.Cyrus ├── events.out.tfevents.1496081237.Cyrus ├── events.out.tfevents.1496081534.Cyrus ├── events.out.tfevents.1496083815.Cyrus ├── events.out.tfevents.1496083988.Cyrus ├── events.out.tfevents.1496084330.Cyrus ├── events.out.tfevents.1496085039.Cyrus ├── events.out.tfevents.1496085339.Cyrus ├── events.out.tfevents.1496086800.Cyrus ├── events.out.tfevents.1496086841.Cyrus ├── events.out.tfevents.1496087979.Cyrus ├── events.out.tfevents.1496088679.Cyrus └── events.out.tfevents.1496088713.Cyrus ├── reconet.h5 ├── s2s.h5 ├── sample_figure.png ├── sample_original.wav ├── sample_reconst.wav └── variational_autoencoder_deconv.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.h5 -------------------------------------------------------------------------------- /.ipynb_checkpoints/Robustness of DNN Activations-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Robustness Test\n", 8 | "I will attempt to demonstrate that DNNs can be trained such that their performance is robust to noisy activations. \n", 9 | "\n", 10 | "During training, I will perturb activations with Gaussian noise that is < 10% the amplitude of the weights. Then at test time, I will test the model on different perturbations of the weights. " 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": { 17 | "collapsed": false 18 | }, 19 | "outputs": [ 20 | { 21 | "name": "stderr", 22 | "output_type": "stream", 23 | "text": [ 24 | "Using TensorFlow backend.\n" 25 | ] 26 | } 27 | ], 28 | "source": [ 29 | "%matplotlib inline\n", 30 | "import IPython.display\n", 31 | "\n", 32 | "import gzip\n", 33 | "import cPickle as pickle\n", 34 | "import pandas as pd\n", 35 | "import random\n", 36 | "import seaborn\n", 37 | "import librosa\n", 38 | "import sklearn\n", 39 | "import numpy as np\n", 40 | "from matplotlib import pyplot as plt\n", 41 | "\n", 42 | "# Keras Imports\n", 43 | "from keras.layers import Input, Dense, Lambda \n", 44 | "from keras.layers import Flatten, Reshape, Layer\n", 45 | "from keras.layers import Conv2D, AveragePooling2D\n", 46 | "from keras.layers import GaussianNoise\n", 47 | "from keras.models import Model\n", 48 | "from keras import backend as K\n", 49 | "from keras.callbacks import TensorBoard\n", 50 | "from keras.utils.np_utils import to_categorical\n", 51 | "\n", 52 | "from keras import metrics\n", 53 | "from sklearn.utils import shuffle\n", 54 | "from scipy.stats import norm\n", 55 | "\n", 56 | "from librosa.display import waveplot, specshow\n", 57 | "seaborn.set(style='ticks')\n", 58 | "# seaborn.set(style='white')" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "## Data Visualization" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 2, 71 | "metadata": { 72 | "collapsed": false 73 | }, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "File loaded as ../SpokenDigitDB.pkl.gz\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "# Loaded Spoken Digits Dataset\n", 85 | "dbfile ='../SpokenDigitDB.pkl.gz'\n", 86 | "with gzip.open(dbfile, 'rb') as ifile:\n", 87 | " df = pickle.load(ifile)\n", 88 | " print('File loaded as '+ dbfile) " 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 3, 94 | "metadata": { 95 | "collapsed": false 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "# df.groupby('Class')\n", 100 | "# df['Class'] = df.Class." 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 4, 106 | "metadata": { 107 | "collapsed": false 108 | }, 109 | "outputs": [ 110 | { 111 | "name": "stdout", 112 | "output_type": "stream", 113 | "text": [ 114 | "[84]\n" 115 | ] 116 | } 117 | ], 118 | "source": [ 119 | "# Padding & Truncating\n", 120 | "maxlen = 84\n", 121 | "pad = lambda a, n: a[:,0: n] if a.shape[1] > n else np.hstack((a, np.min(a[:])*np.ones([a.shape[0],n - a.shape[1]])))\n", 122 | "df.Magnitude = df.Magnitude.apply(pad,args=(maxlen,)) # MaxLen Truncation Voodoo :D\n", 123 | "print(np.unique([np.shape(x)[1] for x in df.Magnitude]))" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 5, 129 | "metadata": { 130 | "collapsed": false 131 | }, 132 | "outputs": [ 133 | { 134 | "data": { 135 | "image/png": "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\nWO0AAAAASUVORK5CYII=\n", 136 | "text/plain": [ 137 | "" 138 | ] 139 | }, 140 | "metadata": {}, 141 | "output_type": "display_data" 142 | } 143 | ], 144 | "source": [ 145 | "# Plot K Random Examples\n", 146 | "k = 5\n", 147 | "sr = 8000\n", 148 | "\n", 149 | "sidx = random.sample(range(len(df)),k)\n", 150 | "sidx = np.append(sidx,sidx) \n", 151 | "\n", 152 | "for i,j in enumerate(sidx):\n", 153 | " if i\n", 180 | " \n", 181 | " Your browser does not support the audio element.\n", 182 | " \n", 183 | " " 184 | ], 185 | "text/plain": [ 186 | "" 187 | ] 188 | }, 189 | "execution_count": 6, 190 | "metadata": {}, 191 | "output_type": "execute_result" 192 | } 193 | ], 194 | "source": [ 195 | "# Play back an example!\n", 196 | "j = sidx[1]\n", 197 | "IPython.display.Audio(data=df.Wave[j], rate=sr)" 198 | ] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "## Data Preparation" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 7, 210 | "metadata": { 211 | "collapsed": false 212 | }, 213 | "outputs": [ 214 | { 215 | "name": "stdout", 216 | "output_type": "stream", 217 | "text": [ 218 | "Training Feature size: (3021, 64, 84, 1)\n", 219 | "Training Target size: (3021, 10)\n", 220 | "\n", 221 | "Testing Feature size: (1488, 64, 84, 1)\n", 222 | "Testing Target size: (1488, 10)\n" 223 | ] 224 | } 225 | ], 226 | "source": [ 227 | "# Prepare Data\n", 228 | "from sklearn.preprocessing import StandardScaler, MinMaxScaler\n", 229 | "from sklearn.cross_validation import train_test_split\n", 230 | "\n", 231 | "# Train Scaler\n", 232 | "x_data = df.Magnitude.values\n", 233 | "normsc = np.hstack(x_data)\n", 234 | "scaler = MinMaxScaler().fit(normsc.T)\n", 235 | "\n", 236 | "# Transform Data using Scaler\n", 237 | "x_data = [scaler.transform(arr.T).T for arr in df.Magnitude.values]\n", 238 | "x_data = np.dstack(x_data).transpose(2,0,1)\n", 239 | "\n", 240 | "# Add Singleton\n", 241 | "x_data = x_data[...,None] # Add singleton class\n", 242 | "y_data = to_categorical(df.Class.cat.codes)\n", 243 | "\n", 244 | "# Shuffle & Split\n", 245 | "x_train,x_test,y_train,y_test=train_test_split(x_data,y_data,\n", 246 | " test_size=0.33, random_state=32)\n", 247 | "\n", 248 | "# Print Dimensions\n", 249 | "print 'Training Feature size:', x_train.shape\n", 250 | "print 'Training Target size:', y_train.shape\n", 251 | "print ''\n", 252 | "print 'Testing Feature size:', x_test.shape\n", 253 | "print 'Testing Target size:', y_test.shape" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "metadata": {}, 259 | "source": [ 260 | "## ConvNet Model" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": 8, 266 | "metadata": { 267 | "collapsed": true 268 | }, 269 | "outputs": [], 270 | "source": [ 271 | "# Parameters\n", 272 | "chns, rows, cols = 1, 64, 84\n", 273 | "img_size = (rows,cols,chns)" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": 9, 279 | "metadata": { 280 | "collapsed": false 281 | }, 282 | "outputs": [ 283 | { 284 | "name": "stdout", 285 | "output_type": "stream", 286 | "text": [ 287 | "_________________________________________________________________\n", 288 | "Layer (type) Output Shape Param # \n", 289 | "=================================================================\n", 290 | "input_1 (InputLayer) (None, 64, 84, 1) 0 \n", 291 | "_________________________________________________________________\n", 292 | "C1 (Conv2D) (None, 32, 42, 16) 256 \n", 293 | "_________________________________________________________________\n", 294 | "C2 (Conv2D) (None, 16, 21, 16) 2320 \n", 295 | "_________________________________________________________________\n", 296 | "C3 (Conv2D) (None, 16, 21, 16) 2320 \n", 297 | "_________________________________________________________________\n", 298 | "average_pooling2d_1 (Average (None, 4, 5, 16) 0 \n", 299 | "_________________________________________________________________\n", 300 | "flatten_1 (Flatten) (None, 320) 0 \n", 301 | "_________________________________________________________________\n", 302 | "Classifier (Dense) (None, 10) 3210 \n", 303 | "=================================================================\n", 304 | "Total params: 8,106\n", 305 | "Trainable params: 8,106\n", 306 | "Non-trainable params: 0\n", 307 | "_________________________________________________________________\n" 308 | ] 309 | } 310 | ], 311 | "source": [ 312 | "# Model\n", 313 | "x = Input(shape=img_size)\n", 314 | "conv1 = Conv2D(16,(3,5),name='C1',padding='same',activation='relu',strides=(2,2))(x)\n", 315 | "conv2 = Conv2D(16,(3,3),name='C2',padding='same',activation='relu',strides=(2,2))(conv1)\n", 316 | "conv3 = Conv2D(16,(3,3),name='C3',padding='same',activation='relu')(conv2)\n", 317 | "avgpl = AveragePooling2D((4,4))(conv3)\n", 318 | "flatn = Flatten()(avgpl)\n", 319 | "y = Dense(10,name='Classifier',activation='softmax')(flatn)\n", 320 | "\n", 321 | "\n", 322 | "network = Model(x,y)\n", 323 | "network.compile(optimizer='adam',\n", 324 | " loss='categorical_crossentropy',\n", 325 | " metrics=['accuracy'])\n", 326 | "network.summary()" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 10, 332 | "metadata": { 333 | "collapsed": false 334 | }, 335 | "outputs": [ 336 | { 337 | "name": "stdout", 338 | "output_type": "stream", 339 | "text": [ 340 | "Train on 2114 samples, validate on 907 samples\n", 341 | "Epoch 1/20\n", 342 | "2s - loss: 2.1794 - acc: 0.2044 - val_loss: 1.7183 - val_acc: 0.4388\n", 343 | "Epoch 2/20\n", 344 | "2s - loss: 1.3173 - acc: 0.5771 - val_loss: 0.8780 - val_acc: 0.7233\n", 345 | "Epoch 3/20\n", 346 | "2s - loss: 0.6422 - acc: 0.7961 - val_loss: 0.4442 - val_acc: 0.8523\n", 347 | "Epoch 4/20\n", 348 | "2s - loss: 0.4142 - acc: 0.8699 - val_loss: 0.3674 - val_acc: 0.8721\n", 349 | "Epoch 5/20\n", 350 | "2s - loss: 0.3562 - acc: 0.8860 - val_loss: 0.2883 - val_acc: 0.8920\n", 351 | "Epoch 6/20\n", 352 | "2s - loss: 0.2990 - acc: 0.9063 - val_loss: 0.4028 - val_acc: 0.8379\n", 353 | "Epoch 7/20\n", 354 | "2s - loss: 0.2444 - acc: 0.9158 - val_loss: 0.1702 - val_acc: 0.9537\n", 355 | "Epoch 8/20\n", 356 | "2s - loss: 0.2016 - acc: 0.9333 - val_loss: 0.1399 - val_acc: 0.9625\n", 357 | "Epoch 9/20\n", 358 | "3s - loss: 0.1702 - acc: 0.9461 - val_loss: 0.1549 - val_acc: 0.9482\n", 359 | "Epoch 10/20\n", 360 | "2s - loss: 0.1395 - acc: 0.9570 - val_loss: 0.2344 - val_acc: 0.9129\n", 361 | "Epoch 11/20\n", 362 | "2s - loss: 0.2628 - acc: 0.9158 - val_loss: 0.1424 - val_acc: 0.9471\n", 363 | "Epoch 12/20\n", 364 | "2s - loss: 0.1186 - acc: 0.9636 - val_loss: 0.0877 - val_acc: 0.9813\n", 365 | "Epoch 13/20\n", 366 | "2s - loss: 0.1076 - acc: 0.9674 - val_loss: 0.0856 - val_acc: 0.9768\n", 367 | "Epoch 14/20\n", 368 | "2s - loss: 0.1335 - acc: 0.9570 - val_loss: 0.0772 - val_acc: 0.9735\n", 369 | "Epoch 15/20\n", 370 | "2s - loss: 0.0977 - acc: 0.9716 - val_loss: 0.1039 - val_acc: 0.9702\n", 371 | "Epoch 16/20\n", 372 | "2s - loss: 0.0919 - acc: 0.9726 - val_loss: 0.0657 - val_acc: 0.9768\n", 373 | "Epoch 17/20\n", 374 | "2s - loss: 0.0830 - acc: 0.9716 - val_loss: 0.1185 - val_acc: 0.9515\n", 375 | "Epoch 18/20\n", 376 | "2s - loss: 0.0720 - acc: 0.9787 - val_loss: 0.0616 - val_acc: 0.9813\n", 377 | "Epoch 19/20\n", 378 | "2s - loss: 0.0629 - acc: 0.9834 - val_loss: 0.0821 - val_acc: 0.9724\n", 379 | "Epoch 20/20\n", 380 | "2s - loss: 0.0465 - acc: 0.9858 - val_loss: 0.0514 - val_acc: 0.9779\n" 381 | ] 382 | } 383 | ], 384 | "source": [ 385 | "# Train Model\n", 386 | "log=network.fit(x_train,y_train,\n", 387 | " shuffle=True,\n", 388 | " epochs=20,\n", 389 | " batch_size=32,\n", 390 | " validation_split=0.3,\n", 391 | " verbose=2,\n", 392 | " callbacks=[TensorBoard(log_dir='/tmp/robustcnn')])" 393 | ] 394 | }, 395 | { 396 | "cell_type": "code", 397 | "execution_count": 11, 398 | "metadata": { 399 | "collapsed": false 400 | }, 401 | "outputs": [ 402 | { 403 | "data": { 404 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjQAAAGACAYAAAC6OPj9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl8VPW9//HXrNkmK0lYw05YFQy4gUELoqgIokBxwVrp\nYqv3eou92uXWQlsat9r+XGjV1loRG611xa0GBGVREAkSIAEkbGFJQiDJJDOZ5ZzfHxMGIsgkmBXe\nz8djHnO275lPImbe8z3f+R6LaZomIiIiIh2Yta0LEBEREfmmFGhERESkw1OgERERkQ5PgUZEREQ6\nPAUaERER6fAUaERERKTDU6ARkUYLBAJccsklfP/732/rUkREGlCgEZFG++CDDxg0aBCbNm1ix44d\nbV2OiEiYAo2INNqLL77IhAkTuPrqq3nuuefC21955RUmTZrElClTuO222zh48OBJtx84cIA1a9Zw\n7bXXhtsev/7EE08we/ZsJk+ezL333suhQ4e48847mTlzJpdffjm33norFRUVAOzcuZNbb72VSZMm\nMXnyZN555x0+//xzLrvssvC5vV4vo0ePDrcRkTOXAo2INMr27dv54osvuPrqq5kyZQpvvfUWlZWV\nFBYW8oc//IG//e1vvPHGG4wbN44///nPJ93+l7/8JeLr7N+/nzfeeIOHHnqIt99+m/POO4/c3Fzy\n8vKIjo7mzTffBGDOnDlcffXVLF68mKeffpo//elPDBw4kOTkZD766CMA3n77bS6++GJSUlJa9Hcj\nIm3P3tYFiEjHkJuby6WXXkp8fDznnHMO3bt3Jzc3l6ioKLKzs+ncuTMAt956KwDPPffcSbevWbPm\nlK8zfPhwLBZLuM1nn33Gc889x86dO9m+fTvDhw8PB6lp06YB0KVLF/7zn/8AcNNNN/Gvf/2LsWPH\n8tJLL3Hvvfc2/y9DRNodBRoRicjj8fD6668THR3N+PHjMU2TmpoaXnzxRb73ve81OLauro6SkhJs\nNls4mBy//fhtAH6/v8F6XFxcePnhhx+moKCAG264gYsuuohAIIBpmuFzH3+u4uJiunfvzrXXXssf\n//hHPv30UzweD6NGjWrOX4WItFO65CQiEb355pukpKSwYsUKlixZwtKlS8nLy6O2tpbKykpWr15N\neXk5AP/85z955JFHuOiii1i1atUJ21NSUti3bx8VFRWYpkleXt7Xvu7KlSv5zne+w+TJk0lOTmbV\n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\noPRla2oAAAAASUVORK5CYII=\n", 405 | "text/plain": [ 406 | "" 407 | ] 408 | }, 409 | "metadata": {}, 410 | "output_type": "display_data" 411 | } 412 | ], 413 | "source": [ 414 | "seaborn.set(style='white')\n", 415 | "fig = plt.figure()\n", 416 | "ax1 = fig.add_subplot(211)\n", 417 | "ax2 = fig.add_subplot(212)\n", 418 | "\n", 419 | "ax1.plot(log.epoch,log.history['acc'])\n", 420 | "ax1.plot(log.epoch,log.history['val_acc'])\n", 421 | "ax1.set_title('Accuracy')\n", 422 | "ax1.legend(['Train','Valid'])\n", 423 | "\n", 424 | "ax2.plot(log.epoch,log.history['loss'])\n", 425 | "ax2.plot(log.epoch,log.history['val_loss'])\n", 426 | "ax2.set_title('Loss')\n", 427 | "ax2.legend(['Train','Valid'])\n", 428 | "\n", 429 | "plt.tight_layout()" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "## Evaluation" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": 12, 442 | "metadata": { 443 | "collapsed": false 444 | }, 445 | "outputs": [ 446 | { 447 | "name": "stdout", 448 | "output_type": "stream", 449 | "text": [ 450 | "Testing accuracy: 97.04\n", 451 | "\n", 452 | "[[144 0 0 0 0 0 0 1 0 0]\n", 453 | " [ 0 133 0 0 0 0 0 0 0 1]\n", 454 | " [ 0 0 143 0 0 0 0 1 0 0]\n", 455 | " [ 0 0 0 153 0 0 0 0 0 0]\n", 456 | " [ 0 1 0 0 137 1 0 0 0 0]\n", 457 | " [ 0 2 0 0 0 127 0 9 0 6]\n", 458 | " [ 1 0 0 3 0 0 161 2 0 0]\n", 459 | " [ 0 0 0 0 0 2 0 154 0 1]\n", 460 | " [ 0 0 0 4 0 0 0 0 151 0]\n", 461 | " [ 3 5 0 0 0 0 0 1 0 141]]\n" 462 | ] 463 | } 464 | ], 465 | "source": [ 466 | "y_scr = network.predict(x_test)\n", 467 | "y_prd = np.argmax(y_scr,-1)\n", 468 | "y_tst = np.argmax(y_test,-1)\n", 469 | "\n", 470 | "acc = sklearn.metrics.accuracy_score(y_tst,y_prd)\n", 471 | "print \"Testing accuracy: %.2f\"%(acc*100)\n", 472 | "print ''\n", 473 | "print sklearn.metrics.confusion_matrix(y_tst,y_prd)" 474 | ] 475 | }, 476 | { 477 | "cell_type": "markdown", 478 | "metadata": {}, 479 | "source": [ 480 | "----" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": { 486 | "collapsed": true 487 | }, 488 | "source": [ 489 | "# Network Trained with Noise\n", 490 | "What we want to do is replace all activations, say: $$g(x) = \\tanh(x)$$ with $$\\hat{g}(x) = a \\tanh(bx) + c$$\n", 491 | "\n", 492 | "where $a$, $b$ and $c$ are Normally distributed variables. \n", 493 | "\n", 494 | "The multiplicative and additive variables $a$ and $c$ can be easily obtained by perturbing layer activations using samples from a normal distribution. \n", 495 | "\n", 496 | "The variable $b$ is a little tricky. It is a multiplicative term for the inputs to each layer. For each layer, this is a multiplier to the previous layer's activations. Since we're already perturbing activations in all layers, we are indirectly doing this $b$ multiplier. Hence, I posit it's not necessary to explicitly define $b$. \n", 497 | "\n", 498 | "I proceed to build the noisy network below:" 499 | ] 500 | }, 501 | { 502 | "cell_type": "code", 503 | "execution_count": 13, 504 | "metadata": { 505 | "collapsed": true 506 | }, 507 | "outputs": [], 508 | "source": [ 509 | "# Create Layer for Additive & Multiplicative Noise\n", 510 | "stdev_mul = 0.01\n", 511 | "stdev_add = 0.01\n", 512 | "\n", 513 | "mean_mul = 1.0\n", 514 | "mean_add = 0.0\n", 515 | "\n", 516 | "def Gnoise(x):\n", 517 | " g = x * K.random_normal(shape=K.shape(x),\n", 518 | " mean=mean_mul,stddev=stdev_mul)\n", 519 | " return g + K.random_normal(shape=K.shape(x),\n", 520 | " mean=mean_add,stddev=stdev_add)" 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "execution_count": 14, 526 | "metadata": { 527 | "collapsed": false 528 | }, 529 | "outputs": [ 530 | { 531 | "name": "stdout", 532 | "output_type": "stream", 533 | "text": [ 534 | "_________________________________________________________________\n", 535 | "Layer (type) Output Shape Param # \n", 536 | "=================================================================\n", 537 | "input_2 (InputLayer) (None, 64, 84, 1) 0 \n", 538 | "_________________________________________________________________\n", 539 | "GnX (Lambda) (None, 64, 84, 1) 0 \n", 540 | "_________________________________________________________________\n", 541 | "nC1 (Conv2D) (None, 32, 42, 16) 256 \n", 542 | "_________________________________________________________________\n", 543 | "Gn1 (Lambda) (None, 32, 42, 16) 0 \n", 544 | "_________________________________________________________________\n", 545 | "nC2 (Conv2D) (None, 16, 21, 16) 2320 \n", 546 | "_________________________________________________________________\n", 547 | "Gn2 (Lambda) (None, 16, 21, 16) 0 \n", 548 | "_________________________________________________________________\n", 549 | "nC3 (Conv2D) (None, 16, 21, 16) 2320 \n", 550 | "_________________________________________________________________\n", 551 | "Gn3 (Lambda) (None, 16, 21, 16) 0 \n", 552 | "_________________________________________________________________\n", 553 | "average_pooling2d_2 (Average (None, 4, 5, 16) 0 \n", 554 | "_________________________________________________________________\n", 555 | "flatten_2 (Flatten) (None, 320) 0 \n", 556 | "_________________________________________________________________\n", 557 | "nClassifier (Dense) (None, 10) 3210 \n", 558 | "_________________________________________________________________\n", 559 | "GnY (Lambda) (None, 10) 0 \n", 560 | "=================================================================\n", 561 | "Total params: 8,106\n", 562 | "Trainable params: 8,106\n", 563 | "Non-trainable params: 0\n", 564 | "_________________________________________________________________\n" 565 | ] 566 | } 567 | ], 568 | "source": [ 569 | "# Model\n", 570 | "nx = Input(shape=img_size)\n", 571 | "ng = Lambda(Gnoise,name='GnX')(nx)\n", 572 | "nconv1 = Conv2D(16,(3,5),name='nC1',padding='same',activation='relu',strides=(2,2))(ng)\n", 573 | "nconv1 = Lambda(Gnoise,name='Gn1')(nconv1)\n", 574 | "nconv2 = Conv2D(16,(3,3),name='nC2',padding='same',activation='relu',strides=(2,2))(nconv1)\n", 575 | "nconv2 = Lambda(Gnoise,name='Gn2')(nconv2)\n", 576 | "nconv3 = Conv2D(16,(3,3),name='nC3',padding='same',activation='relu')(nconv2)\n", 577 | "nconv3 = Lambda(Gnoise,name='Gn3')(nconv3)\n", 578 | "navgpl = AveragePooling2D((4,4))(nconv3)\n", 579 | "nflatn = Flatten()(navgpl)\n", 580 | "ny = Dense(10,name='nClassifier',activation='softmax')(nflatn)\n", 581 | "ny = Lambda(Gnoise,name='GnY')(ny)\n", 582 | "\n", 583 | "noisynet = Model(nx,ny)\n", 584 | "noisynet.compile(optimizer='adam',\n", 585 | " loss='categorical_crossentropy',\n", 586 | " metrics=['accuracy'])\n", 587 | "noisynet.summary()" 588 | ] 589 | }, 590 | { 591 | "cell_type": "code", 592 | "execution_count": 15, 593 | "metadata": { 594 | "collapsed": false 595 | }, 596 | "outputs": [ 597 | { 598 | "name": "stdout", 599 | "output_type": "stream", 600 | "text": [ 601 | "Train on 2114 samples, validate on 907 samples\n", 602 | "Epoch 1/20\n", 603 | "4s - loss: 2.1810 - acc: 0.1793 - val_loss: 1.7872 - val_acc: 0.3749\n", 604 | "Epoch 2/20\n", 605 | "5s - loss: 1.6516 - acc: 0.4385 - val_loss: 1.5272 - val_acc: 0.5248\n", 606 | "Epoch 3/20\n", 607 | "4s - loss: 1.2461 - acc: 0.6433 - val_loss: 0.9450 - val_acc: 0.7332\n", 608 | "Epoch 4/20\n", 609 | "4s - loss: 0.8160 - acc: 0.7649 - val_loss: 0.6574 - val_acc: 0.8037\n", 610 | "Epoch 5/20\n", 611 | "4s - loss: 0.5646 - acc: 0.8344 - val_loss: 0.4880 - val_acc: 0.8688\n", 612 | "Epoch 6/20\n", 613 | "4s - loss: 0.5763 - acc: 0.8354 - val_loss: 0.4084 - val_acc: 0.8787\n", 614 | "Epoch 7/20\n", 615 | "4s - loss: 0.3397 - acc: 0.9063 - val_loss: 0.2922 - val_acc: 0.9383\n", 616 | "Epoch 8/20\n", 617 | "4s - loss: 0.3036 - acc: 0.9144 - val_loss: 0.2472 - val_acc: 0.9316\n", 618 | "Epoch 9/20\n", 619 | "5s - loss: 0.2776 - acc: 0.9191 - val_loss: 0.2716 - val_acc: 0.9383\n", 620 | "Epoch 10/20\n", 621 | "5s - loss: 0.2032 - acc: 0.9390 - val_loss: 0.1866 - val_acc: 0.9471\n", 622 | "Epoch 11/20\n", 623 | "4s - loss: 0.1730 - acc: 0.9536 - val_loss: 0.1959 - val_acc: 0.9493\n", 624 | "Epoch 12/20\n", 625 | "4s - loss: 0.3064 - acc: 0.9305 - val_loss: 0.1700 - val_acc: 0.9592\n", 626 | "Epoch 13/20\n", 627 | "5s - loss: 0.1421 - acc: 0.9693 - val_loss: 0.1595 - val_acc: 0.9625\n", 628 | "Epoch 14/20\n", 629 | "5s - loss: 0.1657 - acc: 0.9518 - val_loss: 0.1405 - val_acc: 0.9757\n", 630 | "Epoch 15/20\n", 631 | "6s - loss: 0.1141 - acc: 0.9707 - val_loss: 0.1219 - val_acc: 0.9724\n", 632 | "Epoch 16/20\n", 633 | "6s - loss: 0.1099 - acc: 0.9768 - val_loss: 0.1264 - val_acc: 0.9857\n", 634 | "Epoch 17/20\n", 635 | "5s - loss: 0.1263 - acc: 0.9754 - val_loss: 0.1376 - val_acc: 0.9636\n", 636 | "Epoch 18/20\n", 637 | "4s - loss: 0.1319 - acc: 0.9612 - val_loss: 0.1072 - val_acc: 0.9724\n", 638 | "Epoch 19/20\n", 639 | "4s - loss: 0.0936 - acc: 0.9830 - val_loss: 0.0858 - val_acc: 0.9857\n", 640 | "Epoch 20/20\n", 641 | "4s - loss: 0.0925 - acc: 0.9801 - val_loss: 0.0695 - val_acc: 0.9846\n" 642 | ] 643 | } 644 | ], 645 | "source": [ 646 | "# Train Model\n", 647 | "log=noisynet.fit(x_train,y_train,\n", 648 | " shuffle=True,\n", 649 | " epochs=20,\n", 650 | " batch_size=32,\n", 651 | " validation_split=0.3,\n", 652 | " verbose=2,\n", 653 | " callbacks=[TensorBoard(log_dir='/tmp/noisycnn')])" 654 | ] 655 | }, 656 | { 657 | "cell_type": "code", 658 | "execution_count": 16, 659 | "metadata": { 660 | "collapsed": false 661 | }, 662 | "outputs": [ 663 | { 664 | "name": "stdout", 665 | "output_type": "stream", 666 | "text": [ 667 | "Testing accuracy: 97.51\n", 668 | "\n", 669 | "[[144 0 0 0 0 0 0 1 0 0]\n", 670 | " [ 0 126 0 0 0 0 0 3 0 5]\n", 671 | " [ 0 0 143 0 0 0 0 1 0 0]\n", 672 | " [ 0 0 0 153 0 0 0 0 0 0]\n", 673 | " [ 0 0 0 0 138 1 0 0 0 0]\n", 674 | " [ 0 2 0 0 0 135 0 1 0 6]\n", 675 | " [ 0 0 0 0 0 0 160 2 5 0]\n", 676 | " [ 0 0 0 0 0 3 0 154 0 0]\n", 677 | " [ 0 0 0 0 0 0 1 0 154 0]\n", 678 | " [ 5 0 0 0 0 0 0 1 0 144]]\n" 679 | ] 680 | } 681 | ], 682 | "source": [ 683 | "y_scr = noisynet.predict(x_test)\n", 684 | "y_prd = np.argmax(y_scr,-1)\n", 685 | "y_tst = np.argmax(y_test,-1)\n", 686 | "\n", 687 | "acc = sklearn.metrics.accuracy_score(y_tst,y_prd)\n", 688 | "print \"Testing accuracy: %.2f\"%(acc*100)\n", 689 | "print ''\n", 690 | "print sklearn.metrics.confusion_matrix(y_tst,y_prd)" 691 | ] 692 | }, 693 | { 694 | "cell_type": "markdown", 695 | "metadata": {}, 696 | "source": [ 697 | "## Conclusion\n", 698 | "Looks like the network performs well even with the noisy perturbations: **as long as the additive and multiplicative noise is kept under 0.05 standard deviations**. \n", 699 | "\n", 700 | "Actually, the noisy training seems to perform better than regular training when the standard deviation is kept at **0.01**. " 701 | ] 702 | }, 703 | { 704 | "cell_type": "code", 705 | "execution_count": 33, 706 | "metadata": { 707 | "collapsed": false 708 | }, 709 | "outputs": [ 710 | { 711 | "name": "stdout", 712 | "output_type": "stream", 713 | "text": [ 714 | "Mean of weights: 0.0344\n", 715 | "Stdv of weights: 0.1131\n", 716 | "\n", 717 | "Mean of biases: 0.0147\n", 718 | "Stdv of biases: 0.1160\n" 719 | ] 720 | } 721 | ], 722 | "source": [ 723 | "# Distribution of Layer Weights\n", 724 | "[w,b] = noisynet.layers[2].get_weights()\n", 725 | "\n", 726 | "print \"Mean of weights: %.4f\"%(w.mean())\n", 727 | "print \"Stdv of weights: %.4f\"%(w.std())\n", 728 | "print \"\"\n", 729 | "print \"Mean of biases: %.4f\"%(b.mean())\n", 730 | "print \"Stdv of biases: %.4f\"%(b.std())" 731 | ] 732 | }, 733 | { 734 | "cell_type": "code", 735 | "execution_count": null, 736 | "metadata": { 737 | "collapsed": true 738 | }, 739 | "outputs": [], 740 | "source": [] 741 | } 742 | ], 743 | "metadata": { 744 | "kernelspec": { 745 | "display_name": "Python 2", 746 | "language": "python", 747 | "name": "python2" 748 | }, 749 | "language_info": { 750 | "codemirror_mode": { 751 | "name": "ipython", 752 | "version": 2 753 | }, 754 | "file_extension": ".py", 755 | "mimetype": "text/x-python", 756 | "name": "python", 757 | "nbconvert_exporter": "python", 758 | "pygments_lexer": "ipython2", 759 | "version": "2.7.11" 760 | } 761 | }, 762 | "nbformat": 4, 763 | "nbformat_minor": 0 764 | } 765 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/Seq2Seq Tutorial-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Sequence to Sequence Learning Example\n", 8 | "Original example is posted on the [Keras blog here](https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html). This is a walkthrough to ensure I can implement similar models. " 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": { 15 | "collapsed": false 16 | }, 17 | "outputs": [ 18 | { 19 | "name": "stderr", 20 | "output_type": "stream", 21 | "text": [ 22 | "Using TensorFlow backend.\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "from __future__ import print_function\n", 28 | "\n", 29 | "from keras.models import Model\n", 30 | "from keras.layers import Input, Dense\n", 31 | "from keras.layers.recurrent import GRU, LSTM\n", 32 | "import numpy as np" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "# Load Data\n", 44 | "filename = 'fra.txt'\n", 45 | "batch_size = 64 # Batch size for training.\n", 46 | "epochs = 100 # Number of epochs to train for.\n", 47 | "latent_dim = 256 # Latent dimensionality of the encoding space.\n", 48 | "num_samples = 10000 # Number of samples to train on." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": { 55 | "collapsed": false 56 | }, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "Number of samples: 10000\n", 63 | "Number of unique input tokens: 73\n", 64 | "Number of unique output tokens: 92\n", 65 | "Max sequence length for inputs: 16\n", 66 | "Max sequence length for outputs: 63\n" 67 | ] 68 | } 69 | ], 70 | "source": [ 71 | "# Vectorize the data.\n", 72 | "input_texts = []\n", 73 | "target_texts = []\n", 74 | "input_characters = set()\n", 75 | "target_characters = set()\n", 76 | "lines = open(filename).read().split('\\n')\n", 77 | "for line in lines[: min(num_samples, len(lines) - 1)]:\n", 78 | " input_text, target_text = line.split('\\t')\n", 79 | " # We use \"tab\" as the \"start sequence\" character\n", 80 | " # for the targets, and \"\\n\" as \"end sequence\" character.\n", 81 | " target_text = '\\t' + target_text + '\\n'\n", 82 | " input_texts.append(input_text)\n", 83 | " target_texts.append(target_text)\n", 84 | " for char in input_text:\n", 85 | " if char not in input_characters:\n", 86 | " input_characters.add(char)\n", 87 | " for char in target_text:\n", 88 | " if char not in target_characters:\n", 89 | " target_characters.add(char)\n", 90 | "\n", 91 | "input_characters = sorted(list(input_characters))\n", 92 | "target_characters = sorted(list(target_characters))\n", 93 | "num_encoder_tokens = len(input_characters)\n", 94 | "num_decoder_tokens = len(target_characters)\n", 95 | "max_encoder_seq_length = max([len(txt) for txt in input_texts])\n", 96 | "max_decoder_seq_length = max([len(txt) for txt in target_texts])\n", 97 | "\n", 98 | "print('Number of samples:', len(input_texts))\n", 99 | "print('Number of unique input tokens:', num_encoder_tokens)\n", 100 | "print('Number of unique output tokens:', num_decoder_tokens)\n", 101 | "print('Max sequence length for inputs:', max_encoder_seq_length)\n", 102 | "print('Max sequence length for outputs:', max_decoder_seq_length)" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 4, 108 | "metadata": { 109 | "collapsed": true 110 | }, 111 | "outputs": [], 112 | "source": [ 113 | "input_token_index = dict(\n", 114 | " [(char, i) for i, char in enumerate(input_characters)])\n", 115 | "target_token_index = dict(\n", 116 | " [(char, i) for i, char in enumerate(target_characters)])\n", 117 | "\n", 118 | "encoder_input_data = np.zeros(\n", 119 | " (len(input_texts), max_encoder_seq_length, num_encoder_tokens),\n", 120 | " dtype='float32')\n", 121 | "decoder_input_data = np.zeros(\n", 122 | " (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n", 123 | " dtype='float32')\n", 124 | "decoder_target_data = np.zeros(\n", 125 | " (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n", 126 | " dtype='float32')\n", 127 | "\n", 128 | "for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):\n", 129 | " for t, char in enumerate(input_text):\n", 130 | " encoder_input_data[i, t, input_token_index[char]] = 1.\n", 131 | " for t, char in enumerate(target_text):\n", 132 | " # decoder_target_data is ahead of decoder_target_data by one timestep\n", 133 | " decoder_input_data[i, t, target_token_index[char]] = 1.\n", 134 | " if t > 0:\n", 135 | " # decoder_target_data will be ahead by one timestep\n", 136 | " # and will not include the start character.\n", 137 | " decoder_target_data[i, t - 1, target_token_index[char]] = 1." 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 5, 143 | "metadata": { 144 | "collapsed": false 145 | }, 146 | "outputs": [ 147 | { 148 | "name": "stdout", 149 | "output_type": "stream", 150 | "text": [ 151 | "(10000, 16, 73)\n", 152 | "(10000, 63, 92)\n", 153 | "(10000, 63, 92)\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "print(encoder_input_data.shape)\n", 159 | "print(decoder_input_data.shape)\n", 160 | "print(decoder_target_data.shape)" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "## Training" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "### Encoder Model" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 6, 180 | "metadata": { 181 | "collapsed": false 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "# Define an input sequence and process it.\n", 186 | "encoder_inputs = Input(shape=(None, num_encoder_tokens),name='E-Input')\n", 187 | "encoder = GRU(latent_dim, return_state=True,name='Encoder')\n", 188 | "encoder_outputs, encoder_state = encoder(encoder_inputs) # Discard `encoder_outputs` and only keep the states." 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": { 194 | "collapsed": true 195 | }, 196 | "source": [ 197 | "### Decoder Model" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": 7, 203 | "metadata": { 204 | "collapsed": false 205 | }, 206 | "outputs": [], 207 | "source": [ 208 | "# Set up the decoder, using `encoder_states` as initial state.\n", 209 | "decoder_inputs = Input(shape=(None, num_decoder_tokens),name='D-Input')\n", 210 | "decoder_gru = GRU(latent_dim, return_sequences=True,return_state=True,name='Decoder')\n", 211 | "decoder_outputs,_ = decoder_gru(decoder_inputs,initial_state=encoder_state)\n", 212 | "decoder_dense = Dense(num_decoder_tokens, activation='softmax',name='Classifier')\n", 213 | "decoder_outputs = decoder_dense(decoder_outputs)" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 8, 219 | "metadata": { 220 | "collapsed": false 221 | }, 222 | "outputs": [ 223 | { 224 | "name": "stdout", 225 | "output_type": "stream", 226 | "text": [ 227 | "____________________________________________________________________________________________________\n", 228 | "Layer (type) Output Shape Param # Connected to \n", 229 | "====================================================================================================\n", 230 | "E-Input (InputLayer) (None, None, 73) 0 \n", 231 | "____________________________________________________________________________________________________\n", 232 | "D-Input (InputLayer) (None, None, 92) 0 \n", 233 | "____________________________________________________________________________________________________\n", 234 | "Encoder (GRU) [(None, 256), (None, 253440 E-Input[0][0] \n", 235 | "____________________________________________________________________________________________________\n", 236 | "Decoder (GRU) [(None, None, 256), ( 268032 D-Input[0][0] \n", 237 | " Encoder[0][1] \n", 238 | "____________________________________________________________________________________________________\n", 239 | "Classifier (Dense) (None, None, 92) 23644 Decoder[0][0] \n", 240 | "====================================================================================================\n", 241 | "Total params: 545,116\n", 242 | "Trainable params: 545,116\n", 243 | "Non-trainable params: 0\n", 244 | "____________________________________________________________________________________________________\n" 245 | ] 246 | } 247 | ], 248 | "source": [ 249 | "# Model\n", 250 | "### Encoding\n", 251 | "# Define the model that will turn\n", 252 | "# `encoder_input_data` & `decoder_input_data` into `decoder_target_data`\n", 253 | "model = Model([encoder_inputs, decoder_inputs], decoder_outputs)\n", 254 | "model.summary()" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "### Train Model" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 25, 267 | "metadata": { 268 | "collapsed": false 269 | }, 270 | "outputs": [ 271 | { 272 | "name": "stdout", 273 | "output_type": "stream", 274 | "text": [ 275 | "Train on 8000 samples, validate on 2000 samples\n", 276 | "Epoch 1/10\n", 277 | "8000/8000 [==============================] - 75s - loss: 0.4704 - val_loss: 0.5698\n", 278 | "Epoch 2/10\n", 279 | "8000/8000 [==============================] - 73s - loss: 0.4428 - val_loss: 0.5491\n", 280 | "Epoch 3/10\n", 281 | "8000/8000 [==============================] - 72s - loss: 0.4237 - val_loss: 0.5426\n", 282 | "Epoch 4/10\n", 283 | "8000/8000 [==============================] - 74s - loss: 0.4040 - val_loss: 0.5180\n", 284 | "Epoch 5/10\n", 285 | "8000/8000 [==============================] - 72s - loss: 0.3869 - val_loss: 0.5055\n", 286 | "Epoch 6/10\n", 287 | "8000/8000 [==============================] - 72s - loss: 0.3720 - val_loss: 0.4971\n", 288 | "Epoch 7/10\n", 289 | "8000/8000 [==============================] - 72s - loss: 0.3586 - val_loss: 0.4852\n", 290 | "Epoch 8/10\n", 291 | "8000/8000 [==============================] - 72s - loss: 0.3466 - val_loss: 0.4768\n", 292 | "Epoch 9/10\n", 293 | "8000/8000 [==============================] - 72s - loss: 0.3358 - val_loss: 0.4675\n", 294 | "Epoch 10/10\n", 295 | "8000/8000 [==============================] - 10372s - loss: 0.3250 - val_loss: 0.4648\n" 296 | ] 297 | }, 298 | { 299 | "data": { 300 | "text/plain": [ 301 | "" 302 | ] 303 | }, 304 | "execution_count": 25, 305 | "metadata": {}, 306 | "output_type": "execute_result" 307 | } 308 | ], 309 | "source": [ 310 | "# Run training\n", 311 | "model.compile(optimizer='rmsprop', loss='categorical_crossentropy')\n", 312 | "model.fit([encoder_input_data, decoder_input_data], decoder_target_data,\n", 313 | " batch_size=batch_size,\n", 314 | " epochs=10,\n", 315 | " validation_split=0.2)\n", 316 | "\n", 317 | "# model.save('s2s.h5')\n" 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "## Inference\n", 325 | "Next: inference mode (sampling). Here's the drill:\n", 326 | "- encode input and retrieve initial decoder state\n", 327 | "- run one step of decoder with this initial state and a \"start of sequence\" token as target. Output will be the next target token\n", 328 | "- Repeat with the current target token and current states\n" 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": 26, 334 | "metadata": { 335 | "collapsed": false 336 | }, 337 | "outputs": [], 338 | "source": [ 339 | "### Define Sampling Models\n", 340 | "encoder_model = Model(encoder_inputs, encoder_state)\n", 341 | "\n", 342 | "decoder_state_input = Input(shape=(latent_dim,))\n", 343 | "decoder_outputs,decoder_state = decoder_gru(decoder_inputs, initial_state=decoder_state_input)\n", 344 | "\n", 345 | "decoder_outputs = decoder_dense(decoder_outputs)\n", 346 | "decoder_model = Model([decoder_inputs, decoder_state_input], [decoder_outputs, decoder_state])" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": 27, 352 | "metadata": { 353 | "collapsed": false 354 | }, 355 | "outputs": [ 356 | { 357 | "name": "stdout", 358 | "output_type": "stream", 359 | "text": [ 360 | "____________________________________________________________________________________________________\n", 361 | "Layer (type) Output Shape Param # Connected to \n", 362 | "====================================================================================================\n", 363 | "D-Input (InputLayer) (None, None, 92) 0 \n", 364 | "____________________________________________________________________________________________________\n", 365 | "input_2 (InputLayer) (None, 256) 0 \n", 366 | "____________________________________________________________________________________________________\n", 367 | "Decoder (GRU) [(None, None, 256), ( 268032 D-Input[0][0] \n", 368 | " input_2[0][0] \n", 369 | "____________________________________________________________________________________________________\n", 370 | "Classifier (Dense) (None, None, 92) 23644 Decoder[2][0] \n", 371 | "====================================================================================================\n", 372 | "Total params: 291,676\n", 373 | "Trainable params: 291,676\n", 374 | "Non-trainable params: 0\n", 375 | "____________________________________________________________________________________________________\n" 376 | ] 377 | } 378 | ], 379 | "source": [ 380 | "decoder_model.summary()" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 28, 386 | "metadata": { 387 | "collapsed": true 388 | }, 389 | "outputs": [], 390 | "source": [ 391 | "# Reverse-lookup token index to decode sequences back to\n", 392 | "# something readable.\n", 393 | "reverse_input_char_index = dict(\n", 394 | " (i, char) for char, i in input_token_index.items())\n", 395 | "reverse_target_char_index = dict(\n", 396 | " (i, char) for char, i in target_token_index.items())" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": {}, 402 | "source": [ 403 | "### Decoding Sequence" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": 29, 409 | "metadata": { 410 | "collapsed": true 411 | }, 412 | "outputs": [], 413 | "source": [ 414 | "def decode_sequence(input_seq):\n", 415 | " states_value = encoder_model.predict(input_seq) # Encode the input as state vectors.\n", 416 | " target_seq = np.zeros((1, 1, num_decoder_tokens)) # Generate empty target sequence of length 1.\n", 417 | " # Populate the first character of target sequence with the start character.\n", 418 | " target_seq[0, 0, target_token_index['\\t']] = 1.\n", 419 | "\n", 420 | " # Sampling loop for a batch of sequences\n", 421 | " # (to simplify, here we assume a batch of size 1).\n", 422 | " stop_condition = False\n", 423 | " decoded_sentence = ''\n", 424 | " while not stop_condition:\n", 425 | " output_tokens, h = decoder_model.predict([target_seq,states_value])\n", 426 | "\n", 427 | " # Sample a token\n", 428 | " sampled_token_index = np.argmax(output_tokens[0, -1, :])\n", 429 | " sampled_char = reverse_target_char_index[sampled_token_index]\n", 430 | " decoded_sentence += sampled_char\n", 431 | "\n", 432 | " # Exit condition: either hit max length\n", 433 | " # or find stop character.\n", 434 | " if (sampled_char == '\\n' or\n", 435 | " len(decoded_sentence) > max_decoder_seq_length):\n", 436 | " stop_condition = True\n", 437 | "\n", 438 | " # Update the target sequence (of length 1).\n", 439 | " target_seq = np.zeros((1, 1, num_decoder_tokens))\n", 440 | " target_seq[0, 0, sampled_token_index] = 1.\n", 441 | "\n", 442 | " # Update states\n", 443 | " states_value = h\n", 444 | "\n", 445 | " return decoded_sentence" 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": 30, 451 | "metadata": { 452 | "collapsed": false 453 | }, 454 | "outputs": [ 455 | { 456 | "name": "stdout", 457 | "output_type": "stream", 458 | "text": [ 459 | "-\n", 460 | "Input sentence: Go.\n", 461 | "Decoded sentence: Restez aller !\n", 462 | "\n", 463 | "-\n", 464 | "Input sentence: Run!\n", 465 | "Decoded sentence: Restez aller !\n", 466 | "\n", 467 | "-\n", 468 | "Input sentence: Run!\n", 469 | "Decoded sentence: Restez aller !\n", 470 | "\n", 471 | "-\n", 472 | "Input sentence: Wow!\n", 473 | "Decoded sentence: Fais-le entrer.\n", 474 | "\n", 475 | "-\n", 476 | "Input sentence: Fire!\n", 477 | "Decoded sentence: Restez aller !\n", 478 | "\n" 479 | ] 480 | } 481 | ], 482 | "source": [ 483 | "for seq_index in range(5):\n", 484 | " # Take one sequence (part of the training test)\n", 485 | " # for trying out decoding.\n", 486 | " input_seq = encoder_input_data[seq_index: seq_index + 1]\n", 487 | " decoded_sentence = decode_sequence(input_seq)\n", 488 | " print('-')\n", 489 | " print('Input sentence:', input_texts[seq_index])\n", 490 | " print('Decoded sentence:', decoded_sentence)" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": null, 496 | "metadata": { 497 | "collapsed": true 498 | }, 499 | "outputs": [], 500 | "source": [] 501 | } 502 | ], 503 | "metadata": { 504 | "kernelspec": { 505 | "display_name": "Python 2", 506 | "language": "python", 507 | "name": "python2" 508 | }, 509 | "language_info": { 510 | "codemirror_mode": { 511 | "name": "ipython", 512 | "version": 2 513 | }, 514 | "file_extension": ".py", 515 | "mimetype": "text/x-python", 516 | "name": "python", 517 | "nbconvert_exporter": "python", 518 | "pygments_lexer": "ipython2", 519 | "version": "2.7.11" 520 | } 521 | }, 522 | "nbformat": 4, 523 | "nbformat_minor": 1 524 | } 525 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Variational 2 | A Playground for Variational Autoencoders 3 | -------------------------------------------------------------------------------- /RecoNet.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # # RecoNet: Using Neural Networks to Reconstruct Phaseless Spectrograms 4 | # This notebook is a first attempt at implementing a reconstructing neural network for recovering audio sounds from magnitude spectrograms only. This is all in hopes of building generative models for audio sounds. 5 | 6 | # In[1]: 7 | 8 | #get_ipython().magic(u'matplotlib inline') 9 | #import IPython.display 10 | 11 | 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import pandas as pd 15 | 16 | import gzip 17 | import cPickle as pickle 18 | import seaborn as sns 19 | import random 20 | import librosa 21 | import sklearn 22 | 23 | # Keras Imports 24 | from keras.models import Model 25 | from keras.layers import Input, Dense, Lambda 26 | from keras.layers import Flatten, Reshape, TimeDistributed 27 | from keras.layers.recurrent import GRU, LSTM 28 | from keras import backend as K 29 | from keras.callbacks import TensorBoard 30 | 31 | from librosa.display import waveplot, specshow 32 | sns.set(style='ticks') 33 | # seaborn.set(style='white') 34 | 35 | 36 | # ## Loading Data 37 | 38 | # In[2]: 39 | 40 | # Loaded Spoken Digits Dataset 41 | dbfile ='../SpokenDigitDB.pkl.gz' 42 | with gzip.open(dbfile, 'rb') as ifile: 43 | df = pickle.load(ifile) 44 | print('File loaded as '+ dbfile) 45 | 46 | df.head(n=3) 47 | 48 | 49 | # In[3]: 50 | 51 | # Distribution of Audio Duration 52 | a = [np.shape(x)[1] for x in df.Magnitude] 53 | b = [np.shape(x) for x in df.Wave] 54 | 55 | plt.figure(figsize=(6,4)) 56 | plt.subplot(211) 57 | sns.boxplot(a) 58 | 59 | plt.subplot(212) 60 | sns.boxplot(b) 61 | plt.tight_layout() 62 | 63 | 64 | # In[4]: 65 | 66 | # y = df.Wave[404][:5120] 67 | # s = librosa.stft(y,n_fft=128-1,hop_length=64) 68 | # s.shape #(64, 80) 69 | 70 | 71 | # In[5]: 72 | 73 | # Padding & Truncating 74 | smax = 80 # Max number of frames in STFT 75 | wmax = 5120 # Corresponding max number of samples 76 | spad = lambda a, n: a[:,0: n] if a.shape[1] > n else np.hstack((a, np.min(a[:])*np.ones([a.shape[0],n - a.shape[1]]))) 77 | wpad = lambda a, n: a[:n] if a.shape[0] > n else np.append(a,np.zeros(n-a.shape[0])) 78 | 79 | df.Magnitude = df.Magnitude.apply(spad,args=(smax,)) # MaxLen Truncation Voodoo :D 80 | df.Wave = df.Wave.apply(wpad,args=(wmax,)) 81 | 82 | print(np.unique([np.shape(x)[1] for x in df.Magnitude])) 83 | print(np.unique([np.shape(x)[0] for x in df.Wave])) 84 | 85 | 86 | # In[6]: 87 | 88 | # Plot K Random Examples 89 | k = 5 90 | sr = 8000 91 | 92 | sidx = random.sample(range(len(df)),k) 93 | sidx = np.append(sidx,sidx) 94 | 95 | sns.set(style='white') 96 | for i,j in enumerate(sidx): 97 | if i\n", 74 | "\n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | "
InputTarget
0Go.\\tVa !\\n
1Run!\\tCours !\\n
2Run!\\tCourez !\\n
3Wow!\\tÇa alors !\\n
4Fire!\\tAu feu !\\n
5Help!\\tÀ l'aide !\\n
6Jump.\\tSaute.\\n
7Stop!\\tÇa suffit !\\n
8Stop!\\tStop !\\n
9Stop!\\tArrête-toi !\\n
\n", 135 | "" 136 | ], 137 | "text/plain": [ 138 | " Input Target\n", 139 | "0 Go. \\tVa !\\n\n", 140 | "1 Run! \\tCours !\\n\n", 141 | "2 Run! \\tCourez !\\n\n", 142 | "3 Wow! \\tÇa alors !\\n\n", 143 | "4 Fire! \\tAu feu !\\n\n", 144 | "5 Help! \\tÀ l'aide !\\n\n", 145 | "6 Jump. \\tSaute.\\n\n", 146 | "7 Stop! \\tÇa suffit !\\n\n", 147 | "8 Stop! \\tStop !\\n\n", 148 | "9 Stop! \\tArrête-toi !\\n" 149 | ] 150 | }, 151 | "execution_count": 16, 152 | "metadata": {}, 153 | "output_type": "execute_result" 154 | } 155 | ], 156 | "source": [ 157 | "# Vectorize the data.\n", 158 | "input_texts = []\n", 159 | "target_texts = []\n", 160 | "input_characters = set()\n", 161 | "target_characters = set()\n", 162 | "lines = open(filename).read().split('\\n')\n", 163 | "for line in lines[: min(num_samples, len(lines) - 1)]:\n", 164 | " input_text, target_text = line.split('\\t')\n", 165 | " # We use \"tab\" as the \"start sequence\" character\n", 166 | " # for the targets, and \"\\n\" as \"end sequence\" character.\n", 167 | " target_text = '\\t' + target_text + '\\n'\n", 168 | " input_texts.append(input_text)\n", 169 | " target_texts.append(target_text)\n", 170 | " for char in input_text:\n", 171 | " if char not in input_characters:\n", 172 | " input_characters.add(char)\n", 173 | " for char in target_text:\n", 174 | " if char not in target_characters:\n", 175 | " target_characters.add(char)\n", 176 | "\n", 177 | "input_characters = sorted(list(input_characters))\n", 178 | "target_characters = sorted(list(target_characters))\n", 179 | "num_encoder_tokens = len(input_characters)\n", 180 | "num_decoder_tokens = len(target_characters)\n", 181 | "max_encoder_seq_length = max([len(txt) for txt in input_texts])\n", 182 | "max_decoder_seq_length = max([len(txt) for txt in target_texts])\n", 183 | "\n", 184 | "print('Number of samples:', len(input_texts))\n", 185 | "print('Number of unique input tokens:', num_encoder_tokens)\n", 186 | "print('Number of unique output tokens:', num_decoder_tokens)\n", 187 | "print('Max sequence length for inputs:', max_encoder_seq_length)\n", 188 | "print('Max sequence length for outputs:', max_decoder_seq_length)\n", 189 | "\n", 190 | "df = pd.DataFrame({'Input':input_texts,'Target':target_texts})\n", 191 | "df.head(n=10)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 10, 197 | "metadata": { 198 | "collapsed": true 199 | }, 200 | "outputs": [], 201 | "source": [ 202 | "input_token_index = dict(\n", 203 | " [(char, i) for i, char in enumerate(input_characters)])\n", 204 | "target_token_index = dict(\n", 205 | " [(char, i) for i, char in enumerate(target_characters)])\n", 206 | "\n", 207 | "encoder_input_data = np.zeros(\n", 208 | " (len(input_texts), max_encoder_seq_length, num_encoder_tokens),\n", 209 | " dtype='float32')\n", 210 | "decoder_input_data = np.zeros(\n", 211 | " (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n", 212 | " dtype='float32')\n", 213 | "decoder_target_data = np.zeros(\n", 214 | " (len(input_texts), max_decoder_seq_length, num_decoder_tokens),\n", 215 | " dtype='float32')\n", 216 | "\n", 217 | "for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):\n", 218 | " for t, char in enumerate(input_text):\n", 219 | " encoder_input_data[i, t, input_token_index[char]] = 1.\n", 220 | " for t, char in enumerate(target_text):\n", 221 | " # decoder_target_data is ahead of decoder_target_data by one timestep\n", 222 | " decoder_input_data[i, t, target_token_index[char]] = 1.\n", 223 | " if t > 0:\n", 224 | " # decoder_target_data will be ahead by one timestep\n", 225 | " # and will not include the start character.\n", 226 | " decoder_target_data[i, t - 1, target_token_index[char]] = 1." 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 5, 232 | "metadata": { 233 | "collapsed": false 234 | }, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "(10000, 16, 73)\n", 241 | "(10000, 63, 92)\n", 242 | "(10000, 63, 92)\n" 243 | ] 244 | } 245 | ], 246 | "source": [ 247 | "print(encoder_input_data.shape)\n", 248 | "print(decoder_input_data.shape)\n", 249 | "print(decoder_target_data.shape)" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "## Training" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "### Encoder Model" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": 6, 269 | "metadata": { 270 | "collapsed": false 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "# Define an input sequence and process it.\n", 275 | "encoder_inputs = Input(shape=(None, num_encoder_tokens),name='E-Input')\n", 276 | "encoder = GRU(latent_dim, return_state=True,name='Encoder')\n", 277 | "encoder_outputs, encoder_state = encoder(encoder_inputs) # Discard `encoder_outputs` and only keep the states." 278 | ] 279 | }, 280 | { 281 | "cell_type": "markdown", 282 | "metadata": { 283 | "collapsed": true 284 | }, 285 | "source": [ 286 | "### Decoder Model" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": 7, 292 | "metadata": { 293 | "collapsed": false 294 | }, 295 | "outputs": [], 296 | "source": [ 297 | "# Set up the decoder, using `encoder_states` as initial state.\n", 298 | "decoder_inputs = Input(shape=(None, num_decoder_tokens),name='D-Input')\n", 299 | "decoder_gru = GRU(latent_dim, return_sequences=True,return_state=True,name='Decoder')\n", 300 | "decoder_outputs,_ = decoder_gru(decoder_inputs,initial_state=encoder_state)\n", 301 | "decoder_dense = Dense(num_decoder_tokens, activation='softmax',name='Classifier')\n", 302 | "decoder_outputs = decoder_dense(decoder_outputs)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 8, 308 | "metadata": { 309 | "collapsed": false 310 | }, 311 | "outputs": [ 312 | { 313 | "name": "stdout", 314 | "output_type": "stream", 315 | "text": [ 316 | "____________________________________________________________________________________________________\n", 317 | "Layer (type) Output Shape Param # Connected to \n", 318 | "====================================================================================================\n", 319 | "E-Input (InputLayer) (None, None, 73) 0 \n", 320 | "____________________________________________________________________________________________________\n", 321 | "D-Input (InputLayer) (None, None, 92) 0 \n", 322 | "____________________________________________________________________________________________________\n", 323 | "Encoder (GRU) [(None, 256), (None, 253440 E-Input[0][0] \n", 324 | "____________________________________________________________________________________________________\n", 325 | "Decoder (GRU) [(None, None, 256), ( 268032 D-Input[0][0] \n", 326 | " Encoder[0][1] \n", 327 | "____________________________________________________________________________________________________\n", 328 | "Classifier (Dense) (None, None, 92) 23644 Decoder[0][0] \n", 329 | "====================================================================================================\n", 330 | "Total params: 545,116\n", 331 | "Trainable params: 545,116\n", 332 | "Non-trainable params: 0\n", 333 | "____________________________________________________________________________________________________\n" 334 | ] 335 | } 336 | ], 337 | "source": [ 338 | "# Model\n", 339 | "### Encoding\n", 340 | "# Define the model that will turn\n", 341 | "# `encoder_input_data` & `decoder_input_data` into `decoder_target_data`\n", 342 | "model = Model([encoder_inputs, decoder_inputs], decoder_outputs)\n", 343 | "model.summary()" 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "### Train Model" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 25, 356 | "metadata": { 357 | "collapsed": false 358 | }, 359 | "outputs": [ 360 | { 361 | "name": "stdout", 362 | "output_type": "stream", 363 | "text": [ 364 | "Train on 8000 samples, validate on 2000 samples\n", 365 | "Epoch 1/10\n", 366 | "8000/8000 [==============================] - 75s - loss: 0.4704 - val_loss: 0.5698\n", 367 | "Epoch 2/10\n", 368 | "8000/8000 [==============================] - 73s - loss: 0.4428 - val_loss: 0.5491\n", 369 | "Epoch 3/10\n", 370 | "8000/8000 [==============================] - 72s - loss: 0.4237 - val_loss: 0.5426\n", 371 | "Epoch 4/10\n", 372 | "8000/8000 [==============================] - 74s - loss: 0.4040 - val_loss: 0.5180\n", 373 | "Epoch 5/10\n", 374 | "8000/8000 [==============================] - 72s - loss: 0.3869 - val_loss: 0.5055\n", 375 | "Epoch 6/10\n", 376 | "8000/8000 [==============================] - 72s - loss: 0.3720 - val_loss: 0.4971\n", 377 | "Epoch 7/10\n", 378 | "8000/8000 [==============================] - 72s - loss: 0.3586 - val_loss: 0.4852\n", 379 | "Epoch 8/10\n", 380 | "8000/8000 [==============================] - 72s - loss: 0.3466 - val_loss: 0.4768\n", 381 | "Epoch 9/10\n", 382 | "8000/8000 [==============================] - 72s - loss: 0.3358 - val_loss: 0.4675\n", 383 | "Epoch 10/10\n", 384 | "8000/8000 [==============================] - 10372s - loss: 0.3250 - val_loss: 0.4648\n" 385 | ] 386 | }, 387 | { 388 | "data": { 389 | "text/plain": [ 390 | "" 391 | ] 392 | }, 393 | "execution_count": 25, 394 | "metadata": {}, 395 | "output_type": "execute_result" 396 | } 397 | ], 398 | "source": [ 399 | "# Run training\n", 400 | "model.compile(optimizer='rmsprop', loss='categorical_crossentropy')\n", 401 | "model.fit([encoder_input_data, decoder_input_data], decoder_target_data,\n", 402 | " batch_size=batch_size,\n", 403 | " epochs=10,\n", 404 | " validation_split=0.2)\n", 405 | "\n", 406 | "# model.save('s2s.h5')\n" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "## Inference\n", 414 | "Next: inference mode (sampling). Here's the drill:\n", 415 | "- encode input and retrieve initial decoder state\n", 416 | "- run one step of decoder with this initial state and a \"start of sequence\" token as target. Output will be the next target token\n", 417 | "- Repeat with the current target token and current states\n" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 26, 423 | "metadata": { 424 | "collapsed": false 425 | }, 426 | "outputs": [], 427 | "source": [ 428 | "### Define Sampling Models\n", 429 | "encoder_model = Model(encoder_inputs, encoder_state)\n", 430 | "\n", 431 | "decoder_state_input = Input(shape=(latent_dim,))\n", 432 | "decoder_outputs,decoder_state = decoder_gru(decoder_inputs, initial_state=decoder_state_input)\n", 433 | "\n", 434 | "decoder_outputs = decoder_dense(decoder_outputs)\n", 435 | "decoder_model = Model([decoder_inputs, decoder_state_input], [decoder_outputs, decoder_state])" 436 | ] 437 | }, 438 | { 439 | "cell_type": "code", 440 | "execution_count": 27, 441 | "metadata": { 442 | "collapsed": false 443 | }, 444 | "outputs": [ 445 | { 446 | "name": "stdout", 447 | "output_type": "stream", 448 | "text": [ 449 | "____________________________________________________________________________________________________\n", 450 | "Layer (type) Output Shape Param # Connected to \n", 451 | "====================================================================================================\n", 452 | "D-Input (InputLayer) (None, None, 92) 0 \n", 453 | "____________________________________________________________________________________________________\n", 454 | "input_2 (InputLayer) (None, 256) 0 \n", 455 | "____________________________________________________________________________________________________\n", 456 | "Decoder (GRU) [(None, None, 256), ( 268032 D-Input[0][0] \n", 457 | " input_2[0][0] \n", 458 | "____________________________________________________________________________________________________\n", 459 | "Classifier (Dense) (None, None, 92) 23644 Decoder[2][0] \n", 460 | "====================================================================================================\n", 461 | "Total params: 291,676\n", 462 | "Trainable params: 291,676\n", 463 | "Non-trainable params: 0\n", 464 | "____________________________________________________________________________________________________\n" 465 | ] 466 | } 467 | ], 468 | "source": [ 469 | "decoder_model.summary()" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": 28, 475 | "metadata": { 476 | "collapsed": true 477 | }, 478 | "outputs": [], 479 | "source": [ 480 | "# Reverse-lookup token index to decode sequences back to\n", 481 | "# something readable.\n", 482 | "reverse_input_char_index = dict(\n", 483 | " (i, char) for char, i in input_token_index.items())\n", 484 | "reverse_target_char_index = dict(\n", 485 | " (i, char) for char, i in target_token_index.items())" 486 | ] 487 | }, 488 | { 489 | "cell_type": "markdown", 490 | "metadata": {}, 491 | "source": [ 492 | "### Decoding Sequence" 493 | ] 494 | }, 495 | { 496 | "cell_type": "code", 497 | "execution_count": 29, 498 | "metadata": { 499 | "collapsed": true 500 | }, 501 | "outputs": [], 502 | "source": [ 503 | "def decode_sequence(input_seq):\n", 504 | " states_value = encoder_model.predict(input_seq) # Encode the input as state vectors.\n", 505 | " target_seq = np.zeros((1, 1, num_decoder_tokens)) # Generate empty target sequence of length 1.\n", 506 | " # Populate the first character of target sequence with the start character.\n", 507 | " target_seq[0, 0, target_token_index['\\t']] = 1.\n", 508 | "\n", 509 | " # Sampling loop for a batch of sequences\n", 510 | " # (to simplify, here we assume a batch of size 1).\n", 511 | " stop_condition = False\n", 512 | " decoded_sentence = ''\n", 513 | " while not stop_condition:\n", 514 | " output_tokens, h = decoder_model.predict([target_seq,states_value])\n", 515 | "\n", 516 | " # Sample a token\n", 517 | " sampled_token_index = np.argmax(output_tokens[0, -1, :])\n", 518 | " sampled_char = reverse_target_char_index[sampled_token_index]\n", 519 | " decoded_sentence += sampled_char\n", 520 | "\n", 521 | " # Exit condition: either hit max length\n", 522 | " # or find stop character.\n", 523 | " if (sampled_char == '\\n' or\n", 524 | " len(decoded_sentence) > max_decoder_seq_length):\n", 525 | " stop_condition = True\n", 526 | "\n", 527 | " # Update the target sequence (of length 1).\n", 528 | " target_seq = np.zeros((1, 1, num_decoder_tokens))\n", 529 | " target_seq[0, 0, sampled_token_index] = 1.\n", 530 | "\n", 531 | " # Update states\n", 532 | " states_value = h\n", 533 | "\n", 534 | " return decoded_sentence" 535 | ] 536 | }, 537 | { 538 | "cell_type": "code", 539 | "execution_count": 30, 540 | "metadata": { 541 | "collapsed": false 542 | }, 543 | "outputs": [ 544 | { 545 | "name": "stdout", 546 | "output_type": "stream", 547 | "text": [ 548 | "-\n", 549 | "Input sentence: Go.\n", 550 | "Decoded sentence: Restez aller !\n", 551 | "\n", 552 | "-\n", 553 | "Input sentence: Run!\n", 554 | "Decoded sentence: Restez aller !\n", 555 | "\n", 556 | "-\n", 557 | "Input sentence: Run!\n", 558 | "Decoded sentence: Restez aller !\n", 559 | "\n", 560 | "-\n", 561 | "Input sentence: Wow!\n", 562 | "Decoded sentence: Fais-le entrer.\n", 563 | "\n", 564 | "-\n", 565 | "Input sentence: Fire!\n", 566 | "Decoded sentence: Restez aller !\n", 567 | "\n" 568 | ] 569 | } 570 | ], 571 | "source": [ 572 | "for seq_index in range(5):\n", 573 | " # Take one sequence (part of the training test)\n", 574 | " # for trying out decoding.\n", 575 | " input_seq = encoder_input_data[seq_index: seq_index + 1]\n", 576 | " decoded_sentence = decode_sequence(input_seq)\n", 577 | " print('-')\n", 578 | " print('Input sentence:', input_texts[seq_index])\n", 579 | " print('Decoded sentence:', decoded_sentence)" 580 | ] 581 | }, 582 | { 583 | "cell_type": "code", 584 | "execution_count": null, 585 | "metadata": { 586 | "collapsed": true 587 | }, 588 | "outputs": [], 589 | "source": [] 590 | } 591 | ], 592 | "metadata": { 593 | "kernelspec": { 594 | "display_name": "Python [default]", 595 | "language": "python", 596 | "name": "python2" 597 | }, 598 | "language_info": { 599 | "codemirror_mode": { 600 | "name": "ipython", 601 | "version": 2 602 | }, 603 | "file_extension": ".py", 604 | "mimetype": "text/x-python", 605 | "name": "python", 606 | "nbconvert_exporter": "python", 607 | "pygments_lexer": "ipython2", 608 | "version": "2.7.12" 609 | } 610 | }, 611 | "nbformat": 4, 612 | "nbformat_minor": 1 613 | } 614 | -------------------------------------------------------------------------------- /SpokenDigitDB.pkl.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/SpokenDigitDB.pkl.gz -------------------------------------------------------------------------------- /VAE Audio 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/VAE Audio 1.png -------------------------------------------------------------------------------- /VAE Audio 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/VAE Audio 2.png -------------------------------------------------------------------------------- /VAE Audio 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/VAE Audio 3.png -------------------------------------------------------------------------------- /VAE Audio 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/VAE Audio 4.png -------------------------------------------------------------------------------- /attention.py: -------------------------------------------------------------------------------- 1 | # Define Frame Skipping Layer 2 | def FrameSkipper(x): 3 | return x[:,0::2,:] 4 | 5 | def FrameSkipper_output_shape(input_shape): 6 | ishape = list(input_shape) 7 | ishape[-2] = np.arange(0,ishape[-2],2).shape[0] 8 | return tuple(ishape) 9 | 10 | 11 | def Attention(x): 12 | hs = x[0] # source hidden state - Encoder layer 13 | ht = x[1] # target hidden state - Decoder layer 14 | 15 | # et = tf.matmul(ht,hs,transpose_a=True) # score(ht,hs) 16 | # # et = K.dot(ht,hs) 17 | # et = K.tanh(et) 18 | # at = K.exp(et) 19 | # at /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx()) 20 | _,source_sequence_length,num_units = K.int_shape(x) 21 | # Create an attention mechanism 22 | attention_mechanism = tf.contrib.seq2seq.LuongAttention( 23 | num_units, x,memory_sequence_length=source_sequence_length) 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | # Sample 34 | x = Input(shape=(16,64),name='Input') 35 | e = GRU(10,return_sequences=True,name='Encoder')(x) 36 | d = GRU(20,return_sequences=True,name='Decoder')(e) 37 | f = Flatten()(d) 38 | y = Dense(1,activation='sigmoid',name='Output')(f) 39 | 40 | model = Model(x,y) 41 | model.summary() 42 | model.compile(optimizer='sgd',loss='binary_crossentropy') 43 | 44 | 45 | 46 | d._keras_shape 47 | 48 | K.matmul(e,d) 49 | tf.matmul(e,d) 50 | 51 | #----- 52 | a = K.placeholder(shape=(None,2, 3)) 53 | b = K.placeholder(shape=(None,3, 4)) 54 | ab = K.dot(a, b) 55 | K.int_shape(ab) 56 | 57 | #----- 58 | a = K.placeholder(shape=(32, 28, 3)) 59 | b = K.placeholder(shape=(3, 4)) 60 | ab = K.dot(a, b) 61 | K.int_shape(ab) 62 | 63 | 64 | #----- 65 | a = K.placeholder(shape=(None,16,10)) 66 | b = K.placeholder(shape=(None,16,20)) 67 | ab = K.dot(a, b) 68 | K.int_shape(ab) 69 | 70 | 71 | -------------------------------------------------------------------------------- /custom_layer.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.engine.topology import Layer 3 | import numpy as np -------------------------------------------------------------------------------- /discovery_submit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -l 2 | # Name your job (used in the PBS output file names) 3 | #PBS -N GPUTEST 4 | # Specify the gpuq queue 5 | #PBS -q gpuq 6 | # Specify the number of gpus 7 | #PBS -l nodes=1:ppn=1:gpus=1 8 | # Specify the gpu feature 9 | #PBS -l feature=gpu 10 | # Specify your resource account (use qr command to determine) 11 | #PBS -A Physics 12 | # Specify how much time you think the job will run 13 | #PBS -l walltime=00:15:00 14 | # Have the job send you email when the job ends or aborts 15 | #PBS -M john.doe@dartmouth.edu 16 | #PBS -m ea 17 | # Join error and standard output into one file 18 | #PBS -j oe 19 | # Change to the directory that the job was submitted from 20 | cd $PBS_O_WORKDIR 21 | # Parse the PBS_GPUFILE to determine which GPU you have been assigned 22 | # and unset CUDA_VISIBLE_DEVICES 23 | gpuNum=`cat $PBS_GPUFILE | sed -e 's/.*-gpu//g'` 24 | unset CUDA_VISIBLE_DEVICES 25 | # if using PyCUDA set the CUDA_DEVICE environment variable 26 | export CUDA_DEVICE=$gpuNum 27 | # Pass the GPU number as an argument to your program 28 | program_name $gpuNum 29 | exit 0 -------------------------------------------------------------------------------- /handel.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/handel.wav -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496080787.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496080787.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496080839.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496080839.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496081175.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496081175.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496081237.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496081237.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496081534.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496081534.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496083815.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496083815.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496083988.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496083988.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496084330.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496084330.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496085039.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496085039.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496085339.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496085339.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496086800.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496086800.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496086841.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496086841.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496087979.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496087979.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496088679.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496088679.Cyrus -------------------------------------------------------------------------------- /logs/events.out.tfevents.1496088713.Cyrus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/logs/events.out.tfevents.1496088713.Cyrus -------------------------------------------------------------------------------- /reconet.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/reconet.h5 -------------------------------------------------------------------------------- /s2s.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/s2s.h5 -------------------------------------------------------------------------------- /sample_figure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/sample_figure.png -------------------------------------------------------------------------------- /sample_original.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/sample_original.wav -------------------------------------------------------------------------------- /sample_reconst.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thayermldac/vae/7caaec13d1a7e92ab44513437a9b90d39c39a781/sample_reconst.wav -------------------------------------------------------------------------------- /variational_autoencoder_deconv.py: -------------------------------------------------------------------------------- 1 | '''This script demonstrates how to build a variational autoencoder 2 | with Keras and deconvolution layers. 3 | 4 | Reference: "Auto-Encoding Variational Bayes" https://arxiv.org/abs/1312.6114 5 | ''' 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | from scipy.stats import norm 9 | 10 | from keras.layers import Input, Dense, Lambda, Flatten, Reshape, Layer 11 | from keras.layers import Conv2D, Conv2DTranspose 12 | from keras.models import Model 13 | from keras import backend as K 14 | from keras import metrics 15 | from keras.datasets import mnist 16 | 17 | # input image dimensions 18 | img_rows, img_cols, img_chns = 28, 28, 1 19 | # number of convolutional filters to use 20 | filters = 64 21 | # convolution kernel size 22 | num_conv = 3 23 | 24 | batch_size = 100 25 | if K.image_data_format() == 'channels_first': 26 | original_img_size = (img_chns, img_rows, img_cols) 27 | else: 28 | original_img_size = (img_rows, img_cols, img_chns) 29 | latent_dim = 2 30 | intermediate_dim = 128 31 | epsilon_std = 1.0 32 | epochs = 5 33 | 34 | x = Input(batch_shape=(batch_size,) + original_img_size) 35 | conv_1 = Conv2D(img_chns, 36 | kernel_size=(2, 2), 37 | padding='same', activation='relu')(x) 38 | conv_2 = Conv2D(filters, 39 | kernel_size=(2, 2), 40 | padding='same', activation='relu', 41 | strides=(2, 2))(conv_1) 42 | conv_3 = Conv2D(filters, 43 | kernel_size=num_conv, 44 | padding='same', activation='relu', 45 | strides=1)(conv_2) 46 | conv_4 = Conv2D(filters, 47 | kernel_size=num_conv, 48 | padding='same', activation='relu', 49 | strides=1)(conv_3) 50 | flat = Flatten()(conv_4) 51 | hidden = Dense(intermediate_dim, activation='relu')(flat) 52 | 53 | z_mean = Dense(latent_dim)(hidden) 54 | z_log_var = Dense(latent_dim)(hidden) 55 | 56 | 57 | def sampling(args): 58 | z_mean, z_log_var = args 59 | epsilon = K.random_normal(shape=(batch_size, latent_dim), 60 | mean=0., stddev=epsilon_std) 61 | return z_mean + K.exp(z_log_var) * epsilon 62 | 63 | # note that "output_shape" isn't necessary with the TensorFlow backend 64 | # so you could write `Lambda(sampling)([z_mean, z_log_var])` 65 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) 66 | 67 | # we instantiate these layers separately so as to reuse them later 68 | decoder_hid = Dense(intermediate_dim, activation='relu') 69 | decoder_upsample = Dense(filters * 14 * 14, activation='relu') 70 | 71 | if K.image_data_format() == 'channels_first': 72 | output_shape = (batch_size, filters, 14, 14) 73 | else: 74 | output_shape = (batch_size, 14, 14, filters) 75 | 76 | decoder_reshape = Reshape(output_shape[1:]) 77 | decoder_deconv_1 = Conv2DTranspose(filters, 78 | kernel_size=num_conv, 79 | padding='same', 80 | strides=1, 81 | activation='relu') 82 | decoder_deconv_2 = Conv2DTranspose(filters, num_conv, 83 | padding='same', 84 | strides=1, 85 | activation='relu') 86 | if K.image_data_format() == 'channels_first': 87 | output_shape = (batch_size, filters, 29, 29) 88 | else: 89 | output_shape = (batch_size, 29, 29, filters) 90 | decoder_deconv_3_upsamp = Conv2DTranspose(filters, 91 | kernel_size=(3, 3), 92 | strides=(2, 2), 93 | padding='valid', 94 | activation='relu') 95 | decoder_mean_squash = Conv2D(img_chns, 96 | kernel_size=2, 97 | padding='valid', 98 | activation='sigmoid') 99 | 100 | hid_decoded = decoder_hid(z) 101 | up_decoded = decoder_upsample(hid_decoded) 102 | reshape_decoded = decoder_reshape(up_decoded) 103 | deconv_1_decoded = decoder_deconv_1(reshape_decoded) 104 | deconv_2_decoded = decoder_deconv_2(deconv_1_decoded) 105 | x_decoded_relu = decoder_deconv_3_upsamp(deconv_2_decoded) 106 | x_decoded_mean_squash = decoder_mean_squash(x_decoded_relu) 107 | 108 | 109 | # Custom loss layer 110 | class CustomVariationalLayer(Layer): 111 | def __init__(self, **kwargs): 112 | self.is_placeholder = True 113 | super(CustomVariationalLayer, self).__init__(**kwargs) 114 | 115 | def vae_loss(self, x, x_decoded_mean_squash): 116 | x = K.flatten(x) 117 | x_decoded_mean_squash = K.flatten(x_decoded_mean_squash) 118 | xent_loss = img_rows * img_cols * metrics.binary_crossentropy(x, x_decoded_mean_squash) 119 | kl_loss = - 0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 120 | return K.mean(xent_loss + kl_loss) 121 | 122 | def call(self, inputs): 123 | x = inputs[0] 124 | x_decoded_mean_squash = inputs[1] 125 | loss = self.vae_loss(x, x_decoded_mean_squash) 126 | self.add_loss(loss, inputs=inputs) 127 | # We don't use this output. 128 | return x 129 | 130 | 131 | y = CustomVariationalLayer()([x, x_decoded_mean_squash]) 132 | vae = Model(x, y) 133 | vae.compile(optimizer='rmsprop', loss=None) 134 | vae.summary() 135 | 136 | # train the VAE on MNIST digits 137 | (x_train, _), (x_test, y_test) = mnist.load_data() 138 | 139 | x_train = x_train.astype('float32') / 255. 140 | x_train = x_train.reshape((x_train.shape[0],) + original_img_size) 141 | x_test = x_test.astype('float32') / 255. 142 | x_test = x_test.reshape((x_test.shape[0],) + original_img_size) 143 | 144 | print('x_train.shape:', x_train.shape) 145 | 146 | vae.fit(x_train, 147 | shuffle=True, 148 | epochs=epochs, 149 | batch_size=batch_size, 150 | validation_data=(x_test, x_test)) 151 | 152 | # build a model to project inputs on the latent space 153 | encoder = Model(x, z_mean) 154 | 155 | # display a 2D plot of the digit classes in the latent space 156 | x_test_encoded = encoder.predict(x_test, batch_size=batch_size) 157 | plt.figure(figsize=(6, 6)) 158 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 159 | plt.colorbar() 160 | plt.show() 161 | 162 | # build a digit generator that can sample from the learned distribution 163 | decoder_input = Input(shape=(latent_dim,)) 164 | _hid_decoded = decoder_hid(decoder_input) 165 | _up_decoded = decoder_upsample(_hid_decoded) 166 | _reshape_decoded = decoder_reshape(_up_decoded) 167 | _deconv_1_decoded = decoder_deconv_1(_reshape_decoded) 168 | _deconv_2_decoded = decoder_deconv_2(_deconv_1_decoded) 169 | _x_decoded_relu = decoder_deconv_3_upsamp(_deconv_2_decoded) 170 | _x_decoded_mean_squash = decoder_mean_squash(_x_decoded_relu) 171 | generator = Model(decoder_input, _x_decoded_mean_squash) 172 | 173 | # display a 2D manifold of the digits 174 | n = 15 # figure with 15x15 digits 175 | digit_size = 28 176 | figure = np.zeros((digit_size * n, digit_size * n)) 177 | # linearly spaced coordinates on the unit square were transformed through the inverse CDF (ppf) of the Gaussian 178 | # to produce values of the latent variables z, since the prior of the latent space is Gaussian 179 | grid_x = norm.ppf(np.linspace(0.05, 0.95, n)) 180 | grid_y = norm.ppf(np.linspace(0.05, 0.95, n)) 181 | 182 | for i, yi in enumerate(grid_x): 183 | for j, xi in enumerate(grid_y): 184 | z_sample = np.array([[xi, yi]]) 185 | z_sample = np.tile(z_sample, batch_size).reshape(batch_size, 2) 186 | x_decoded = generator.predict(z_sample, batch_size=batch_size) 187 | digit = x_decoded[0].reshape(digit_size, digit_size) 188 | figure[i * digit_size: (i + 1) * digit_size, 189 | j * digit_size: (j + 1) * digit_size] = digit 190 | 191 | plt.figure(figsize=(10, 10)) 192 | plt.imshow(figure, cmap='Greys_r') 193 | plt.show() 194 | --------------------------------------------------------------------------------