{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.152526Z",
     "start_time": "2018-10-25T22:13:37.503680Z"
    }
   },
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "\n",
    "import lightgbm as lgb\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "try:\n",
    "    # To enable interactive mode you should install ipywidgets\n",
    "    # https://github.com/jupyter-widgets/ipywidgets\n",
    "    from ipywidgets import interact, SelectMultiple\n",
    "    INTERACTIVE = True\n",
    "except ImportError:\n",
    "    INTERACTIVE = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.238695Z",
     "start_time": "2018-10-25T22:13:39.160165Z"
    }
   },
   "outputs": [],
   "source": [
    "regression_example_dir = Path().absolute().parents[1] / 'regression'\n",
    "df_train = pd.read_csv(str(regression_example_dir / 'regression.train'), header=None, sep='\\t')\n",
    "df_test = pd.read_csv(str(regression_example_dir / 'regression.test'), header=None, sep='\\t')\n",
    "\n",
    "y_train = df_train[0]\n",
    "y_test = df_test[0]\n",
    "X_train = df_train.drop(0, axis=1)\n",
    "X_test = df_test.drop(0, axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create Dataset object for LightGBM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "lgb_train = lgb.Dataset(X_train, y_train)\n",
    "lgb_test = lgb.Dataset(X_test, y_test, reference=lgb_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configuration dictionary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.243104Z",
     "start_time": "2018-10-25T22:13:39.240578Z"
    }
   },
   "outputs": [],
   "source": [
    "params = {\n",
    "    'num_leaves': 5,\n",
    "    'metric': ['l1', 'l2'],\n",
    "    'verbose': -1\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.336630Z",
     "start_time": "2018-10-25T22:13:39.246006Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10]\ttraining's l1: 0.457448\ttraining's l2: 0.217995\tvalid_1's l1: 0.456464\tvalid_1's l2: 0.21641\n",
      "[20]\ttraining's l1: 0.436869\ttraining's l2: 0.205099\tvalid_1's l1: 0.434057\tvalid_1's l2: 0.201616\n",
      "[30]\ttraining's l1: 0.421302\ttraining's l2: 0.197421\tvalid_1's l1: 0.417019\tvalid_1's l2: 0.192514\n",
      "[40]\ttraining's l1: 0.411107\ttraining's l2: 0.192856\tvalid_1's l1: 0.406303\tvalid_1's l2: 0.187258\n",
      "[50]\ttraining's l1: 0.403695\ttraining's l2: 0.189593\tvalid_1's l1: 0.398997\tvalid_1's l2: 0.183688\n",
      "[60]\ttraining's l1: 0.398704\ttraining's l2: 0.187043\tvalid_1's l1: 0.393977\tvalid_1's l2: 0.181009\n",
      "[70]\ttraining's l1: 0.394876\ttraining's l2: 0.184982\tvalid_1's l1: 0.389805\tvalid_1's l2: 0.178803\n",
      "[80]\ttraining's l1: 0.391147\ttraining's l2: 0.1828\tvalid_1's l1: 0.386476\tvalid_1's l2: 0.176799\n",
      "[90]\ttraining's l1: 0.388101\ttraining's l2: 0.180817\tvalid_1's l1: 0.384404\tvalid_1's l2: 0.175775\n",
      "[100]\ttraining's l1: 0.385174\ttraining's l2: 0.179171\tvalid_1's l1: 0.382929\tvalid_1's l2: 0.175321\n"
     ]
    }
   ],
   "source": [
    "evals_result = {}  # to record eval results for plotting\n",
    "gbm = lgb.train(params,\n",
    "                lgb_train,\n",
    "                num_boost_round=100,\n",
    "                valid_sets=[lgb_train, lgb_test],\n",
    "                feature_name=[f'f{i + 1}' for i in range(X_train.shape[-1])],\n",
    "                categorical_feature=[21],\n",
    "                evals_result=evals_result,\n",
    "                verbose_eval=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Plot metrics recorded during training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.809203Z",
     "start_time": "2018-10-25T22:13:39.338985Z"
    }
   },
   "outputs": [],
   "source": [
    "def render_metric(metric_name):\n",
    "    ax = lgb.plot_metric(evals_result, metric=metric_name, figsize=(10, 5))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27996 characters]\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "if INTERACTIVE:\n",
    "    # create widget to switch between metrics\n",
    "    interact(render_metric, metric_name=params['metric'])\n",
    "else:\n",
    "    render_metric(params['metric'][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Plot feature importances"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:39.958548Z",
     "start_time": "2018-10-25T22:13:39.811530Z"
    }
   },
   "outputs": [],
   "source": [
    "def render_plot_importance(importance_type, max_features=10,\n",
    "                           ignore_zero=True, precision=3):\n",
    "    ax = lgb.plot_importance(gbm, importance_type=importance_type,\n",
    "                             max_num_features=max_features,\n",
    "                             ignore_zero=ignore_zero, figsize=(12, 8),\n",
    "                             precision=precision)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18816 characters]\n",
      "text/plain": [
       "<Figure size 864x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "if INTERACTIVE:\n",
    "    # create widget for interactive feature importance plot\n",
    "    interact(render_plot_importance,\n",
    "             importance_type=['split', 'gain'],\n",
    "             max_features=(1, X_train.shape[-1]),\n",
    "             precision=(0, 10))\n",
    "else:\n",
    "    render_plot_importance(importance_type='split')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Plot split value histogram"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def render_histogram(feature):\n",
    "    ax = lgb.plot_split_value_histogram(gbm, feature=feature,\n",
    "                                        bins='auto', figsize=(10, 5))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12920 characters]\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "if INTERACTIVE:\n",
    "    # create widget for interactive split value histogram\n",
    "    interact(render_histogram,\n",
    "             feature=gbm.feature_name())\n",
    "else:\n",
    "    render_histogram(feature='f26')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-25T22:13:40.027803Z",
     "start_time": "2018-10-25T22:13:39.960713Z"
    }
   },
   "source": [
    "## Plot trees"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def render_tree(tree_index, show_info, precision=3):\n",
    "    show_info = None if 'None' in show_info else show_info\n",
    "    return lgb.create_tree_digraph(gbm, tree_index=tree_index,\n",
    "                                   show_info=show_info, precision=precision)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 125720 characters]\n",
      "text/plain": [
       "<Figure size 7200x7200 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "if INTERACTIVE:\n",
    "    # create widget to switch between trees and control info in nodes\n",
    "    interact(render_tree,\n",
    "             tree_index=(0, gbm.num_trees() - 1),\n",
    "             show_info=SelectMultiple(  # allow multiple values to be selected\n",
    "                 options=['None',\n",
    "                          'split_gain',\n",
    "                          'internal_value',\n",
    "                          'internal_count',\n",
    "                          'internal_weight',\n",
    "                          'leaf_count',\n",
    "                          'leaf_weight',\n",
    "                          'data_percentage'],\n",
    "                 value=['None']),\n",
    "             precision=(0, 10))\n",
    "    tree = None\n",
    "else:\n",
    "    tree = render_tree(53, ['None'])\n",
    "tree"
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "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.7.1"
  },
  "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
}
