{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# High-level Keras (Theano) Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using Theano backend.\n",
      "Using cuDNN version 6021 on context None\n",
      "Mapped name None to device cuda: Tesla K80 (BF4E:00:00.0)\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "import numpy as np\n",
    "os.environ['KERAS_BACKEND'] = \"theano\"\n",
    "import keras as K\n",
    "import theano\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout, Flatten\n",
    "from keras.layers import Conv2D, MaxPooling2D\n",
    "from common.params import *\n",
    "from common.utils import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# channels_first is faster\n",
    "K.backend.set_image_data_format('channels_first')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OS:  linux\n",
      "Python:  3.5.2 |Anaconda custom (64-bit)| (default, Jul  2 2016, 17:53:06) \n",
      "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]\n",
      "Keras:  2.0.8\n",
      "Numpy:  1.13.1\n",
      "Theano:  0.10.0beta1.dev-RELEASE\n",
      "theano\n",
      "channels_first\n"
     ]
    }
   ],
   "source": [
    "print(\"OS: \", sys.platform)\n",
    "print(\"Python: \", sys.version)\n",
    "print(\"Keras: \", K.__version__)\n",
    "print(\"Numpy: \", np.__version__)\n",
    "print(\"Theano: \", theano.__version__)\n",
    "print(K.backend.backend())\n",
    "# Should be channels-first, otherwise slow\n",
    "print(K.backend.image_data_format())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#CuDNN auto-tune\n",
    "theano.config.dnn.conv.algo_fwd = \"time_once\"\n",
    "theano.config.dnn.conv.algo_bwd_filter = \"time_once\"\n",
    "theano.config.dnn.conv.algo_bwd_data = \"time_once\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def create_symbol():\n",
    "    model = Sequential()\n",
    "    \n",
    "    model.add(Conv2D(50, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(3, 32, 32)))\n",
    "    model.add(Conv2D(50, kernel_size=(3, 3), padding='same', activation='relu'))    \n",
    "    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))\n",
    "    model.add(Dropout(0.25))\n",
    "    \n",
    "    model.add(Conv2D(100, kernel_size=(3, 3), padding='same', activation='relu'))\n",
    "    model.add(Conv2D(100, kernel_size=(3, 3), padding='same', activation='relu'))    \n",
    "    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))\n",
    "    model.add(Dropout(0.25))\n",
    "        \n",
    "    model.add(Flatten())\n",
    "    model.add(Dense(512, activation='relu'))\n",
    "    model.add(Dropout(0.5))\n",
    "    model.add(Dense(N_CLASSES, activation='softmax'))\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def init_model(m):\n",
    "    m.compile(\n",
    "        loss = \"categorical_crossentropy\",\n",
    "        optimizer = K.optimizers.SGD(LR, MOMENTUM),\n",
    "        metrics = ['accuracy'])\n",
    "    return m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz\n",
      "Done.\n",
      "Extracting files...\n",
      "Done.\n",
      "Preparing train set...\n",
      "Preparing test set...\n",
      "Done.\n",
      "(50000, 3, 32, 32) (10000, 3, 32, 32) (50000, 10) (10000, 10)\n",
      "float32 float32 int32 int32\n",
      "CPU times: user 2.92 s, sys: 1.43 s, total: 4.34 s\n",
      "Wall time: 27.7 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Data into format for library\n",
    "x_train, x_test, y_train, y_test = cifar_for_library(channel_first=True, one_hot=True)\n",
    "print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)\n",
    "print(x_train.dtype, x_test.dtype, y_train.dtype, y_test.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 964 ms, sys: 116 ms, total: 1.08 s\n",
      "Wall time: 3.16 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Load symbol\n",
    "sym = create_symbol()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 12 ms, sys: 0 ns, total: 12 ms\n",
      "Wall time: 11.3 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Initialise model\n",
    "model = init_model(sym)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_1 (Conv2D)            (None, 50, 32, 32)        1400      \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 50, 32, 32)        22550     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 50, 16, 16)        0         \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 50, 16, 16)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_3 (Conv2D)            (None, 100, 16, 16)       45100     \n",
      "_________________________________________________________________\n",
      "conv2d_4 (Conv2D)            (None, 100, 16, 16)       90100     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 100, 8, 8)         0         \n",
      "_________________________________________________________________\n",
      "dropout_2 (Dropout)          (None, 100, 8, 8)         0         \n",
      "_________________________________________________________________\n",
      "flatten_1 (Flatten)          (None, 6400)              0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 512)               3277312   \n",
      "_________________________________________________________________\n",
      "dropout_3 (Dropout)          (None, 512)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 10)                5130      \n",
      "=================================================================\n",
      "Total params: 3,441,592\n",
      "Trainable params: 3,441,592\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "50000/50000 [==============================] - 22s - loss: 1.8528 - acc: 0.3227    \n",
      "Epoch 2/10\n",
      "50000/50000 [==============================] - 25s - loss: 1.4089 - acc: 0.4873    \n",
      "Epoch 3/10\n",
      "50000/50000 [==============================] - 25s - loss: 1.1726 - acc: 0.5821    \n",
      "Epoch 4/10\n",
      "50000/50000 [==============================] - 25s - loss: 1.0034 - acc: 0.6460    \n",
      "Epoch 5/10\n",
      "50000/50000 [==============================] - 26s - loss: 0.8888 - acc: 0.6873    \n",
      "Epoch 6/10\n",
      "50000/50000 [==============================] - 26s - loss: 0.7867 - acc: 0.7238    \n",
      "Epoch 7/10\n",
      "50000/50000 [==============================] - 26s - loss: 0.7200 - acc: 0.7473    \n",
      "Epoch 8/10\n",
      "50000/50000 [==============================] - 26s - loss: 0.6515 - acc: 0.7722    \n",
      "Epoch 9/10\n",
      "50000/50000 [==============================] - 27s - loss: 0.5975 - acc: 0.7897    - ETA: 1s - \n",
      "Epoch 10/10\n",
      "50000/50000 [==============================] - 27s - loss: 0.5483 - acc: 0.8055    \n",
      "CPU times: user 2min 25s, sys: 51.5 s, total: 3min 17s\n",
      "Wall time: 4min 29s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7fb1a4244908>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "# Train model\n",
    "model.fit(x_train,\n",
    "          y_train,\n",
    "          batch_size=BATCHSIZE,\n",
    "          epochs=EPOCHS,\n",
    "          verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 6.33 s, sys: 408 ms, total: 6.74 s\n",
      "Wall time: 8.27 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "y_guess = model.predict(x_test, batch_size=BATCHSIZE)\n",
    "y_guess = np.argmax(y_guess, axis=-1)\n",
    "y_truth = np.argmax(y_test, axis=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy:  0.7783\n"
     ]
    }
   ],
   "source": [
    "print(\"Accuracy: \", sum(y_guess == y_truth)/len(y_guess))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}