{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# High-level Keras (TF) Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "import numpy as np\n",
    "os.environ['KERAS_BACKEND'] = \"tensorflow\"\n",
    "import keras as K\n",
    "import tensorflow\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout, Flatten\n",
    "from keras.layers import Conv2D, MaxPooling2D, Dropout\n",
    "from common.params import *\n",
    "from common.utils import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# channels_last is faster\n",
    "K.backend.set_image_data_format('channels_last')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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.1.1\n",
      "Numpy:  1.13.3\n",
      "Tensorflow:  1.4.0\n",
      "tensorflow\n",
      "channels_last\n",
      "GPU:  ['Tesla K80']\n"
     ]
    }
   ],
   "source": [
    "print(\"OS: \", sys.platform)\n",
    "print(\"Python: \", sys.version)\n",
    "print(\"Keras: \", K.__version__)\n",
    "print(\"Numpy: \", np.__version__)\n",
    "print(\"Tensorflow: \", tensorflow.__version__)\n",
    "print(K.backend.backend())\n",
    "# Channels should be last (otherwise slow)\n",
    "print(K.backend.image_data_format())\n",
    "print(\"GPU: \", get_gpu_name())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ['TF_ENABLE_WINOGRAD_NONFUSED'] = '1'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_symbol():\n",
    "    model = Sequential()\n",
    "    \n",
    "    model.add(Conv2D(50, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))\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": 6,
   "metadata": {},
   "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": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Preparing train set...\n",
      "Preparing test set...\n",
      "(50000, 32, 32, 3) (10000, 32, 32, 3) (50000, 10) (10000, 10)\n",
      "float32 float32 int32 int32\n",
      "CPU times: user 829 ms, sys: 565 ms, total: 1.39 s\n",
      "Wall time: 1.39 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Data into format for library\n",
    "x_train, x_test, y_train, y_test = cifar_for_library(channel_first=False, 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": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 205 ms, sys: 0 ns, total: 205 ms\n",
      "Wall time: 204 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Load symbol\n",
    "sym = create_symbol()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 146 ms, sys: 4.38 ms, total: 150 ms\n",
      "Wall time: 150 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# Initialise model\n",
    "model = init_model(sym)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_1 (Conv2D)            (None, 32, 32, 50)        1400      \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 32, 32, 50)        22550     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 16, 16, 50)        0         \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 16, 16, 50)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_3 (Conv2D)            (None, 16, 16, 100)       45100     \n",
      "_________________________________________________________________\n",
      "conv2d_4 (Conv2D)            (None, 16, 16, 100)       90100     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 8, 8, 100)         0         \n",
      "_________________________________________________________________\n",
      "dropout_2 (Dropout)          (None, 8, 8, 100)         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": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "50000/50000 [==============================] - 26s 514us/step - loss: 1.8262 - acc: 0.3318\n",
      "Epoch 2/10\n",
      "50000/50000 [==============================] - 24s 478us/step - loss: 1.3565 - acc: 0.5100\n",
      "Epoch 3/10\n",
      "50000/50000 [==============================] - 24s 478us/step - loss: 1.1200 - acc: 0.5996\n",
      "Epoch 4/10\n",
      "50000/50000 [==============================] - 24s 478us/step - loss: 0.9835 - acc: 0.6507\n",
      "Epoch 5/10\n",
      "50000/50000 [==============================] - 24s 479us/step - loss: 0.8590 - acc: 0.6977\n",
      "Epoch 6/10\n",
      "50000/50000 [==============================] - 24s 479us/step - loss: 0.7826 - acc: 0.7261\n",
      "Epoch 7/10\n",
      "50000/50000 [==============================] - ETA: 0s - loss: 0.7106 - acc: 0.750 - 24s 479us/step - loss: 0.7107 - acc: 0.7503\n",
      "Epoch 8/10\n",
      "50000/50000 [==============================] - 24s 479us/step - loss: 0.6460 - acc: 0.7709\n",
      "Epoch 9/10\n",
      "50000/50000 [==============================] - 24s 478us/step - loss: 0.5953 - acc: 0.7895\n",
      "Epoch 10/10\n",
      "50000/50000 [==============================] - 24s 479us/step - loss: 0.5443 - acc: 0.8054\n",
      "CPU times: user 3min 9s, sys: 23.7 s, total: 3min 32s\n",
      "Wall time: 4min 1s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7fb6781eef98>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "# 241s\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": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 529 ms, sys: 92.4 ms, total: 621 ms\n",
      "Wall time: 1.39 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": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy:  0.773\n"
     ]
    }
   ],
   "source": [
    "print(\"Accuracy: \", sum(y_guess == y_truth)/len(y_guess))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "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": 1
}