{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6bbdabb2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "import panel_material_ui as pmui\n",
    "\n",
    "from sklearn.datasets import load_iris\n",
    "from sklearn.metrics import accuracy_score\n",
    "from xgboost import XGBClassifier\n",
    "\n",
    "pn.extension(sizing_mode=\"stretch_width\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "860a31bd",
   "metadata": {},
   "source": [
    "This example was adapted from an example by [Bojan Tunguz](https://twitter.com/tunguz). It demonstrates how to build a simple ML demo demonstrating how hyper-parameters affect the accuracy of the XGBoostClassifier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3dd96529",
   "metadata": {},
   "outputs": [],
   "source": [
    "iris_df = load_iris(as_frame=True)\n",
    "\n",
    "n_trees = pmui.IntSlider(start=2, end=30, label=\"Number of trees\")\n",
    "max_depth = pmui.IntSlider(start=1, end=10, value=2, label=\"Maximum Depth\") \n",
    "booster = pmui.Select(options=['gbtree', 'gblinear', 'dart'], label=\"Booster\")\n",
    "\n",
    "def pipeline(n_trees, max_depth, booster):\n",
    "    model = XGBClassifier(max_depth=max_depth, n_estimators=n_trees, booster=booster)\n",
    "    model.fit(iris_df.data, iris_df.target)\n",
    "    accuracy = round(accuracy_score(iris_df.target, model.predict(iris_df.data)) * 100, 1)\n",
    "    return pn.indicators.Number(\n",
    "        name=f\"Test score\",\n",
    "        value=accuracy,\n",
    "        format=\"{value}%\",\n",
    "        colors=[(97.5, \"red\"), (99.0, \"orange\"), (100, \"green\")],\n",
    "        align='center'\n",
    "    )\n",
    "\n",
    "widgets = pn.Column(booster, n_trees, max_depth, width=320)\n",
    "\n",
    "main = pn.Column(\n",
    "    \"Simple example of training an XGBoost classification model on the small Iris dataset.\",\n",
    "    iris_df.data.head(),\n",
    "    \n",
    "    \"Adjust the hyperparameters to re-run the XGBoost classifier. The training accuracy score will adjust accordingly:\",\n",
    "    pn.bind(pipeline, n_trees, max_depth, booster),\n",
    "    pn.bind(lambda n_trees, max_depth, booster: f'# <code>{n_trees=}, {max_depth=}, {booster=}</code>', n_trees, max_depth, booster),\n",
    ")\n",
    "\n",
    "pn.Row(widgets, main)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cccfaef8-e8e1-43c0-a829-5a2803ad7383",
   "metadata": {},
   "source": [
    "### Served App"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c85f9c9b-1b20-4c4f-92c5-e58324b440d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "if pn.state.served:\n",
    "    pmui.Page(\n",
    "        main=[main],\n",
    "        sidebar=[widgets],\n",
    "        title=\"XGBoost Example\"\n",
    "    ).servable()"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
