diff --git a/demo/gpu_acceleration/README.md b/demo/gpu_acceleration/README.md index 7890bcfcf03f..a49cd0c188f4 100644 --- a/demo/gpu_acceleration/README.md +++ b/demo/gpu_acceleration/README.md @@ -1,3 +1,5 @@ # GPU Acceleration Demo -`cover_type.py` shows how to train a model on the [forest cover type](https://archive.ics.uci.edu/ml/datasets/covertype) dataset using GPU acceleration. The forest cover type dataset has 581,012 rows and 54 features, making it time consuming to process. We compare the run-time and accuracy of the GPU and CPU histogram algorithms. \ No newline at end of file +`cover_type.py` shows how to train a model on the [forest cover type](https://archive.ics.uci.edu/ml/datasets/covertype) dataset using GPU acceleration. The forest cover type dataset has 581,012 rows and 54 features, making it time consuming to process. We compare the run-time and accuracy of the GPU and CPU histogram algorithms. + +`shap.ipynb` demonstrates using GPU acceleration to compute SHAP values for feature importance. diff --git a/demo/gpu_acceleration/shap.ipynb b/demo/gpu_acceleration/shap.ipynb new file mode 100644 index 000000000000..7f1ee87d51a1 --- /dev/null +++ b/demo/gpu_acceleration/shap.ipynb @@ -0,0 +1,211 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ".. _california_housing_dataset:\n", + "\n", + "California Housing dataset\n", + "--------------------------\n", + "\n", + "**Data Set Characteristics:**\n", + "\n", + " :Number of Instances: 20640\n", + "\n", + " :Number of Attributes: 8 numeric, predictive attributes and the target\n", + "\n", + " :Attribute Information:\n", + " - MedInc median income in block\n", + " - HouseAge median house age in block\n", + " - AveRooms average number of rooms\n", + " - AveBedrms average number of bedrooms\n", + " - Population block population\n", + " - AveOccup average house occupancy\n", + " - Latitude house block latitude\n", + " - Longitude house block longitude\n", + "\n", + " :Missing Attribute Values: None\n", + "\n", + "This dataset was obtained from the StatLib repository.\n", + "http://lib.stat.cmu.edu/datasets/\n", + "\n", + "The target variable is the median house value for California districts.\n", + "\n", + "This dataset was derived from the 1990 U.S. census, using one row per census\n", + "block group. A block group is the smallest geographical unit for which the U.S.\n", + "Census Bureau publishes sample data (a block group typically has a population\n", + "of 600 to 3,000 people).\n", + "\n", + "It can be downloaded/loaded using the\n", + ":func:`sklearn.datasets.fetch_california_housing` function.\n", + "\n", + ".. topic:: References\n", + "\n", + " - Pace, R. Kelley and Ronald Barry, Sparse Spatial Autoregressions,\n", + " Statistics and Probability Letters, 33 (1997) 291-297\n", + "\n", + "Wall time: 28.9 s\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "import xgboost as xgb\n", + "from sklearn.datasets import fetch_california_housing\n", + "\n", + "# Fetch dataset using sklearn\n", + "data = fetch_california_housing()\n", + "print( data.DESCR)\n", + "X = data.data\n", + "y = data.target\n", + "\n", + "num_round = 500\n", + "\n", + "param = {\n", + " \"eta\": 0.05,\n", + " \"max_depth\": 10,\n", + " \"tree_method\": \"gpu_hist\",\n", + "}\n", + "\n", + "# GPU accelerated training\n", + "dtrain = xgb.DMatrix(X, label=y, feature_names=data.feature_names)\n", + "%time model = xgb.train(param, dtrain,num_round)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wall time: 3.73 s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Compute shap values using GPU with xgboost\n", + "# model.set_param({\"predictor\":\"cpu_predictor\"})\n", + "model.set_param({\"predictor\": \"gpu_predictor\"})\n", + "shap_values = model.predict(dtrain, pred_contribs=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wall time: 49.3 s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Compute shap interaction values using GPU\n", + "shap_interaction_values = model.predict(dtrain, pred_interactions=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wall time: 3.69 s\n" + ] + }, + { + "data": { + "image/png": "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G6PdjKOyYMECXn755Wg3Q0REROLMq6++yvz58xs0bTzvKzUV7XM1jMInEREREREREYkZTz75JJ999lnMzk8aT+GTiIiIiIiIiIhEjCfaDRAREYll27ZtY968eRQXFzNw4ECmTp2Kx+OhtLSUV155ha1bt+L3++nRowdTp07F6/UC8MUXX/Dhhx9y6NAhUlNTOe200xg2bBgAn3/+OYsWLeLgwYN07dqVc845h8zMzMOe+5lnnqF///6MHj26+raHH36YSZMmMWjQIObNm8eaNWsoLy+nXbt2nHXWWeTk5Bw2n02bNvHyyy9zyy23VN82a9Yszj33XHr37o1t2yxatIgVK1ZQVlZG7969mTp1KikpKU29OEVERKQJzJo1ixNPPJGVK1eyf/9+hg4dyumnn86rr77K5s2b6datG9OmTav+Ll+3bh3vvfcexcXFdO7cmSlTppCVlQXAjh07mDt3Lvv27aNfv35YVvgJ1tavX8/8+fMpKCggKyuLqVOn0qlTpyO2saysjHnz5vHNN9+QkJDAyJEjmTBhApZlsWDBAvbv38+FF14IQEFBAbNmzeLOO+/kgw8+ID8/n61bt/LWW28xYsQIvv/973PXXXdx9tlns3TpUsrLyxkxYgSTJ08+6vmF0j5X5Cl8EhERqceqVau47LLLSExM5LnnnuOjjz7itNNOw7ZtRowYwbRp0/D7/bz22mu8+eab5Obm4vP5mDdvHtdccw0dOnSguLiY0tJSANauXcvChQuZPn067du35+OPP2bOnDlcffXVhz33cccdx/Lly6t3hPbs2UNhYSH9+vUDoGvXrpxyyikkJyezdOlSXnrpJW6++WY8nsZ9vS9btoy1a9dy1VVXkZqayrx583jjjTe4+OKLj3HpiYiISKSsWbOGyy+/HL/fz6OPPsrOnTs599xzycrK4tlnn2XZsmVMmjSJffv2MXv2bHJzc+nZsydLly7l+eef5/rrrwcgLy+PMWPGMHr0aNatW8fs2bMZP348YIKp1157jenTp5Odnc3KlSt5/vnnueGGG464vzFv3jzKysq46aabKC0t5emnnyYtLY0TTjih3sedfvrpbNmyhWHDhh027Zo1a/jpT3+Kz+fjqaeeokOHDsc0vwDtc0Weut2JiIjUY/To0WRkZJCSksLEiRNZtWoVAKmpqQwePJiEhASSkpKYOHEimzZt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jK2XpqTwSURERERERESa3N13382yZcv4xz/+Qa9evZr0cVOmTCE9PR2A8ePHc/zxx3PuuedW379t27Zja7w0KYVPIiIiIiIiItKkli9fzr333stll13GpZde2uSP69WrF++//z6TJ08mMTGRzZs3c9FFF5GZmQlAQkLCMb8GaTqWbdvRboOIiIiIiIiIxK/DgoUnn3ySq666iuTk5OpucyUlJdi2jdvtJjk5mW3btpGRkdEkjwNT7RQYH+rBBx/khhtuqKu9Vl13SGSo8klEREREREREIqKsrIxDhw5x6NAhAsUvVVVV1ddPP/10Bg4cyK9//etGPQ7g448/prKyEjAB1fXXXw9AYmIiF154YXO9RGkAhU8iIiIiIiIi0qSuvPJKbNsO+8vJyQHgoosuwrZtMjMz+fbbb1m3bh07duxo1OMAbrjhBjp06MCwYcPo3Lkzr732GgB//vOfyc7OjsKrlroofBIREYlBxcXFdnFxsfrGi4iIiNThjDPOoG3btqxfvx6ASZMm8frrr9fX3U6iRGM+iYiIxKBA8JSenq4xCURERCTWxVuwoP2rZqbKJxERERERERERiRiFTyIiIiIiIiIiEjEKn0REREREREREJGIUPomIiIiIiIiISMQofBIRERERERERkYhR+CQiIiIiIiIiIhGj8ElEREREREREjsWuaDegEeKprS2Gwqc4Y1nWWZZlrbMsa4NlWbfVcv+VlmXtsSzrC+fvJ9FopzSeZVn/tixrt2VZq+u437Is62/Oul9pWdYJzd1GOToNWLeTLMsqDNlu72zuNsrRsSyru2VZH1iWtcayrK8sy7qplmm07capBq5fbb9xyLKsZMuyPrEs60tn3d5dyzRJlmW94Gy7yyzL6tn8LZWj0cD1q33mOGZZltuyrM8ty3q9lvu07UZHZ8Bqij/LsjyWZX1RXFxMcXExNe67yrKsvc72/aVlWdccxXN0jvCykFp4ot0AaTjLstzAQ8BkYCvwqWVZc23b/rrGpC/Ytn1DszdQjtWTwN+Bp+q4/2ygn/N3EvCw819i35PUv24BFtq2PbV5miNNqBK41bbtzyzLSgdWWJb1bo3PZW278ash6xe0/cajcuA027YPWpaVAHxsWdY827aXhkxzNXDAtu2+lmXlAjOBS6LRWGm0hqxf0D5zPLsJWAN4a7lP2278C6zfEXXcr203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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# We can use the shap package\n", + "import shap\n", + "\n", + "\n", + "# shap will call the GPU accelerated version as long as the predictor parameter is set to \"gpu_predictor\"\n", + "model.set_param({\"predictor\": \"gpu_predictor\"})\n", + "explainer = shap.TreeExplainer(model)\n", + "%time shap_values = explainer.shap_values(X)\n", + "\n", + "# visualize the first prediction's explanation\n", + "shap.force_plot(\n", + " explainer.expected_value,\n", + " shap_values[0, :],\n", + " X[0, :],\n", + " feature_names=data.feature_names,\n", + " matplotlib=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Show a summary of feature importance\n", + "shap.summary_plot(shap_values, X, plot_type=\"bar\", feature_names=data.feature_names)" + ] + } + ], + "metadata": { + "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.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/gpu/index.rst b/doc/gpu/index.rst index d716d9b4c1fc..37cc5b359bff 100644 --- a/doc/gpu/index.rst +++ b/doc/gpu/index.rst @@ -85,6 +85,19 @@ The GPU algorithms currently work with CLI, Python and R packages. See :doc:`/bu XGBRegressor(tree_method='gpu_hist', gpu_id=0) +GPU-Accelerated SHAP values +============================= +XGBoost makes use of `GPUTreeShap `_ as a backend for computing shap values when the GPU predictor is selected. + +.. code-block:: python + + model.set_param({"predictor": "gpu_predictor"}) + shap_values = model.predict(dtrain, pred_contribs=True) + shap_interaction_values = model.predict(dtrain, pred_interactions=True) + +See examples `here +`_. + Multi-node Multi-GPU Training ============================= XGBoost supports fully distributed GPU training using `Dask `_. For diff --git a/gputreeshap b/gputreeshap index 5f33132d7548..3310a30bb123 160000 --- a/gputreeshap +++ b/gputreeshap @@ -1 +1 @@ -Subproject commit 5f33132d75482338f78cfba562791d8445e157f6 +Subproject commit 3310a30bb123a49ab12c58e03edc2479512d2f64 diff --git a/src/predictor/gpu_predictor.cu b/src/predictor/gpu_predictor.cu index d8c3e5c065df..0431f70bde1b 100644 --- a/src/predictor/gpu_predictor.cu +++ b/src/predictor/gpu_predictor.cu @@ -671,17 +671,6 @@ class GPUPredictor : public xgboost::Predictor { model.learner_model_param->num_output_group); out_contribs->Fill(0.0f); auto phis = out_contribs->DeviceSpan(); - p_fmat->Info().base_margin_.SetDevice(generic_param_->gpu_id); - const auto margin = p_fmat->Info().base_margin_.ConstDeviceSpan(); - float base_score = model.learner_model_param->base_score; - // Add the base margin term to last column - dh::LaunchN( - generic_param_->gpu_id, - p_fmat->Info().num_row_ * model.learner_model_param->num_output_group, - [=] __device__(size_t idx) { - phis[(idx + 1) * contributions_columns - 1] = - margin.empty() ? base_score : margin[idx]; - }); dh::device_vector device_paths; ExtractPaths(&device_paths, model, real_ntree_limit, @@ -695,6 +684,17 @@ class GPUPredictor : public xgboost::Predictor { X, device_paths.begin(), device_paths.end(), ngroup, phis.data() + batch.base_rowid * contributions_columns, phis.size()); } + // Add the base margin term to last column + p_fmat->Info().base_margin_.SetDevice(generic_param_->gpu_id); + const auto margin = p_fmat->Info().base_margin_.ConstDeviceSpan(); + float base_score = model.learner_model_param->base_score; + dh::LaunchN( + generic_param_->gpu_id, + p_fmat->Info().num_row_ * model.learner_model_param->num_output_group, + [=] __device__(size_t idx) { + phis[(idx + 1) * contributions_columns - 1] += + margin.empty() ? base_score : margin[idx]; + }); } void PredictInteractionContributions(DMatrix* p_fmat, @@ -726,21 +726,6 @@ class GPUPredictor : public xgboost::Predictor { model.learner_model_param->num_output_group); out_contribs->Fill(0.0f); auto phis = out_contribs->DeviceSpan(); - p_fmat->Info().base_margin_.SetDevice(generic_param_->gpu_id); - const auto margin = p_fmat->Info().base_margin_.ConstDeviceSpan(); - float base_score = model.learner_model_param->base_score; - // Add the base margin term to last column - size_t n_features = model.learner_model_param->num_feature; - dh::LaunchN( - generic_param_->gpu_id, - p_fmat->Info().num_row_ * model.learner_model_param->num_output_group, - [=] __device__(size_t idx) { - size_t group = idx % ngroup; - size_t row_idx = idx / ngroup; - phis[gpu_treeshap::IndexPhiInteractions( - row_idx, ngroup, group, n_features, n_features, n_features)] = - margin.empty() ? base_score : margin[idx]; - }); dh::device_vector device_paths; ExtractPaths(&device_paths, model, real_ntree_limit, @@ -754,6 +739,21 @@ class GPUPredictor : public xgboost::Predictor { X, device_paths.begin(), device_paths.end(), ngroup, phis.data() + batch.base_rowid * contributions_columns, phis.size()); } + // Add the base margin term to last column + p_fmat->Info().base_margin_.SetDevice(generic_param_->gpu_id); + const auto margin = p_fmat->Info().base_margin_.ConstDeviceSpan(); + float base_score = model.learner_model_param->base_score; + size_t n_features = model.learner_model_param->num_feature; + dh::LaunchN( + generic_param_->gpu_id, + p_fmat->Info().num_row_ * model.learner_model_param->num_output_group, + [=] __device__(size_t idx) { + size_t group = idx % ngroup; + size_t row_idx = idx / ngroup; + phis[gpu_treeshap::IndexPhiInteractions( + row_idx, ngroup, group, n_features, n_features, n_features)] += + margin.empty() ? base_score : margin[idx]; + }); } protected: