{ "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-06-17T02:51:01.681109Z", "iopub.status.busy": "2022-06-17T02:51:01.680651Z", "iopub.status.idle": "2022-06-17T02:51:05.005555Z", "shell.execute_reply": "2022-06-17T02:51:05.004594Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
\n", "
\n", "

Client

\n", "

Client-52ef391c-ede8-11ec-a773-000d3a5c8937

\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", "

054da482

\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-08eaa296-7399-4a95-ac8c-6c2e6d1c1df8

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " Comm: tcp://127.0.0.1:37507\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:42055\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:36133/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:37185\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-a8ig60uf\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:43941\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:34561/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:36329\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-3g1qehl6\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:33943\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:36707/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:35927\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-q634dz7r\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:42971\n", " \n", " Total threads: 1\n", "
\n", " Dashboard: http://127.0.0.1:34239/status\n", " \n", " Memory: 1.70 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:46525\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/machine-learning/dask-worker-space/worker-f9dd7gr0\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-06-17T02:51:05.008874Z", "iopub.status.busy": "2022-06-17T02:51:05.008599Z", "iopub.status.idle": "2022-06-17T02:51:05.822738Z", "shell.execute_reply": "2022-06-17T02:51:05.821707Z" } }, "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-06-17T02:51:05.826227Z", "iopub.status.busy": "2022-06-17T02:51:05.825795Z", "iopub.status.idle": "2022-06-17T02:51:06.087747Z", "shell.execute_reply": "2022-06-17T02:51:06.086929Z" } }, "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-06-17T02:51:06.091911Z", "iopub.status.busy": "2022-06-17T02:51:06.091458Z", "iopub.status.idle": "2022-06-17T02:51:06.138424Z", "shell.execute_reply": "2022-06-17T02:51:06.137553Z" } }, "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-06-17T02:51:06.141271Z", "iopub.status.busy": "2022-06-17T02:51:06.141078Z", "iopub.status.idle": "2022-06-17T02:51:11.966535Z", "shell.execute_reply": "2022-06-17T02:51:11.965906Z" } }, "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-06-17T02:51:11.973860Z", "iopub.status.busy": "2022-06-17T02:51:11.973201Z", "iopub.status.idle": "2022-06-17T02:51:11.981268Z", "shell.execute_reply": "2022-06-17T02:51:11.980541Z" } }, "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-06-17T02:51:11.986292Z", "iopub.status.busy": "2022-06-17T02:51:11.985368Z", "iopub.status.idle": "2022-06-17T02:51:12.823144Z", "shell.execute_reply": "2022-06-17T02:51:12.822411Z" } }, "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-06-17T02:51:12.826078Z", "iopub.status.busy": "2022-06-17T02:51:12.825696Z", "iopub.status.idle": "2022-06-17T02:51:12.912622Z", "shell.execute_reply": "2022-06-17T02:51:12.905004Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[02:51:12] 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-06-17T02:51:12.918906Z", "iopub.status.busy": "2022-06-17T02:51:12.916877Z", "iopub.status.idle": "2022-06-17T02:51:14.911604Z", "shell.execute_reply": "2022-06-17T02:51:14.895763Z" } }, "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-06-17T02:51:14.921663Z", "iopub.status.busy": "2022-06-17T02:51:14.920578Z", "iopub.status.idle": "2022-06-17T02:51:15.084702Z", "shell.execute_reply": "2022-06-17T02:51:15.083782Z" } }, "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 }