{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "# import tensorflow.keras as keras\n",
    "import keras\n",
    "import numpy as np\n",
    "\n",
    "from keras.initializers import glorot_uniform, uniform\n",
    "\n",
    "from keras.datasets import mnist\n",
    "from keras.layers import Dense, BatchNormalization, Dropout"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Функция загрузки данных из датасета"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def prepare_data_for_nn():\n",
    "    (train_X, train_y), (test_X, test_y) = mnist.load_data()\n",
    "\n",
    "    train_X = (train_X / (train_X.max() / 2) - 1).reshape((-1, 784))\n",
    "    test_X = (test_X / (test_X.max() / 2) - 1).reshape((-1, 784))\n",
    "    # train_y, test_y = [keras.utils.to_categorical(t) for t in (train_y, test_y)]\n",
    "\n",
    "    return train_X, train_y, test_X, test_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_X, train_y, test_X, test_y = prepare_data_for_nn()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Модель\n",
    "\n",
    "Наследует от класса `keras.Model`, 4 слоя. Слои определяются внутри `__init__`, функция `call` отвечает за \"соединение\" слоев, т.е. за создание правильной архитектуры. На вход `call` передаются входные данные сети.\n",
    "\n",
    "Размерность входных данных и выходные размерности слоев вычисляются автоматически.\n",
    "\n",
    "Функции активации, количество нейронов и инициализаторы передаются в конструктор слоя `keras.layers.Dense`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import keras\n",
    "\n",
    "class SimpleMLP(keras.Model):\n",
    "\n",
    "    def __init__(self, use_bn=False, use_dp=False, num_classes=10, initializer='uniform'):\n",
    "        super(SimpleMLP, self).__init__(name='mlp')\n",
    "        self.use_bn = use_bn\n",
    "        self.use_dp = use_dp\n",
    "        self.num_classes = num_classes\n",
    "        \n",
    "        units = 128\n",
    "        self.dense1 = keras.layers.Dense(units, activation='tanh', kernel_initializer=initializer)\n",
    "        self.dense2 = keras.layers.Dense(units, activation='tanh', kernel_initializer=initializer)\n",
    "        self.dense3 = keras.layers.Dense(units, activation='tanh', kernel_initializer=initializer)\n",
    "        self.dense4 = keras.layers.Dense(num_classes, activation='softmax', kernel_initializer=initializer)\n",
    "\n",
    "        if self.use_dp:\n",
    "            self.dp = keras.layers.Dropout(0.5)\n",
    "        if self.use_bn:\n",
    "            self.bn = keras.layers.BatchNormalization(axis=-1)\n",
    "\n",
    "    def call(self, inputs):\n",
    "        x = self.dense1(inputs)\n",
    "        if self.use_bn:\n",
    "            x = self.bn(x)\n",
    "        x = self.dense2(x)\n",
    "        if self.use_dp:\n",
    "            x = self.dp(x)\n",
    "        x = self.dense3(x)\n",
    "        x = self.dense4(x)\n",
    "        return x\n",
    "\n",
    "                    \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Опциональная ячейка для \"очистки\" сессии \n",
    "\n",
    "Может быть полезна при работе  сtensorboard, \"очищает\" граф и делает визуализацию более понятной. Обученная модель при вызове стирается, **будьте осторожны**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import keras.backend as K\n",
    "# K.clear_session()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Создание модели, компиляция, обучение"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/10\n",
      "60000/60000 [==============================] - 2s 42us/step - loss: 1.4157 - sparse_categorical_accuracy: 0.5867 - val_loss: 0.5401 - val_sparse_categorical_accuracy: 0.8459\n",
      "Epoch 2/10\n",
      "60000/60000 [==============================] - 2s 39us/step - loss: 0.4145 - sparse_categorical_accuracy: 0.8821 - val_loss: 0.3192 - val_sparse_categorical_accuracy: 0.9063\n",
      "Epoch 3/10\n",
      "60000/60000 [==============================] - 3s 43us/step - loss: 0.2902 - sparse_categorical_accuracy: 0.9159 - val_loss: 0.2585 - val_sparse_categorical_accuracy: 0.9257\n",
      "Epoch 4/10\n",
      "60000/60000 [==============================] - 3s 43us/step - loss: 0.2260 - sparse_categorical_accuracy: 0.9342 - val_loss: 0.1946 - val_sparse_categorical_accuracy: 0.9433\n",
      "Epoch 5/10\n",
      "60000/60000 [==============================] - 3s 45us/step - loss: 0.1841 - sparse_categorical_accuracy: 0.9464 - val_loss: 0.1673 - val_sparse_categorical_accuracy: 0.9505\n",
      "Epoch 6/10\n",
      "60000/60000 [==============================] - 3s 46us/step - loss: 0.1553 - sparse_categorical_accuracy: 0.9550 - val_loss: 0.1429 - val_sparse_categorical_accuracy: 0.9571\n",
      "Epoch 7/10\n",
      "60000/60000 [==============================] - 3s 47us/step - loss: 0.1352 - sparse_categorical_accuracy: 0.9605 - val_loss: 0.1342 - val_sparse_categorical_accuracy: 0.9606\n",
      "Epoch 8/10\n",
      "60000/60000 [==============================] - 3s 46us/step - loss: 0.1196 - sparse_categorical_accuracy: 0.9651 - val_loss: 0.1352 - val_sparse_categorical_accuracy: 0.9574\n",
      "Epoch 9/10\n",
      "60000/60000 [==============================] - 3s 42us/step - loss: 0.1075 - sparse_categorical_accuracy: 0.9690 - val_loss: 0.1316 - val_sparse_categorical_accuracy: 0.9606\n",
      "Epoch 10/10\n",
      "60000/60000 [==============================] - 3s 45us/step - loss: 0.0961 - sparse_categorical_accuracy: 0.9724 - val_loss: 0.1131 - val_sparse_categorical_accuracy: 0.9651\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f0ba8e42518>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = SimpleMLP(initializer='uniform')\n",
    "\n",
    "model.compile(optimizer=keras.optimizers.SGD(),\n",
    "              loss=keras.losses.sparse_categorical_crossentropy,\n",
    "              metrics=[keras.metrics.sparse_categorical_accuracy],\n",
    "             )\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Использование callback'a TensorBoard для записи данных в формате tensorbaord\n",
    "\n",
    "* `log_dir` - директория для записи\n",
    "* `histogram_frequency` - частота записи гистограм (весов, сдвигов ..., градиентов) - в _эпохах_. Для записи с частотой до батча требуется модифицировать callback, [см. здесь](https://keras.io/callbacks/#lambdacallback)\n",
    "* `write_grads` - нужно ли записывать градиенты\n",
    "* Еще рекомендую по той же ссылке посмотреть описания callback'ов `History`, `LearningRateScheduler`, `EarlyStopping`, `ModelCheckpoint`, по возможности использовать их при обучении моделей (часто экономят много времени)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.fit(train_X, train_y, \n",
    "          validation_data=(test_X, test_y), \n",
    "          epochs=10,\n",
    "          callbacks=[TensorBoard(log_dir='./uniform', histogram_freq=1, write_grads=True)],         \n",
    "         )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Просмотр данных в tensorboard\n",
    "\n",
    "Смотрим результаты в tensorboard так:\n",
    "\n",
    "* Открываем терминал и (подключаемся по ssh, если необходимо) заходим в директорию, где расположена папка с логами (uniform или xavier или ваш вариант).\n",
    "* Запускаем tensorboard: `tensorboard --logdir <путь до директории>`, например, `tensorboard --logdir ./uniform`. Опционально можно указать абсолютный путь\n",
    "* Открываем в браузере `localhost:6006` или `<host_ip>:6006`, смотрим графики в веб-интрфейсе (справа сверху меню, пункт гистограммы)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Еще одна модель с инициализацией Ксавье"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/10\n",
      "60000/60000 [==============================] - 3s 42us/step - loss: 0.4863 - sparse_categorical_accuracy: 0.8678 - val_loss: 0.2748 - val_sparse_categorical_accuracy: 0.9207\n",
      "Epoch 2/10\n",
      "60000/60000 [==============================] - 2s 41us/step - loss: 0.2493 - sparse_categorical_accuracy: 0.9271 - val_loss: 0.2159 - val_sparse_categorical_accuracy: 0.9344\n",
      "Epoch 3/10\n",
      "60000/60000 [==============================] - 3s 42us/step - loss: 0.1963 - sparse_categorical_accuracy: 0.9418 - val_loss: 0.1754 - val_sparse_categorical_accuracy: 0.9483\n",
      "Epoch 4/10\n",
      "60000/60000 [==============================] - 3s 42us/step - loss: 0.1621 - sparse_categorical_accuracy: 0.9515 - val_loss: 0.1596 - val_sparse_categorical_accuracy: 0.9542\n",
      "Epoch 5/10\n",
      "60000/60000 [==============================] - 2s 40us/step - loss: 0.1381 - sparse_categorical_accuracy: 0.9591 - val_loss: 0.1432 - val_sparse_categorical_accuracy: 0.9561\n",
      "Epoch 6/10\n",
      "60000/60000 [==============================] - 3s 44us/step - loss: 0.1207 - sparse_categorical_accuracy: 0.9643 - val_loss: 0.1282 - val_sparse_categorical_accuracy: 0.9622\n",
      "Epoch 7/10\n",
      "60000/60000 [==============================] - 3s 46us/step - loss: 0.1071 - sparse_categorical_accuracy: 0.9682 - val_loss: 0.1159 - val_sparse_categorical_accuracy: 0.9647\n",
      "Epoch 8/10\n",
      "60000/60000 [==============================] - 3s 44us/step - loss: 0.0959 - sparse_categorical_accuracy: 0.9716 - val_loss: 0.1114 - val_sparse_categorical_accuracy: 0.9677\n",
      "Epoch 9/10\n",
      "60000/60000 [==============================] - 3s 43us/step - loss: 0.0863 - sparse_categorical_accuracy: 0.9748 - val_loss: 0.1007 - val_sparse_categorical_accuracy: 0.9684\n",
      "Epoch 10/10\n",
      "60000/60000 [==============================] - 3s 43us/step - loss: 0.0783 - sparse_categorical_accuracy: 0.9770 - val_loss: 0.0962 - val_sparse_categorical_accuracy: 0.9707\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f0b91085ef0>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = SimpleMLP(initializer='glorot_uniform')\n",
    "\n",
    "model.compile(optimizer=keras.optimizers.SGD(),\n",
    "              loss=keras.losses.sparse_categorical_crossentropy,\n",
    "              metrics=[keras.metrics.sparse_categorical_accuracy],\n",
    "             )\n",
    "\n",
    "model.fit(train_X, train_y, \n",
    "          validation_data=(test_X, test_y), \n",
    "          epochs=10,\n",
    "          callbacks=[TensorBoard(log_dir='./xavier', histogram_freq=1, write_grads=True)],         \n",
    "         )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_graphs(test_log, 'accuracy')"
   ]
  }
 ],
 "metadata": {
  "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.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
