<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/dalex-and-h2o-machine-learning-model-interpretability-and-feature-explanation/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html"> business-science.io - Articles</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>As advanced machine learning algorithms are gaining acceptance across many organizations and domains, machine learning interpretability is growing in importance to help extract insight and clarity regarding how these algorithms are performing and why one prediction is made over another. There are many methodologies to interpret machine learning results (i.e. variable importance via permutation, partial dependence plots, local interpretable model-agnostic explanations), and many machine learning R packages implement their own versions of one or more methodologies. However, some recent R packages that focus purely on ML interpretability agnostic to any specific ML algorithm are gaining popularity. One such package is <code>DALEX</code> and this post covers what this package does (and does not do) so that you can determine if it should become part of your preferred machine learning toolbox.</p>
<p>We implement machine learning models using <code>H2O</code>, a high performance ML toolkit. Let’s see how <code>DALEX</code> and <code>H2O</code> work together to get the best of both worlds with high performance and feature explainability!</p>
<h2>Similar Articles You Might Enjoy</h2>
<p>Data science for business tutorials:</p>
<ul>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2017/09/18/hr_employee_attrition.html" target="_blank">HR Analytics: Using Machine Learning To Predict Employee Turnover</a></p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2017/11/28/customer_churn_analysis_keras.html" target="_blank">Customer Analytics: Using Deep Learning With Keras To Predict Customer Churn</a></p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2017/10/16/sales_backorder_prediction.html" target="_blank">Sales Analytics: How To Use Machine Learning To Predict And Optimize Product Backorders</a></p>
</li>
</ul>
<p>LIME for black-box model interpretability and feature:</p>
<ul>
<li><a rel="nofollow" href="http://www.business-science.io/business/2018/06/25/lime-local-feature-interpretation.html" target="_blank">Using Machine Learning With LIME To Understand Employee Churn</a></li>
</ul>
<p>Expected Value Framework for ML Classification in Business:</p>
<ul>
<li><a rel="nofollow" href="http://www.business-science.io/business/2018/07/11/expected-value-framework-data-science.html" target="_blank">3 Reasons You Need To Learn The Expected Value Framework</a></li>
</ul>
<h2>Learning Trajectory</h2>
<p>We’ll cover the following topics on <code>DALEX</code> in this article:</p>
<ol>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#adv-dis" target="_blank">Advantages &amp; disadvantages</a>: a quick breakdown of what DALEX does and does not do.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#rep" target="_blank">Replication requirements</a>: what you’ll need to reproduce the analysis.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#procedures" target="_blank">DALEX procedures</a>: necessary functions for downstream explainers.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#resids" target="_blank">Residual diagnostics</a>: understanding and comparing errors.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#vi" target="_blank">Variable importance</a>: permutation based importance score.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#pdp" target="_blank">Predictor-response relationship</a>: PDP and ALE plots.</p>
</li>
<li>
<p><a rel="nofollow" href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html#local" target="_blank">Local interpretation</a>: explanations for a single prediction.</p>
</li>
</ol>
<p></p>
<hr>
<h2>Get The Best Resources In Data Science. Every Friday!</h2>
<p>
Sign up for our free <strong>“5 Topic Friday” Newsletter</strong>. Every week, I’ll send you the five coolest topics in data science for business that I’ve found that week. These could be new R packages, free books, or just some fun to end the week on.
</p>
<p>
<a rel="nofollow" href="https://mailchi.mp/business-science.io/five-topic-friday" target="_blank"><strong>Sign Up For Five-Topic-Friday!</strong></a>
</p>
<hr>
<p></p>
<h2>DALEX and H2O: Machine Learning Model Interpretability And Feature Explanation</h2>
<blockquote>
<p>By Brad Boehmke, Director of Data Science at 84.51°</p>
</blockquote>
<h3>1.0 Advantages &amp; disadvantages</h3>
<p><code>DALEX</code> is an R package with a set of tools that help to provide <strong>D</strong>escriptive m<strong>A</strong>chine <strong>L</strong>earning <strong>EX</strong>planations ranging from global to local interpretability methods. In particular, it makes comparing performance across multiple models convenient. However, as is, there are some problems with this package scaling to wider data sets commonly used by organizations. The following provides a quick list of its pros and cons:</p>
<p><strong>Advantages</strong></p>
<ul>
<li>ML model and package agnostic: can be used for any supervised regression and binary classification ML model where you can customize the format of the predicted output.</li>
<li>Provides convenient approaches to compare results across multiple models.</li>
<li>Residual diagnostics: allows you to compare residual distributions.</li>
<li>Variable importance: uses a permutation-based approach for variable importance, which is model agnostic, and accepts any loss function to assess importance.</li>
<li>Partial dependence plots: leverages the <code>pdp</code> package.</li>
<li>Provides an alternative to PDPs for categorical predictor variables (merging path plots).</li>
<li>Includes a unique and intuitive approach for local intepretation.</li>
</ul>
<p><strong>Disadvantages</strong></p>
<ul>
<li>Some functions do not scale well to wide data (many predictor variables)</li>
<li>Currently only supports regression and binary classification problems (i.e. no multinomial support).</li>
<li>Only provides permutation-based variable importance scores (which become slow as number of features increase).</li>
<li>PDP plots can only be performed one variable at a time (options for two-way interaction PDP plots).</li>
<li>Does not provide ICE curves.</li>
<li>Does not provide alternative local interpretation algorithms (i.e. LIME, SHAP values).</li>
</ul>
<h3>2.0 Replication requirements</h3>
<p>We leverage the following packages:</p>
<figure>
<pre><code data-lang="r"><span># load required packages</span><span>
</span><span>library</span><span>(</span><span>rsample</span><span>)</span><span>
</span><span>library</span><span>(</span><span>dplyr</span><span>)</span><span>
</span><span>library</span><span>(</span><span>purrr</span><span>)</span><span>
</span><span>library</span><span>(</span><span>ggplot2</span><span>)</span><span>
</span><span>library</span><span>(</span><span>h</span><span>2</span><span>o</span><span>)</span><span>
</span><span>library</span><span>(</span><span>DALEX</span><span>)</span><span>
</span><span># initialize h2o session</span><span>
</span><span>h</span><span>2</span><span>o.no_progress</span><span>()</span><span>
</span><span>h</span><span>2</span><span>o.init</span><span>()</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## 
## H2O is not running yet, starting it now...
## 
## Note:  In case of errors look at the following log files:
##     C:\Users\mdancho\AppData\Local\Temp\Rtmp6f3d5n/h2o_mdancho_started_from_r.out
##     C:\Users\mdancho\AppData\Local\Temp\Rtmp6f3d5n/h2o_mdancho_started_from_r.err
## 
## 
## Starting H2O JVM and connecting: . Connection successful!
## 
## R is connected to the H2O cluster: 
##     H2O cluster uptime:         7 seconds 710 milliseconds 
##     H2O cluster timezone:       America/New_York 
##     H2O data parsing timezone:  UTC 
##     H2O cluster version:        3.19.0.4208 
##     H2O cluster version age:    5 months and 3 days !!! 
##     H2O cluster name:           H2O_started_from_R_mdancho_dpc744 
##     H2O cluster total nodes:    1 
##     H2O cluster total memory:   3.51 GB 
##     H2O cluster total cores:    4 
##     H2O cluster allowed cores:  4 
##     H2O cluster healthy:        TRUE 
##     H2O Connection ip:          localhost 
##     H2O Connection port:        54321 
##     H2O Connection proxy:       NA 
##     H2O Internal Security:      FALSE 
##     H2O API Extensions:         Algos, AutoML, Core V3, Core V4 
##     R Version:                  R version 3.4.4 (2018-03-15)</code></pre>
</figure>
<p>To demonstrate model visualization techniques we’ll use the employee attrition data that has been included in the rsample package. This demonstrates a binary classification problem (“Yes” vs. “No”) but the same process that you’ll observe can be used for a regression problem.</p>
<p>To demonstrate <code>DALEX</code>’s capabilities we’ll use the employee attrition data that has been included in the <code>rsample</code> package. This demonstrates a binary classification problem (“Yes” vs. “No”) but the same process that you’ll observe can be used for a regression problem.<br>
I perform a few house cleaning tasks on the data prior to converting to an <code>h2o</code> object and splitting.</p>
<p><strong>NOTE</strong>: To use some of <code>DALEX</code>’s functions, categorical predictor variables need to be converted to factors. Also, I force ordered factors to be unordered as <code>h2o</code> does not support ordered categorical variables.</p>
<figure>
<pre><code data-lang="r"><span># classification data</span><span>
</span><span>df</span><span> </span><span>&lt;-</span><span> </span><span>rsample</span><span>::</span><span>attrition</span><span> </span><span>%>%</span><span> </span><span>mutate_if</span><span>(</span><span>is.ordered</span><span>,</span><span> </span><span>factor</span><span>,</span><span> </span><span>ordered</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>Attrition</span><span> </span><span>=</span><span> </span><span>recode</span><span>(</span><span>Attrition</span><span>,</span><span> </span><span>&quot;Yes&quot;</span><span> </span><span>=</span><span> </span><span>&quot;1&quot;</span><span>,</span><span> </span><span>&quot;No&quot;</span><span> </span><span>=</span><span> </span><span>&quot;0&quot;</span><span>)</span><span> </span><span>%>%</span><span> </span><span>factor</span><span>(</span><span>levels</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;1&quot;</span><span>,</span><span> </span><span>&quot;0&quot;</span><span>)))</span><span>
</span><span># convert to h2o object</span><span>
</span><span>df.h2o</span><span> </span><span>&lt;-</span><span> </span><span>as.h2o</span><span>(</span><span>df</span><span>)</span><span>
</span><span># create train, validation, and test splits</span><span>
</span><span>set.seed</span><span>(</span><span>123</span><span>)</span><span>
</span><span>splits</span><span> </span><span>&lt;-</span><span> </span><span>h</span><span>2</span><span>o.splitFrame</span><span>(</span><span>df.h2o</span><span>,</span><span> </span><span>ratios</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>.7</span><span>,</span><span> </span><span>.15</span><span>),</span><span> </span><span>destination_frames</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;train&quot;</span><span>,</span><span>&quot;valid&quot;</span><span>,</span><span>&quot;test&quot;</span><span>))</span><span>
</span><span>names</span><span>(</span><span>splits</span><span>)</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;train&quot;</span><span>,</span><span>&quot;valid&quot;</span><span>,</span><span>&quot;test&quot;</span><span>)</span><span>
</span><span># variable names for resonse &amp; features</span><span>
</span><span>y</span><span> </span><span>&lt;-</span><span> </span><span>&quot;Attrition&quot;</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>setdiff</span><span>(</span><span>names</span><span>(</span><span>df</span><span>),</span><span> </span><span>y</span><span>)</span><span> </span></code></pre>
</figure>
<p>We will explore how to visualize a few of the more common machine learning algorithms implemented with <code>h2o</code>. For brevity I train default models and do not emphasize hyperparameter tuning. The following produces a regularized logistic regression, random forest, and gradient boosting machine models; all of which provide AUCs ranging between .75-.79. Although these models have distinct AUC scores, our objective is to understand how these models come to this conclusion in similar or different ways based on underlying logic and data structure.</p>
<figure>
<pre><code data-lang="r"><span># elastic net model </span><span>
</span><span>glm</span><span> </span><span>&lt;-</span><span> </span><span>h</span><span>2</span><span>o.glm</span><span>(</span><span>
</span><span>x</span><span> </span><span>=</span><span> </span><span>x</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y</span><span>,</span><span> </span><span>training_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>train</span><span>,</span><span>
</span><span>validation_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>valid</span><span>,</span><span>
</span><span>family</span><span> </span><span>=</span><span> </span><span>&quot;binomial&quot;</span><span>,</span><span>
</span><span>seed</span><span> </span><span>=</span><span> </span><span>123</span><span>
</span><span>)</span><span>
</span><span># random forest model</span><span>
</span><span>rf</span><span> </span><span>&lt;-</span><span> </span><span>h</span><span>2</span><span>o.randomForest</span><span>(</span><span>
</span><span>x</span><span> </span><span>=</span><span> </span><span>x</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y</span><span>,</span><span>
</span><span>training_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>train</span><span>,</span><span>
</span><span>validation_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>valid</span><span>,</span><span>
</span><span>ntrees</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span>
</span><span>stopping_metric</span><span> </span><span>=</span><span> </span><span>&quot;AUC&quot;</span><span>,</span><span> </span><span>stopping_rounds</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>stopping_tolerance</span><span> </span><span>=</span><span> </span><span>0.005</span><span>,</span><span>
</span><span>seed</span><span> </span><span>=</span><span> </span><span>123</span><span>
</span><span>)</span><span>
</span><span># gradient boosting machine model</span><span>
</span><span>gbm</span><span> </span><span>&lt;-</span><span> </span><span>h</span><span>2</span><span>o.gbm</span><span>(</span><span>
</span><span>x</span><span> </span><span>=</span><span> </span><span>x</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y</span><span>,</span><span>
</span><span>training_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>train</span><span>,</span><span>
</span><span>validation_frame</span><span> </span><span>=</span><span> </span><span>splits</span><span>$</span><span>valid</span><span>,</span><span>
</span><span>ntrees</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span>
</span><span>stopping_metric</span><span> </span><span>=</span><span> </span><span>&quot;AUC&quot;</span><span>,</span><span> </span><span>stopping_rounds</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>stopping_tolerance</span><span> </span><span>=</span><span> </span><span>0.005</span><span>,</span><span>
</span><span>seed</span><span> </span><span>=</span><span> </span><span>123</span><span>
</span><span>)</span><span>
</span><span># model performance</span><span>
</span><span>h</span><span>2</span><span>o.auc</span><span>(</span><span>glm</span><span>,</span><span> </span><span>valid</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0.7870935</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>h</span><span>2</span><span>o.auc</span><span>(</span><span>rf</span><span>,</span><span> </span><span>valid</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0.7681021</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>h</span><span>2</span><span>o.auc</span><span>(</span><span>gbm</span><span>,</span><span> </span><span>valid</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0.7468242</code></pre>
</figure>
<h3>3.0 DALEX procedures</h3>
<p>The <code>DALEX</code> architecture can be split into three primary operations:</p>
<ol>
<li>Any supervised regression or binary classification model with defined input (<em>X</em>) and output (<em>Y</em>) where the output can be customized to a defined format can be used.</li>
<li>The machine learning model is converted to an “explainer” object via <code>DALEX::explain()</code>, which is just a list that contains the training data and meta data on the machine learning model.</li>
<li>The explainer object can be passed onto multiple functions that explain different components of the given model.</li>
</ol>
<p>
<a rel="nofollow" href="https://pbiecek.github.io/DALEX_docs/2-architecture.html#architecture" target="_blank"><br>
<img alt="DALEX Architecture" src="https://i2.wp.com/www.business-science.io/assets/2018-07-23-dalex/architecture.png?w=456" data-recalc-dims="1"><br>
</a>
</p>
<p><a rel="nofollow" href="https://pbiecek.github.io/DALEX_docs/2-architecture.html#architecture" target="_blank">DALEX Application Process and Architecture</a></p>
<p></p>
<p>Although <code>DALEX</code> does have native support for some ML model objects (i.e. <code>lm</code>, <code>randomForest</code>), it does not have native many of the preferred ML packages produced more recently (i.e. <code>h2o</code>, <code>xgboost</code>, <code>ranger</code>). To make <code>DALEX</code> compatible with these objects, we need three things:</p>
<ol>
<li><code>x_valid</code>: Our feature set needs to be in its original form not as an <code>h2o</code> object.</li>
<li><code>y_valid</code>: Our response variable needs to be a numeric vector. For regression problems this is simple, as it will already be in this format. For binary classification this requires you to convert the responses to 0/1.</li>
<li><code>pred</code>: a custom predict function that returns a <strong>vector</strong> of numeric values. For binary classification problems, this means extracting the probability of the response.</li>
</ol>
<figure>
<pre><code data-lang="r"><span># convert feature data to non-h2o objects</span><span>
</span><span>x_valid</span><span> </span><span>&lt;-</span><span> </span><span>as.data.frame</span><span>(</span><span>splits</span><span>$</span><span>valid</span><span>)[,</span><span> </span><span>x</span><span>]</span><span>
</span><span># make response variable numeric binary vector</span><span>
</span><span>y_valid</span><span> </span><span>&lt;-</span><span> </span><span>as.vector</span><span>(</span><span>as.numeric</span><span>(</span><span>as.character</span><span>(</span><span>splits</span><span>$</span><span>valid</span><span>$</span><span>Attrition</span><span>)))</span><span>
</span><span>head</span><span>(</span><span>y_valid</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0 0 0 0 0 0</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span># create custom predict function</span><span>
</span><span>pred</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>model</span><span>,</span><span> </span><span>newdata</span><span>)</span><span> </span><span>{</span><span>
</span><span>results</span><span> </span><span>&lt;-</span><span> </span><span>as.data.frame</span><span>(</span><span>h</span><span>2</span><span>o.predict</span><span>(</span><span>model</span><span>,</span><span> </span><span>as.h2o</span><span>(</span><span>newdata</span><span>)))</span><span>
</span><span>return</span><span>(</span><span>results</span><span>[[</span><span>3L</span><span>]])</span><span>
</span><span>}</span><span>
</span><span>pred</span><span>(</span><span>rf</span><span>,</span><span> </span><span>x_valid</span><span>)</span><span> </span><span>%>%</span><span> </span><span>head</span><span>()</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0.18181818 0.27272727 0.06060606 0.54545455 0.03030303 0.42424242</code></pre>
</figure>
<p>Once you have these three components, you can now create your explainer objects for each ML model. Considering I used a validation set to compute the AUC, we want to use that same validation set for ML interpretability.</p>
<figure>
<pre><code data-lang="r"><span># elastic net explainer</span><span>
</span><span>explainer_glm</span><span> </span><span>&lt;-</span><span> </span><span>explain</span><span>(</span><span>
</span><span>model</span><span> </span><span>=</span><span> </span><span>glm</span><span>,</span><span>
</span><span>data</span><span> </span><span>=</span><span> </span><span>x_valid</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>y_valid</span><span>,</span><span>
</span><span>predict_function</span><span> </span><span>=</span><span> </span><span>pred</span><span>,</span><span>
</span><span>label</span><span> </span><span>=</span><span> </span><span>&quot;h2o glm&quot;</span><span>
</span><span>)</span><span>
</span><span># random forest explainer</span><span>
</span><span>explainer_rf</span><span> </span><span>&lt;-</span><span> </span><span>explain</span><span>(</span><span>
</span><span>model</span><span> </span><span>=</span><span> </span><span>rf</span><span>,</span><span>
</span><span>data</span><span> </span><span>=</span><span> </span><span>x_valid</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>y_valid</span><span>,</span><span>
</span><span>predict_function</span><span> </span><span>=</span><span> </span><span>pred</span><span>,</span><span>
</span><span>label</span><span> </span><span>=</span><span> </span><span>&quot;h2o rf&quot;</span><span>
</span><span>)</span><span>
</span><span># GBM explainer</span><span>
</span><span>explainer_gbm</span><span> </span><span>&lt;-</span><span> </span><span>explain</span><span>(</span><span>
</span><span>model</span><span> </span><span>=</span><span> </span><span>gbm</span><span>,</span><span>
</span><span>data</span><span> </span><span>=</span><span> </span><span>x_valid</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>y_valid</span><span>,</span><span>
</span><span>predict_function</span><span> </span><span>=</span><span> </span><span>pred</span><span>,</span><span>
</span><span>label</span><span> </span><span>=</span><span> </span><span>&quot;h2o gbm&quot;</span><span>
</span><span>)</span><span>
</span><span># example of explainer object</span><span>
</span><span>class</span><span>(</span><span>explainer_glm</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] &quot;explainer&quot;</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>summary</span><span>(</span><span>explainer_glm</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##                  Length Class            Mode     
## model              1    H2OBinomialModel S4       
## data              30    data.frame       list     
## y                233    -none-           numeric  
## predict_function   1    -none-           function 
## link               1    -none-           function 
## class              1    -none-           character
## label              1    -none-           character</code></pre>
</figure>
<h3>4.0 Residual diagnostics</h3>
<p>As we saw earlier, the GLM model had the highest AUC followed by the random forest model then GBM. However, a single accuracy metric can be a poor indicator of performance. Assessing residuals of predicted versus actuals can allow you to identify where models deviate in their predictive accuracy. We can use <code>DALEX::model_performance</code> to compute the predictions and residuals. Printing the output returns residual quantiles and plotting the output allows for easy comparison of absolute residual values across models.</p>
<p>In this example, the residuals are comparing the probability of attrition to the binary attrition value (1-yes, 0-no). Looking at the quantiles you can see that the median residuals are lowest for the GBM model. And looking at the boxplots you can see that the GBM model also had the lowest median <strong><em>absolute</em></strong> residual value. Thus, although the GBM model had the lowest AUC score, it actually performs best when considering the median absoluate residuals. However, you can also see a higher number of residuals in the tail of the GBM residual distribution (left plot) suggesting that there may be a higher number of large residuals compared to the GLM model. This helps to illustrate how your residuals behave similarly and differently across models.</p>
<figure>
<pre><code data-lang="r"><span># compute predictions &amp; residuals</span><span>
</span><span>resids_glm</span><span> </span><span>&lt;-</span><span> </span><span>model_performance</span><span>(</span><span>explainer_glm</span><span>)</span><span>
</span><span>resids_rf</span><span> </span><span>&lt;-</span><span> </span><span>model_performance</span><span>(</span><span>explainer_rf</span><span>)</span><span>
</span><span>resids_gbm</span><span> </span><span>&lt;-</span><span> </span><span>model_performance</span><span>(</span><span>explainer_gbm</span><span>)</span><span>
</span><span># assess quantiles for residuals</span><span>
</span><span>resids_glm</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##          0%         10%         20%         30%         40% 
## -0.99155845 -0.70432615  0.01281214  0.03402030  0.06143281 
##         50%         60%         70%         80%         90% 
##  0.08362550  0.10051641  0.12637877  0.17583980  0.22675709 
##        100% 
##  0.47507569</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>resids_rf</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##          0%         10%         20%         30%         40% 
## -0.96969697 -0.66666667  0.00000000  0.03030303  0.06060606 
##         50%         60%         70%         80%         90% 
##  0.09090909  0.12121212  0.15151515  0.18181818  0.27272727 
##        100% 
##  0.66666667</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>resids_gbm</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##          0%         10%         20%         30%         40% 
## -0.96307337 -0.75623698  0.03258538  0.04195091  0.05344621 
##         50%         60%         70%         80%         90% 
##  0.06382511  0.07845749  0.09643740  0.11312648  0.18169305 
##        100% 
##  0.66208105</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span># create comparison plot of residuals for each model</span><span>
</span><span>p</span><span>1</span><span> </span><span>&lt;-</span><span> </span><span>plot</span><span>(</span><span>resids_glm</span><span>,</span><span> </span><span>resids_rf</span><span>,</span><span> </span><span>resids_gbm</span><span>)</span><span>
</span><span>p</span><span>2</span><span> </span><span>&lt;-</span><span> </span><span>plot</span><span>(</span><span>resids_glm</span><span>,</span><span> </span><span>resids_rf</span><span>,</span><span> </span><span>resids_gbm</span><span>,</span><span> </span><span>geom</span><span> </span><span>=</span><span> </span><span>&quot;boxplot&quot;</span><span>)</span><span>
</span><span>gridExtra</span><span>::</span><span>grid.arrange</span><span>(</span><span>p</span><span>1</span><span>,</span><span> </span><span>p</span><span>2</span><span>,</span><span> </span><span>nrow</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk plot-residuals" src="https://i2.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/plot-residuals-1.png?w=456" data-recalc-dims="1"></p>
<h3>5.0 Variable importance</h3>
<p>An important task in ML interpretation is to understand which predictor variables are relatively influential on the predicted outcome. Many ML algorithms have their own unique ways to quantify the importance or relative influence of each feature (i.e. coefficients for linear models, impurity for tree-based models). However, other algorithms like naive Bayes classifiers and support vector machines do not. This makes it difficult to compare variable importance across multiple models.</p>
<p><code>DALEX</code> uses a model agnostic variable importance measure computed via permutation. This approach follows the following steps:</p>
<div>
<div>
<pre><code>For any given loss function do
1: compute loss function for full model (denote _full_model_)
2: randomize response variable, apply given ML, and compute loss function (denote _baseline_)
3: for variable j
     | randomize values
     | apply given ML model
     | compute &amp; record loss function
   end
</code></pre>
</div>
</div>
<p>To compute the permuted variable importance we use <code>DALEX::variable_importance()</code>. The printed output just provides a data frame with the output and plotting the three variable importance objects allows us to compare the most influential variables for each model. How do we interpret this plot?</p>
<ol>
<li>Left edge of x-axis is the loss function for the <code>_full_model_</code>. The default loss function is squared error but any custom loss function can be supplied.</li>
<li>The first item listed in each plot is <code>_baseline_</code>. This value represents the loss function when our response values are randomized and should be a good indication of the worst-possible loss function value when there is no predictive signal in the data.</li>
<li>The length of the remaining variables represent the variable importance. The larger the line segment, the larger the loss when that variable is randomized.</li>
</ol>
<p>The results provide some interesting insights. First, the shifted x-axis left edge helps to illustrate the difference in the RMSE loss between the three models (i.e. GLM model has the lowest RMSE suggesting that the greater number of tail residuals in the GBM model is likely penalizing the RMSE score. Second, we can see which variables are consistently influential across all models (i.e. <code>OverTime</code>, <code>EnvironmentSatisfaction</code>, <code>Age</code>), variables that are influential in two but not all three (i.e. <code>BusinessTravel</code>, <code>WorkLifeBalance</code>), and variables which are only influential in one model but not others (i.e. <code>DailyRate</code>, <code>YearsInCurrentRole</code>). This helps you to see if models are picking up unique structure in the data or if they are using common logic.</p>
<p>In this example, all three models appear to be largely influenced by the <code>OverTime</code>, <code>EnvironmentSatisfaction</code>, <code>Age</code>, <code>TotalWorkingYears</code>, and <code>JobLevel</code> variables. This gives us confidences that these features have strong predictive signals.</p>
<p><strong>TIP</strong>: You can incorporate custom loss functions using the <code>loss_function</code> argument.</p>
<figure>
<pre><code data-lang="r"><span># compute permutation-based variable importance</span><span>
</span><span>vip_glm</span><span> </span><span>&lt;-</span><span> </span><span>variable_importance</span><span>(</span><span>explainer_glm</span><span>,</span><span> </span><span>n_sample</span><span> </span><span>=</span><span> </span><span>-1</span><span>,</span><span> </span><span>loss_function</span><span> </span><span>=</span><span> </span><span>loss_root_mean_square</span><span>)</span><span> </span><span>vip_rf</span><span> </span><span>&lt;-</span><span> </span><span>variable_importance</span><span>(</span><span>explainer_rf</span><span>,</span><span> </span><span>n_sample</span><span> </span><span>=</span><span> </span><span>-1</span><span>,</span><span> </span><span>loss_function</span><span> </span><span>=</span><span> </span><span>loss_root_mean_square</span><span>)</span><span>
</span><span>vip_gbm</span><span> </span><span>&lt;-</span><span> </span><span>variable_importance</span><span>(</span><span>explainer_gbm</span><span>,</span><span> </span><span>n_sample</span><span> </span><span>=</span><span> </span><span>-1</span><span>,</span><span> </span><span>loss_function</span><span> </span><span>=</span><span> </span><span>loss_root_mean_square</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>vip_glm</span><span>,</span><span> </span><span>vip_rf</span><span>,</span><span> </span><span>vip_gbm</span><span>,</span><span> </span><span>max_vars</span><span> </span><span>=</span><span> </span><span>10</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk vip" src="https://i0.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/vip-1.png?w=456" data-recalc-dims="1"></p>
<p>One downfall of the permutation-based approach to variable importance is it can become slow. Since the algorithm loops through and applies a model for each predictor variable, the more features in your model the longer it will take. For this example, which includes 30 features, it takes 81 seconds to compute variable importance for all three models. However, when tested on a data set with 100 predictors it took nearly 5 minutes to compute.</p>
<p><strong>TIP</strong>: <code>variable_importance</code> includes an <code>n_sample</code> argument that, by default, will sample only 1000 observations to try increase the speed of computation. Adjusting <code>n_sample = -1</code> as I did in the above code chunk just means to use all observations.</p>
<h3>6.0 Predictor-response relationship</h3>
<p>Once we’ve identified influential variables across all three models, next we likely want to understand how the relationship between these influential variables and the predicted response differ between the models. This helps to indicate if each model is responding to the predictor signal similarly or if one or more models respond differently. For example, we saw that the <code>Age</code> variable was one of the most influential variables across all three models. The below partial dependence plot illustrates that the GBM and random forest models are using the <code>Age</code> signal in a similar non-linear manner; however, the GLM model is not able to capture this same non-linear relationship. So although the GLM model may perform better (re: AUC score), it may be using features in biased or misleading ways.</p>
<figure>
<pre><code data-lang="r"><span># compute PDP for a given variable --> uses the pdp package</span><span>
</span><span>pdp_glm</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_glm</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;Age&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;pdp&quot;</span><span>)</span><span>
</span><span>pdp_rf</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_rf</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;Age&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;pdp&quot;</span><span>)</span><span>
</span><span>pdp_gbm</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_gbm</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;Age&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;pdp&quot;</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>pdp_glm</span><span>,</span><span> </span><span>pdp_rf</span><span>,</span><span> </span><span>pdp_gbm</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk pdp" src="https://i0.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/pdp-1.png?w=456" data-recalc-dims="1"></p>
<p>Although you can use PDPs for categorical predictor variables, <code>DALEX</code> provides <em>merging path plots</em> originally provided by the <a rel="nofollow" href="https://mi2datalab.github.io/factorMerger/" target="_blank"><code>factoMerger</code></a> package. For example, the <code>EnvironmentSatisfaction</code> variable captures the level of satisfaction regarding the working environment among employees. This variable showed up in all three models’ top 10 most influential variable lists. We can use <code>type = &quot;factor&quot;</code> to create a merging path plot and it shows very similar results for each model. Those employees that have low level of satisfaction have, on average, higher probabilities of attrition. Whereas, employees with medium to very high have about the same likelihood of attriting. The left side of the plot is the merging path plot, which shows the similarity between groups via hierarchical clustering. It illustrates that employees with medium and high satisfaction are most similar, then these employees are next most similar to employees with very high satisfaction. Then finally, the least similar group is the low satisfaction employees.</p>
<figure>
<pre><code data-lang="r"><span>cat_glm</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_glm</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;EnvironmentSatisfaction&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;factor&quot;</span><span>)</span><span>
</span><span>cat_rf</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_rf</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;EnvironmentSatisfaction&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;factor&quot;</span><span>)</span><span>
</span><span>cat_gbm</span><span> </span><span>&lt;-</span><span> </span><span>variable_response</span><span>(</span><span>explainer_gbm</span><span>,</span><span> </span><span>variable</span><span> </span><span>=</span><span> </span><span>&quot;EnvironmentSatisfaction&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;factor&quot;</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>cat_glm</span><span>,</span><span> </span><span>cat_rf</span><span>,</span><span> </span><span>cat_gbm</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk pdp-categorical" src="https://i0.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/pdp-categorical-1.png?w=456" data-recalc-dims="1"></p>
<h3>7.0 Local interpretation</h3>
<p>The previous plots help us to understand our model from a <strong><em>global perspective</em></strong> by illustrating errors, identifying the variables with the largest overall impact, and understanding predictor-response relationships across all observations. However, often, we also need to perform <strong><em>local interpretation</em></strong> which allows us to understand why a particular prediction was made for an observation. Understanding and comparing how a model uses the predictor variables to make a given prediction can provide trust to you (the analyst) and also the stakeholder(s) that will be using the model output for decision making purposes.</p>
<p>Although <a rel="nofollow" href="https://github.8451.com/r-for-data-science/r_for_data_science/blob/master/papers/lime.pdf" target="_blank">LIME</a> and SHAP (<a rel="nofollow" href="https://github.8451.com/r-for-data-science/r_for_data_science/blob/master/papers/shapley_lundberg_lee.pdf" target="_blank">1</a>, <a rel="nofollow" href="https://github.8451.com/r-for-data-science/r_for_data_science/blob/master/papers/shapley_paper2.pdf" target="_blank">2</a>) values have recently become popular for local ML interpretation, <code>DALEX</code> uses a process called <a rel="nofollow" href="https://github.8451.com/r-for-data-science/r_for_data_science/blob/master/papers/Explanations_of_model_predictions_with_live_and_breakDown_packages.pdf" target="_blank">break down</a> to compute localized variable importance scores.</p>
<p>There are two break down approaches that can be applied. The default is called <strong><em>step up</em></strong> and the algorithm performs the following steps:</p>
<div>
<div>
<pre><code>existing_data = validation data set used in explainer
new_ob = single observation to perform local interpretation on
p = number of predictors
l = list of predictors
baseline = mean predicted response of existing_data

for variable i in {1,...,p} do
  for variable j in {1,...,l} do
    | substitue variable j in existing_data with variable j value in new_ob
    | predicted_j = mean predicted response of altered existing_data
    | diff_j = absolute difference between baseline - predicted
    | reset existing_data
    end
  | t = variable j with largest diff value
  | contribution for variable t = diff value for variable t 
  | remove variable t from l
  end
</code></pre>
</div>
</div>
<p>This is called step up because, essentially, it sweeps through each column, identifies the column with the largest difference score, adds that variable to the list as the most important, sweeps through the remaining columns, identifies the column with the largest score, adds that variable to the list as second most important, etc. until all variables have been assessed.</p>
<p>An alternative approach is called the <strong><em>step down</em></strong> which follows a similar algorithm but rather than remove the variable with the largest difference score on each sweep, it removes the variable with the smallest difference score. Both approaches are analogous to backward stepwise selection where <em>step up</em> removes variables with largest impact and <em>step down</em> removes variables with smallest impact.</p>
<p>To perform the break down algorithm on a single observation, use the <code>DALEX::prediction_breakdown</code> function. The output is a data frame with class “prediction_breakdown_explainer” that lists the contribution for each variable.</p>
<p><strong>TIP</strong>: The default approach is <strong><em>step up</em></strong> but you can perform <strong><em>step down</em></strong> by adding the following argument <code>direction = &quot;down&quot;</code>.</p>
<figure>
<pre><code data-lang="r"><span># create a single observation</span><span>
</span><span>new_cust</span><span> </span><span>&lt;-</span><span> </span><span>splits</span><span>$</span><span>valid</span><span>[</span><span>1</span><span>,</span><span> </span><span>]</span><span> </span><span>%>%</span><span> </span><span>as.data.frame</span><span>()</span><span>
</span><span># compute breakdown distances</span><span>
</span><span>new_cust_glm</span><span> </span><span>&lt;-</span><span> </span><span>prediction_breakdown</span><span>(</span><span>explainer_glm</span><span>,</span><span> </span><span>observation</span><span> </span><span>=</span><span> </span><span>new_cust</span><span>)</span><span>
</span><span>new_cust_rf</span><span> </span><span>&lt;-</span><span> </span><span>prediction_breakdown</span><span>(</span><span>explainer_rf</span><span>,</span><span> </span><span>observation</span><span> </span><span>=</span><span> </span><span>new_cust</span><span>)</span><span>
</span><span>new_cust_gbm</span><span> </span><span>&lt;-</span><span> </span><span>prediction_breakdown</span><span>(</span><span>explainer_gbm</span><span>,</span><span> </span><span>observation</span><span> </span><span>=</span><span> </span><span>new_cust</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span># class of prediction_breakdown output</span><span>
</span><span>class</span><span>(</span><span>new_cust_gbm</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] &quot;prediction_breakdown_explainer&quot; &quot;data.frame&quot;</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span># check out the top 10 influential variables for this observation</span><span>
</span><span>new_cust_gbm</span><span>[</span><span>1</span><span>:</span><span>10</span><span>,</span><span> </span><span>1</span><span>:</span><span>5</span><span>]</span><span> </span><span>%>%</span><span>
</span><span>knitr</span><span>::</span><span>kable</span><span>()</span></code></pre>
</figure>
<table>
<thead>
<tr>
<th> </th>
<th>variable</th>
<th>contribution</th>
<th>variable_name</th>
<th>variable_value</th>
<th>cummulative</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>(Intercept)</td>
<td>0.0000000</td>
<td>Intercept</td>
<td>1</td>
<td>0.0000000</td>
</tr>
<tr>
<td>JobRole</td>
<td>+ JobRole = Laboratory_Technician</td>
<td>0.0377084</td>
<td>JobRole</td>
<td>Laboratory_Technician</td>
<td>0.0377084</td>
</tr>
<tr>
<td>StockOptionLevel</td>
<td>+ StockOptionLevel = 0</td>
<td>0.0243714</td>
<td>StockOptionLevel</td>
<td>0</td>
<td>0.0620798</td>
</tr>
<tr>
<td>MaritalStatus</td>
<td>+ MaritalStatus = Single</td>
<td>0.0242334</td>
<td>MaritalStatus</td>
<td>Single</td>
<td>0.0863132</td>
</tr>
<tr>
<td>JobLevel</td>
<td>+ JobLevel = 1</td>
<td>0.0318771</td>
<td>JobLevel</td>
<td>1</td>
<td>0.1181902</td>
</tr>
<tr>
<td>Age</td>
<td>+ Age = 32</td>
<td>0.0261924</td>
<td>Age</td>
<td>32</td>
<td>0.1443826</td>
</tr>
<tr>
<td>BusinessTravel</td>
<td>+ BusinessTravel = Travel_Frequently</td>
<td>0.0210466</td>
<td>BusinessTravel</td>
<td>Travel_Frequently</td>
<td>0.1654292</td>
</tr>
<tr>
<td>RelationshipSatisfaction</td>
<td>+ RelationshipSatisfaction = High</td>
<td>0.0108112</td>
<td>RelationshipSatisfaction</td>
<td>High</td>
<td>0.1762404</td>
</tr>
<tr>
<td>Education</td>
<td>+ Education = College</td>
<td>0.0016912</td>
<td>Education</td>
<td>College</td>
<td>0.1779315</td>
</tr>
<tr>
<td>PercentSalaryHike</td>
<td>+ PercentSalaryHike = 13</td>
<td>0.0001158</td>
<td>PercentSalaryHike</td>
<td>13</td>
<td>0.1780473</td>
</tr>
</tbody>
</table>
<p>We can plot the entire list of contributions for each variable of a particular model. We can see that several predictors have zero contribution, while others have positive and negative contributions. For the GBM model, the predicted value for this individual observation was positively influenced (increased probability of attrition) by variables such as <code>JobRole</code>, <code>StockOptionLevel</code>, and <code>MaritalStatus</code>. Alternatively, variables such as <code>JobSatisfaction</code>, <code>OverTime</code>, and <code>EnvironmentSatisfaction</code> reduced this observations probability of attriting.</p>
<figure>
<pre><code data-lang="r"><span>plot</span><span>(</span><span>new_cust_gbm</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk unnamed-chunk-3" src="https://i0.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/unnamed-chunk-3-1.png?w=456" data-recalc-dims="1"></p>
<p>For data sets with a small number of predictors, you can compare across multiple models in a similar way as with earlier plotting (<code>plot(new_cust_glm, new_cust_rf, new_cust_gbm)</code>). However, with wider data sets, this becomes cluttered and difficult to interpret. Alternatively, you can filter for the largest absolute contribution values. This causes the output class to lose its prediction_breakdown_explainer class so we can plot the results with <code>ggplot</code>.</p>
<p>Each model has a similar prediction that the new observation has a low probability of predicting:</p>
<ul>
<li>GLM: .12</li>
<li>random forest: 0.18</li>
<li>GBM: 0.06</li>
</ul>
<p>However, how each model comes to that conclusion in a slightly different way. However, there are several predictors that we see consistently having a positive or negative impact on this observations’ probability of attriting (i.e. <code>OverTime</code>, <code>EnvironmentSatisfaction</code>, <code>JobSatisfaction</code> are reducing this employees probability of attriting while <code>JobLevel</code>, <code>MaritalStatus</code>, <code>StockOptionLevel</code>, and <code>JobLevel</code> are all increasing the probability of attriting). Consequently, we can have a decent amount of trust that these are strong signals for this observation regardless of model. However, when each model picks up unique signals in variables that the other models do not capture (i.e. <code>DistanceFromHome</code>, <code>NumCompaniesWorked</code>), its important to be careful how we communicate these signals to stakeholders. Since these variables do not provide consistent signals across all models we should use domain experts or other sources to help validate whether or not these predictors are trustworthy. This will help us understand if the model is using proper logic that translates well to business decisions.</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>ggplot2</span><span>)</span><span>
</span><span># filter for top 10 influential variables for each model and plot</span><span>
</span><span>list</span><span>(</span><span>new_cust_glm</span><span>,</span><span> </span><span>new_cust_rf</span><span>,</span><span> </span><span>new_cust_gbm</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>purrr</span><span>::</span><span>map</span><span>(</span><span>~</span><span> </span><span>top_n</span><span>(</span><span>.</span><span>,</span><span> </span><span>11</span><span>,</span><span> </span><span>wt</span><span> </span><span>=</span><span> </span><span>abs</span><span>(</span><span>contribution</span><span>)))</span><span> </span><span>%>%</span><span>
</span><span>do.call</span><span>(</span><span>rbind</span><span>,</span><span> </span><span>.</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>variable</span><span> </span><span>=</span><span> </span><span>paste0</span><span>(</span><span>variable</span><span>,</span><span> </span><span>&quot; (&quot;</span><span>,</span><span> </span><span>label</span><span>,</span><span> </span><span>&quot;)&quot;</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>contribution</span><span>,</span><span> </span><span>reorder</span><span>(</span><span>variable</span><span>,</span><span> </span><span>contribution</span><span>)))</span><span> </span><span>+</span><span>
</span><span>geom_point</span><span>()</span><span> </span><span>+</span><span>
</span><span>geom_vline</span><span>(</span><span>xintercept</span><span> </span><span>=</span><span> </span><span>0</span><span>,</span><span> </span><span>size</span><span> </span><span>=</span><span> </span><span>3</span><span>,</span><span> </span><span>color</span><span> </span><span>=</span><span> </span><span>&quot;white&quot;</span><span>)</span><span> </span><span>+</span><span>
</span><span>facet_wrap</span><span>(</span><span>~</span><span> </span><span>label</span><span>,</span><span> </span><span>scales</span><span> </span><span>=</span><span> </span><span>&quot;free_y&quot;</span><span>,</span><span> </span><span>ncol</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span> </span><span>+</span><span>
</span><span>ylab</span><span>(</span><span>NULL</span><span>)</span></code></pre>
</figure>
<p><img alt="plot of chunk unnamed-chunk-4" src="https://i0.wp.com/www.business-science.io/figure/source/2018-07-23-dalex-feature-interpretation/unnamed-chunk-4-1.png?w=456" data-recalc-dims="1"></p>
<p>Unfortunately, a major drawback to <code>DALEX</code>’s implementation of these algorithm’s is that they are not parallelized. Consequently, wide data sets become extremely slow. For example, performing the previous three <code>prediction_breakdown</code> functions on this attrition data set with 30 predictors takes about 12 minutes. However, this grows exponentially as more predictors are added. When we apply a single instance of <code>prediction_breakdown</code> to the Ames housing data (80 predictors), it <strong><em>took over 3 hours to execute</em></strong>!</p>
<figure>
<pre><code data-lang="r"><span># ames data</span><span>
</span><span>ames.h2o</span><span> </span><span>&lt;-</span><span> </span><span>as.h2o</span><span>(</span><span>AmesHousing</span><span>::</span><span>make_ames</span><span>())</span><span>
</span><span># create local observation</span><span>
</span><span>local_ob</span><span> </span><span>&lt;-</span><span> </span><span>as.data.frame</span><span>(</span><span>ames.h2o</span><span>[</span><span>1</span><span>,</span><span> </span><span>])</span><span>
</span><span># variable names for resonse &amp; features</span><span>
</span><span>y</span><span> </span><span>&lt;-</span><span> </span><span>&quot;Sale_Price&quot;</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>setdiff</span><span>(</span><span>names</span><span>(</span><span>ames.h2o</span><span>),</span><span> </span><span>y</span><span>)</span><span>
</span><span># random forest model</span><span>
</span><span>rf</span><span> </span><span>&lt;-</span><span> </span><span>h</span><span>2</span><span>o.randomForest</span><span>(</span><span>
</span><span>x</span><span> </span><span>=</span><span> </span><span>x</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y</span><span>,</span><span>
</span><span>training_frame</span><span> </span><span>=</span><span> </span><span>ames.h2o</span><span>,</span><span>
</span><span>ntrees</span><span> </span><span>=</span><span> </span><span>1000</span><span>
</span><span>)</span><span>
</span><span># get features for explainer</span><span>
</span><span>x_valid</span><span> </span><span>&lt;-</span><span> </span><span>as.data.frame</span><span>(</span><span>ames.h2o</span><span>)[,</span><span> </span><span>x</span><span>]</span><span>
</span><span>y_valid</span><span> </span><span>&lt;-</span><span> </span><span>as.vector</span><span>(</span><span>ames.h2o</span><span>[</span><span>y</span><span>])</span><span>
</span><span># create custom predict function</span><span>
</span><span>pred</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>model</span><span>,</span><span> </span><span>newdata</span><span>)</span><span> </span><span>{</span><span>
</span><span>results</span><span> </span><span>&lt;-</span><span> </span><span>as.vector</span><span>(</span><span>predict</span><span>(</span><span>model</span><span>,</span><span> </span><span>as.h2o</span><span>(</span><span>newdata</span><span>)))</span><span>
</span><span>return</span><span>(</span><span>results</span><span>)</span><span>
</span><span>}</span><span>
</span><span># create explainer</span><span>
</span><span>ames_rf</span><span> </span><span>&lt;-</span><span> </span><span>explain</span><span>(</span><span>
</span><span>model</span><span> </span><span>=</span><span> </span><span>rf</span><span>,</span><span>
</span><span>data</span><span> </span><span>=</span><span> </span><span>x_valid</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>y_valid</span><span>,</span><span>
</span><span>predict_function</span><span> </span><span>=</span><span> </span><span>pred</span><span>,</span><span>
</span><span>label</span><span> </span><span>=</span><span> </span><span>&quot;ames&quot;</span><span>
</span><span>)</span><span>
</span><span># time to compute prediction break down</span><span>
</span><span>system.time</span><span>({</span><span>
</span><span>ames_example</span><span> </span><span>&lt;-</span><span> </span><span>prediction_breakdown</span><span>(</span><span>ames_rf</span><span>,</span><span> </span><span>observation</span><span> </span><span>=</span><span> </span><span>local_ob</span><span>)</span><span>
</span><span>})</span></code></pre>
</figure>
<p>Looking at the <a rel="nofollow" href="https://github.com/pbiecek/breakDown/blob/master/R/break_agnostic.R" target="_blank">underlying code</a> for the <code>prediction_breakdown</code> function (it simply calls <code>breakDown::broken.default</code>), there are opportunities for integrating parallelization capabilities (i.e. via <code>foreach</code> package). Consequently, prior to adding it to your preferred ML toolkit, you should determine:</p>
<ol>
<li>if you are satisfied with its general alorithmic approach,</li>
<li>do you typically use wide data sets, and if so…</li>
<li>what is your appetite and bandwidth for integrating parallelization (either in your own version or collaborating with the package authors),</li>
<li>and how is performance after parallelization (do you see enough speed improvement to justify use).</li>
</ol>
<h2>Next Steps: Take The Data Science For Business With R Course!</h2>
<p>If interested in learning more about modeling using H2O and model explanations, definitely check out <a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank"><strong>Data Science For Business With R (DS4B 201-R)</strong></a>. Over the course of 10 weeks, the the student learn all of the steps to solve a $15M employee turnover problem with H2O along with a host of other tools, frameworks, and techniques.</p>
<p>The students love it. Here’s a comment we received from one of our students, <a rel="nofollow" href="https://www.linkedin.com/in/siddhartha-choudhury-715524100/" target="_blank">Siddhartha Choudhury, Data Architect at Accenture</a>.</p>
<p><img alt="Testimonial" src="https://i0.wp.com/www.business-science.io/assets/2018-07-11-expected-value/testimonial.png?w=456" data-recalc-dims="1"></p>
<blockquote>
<p><em>“To be honest, this course is the best example of an end to end project I have seen from business understanding to communication.”</em></p>
<p>Siddhartha Choudhury, Data Architect at Accenture</p>
</blockquote>
<p>See for yourself why our students have rated <a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank">Data Science For Business With R (DS4B 201-R)</a> a 9.0 of 10.0 for Course Satisfaction!</p>
<p><a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank"><br>
Get Started Today!<br>
</a></p>
<h4>Data Science For Business With Python (DS4B 201-P)</h4>
<p>P.S. Did we mention with have a <strong>DS4B Python Course coming</strong>?!?! Well we do! <a rel="nofollow" href="https://www.linkedin.com/in/faviovazquez/" target="_blank">Favio Vazquez</a>, Principle Data Scientist at OXXO, is building the Python equivalent of DS4B 201. The problem changes: Customer Churn! The tools will be H2O, LIME, and a host of other tools implemented in Python. More information is forthcoming. Sign up for <a rel="nofollow" href="https://university.business-science.io/" target="_blank">Business Science University</a> to stay updated.</p>
<h2>About The Author</h2>
<p>This <strong><em>MACHINE LEARNING TUTORIAL</em></strong> comes from <a rel="nofollow" href="https://www.linkedin.com/in/brad-boehmke-ph-d-9b0a257/" target="_blank">Brad Boehmke</a>, Director of Data Science at <a rel="nofollow" href="https://www.linkedin.com/company/84-51/" target="_blank">84.51°</a>, where he and his team develops algorithmic processes, solutions, and tools that enable 84.51° and its analysts to efficiently extract insights from data and provide solution alternatives to decision-makers. Brad is not only a talented data scientist, he’s an adjunct professor at the University of Cincinnati, Wake Forest, and Air Force Institute of Technology. Most importantly, he’s an <a rel="nofollow" href="https://github.com/bradleyboehmke" target="_blank">active contributor</a> to the <strong>Data Science Community</strong> and he enjoys giving back via advanced machine learning education available at the <a rel="nofollow" href="http://uc-r.github.io/" target="_blank">UC Business Analytics R Programming Guide</a>!</p>
<h2>Additional DALEX Resources</h2>
<p>The following provides resources to learn more about the <code>DALEX</code> package:</p>
<ul>
<li><code>DALEX</code> GitHub repo: https://github.com/pbiecek/DALEX</li>
<li><code>breakDown</code> package which is called by <code>DALEX</code>: https://github.com/pbiecek/breakDown</li>
<li>Paper that explains the prediction break down algorithm <a rel="nofollow" href="https://github.8451.com/r-for-data-science/r_for_data_science/blob/master/papers/Explanations_of_model_predictions_with_live_and_breakDown_packages.pdf" target="_blank">link</a></li>
</ul>
<h2>Business Science University <a></a></h2>
<p>If you are looking to take the next step and learn <strong>Data Science For Business (DS4B)</strong>, <a rel="nofollow" href="https://university.business-science.io/" target="_blank">Business Science University</a> is for you! Our goal is to <strong>empower data scientists</strong> through teaching the tools and techniques we implement every day. You’ll learn:</p>
<ul>
<li><strong>TO SOLVE A REAL WORLD CHURN PROBLEM: Employee Turnover</strong>!</li>
<li>Data Science Framework: <a rel="nofollow" href="http://www.business-science.io/bspf.html" target="_blank">Business Science Problem Framework</a></li>
<li>Tidy Eval</li>
<li>H2O Automated Machine Learning</li>
<li>LIME Feature Explanations</li>
<li>Sensitivity Analysis</li>
<li>Tying data science to financial improvement (<strong>ROI-Driven Data Science</strong>)</li>
</ul>
<h3>Data Science For Business With R Virtual Workshop <a></a></h3>
<p>Did you know that <strong>an organization that loses 200 high performing employees per year is essentially losing $15M/year in lost productivity</strong>? Many organizations don’t realize this because it’s an indirect cost. It goes unnoticed.</p>
<p>What if you could use data science to predict and explain turnover in a way that managers could make better decisions and executives would see results? You will learn the tools to do so in our Virtual Workshop using the R Statistical Programming Language. Here’s an example of a Shiny app you will create.</p>
<p><a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank"><br>
Get 15% OFF!<br>
</a></p>
<p><img alt="HR 301 Shiny Application: Employee Prediction" src="https://i0.wp.com/www.business-science.io/img/hr_301_app.png?w=456" data-recalc-dims="1"></p>
<p>Shiny App That Predicts Attrition and Recommends Management Strategies, Taught in DS4B 301 (Building A Shiny Web App)</p>
<p>Our first <strong>Data Science For Business Virtual Workshop</strong> teaches you how to solve this employee attrition problem in four courses that are fully integrated:</p>
<ul>
<li><a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank">DS4B 201-R: Predicting Employee Attrition with <code>h2o</code> and <code>lime</code></a></li>
<li>DS4B 301-R (Coming Soon): Building A <code>Shiny</code> Web Application</li>
<li>DS4B 302-R (EST Q4): Data Communication With <code>RMarkdown</code> Reports and Presentations</li>
<li>DS4B 303-R (EST Q4): Building An R Package For Your Organization, <code>tidyattrition</code></li>
</ul>
<p>The Virtual Workshop is intended for <strong>intermediate and advanced R users</strong>. It’s <strong>code intensive (like these articles)</strong>, but also teaches you fundamentals of data science consulting including CRISP-DM and the Business Science Problem Framework. <strong>The content bridges the gap between data science and the business, making you even more effective and improving your organization in the process.</strong></p>
<p><a rel="nofollow" href="https://university.business-science.io/p/hr201-using-machine-learning-h2o-lime-to-predict-employee-turnover/?product_id=635023&coupon_code=DS4B_15" target="_blank"><br>
Get 15% OFF!<br>
</a></p>
<h3>Data Science For Business With Python (DS4B 201-P)</h3>
<p>Did we mention with have a <strong>DS4B Python Course coming</strong>?!?! Well we do! <a rel="nofollow" href="https://www.linkedin.com/in/faviovazquez/" target="_blank">Favio Vazquez</a>, Principle Data Scientist at OXXO, is building the Python equivalent of DS4B 201. The problem changes: Customer Churn! The tools will be H2O, LIME, and a host of other tools implemented in Python. More information is forthcoming. Sign up for <a rel="nofollow" href="https://university.business-science.io/" target="_blank">Business Science University</a> to stay updated.</p>
<h2>Don’t Miss A Beat</h2>
<ul>
<li>Sign up for the <a rel="nofollow" href="https://mailchi.mp/business-science.io/five-topic-friday" target="_blank">Business Science “5 Topic Friday” Newsletter!</a></li>
<li>Get started with <a rel="nofollow" href="https://university.business-science.io/" target="_blank">Business Science University</a> to learn how to solve real-world data science problems from Business Science</li>
<li>Check out our <a rel="nofollow" href="http://www.business-science.io/r-packages.html" target="_blank">Open Source Software</a></li>
</ul>
<p><span data-sumome-listbuilder-embed-id="8944080265e0a41a6249cd11ea3299d46ee953ea5bc9a1cd5635069be5bf0987"></span></p>
<h2>Connect With Business Science <a></a></h2>
<p>If you like our software (<code>anomalize</code>, <code>tidyquant</code>, <code>tibbletime</code>, <code>timetk</code>, and <code>sweep</code>), our courses, and our company, you can connect with us:</p>
<ul>
<li><a rel="nofollow" href="https://github.com/business-science" target="_blank"><strong>business-science</strong> on GitHub</a></li>
<li><a rel="nofollow" href="https://www.linkedin.com/company/business.science" target="_blank"><strong>Business Science, LLC</strong> on LinkedIn</a></li>
<li><a rel="nofollow" href="https://twitter.com/bizScienc" target="_blank"><strong>bizScienc</strong> on twitter</a></li>
<li><a rel="nofollow" href="https://www.facebook.com/Business-Science-LLC-754699134699054/" target="_blank"><strong>Business Science, LLC</strong> on Facebook</a></li>
</ul>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.business-science.io/business/2018/07/23/dalex-feature-interpretation.html"> business-science.io - Articles</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/1vCYg62VhoY" height="1"></a></div>