How to overcome the dependency pitfall in explaining predictive model?

The answer is to use Aspect — a new module in the dalex Python package.

Mateusz Krzyziński
ResponsibleML
7 min readSep 13, 2021

--

By Mateusz Krzyziński

Motivation

Let’s start with philosophy. Yes, literally, philosophy.

The whole is greater than the sum of the parts.
— Aristotle

You may now be wondering how this timeless thought relates to explaining machine learning models? We’ll find out soon!

In the real world, we come across data with dependencies. It is almost impossible to avoid dependence among predictors when building predictive models.

Unfortunately, many commonly used XAI methods ignore these dependencies, often assuming independence of variables (e.g., permutation methods), which leads to unrealistic settings and misleading explanations. This is one of the explanation pitfalls.

For example, imagine that we were to analyze the behavior of a model predicting the value of housing based on some information, including the area of the flat and the number of rooms, which are naturally dependent on each other.

To estimate the importance of variables, we can use the well-known, easy-to-use technique of permutation importance. During the calculations for the variable describing the flat area, we permute the values ​​only in the appropriate data set column while leaving the others as they are. Then, using the analyzed model, we make predictions on the changed data set. Finally, based on the loss in a score, we calculate the importance of the flat area variable.

However, remember that we also have a variable that describes the number of rooms in the apartment and the values ​​in this column remain unchanged. Therefore, data points were created that describe apartments with e.g., 120 m² and one room, or 30 m² and five rooms.

Of course, the model we are analyzing has not dealt with such unrealistic examples before and must extrapolate to this new feature space. An analysis using such ridiculous, artificially generated observations leads to misleading results and, consequently, incorrect conclusions about the operation of the model.

We propose a way in which you can explain your model, avoiding this pitfall. The solution is based on grouping variables in the so-called aspects by taking into account the dependencies between them.

Going back to Aristotle’s words, these aspects of the correlated variables constitute a kind of ‘whole’. To avoid misleading results, it is better to analyze these ‘wholes’, rather than just individual variables (‘parts’).

That’s exactly what the new dalex module named Aspect makes possible. Currently available part of the module includes functionalities that enable estimating the importance and contribution of variables (joint work with Artur Żółkowski under the tutoring of Hubert Baniecki).

How to use it?

  1. You need to install or update the dalex package to access the new module.
pip install -U dalex

2. Initialize the Aspect object on the basis of the Explainer object.

import dalex as dx
explainer = dx.Explainer(model, X, y)
aspect = dx.Aspect(explainer, depend_method='association', clust_method='complete')

The Aspect object itself contains information about the dependencies between variables and their hierarchical clustering into aspects. It is in this step that you can choose how the dependencies will be calculated — depend_method, and groups created — clust_method.

3. That’s it! Use the Aspect object to create explanations on a global and local level using the well-known grammar from dalex.

Let’s check it out with an example of the explanations for the model predicting the next-day rain in Australia (Kaggle dataset).

Triplot methods

The aspect module introduces a new type of explanation — the triplot. It is a tool that creates explanations based on the identified variables’ dependency structure. The triplot analysis enables a deeper understanding of the influence of dependencies between the variables on the model behavior, allows to find an appropriate approach to grouping variables, and provides a background for further model analysis.

Model Triplot

One can use a model_triplot method in the Aspect object to create the global explanation.

mt = aspect.model_triplot(random_state=42)
mt.plot()
Model Triplot

Perhaps you think the triplot looks quite complicated? So let’s break it down! The triplot gives a more holistic explanation of the importance of variables by combining three panels:

  • Variable importance — the importance of every single variable;
  • Hierarchical clustering — dependency structure between variables visualized by hierarchical clustering dendrogram;
  • Hierarchical aspect importance — the importance of groups of dependent variables determined by hierarchical clustering.

Looking at the triplot, we can simultaneously check which variables are most dependent on each other and their importance, considering each of them both individually and in a group.

For example, we can observe a very interesting situation above. Although the Pressure3pm is the most important variable when considered individually, the situation changes when considering the pressure aspect. The group of two variables describing atmospheric pressure (which have a very high correlation of 0.96) is noticeably less critical for the model.

Where does this difference come from? This is due to the use of the variable importance estimation method based on permutations. Single column perturbation breaks the dependencies between variables and produces unrealistic data points, i.e., data points that lie off the true data manifold.

Thus, the analysis of the triplot allows us to avoid the pitfall dependency and keeps us from drawing wrong conclusions!

Predict Triplot

In order to create the local explanation, you can use the predict_triplot method in the Aspect object specifying the observation for analysis.

pt = aspect.predict_triplot(observation, random_state=42)
pt.plot()
Predict Triplot

The predict-level triplot, created for the selected observation, has a similar structure — the plot panels have the same meaning. However, the middle part of the local triplot may seem even more complicated, after all, aspects can have both positive and negative effects on the prediction. It can be challenging to read and analyze the explanation accurately when the importance of aspects varies significantly as at the bottom of the plot.

Thus, to facilitate exploratory analysis of the explanation, there is also an option to create an interactive widget version of the triplot (option available for both versions). After clicking on the dendrogram line in the widget, the plot elements corresponding to the selected aspect only are highlighted. Simple but effective!

pt.plot(widget=True)
Predict Triplot — interactive widget version

Here, in the highlighted part of the plot, we can see that although the northern wind direction increases the probability of rain in the context of the model predicting the weather for different localities, taking into account this particular location, the effect is quite the opposite.

Aspect Importance methods

The triplot explanation shows the hierarchical importance of the aspects, but it doesn’t give the complete picture of the situation at a given cut-off level. For this purpose, the Aspect module includes different methods. They do not use the entire hierarchical structure of dependencies but create an explanation in certain specific aspects (at a selected cut-off level or created based on domain knowledge, e.g., groups of variables with a similar meaning).

Model Aspect Importance

Again, let’s start with the global version of the method. We can specify the groups in which we want to obtain explanations using h - cut-off level (the minimum value of the dependency between the variables grouped in one aspect, shown on the dendrogram).

mai = aspect.model_parts(h=0.35, 
label = 'for aspects created on treshold h=0.35')
mai.plot()
Model Aspect Importance

Predict Aspect Importance

Of course, it’s time to take a look at the local version of the method. This time, let’s choose an algorithm based on SHAP and define the aspects of interest manually.

aspects = {
'Pressure': ['Pressure9am', 'Pressure3pm'],
'Temperature': ['MinTemp', 'MaxTemp', 'Temp9am', 'Temp3pm'],
'Wind': ['WindGustDir', 'WindDir9am', 'WindDir3pm', 'WindGustSpeed', 'WindSpeed9am', 'WindSpeed3pm'],
'Other': ['Location', 'Evaporation'],
'SkyConditions': ['Sunshine', 'Cloud9am', 'Cloud3pm'],
'Rainfall': ['Rainfall', 'RainToday'],
'Humidity': ['Humidity9am', 'Humidity3pm']
}
pai = aspect.predict_parts(observation, type='shap', variable_groups=aspects, label='for aspects created manually')pai.plot(show_variable_names=False)
Predict Aspect Importance

Summary

The Aspect module in dalex is designed to facilitate the explanation process for groups of variables. This is done by keeping track of the hierarchical structure of dependencies between the variables represented by the dendrogram. It is also an alternative to explanations that operate only on single variables, which are often misleading. All in all, it is the remedy for dealing with dependent variables in explanations.

So… why wait? Try it out!

If you want to learn more:

If you are interested in other posts about explainable, fair, and responsible ML, follow #ResponsibleML on Medium.

--

--