{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Scale XGBoost\n", "=============\n", "\n", "Dask and XGBoost can work together to train gradient boosted trees in parallel. This notebook shows how to use Dask and XGBoost together.\n", "\n", "XGBoost provides a powerful prediction framework, and it works well in practice. It wins Kaggle contests and is popular in industry because it has good performance and can be easily interpreted (i.e., it's easy to find the important features from a XGBoost model).\n", "\n", "\"Dask \"Dask" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup Dask\n", "We setup a Dask client, which provides performance and progress metrics via the dashboard.\n", "\n", "You can view the dashboard by clicking the link after running the cell." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:05.696722Z", "iopub.status.busy": "2022-07-27T19:24:05.696078Z", "iopub.status.idle": "2022-07-27T19:24:09.100023Z", "shell.execute_reply": "2022-07-27T19:24:09.099239Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
\n", "
\n", "

Client

\n", "

Client-ae48a4c8-0de1-11ed-a6d2-000d3a8f7959

\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
Connection method: Cluster objectCluster type: distributed.LocalCluster
\n", " Dashboard: http://127.0.0.1:8787/status\n", "
\n", "\n", " \n", "
\n", "

Cluster Info

\n", "
\n", "
\n", "
\n", "
\n", "

LocalCluster

\n", "

d17d0b16

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", " \n", "
\n", " Dashboard: http://127.0.0.1:8787/status\n", " \n", " Workers: 4\n", "
\n", " Total threads: 4\n", " \n", " Total memory: 6.78 GiB\n", "
Status: runningUsing processes: True
\n", "\n", "
\n", " \n", "

Scheduler Info

\n", "
\n", "\n", "
\n", "
\n", "
\n", "
\n", "

Scheduler

\n", "

Scheduler-63756a1e-88c9-43fb-9a77-fb66783417d3

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " Comm: tcp://127.0.0.1:36303\n", " \n", " Workers: 4\n", "
\n", " Dashboard: http://127.0.0.1:8787/status\n", " \n", " Total threads: 4\n", "
\n", " Started: Just now\n", " \n", " Total memory: 6.78 GiB\n", "
\n", "
\n", "
\n", "\n", "
\n", " \n", "

Workers

\n", "
\n", "\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 0

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:36301\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:39597/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:46201\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-ddcw2w5v\n", "
\n", "
\n", "
\n", "
\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 1

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:40821\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:33095/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:36319\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-5hsjt1n7\n", "
\n", "
\n", "
\n", "
\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 2

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:34869\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:44313/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:40433\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-a0hc6mn9\n", "
\n", "
\n", "
\n", "
\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 3

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:44521\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:38003/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:34813\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-r6mejztr\n", "
\n", "
\n", "
\n", "
\n", " \n", "\n", "
\n", "
\n", "\n", "
\n", "
\n", "
\n", "
\n", " \n", "\n", "
\n", "
" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from dask.distributed import Client\n", "\n", "client = Client(n_workers=4, threads_per_worker=1)\n", "client" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we create a bunch of synthetic data, with 100,000 examples and 20 features." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:09.103687Z", "iopub.status.busy": "2022-07-27T19:24:09.103117Z", "iopub.status.idle": "2022-07-27T19:24:09.910766Z", "shell.execute_reply": "2022-07-27T19:24:09.910187Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/share/miniconda3/envs/dask-examples/lib/python3.9/site-packages/dask/base.py:1283: UserWarning: Running on a single-machine scheduler when a distributed client is active might lead to unexpected results.\n", " warnings.warn(\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Array Chunk
Bytes 15.26 MiB 156.25 kiB
Shape (100000, 20) (1000, 20)
Count 100 Tasks 100 Chunks
Type float64 numpy.ndarray
\n", "
\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", "\n", " \n", " 20\n", " 100000\n", "\n", "
" ], "text/plain": [ "dask.array" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from dask_ml.datasets import make_classification\n", "\n", "X, y = make_classification(n_samples=100000, n_features=20,\n", " chunks=1000, n_informative=4,\n", " random_state=0)\n", "X" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dask-XGBoost works with both arrays and dataframes. For more information on creating dask arrays and dataframes from real data, see documentation on [Dask arrays](https://dask.pydata.org/en/latest/array-creation.html) or [Dask dataframes](https://dask.pydata.org/en/latest/dataframe-create.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Split data for training and testing\n", "We split our dataset into training and testing data to aid evaluation by making sure we have a fair test:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:09.913973Z", "iopub.status.busy": "2022-07-27T19:24:09.913564Z", "iopub.status.idle": "2022-07-27T19:24:10.150306Z", "shell.execute_reply": "2022-07-27T19:24:10.149670Z" } }, "outputs": [], "source": [ "from dask_ml.model_selection import train_test_split\n", "\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's try to do something with this data using [dask-xgboost][dxgb].\n", "\n", "[dxgb]:https://github.com/dask/dask-xgboost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Train Dask-XGBoost" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:10.154009Z", "iopub.status.busy": "2022-07-27T19:24:10.153574Z", "iopub.status.idle": "2022-07-27T19:24:10.199907Z", "shell.execute_reply": "2022-07-27T19:24:10.199244Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/share/miniconda3/envs/dask-examples/lib/python3.9/site-packages/xgboost/compat.py:36: FutureWarning: pandas.Int64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.\n", " from pandas import MultiIndex, Int64Index\n" ] } ], "source": [ "import dask\n", "import xgboost\n", "import dask_xgboost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "dask-xgboost is a small wrapper around xgboost. Dask sets XGBoost up, gives XGBoost data and lets XGBoost do it's training in the background using all the workers Dask has available." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's do some training:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:10.203663Z", "iopub.status.busy": "2022-07-27T19:24:10.203158Z", "iopub.status.idle": "2022-07-27T19:24:15.697658Z", "shell.execute_reply": "2022-07-27T19:24:15.693295Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Exception in thread Thread-4:\n", "Traceback (most recent call last):\n", " File \"/usr/share/miniconda3/envs/dask-examples/lib/python3.9/threading.py\", line 973, in _bootstrap_inner\n", " self.run()\n", " File \"/usr/share/miniconda3/envs/dask-examples/lib/python3.9/threading.py\", line 910, in run\n", " self._target(*self._args, **self._kwargs)\n", " File \"/usr/share/miniconda3/envs/dask-examples/lib/python3.9/site-packages/dask_xgboost/tracker.py\", line 365, in join\n", " while self.thread.isAlive():\n", "AttributeError: 'Thread' object has no attribute 'isAlive'\n" ] } ], "source": [ "params = {'objective': 'binary:logistic',\n", " 'max_depth': 4, 'eta': 0.01, 'subsample': 0.5, \n", " 'min_child_weight': 0.5}\n", "\n", "bst = dask_xgboost.train(client, params, X_train, y_train, num_boost_round=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `bst` object is a regular `xgboost.Booster` object. " ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:15.705148Z", "iopub.status.busy": "2022-07-27T19:24:15.701284Z", "iopub.status.idle": "2022-07-27T19:24:15.712171Z", "shell.execute_reply": "2022-07-27T19:24:15.711623Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bst" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This means all the methods mentioned in the [XGBoost documentation][2] are available. We show two examples to expand on this, but these examples are of XGBoost instead of Dask.\n", "\n", "[2]:https://xgboost.readthedocs.io/en/latest/python/python_intro.html#" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plot feature importance" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:15.715948Z", "iopub.status.busy": "2022-07-27T19:24:15.714611Z", "iopub.status.idle": "2022-07-27T19:24:16.525209Z", "shell.execute_reply": "2022-07-27T19:24:16.524705Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "ax = xgboost.plot_importance(bst, height=0.8, max_num_features=9)\n", "ax.grid(False, axis=\"y\")\n", "ax.set_title('Estimated feature importance')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We specified that only 4 features were informative while creating our data, and only 3 features show up as important." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plot the Receiver Operating Characteristic curve\n", "We can use a fancier metric to determine how well our classifier is doing by plotting the [Receiver Operating Characteristic (ROC) curve](https://en.wikipedia.org/wiki/Receiver_operating_characteristic):" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:16.528288Z", "iopub.status.busy": "2022-07-27T19:24:16.527835Z", "iopub.status.idle": "2022-07-27T19:24:16.596872Z", "shell.execute_reply": "2022-07-27T19:24:16.596102Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[19:24:16] WARNING: /home/conda/feedstock_root/build_artifacts/xgboost-split_1645117766796/work/src/learner.cc:1264: Empty dataset at worker: 0\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Array Chunk
Bytes 58.59 kiB 600 B
Shape (15000,) (150,)
Count 100 Tasks 100 Chunks
Type float32 numpy.ndarray
\n", "
\n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", "\n", " \n", " 15000\n", " 1\n", "\n", "
" ], "text/plain": [ "dask.array<_predict_part, shape=(15000,), dtype=float32, chunksize=(150,), chunktype=numpy.ndarray>" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_hat = dask_xgboost.predict(client, bst, X_test).persist()\n", "y_hat" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:16.599758Z", "iopub.status.busy": "2022-07-27T19:24:16.599424Z", "iopub.status.idle": "2022-07-27T19:24:18.592923Z", "shell.execute_reply": "2022-07-27T19:24:18.577114Z" } }, "outputs": [], "source": [ "from sklearn.metrics import roc_curve\n", "\n", "y_test, y_hat = dask.compute(y_test, y_hat)\n", "fpr, tpr, _ = roc_curve(y_test, y_hat)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:24:18.597157Z", "iopub.status.busy": "2022-07-27T19:24:18.596945Z", "iopub.status.idle": "2022-07-27T19:24:18.742262Z", "shell.execute_reply": "2022-07-27T19:24:18.741740Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from sklearn.metrics import auc\n", "\n", "fig, ax = plt.subplots(figsize=(5, 5))\n", "ax.plot(fpr, tpr, lw=3,\n", " label='ROC Curve (area = {:.2f})'.format(auc(fpr, tpr)))\n", "ax.plot([0, 1], [0, 1], 'k--', lw=2)\n", "ax.set(\n", " xlim=(0, 1),\n", " ylim=(0, 1),\n", " title=\"ROC Curve\",\n", " xlabel=\"False Positive Rate\",\n", " ylabel=\"True Positive Rate\",\n", ")\n", "ax.legend();\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This Receiver Operating Characteristic (ROC) curve tells how well our classifier is doing. We can tell it's doing well by how far it bends the upper-left. A perfect classifier would be in the upper-left corner, and a random classifier would follow the diagonal line.\n", "\n", "The area under this curve is `area = 0.76`. This tells us the probability that our classifier will predict correctly for a randomly chosen instance." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Learn more\n", "* Recorded screencast stepping through the real world example above:\n", "* A blogpost on dask-xgboost http://matthewrocklin.com/blog/work/2017/03/28/dask-xgboost\n", "* XGBoost documentation: https://xgboost.readthedocs.io/en/latest/python/python_intro.html#\n", "* Dask-XGBoost documentation: http://ml.dask.org/xgboost.html" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.12" } }, "nbformat": 4, "nbformat_minor": 4 }