{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# High-level Keras (CNTK) Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using CNTK backend\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "import numpy as np\n",
    "os.environ['KERAS_BACKEND'] = \"cntk\"\n",
    "import keras as K\n",
    "import cntk\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": 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",
      "CNTK:  2.2\n",
      "cntk\n",
      "channels_first\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(\"CNTK: \", cntk.__version__)\n",
    "print(K.backend.backend())\n",
    "# Should be channels-first, otherwise slow\n",
    "print(K.backend.image_data_format())\n",
    "print(\"GPU: \", get_gpu_name())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "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=(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": {},
   "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": [
      "Preparing train set...\n",
      "Preparing test set...\n",
      "(50000, 3, 32, 32) (10000, 3, 32, 32) (50000, 10) (10000, 10)\n",
      "float32 float32 int32 int32\n",
      "CPU times: user 876 ms, sys: 535 ms, total: 1.41 s\n",
      "Wall time: 1.41 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 189 ms, sys: 232 ms, total: 420 ms\n",
      "Wall time: 429 ms\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 4.89 ms, sys: 1.74 ms, total: 6.63 ms\n",
      "Wall time: 6.61 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 [==============================] - 20s 409us/step - loss: 1.8268 - acc: 0.3311\n",
      "Epoch 2/10\n",
      "50000/50000 [==============================] - 19s 385us/step - loss: 1.3521 - acc: 0.5112\n",
      "Epoch 3/10\n",
      "50000/50000 [==============================] - 19s 385us/step - loss: 1.1328 - acc: 0.5959\n",
      "Epoch 4/10\n",
      "50000/50000 [==============================] - 19s 387us/step - loss: 0.9807 - acc: 0.6517\n",
      "Epoch 5/10\n",
      "50000/50000 [==============================] - 19s 385us/step - loss: 0.8652 - acc: 0.6922\n",
      "Epoch 6/10\n",
      "50000/50000 [==============================] - 19s 386us/step - loss: 0.7804 - acc: 0.7242\n",
      "Epoch 7/10\n",
      "50000/50000 [==============================] - 19s 387us/step - loss: 0.7033 - acc: 0.7514\n",
      "Epoch 8/10\n",
      "50000/50000 [==============================] - 19s 386us/step - loss: 0.6422 - acc: 0.7734\n",
      "Epoch 9/10\n",
      "50000/50000 [==============================] - 19s 385us/step - loss: 0.5917 - acc: 0.7911\n",
      "Epoch 10/10\n",
      "50000/50000 [==============================] - 19s 386us/step - loss: 0.5363 - acc: 0.8099\n",
      "CPU times: user 2min 44s, sys: 29.2 s, total: 3min 14s\n",
      "Wall time: 3min 14s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7fc8a856ac50>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%time\n",
    "# 194s\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 1.06 s, sys: 225 ms, total: 1.29 s\n",
      "Wall time: 1.46 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.7687\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
}