{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CS 20 : TensorFlow for Deep Learning Research\n",
    "## Lecture 03 : Linear and Logistic Regression\n",
    "### Linear Regression with tf.data\n",
    "\n",
    "**Reference**\n",
    "\n",
    "* https://jhui.github.io/2017/11/21/TensorFlow-Importing-data/\n",
    "* https://towardsdatascience.com/how-to-use-dataset-in-tensorflow-c758ef9e4428\n",
    "* https://stackoverflow.com/questions/47356764/how-to-use-tensorflow-dataset-api-with-training-and-validation-sets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.12.0\n"
     ]
    }
   ],
   "source": [
    "import os, sys\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import tensorflow as tf\n",
    "from pprint import pprint\n",
    "%matplotlib inline\n",
    "\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build input pipeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_6.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_7.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_5.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_4.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_14.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_10.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_1.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_11.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_13.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_3.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_2.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_12.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_9.txt',\n",
      " '../data/lecture03/example_with_data/train_dir/birth_life_2010_tr_8.txt']\n"
     ]
    }
   ],
   "source": [
    "train_dir = os.listdir('../data/lecture03/example_with_data/train_dir/')\n",
    "train_dir = list(map(lambda path : '../data/lecture03/example_with_data/train_dir/' + path, train_dir))\n",
    "pprint(train_dir, compact = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'../data/lecture03/example_with_data/val_dir/birth_life_2010_val.txt'\n"
     ]
    }
   ],
   "source": [
    "val_dir = '../data/lecture03/example_with_data/val_dir/birth_life_2010_val.txt'\n",
    "pprint(val_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# hyper parameters\n",
    "epochs = 100\n",
    "batch_size = 8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# datasets construction\n",
    "# for training dataset\n",
    "tr_dataset = tf.data.TextLineDataset(filenames = train_dir)\n",
    "tr_dataset = tr_dataset.map(lambda record : tf.decode_csv(records = record,\n",
    "                                                          record_defaults = [[''],[.0],[.0]],\n",
    "                                                          field_delim = '\\t')[1:])\n",
    "tr_dataset = tr_dataset.shuffle(200)\n",
    "tr_dataset = tr_dataset.batch(batch_size = batch_size)\n",
    "tr_iterator = tr_dataset.make_initializable_iterator()\n",
    "\n",
    "# for validation dataset\n",
    "val_dataset = tf.data.TextLineDataset(filenames = val_dir)\n",
    "val_dataset = val_dataset.map(lambda record : tf.decode_csv(records = record,\n",
    "                                                          record_defaults = [[''],[.0],[.0]],\n",
    "                                                          field_delim = '\\t')[1:])\n",
    "val_dataset = val_dataset.batch(batch_size = batch_size)\n",
    "val_iterator = val_dataset.make_initializable_iterator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# handle constructions. Handle allows us to feed data from different dataset by providing a parameter in feed_dict \n",
    "handle = tf.placeholder(dtype = tf.string)\n",
    "iterator = tf.data.Iterator.from_string_handle(string_handle = handle,\n",
    "                                               output_types = tr_iterator.output_types)\n",
    "X, Y = iterator.get_next()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "sess_config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True))\n",
    "sess = tf.Session(config = sess_config)\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the graph of Simple Linear Regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create weight and bias, initialized to 0 \n",
    "w = tf.get_variable(name = 'weight', initializer = tf.constant(.0))\n",
    "b = tf.get_variable(name = 'bias', initializer = tf.constant(.0))\n",
    "\n",
    "# construct model to predict Y\n",
    "yhat = X * w + b\n",
    "\n",
    "# use the square error as loss function\n",
    "mse_loss = tf.reduce_mean(tf.square(Y - yhat))\n",
    "mse_loss_summ = tf.summary.scalar(name = 'mse_loss', tensor = mse_loss) # for tensorboard\n",
    "\n",
    "# using gradient descent with learning rate of 0.01 to minimize loss\n",
    "opt = tf.train.GradientDescentOptimizer(learning_rate=.01)\n",
    "training_op = opt.minimize(mse_loss)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_writer = tf.summary.FileWriter(logdir = '../graphs/lecture03/linreg_mse_with_tf_data/train',\n",
    "                                     graph = tf.get_default_graph())\n",
    "val_writer = tf.summary.FileWriter(logdir = '../graphs/lecture03/linreg_mse_with_tf_data/val',\n",
    "                                     graph = tf.get_default_graph())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch :   0, tr_loss : 1757.168, val_loss : 1228.869\n",
      "epoch :  10, tr_loss : 376.397, val_loss : 347.431\n",
      "epoch :  20, tr_loss : 119.488, val_loss : 131.623\n",
      "epoch :  30, tr_loss : 57.805, val_loss : 56.236\n",
      "epoch :  40, tr_loss : 40.083, val_loss : 41.398\n",
      "epoch :  50, tr_loss : 35.828, val_loss : 37.847\n",
      "epoch :  60, tr_loss : 33.837, val_loss : 38.415\n",
      "epoch :  70, tr_loss : 33.972, val_loss : 37.400\n",
      "epoch :  80, tr_loss : 33.842, val_loss : 37.901\n",
      "epoch :  90, tr_loss : 33.386, val_loss : 38.766\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "# hyper parameters\n",
    "epochs = 100\n",
    "batch_size = 8\n",
    "'''\n",
    "\n",
    "tr_loss_hist = []\n",
    "val_loss_hist = []\n",
    "\n",
    "sess = tf.Session()\n",
    "sess.run(tf.global_variables_initializer())\n",
    "tr_handle, val_handle = sess.run(fetches = [tr_iterator.string_handle(), val_iterator.string_handle()])\n",
    "\n",
    "for epoch in range(epochs):\n",
    "\n",
    "    avg_tr_loss = 0\n",
    "    avg_val_loss = 0\n",
    "    tr_step = 0\n",
    "    val_step = 0\n",
    "    \n",
    "    # for mini-batch training\n",
    "    sess.run(tr_iterator.initializer)\n",
    "    try:\n",
    "        while True:\n",
    "            _, tr_loss, tr_loss_summ = sess.run(fetches = [training_op, mse_loss, mse_loss_summ], feed_dict = {handle : tr_handle})\n",
    "            avg_tr_loss += tr_loss\n",
    "            tr_step += 1\n",
    "\n",
    "    except tf.errors.OutOfRangeError:\n",
    "        pass\n",
    "    \n",
    "    # for validation\n",
    "    sess.run(val_iterator.initializer)\n",
    "    try:\n",
    "        while True:\n",
    "            val_loss, val_loss_summ = sess.run(fetches = [mse_loss, mse_loss_summ], feed_dict = {handle : val_handle})\n",
    "            avg_val_loss += val_loss\n",
    "            val_step += 1\n",
    "    \n",
    "    except tf.errors.OutOfRangeError:\n",
    "        pass\n",
    "    \n",
    "    train_writer.add_summary(tr_loss_summ, global_step = epoch)\n",
    "    val_writer.add_summary(val_loss_summ, global_step = epoch)\n",
    "    \n",
    "    avg_tr_loss /= tr_step\n",
    "    avg_val_loss /= val_step\n",
    "    \n",
    "    tr_loss_hist.append(avg_tr_loss)\n",
    "    val_loss_hist.append(avg_val_loss)\n",
    "    \n",
    "    if epoch % 10 == 0:\n",
    "        print('epoch : {:3}, tr_loss : {:.3f}, val_loss : {:.3f}'.format(epoch, avg_tr_loss, avg_val_loss))\n",
    "\n",
    "train_writer.close()\n",
    "val_writer.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x11e0651d0>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(tr_loss_hist, label = 'train')\n",
    "plt.plot(val_loss_hist, label = 'validation')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x11e0e7ef0>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "data = pd.read_table('../data/lecture03/example_with_placeholder/birth_life_2010.txt') # loading data for Visualization\n",
    "w_out, b_out = sess.run([w, b])\n",
    "plt.plot(data.iloc[:,1], data.iloc[:,2], 'bo', label='Real data')\n",
    "plt.plot(data.iloc[:,1], data.iloc[:,1] * w_out + b_out, 'r', label='Predicted data')\n",
    "plt.legend()"
   ]
  }
 ],
 "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.6"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}