{
 "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 SelectMultiple, interact\n",
    "\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(\n",
    "    X_train,\n",
    "    y_train,\n",
    "    feature_name=[f\"f{i + 1}\" for i in range(X_train.shape[-1])],\n",
    "    categorical_feature=[21],\n",
    ")\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 = {\"num_leaves\": 5, \"metric\": [\"l1\", \"l2\"], \"verbose\": -1}"
   ]
  },
  {
   "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(\n",
    "    params,\n",
    "    lgb_train,\n",
    "    num_boost_round=100,\n",
    "    valid_sets=[lgb_train, lgb_test],\n",
    "    callbacks=[lgb.log_evaluation(10), lgb.record_evaluation(evals_result)],\n",
    ")"
   ]
  },
  {
   "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",
    "    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]",
      "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, ignore_zero=True, precision=3):\n",
    "    lgb.plot_importance(\n",
    "        gbm,\n",
    "        importance_type=importance_type,\n",
    "        max_num_features=max_features,\n",
    "        ignore_zero=ignore_zero,\n",
    "        figsize=(12, 8),\n",
    "        precision=precision,\n",
    "    )\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18816 characters]",
      "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(\n",
    "        render_plot_importance,\n",
    "        importance_type=[\"split\", \"gain\"],\n",
    "        max_features=(1, X_train.shape[-1]),\n",
    "        precision=(0, 10),\n",
    "    )\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",
    "    lgb.plot_split_value_histogram(gbm, feature=feature, bins=\"auto\", figsize=(10, 5))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12920 characters]",
      "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, 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, show_info=show_info, precision=precision)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 125720 characters]",
      "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(\n",
    "        render_tree,\n",
    "        tree_index=(0, gbm.num_trees() - 1),\n",
    "        show_info=SelectMultiple(  # allow multiple values to be selected\n",
    "            options=[\n",
    "                \"None\",\n",
    "                \"split_gain\",\n",
    "                \"internal_value\",\n",
    "                \"internal_count\",\n",
    "                \"internal_weight\",\n",
    "                \"leaf_count\",\n",
    "                \"leaf_weight\",\n",
    "                \"data_percentage\",\n",
    "            ],\n",
    "            value=[\"None\"],\n",
    "        ),\n",
    "        precision=(0, 10),\n",
    "    )\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.11.7"
  },
  "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
}
