Automatiser la réduction des corrélations par clustering

Filtrer les corrélations est essentiel en Machine Learning pour avoir des modèles robustes et interprétables. Cette étape trop souvent laissée de côté peut être automatisée par clustering.
00 clustering corrélation matrice corrélation
Sommaire

La sélection des variables reste cruciale en machine learning pour améliorer l’interprétabilité et la robustesse des modèles, tout en limitant leur temps d’entraînement.

Pourtant le rôle des corrélations dans la sélection des variables est fréquemment sous-estimé par les data scientists, pour plusieurs raisons :

  • ils savent que les principaux modèles de Machine Learning sont immunes aux corrélations en termes de performance.
  • ils ignorent en revanche souvent que les mesures d’importance de variables à partir des modèles sont, elles, très sensibles aux corrélations.
  • l’analyse de matrices de corrélation avec des centaines de variables est laborieuse. On identifie bien les variables corrélées deux à deux mais il est difficile d’identifier des groupes de variables très corrélées pour n’en conserver qu’une seule par groupe.

Cet article vous montrera comment en quelques lignes de code identifier rapidement et automatiquement les groupes de corrélations entre vos variables, pour réaliser une première sélection de variables mais surtout pour fiabiliser les sélections post-modèles. Une méthode que nous avons intégrée à chaque projet désormais : l’essayer c’est l’adopter!

Les corrélations, un enjeu même en machine learning

Dans les modèles linéaires le problème de multicolinéarité des variables est identifié depuis longtemps. En 1967, Farrar et Glauber [1]  détaillaient déjà les effets introduits par la multicolinéarité dans les régressions linéaires. Les modèles linéaires ont évolué depuis mais la question de l’estimation des paramètres et de leur interprétation en présence de fortes corrélations est toujours d’actualité [2].

En Machine Learning en revanche, la question des corrélations s’est posée avec moins d’urgence : les algos de ML ont d’abord été utilisés pour leur performance, qui est souvent immune aux corrélations.

Mais qu’en est-il de l’importance des variables corrélées au sein de ces algorithmes? Une réponse de Tianqi Chen en 2018 [3] nous éclaire :

“ This difference has an impact on a corner case in feature importance analysis: the correlated features. Imagine two features perfectly correlated, feature A and feature B. For one specific tree, if the algorithm needs one of them, it will choose randomly (true in both boosting and Random Forests™).
However, in Random Forests™ this random choice will be done for each tree, because each tree is independent from the others. Therefore, approximatively, depending of your parameters, 50% of the trees will choose feature A and the other 50% will choose feature B. So the importance of the information contained in A and B (which is the same, because they are perfectly correlated) is diluted in A and B. So you won’t easily know this information is important to predict what you want to predict! It is even worse when you have 10 correlated features…
In boosting, when a specific link between feature and outcome have been learned by the algorithm, it will try to not refocus on it (in theory it is what happens, the reality is not always that simple). Therefore, all the importance will be on feature A or on feature B (but not both). You will know that one feature has an important role in the link between the observations and the label. It is still up to you to search for the correlated features to the one detected as important if you need to know all of them. “

Résumons donc :

  • Si vous avez un groupe de 5 variables très corrélées, dont l’information représente 10% des feature importance measures de votre Random Forest, elles ont en moyenne 2% chacune de cette feature importance. Vous avez donc une myriade de petites variables difficilement interprétables, qui cachent en réalité le principal feature de votre modèle.
  • Pour un Gradient Boosting, une de ces variables ressortira fortement si vous êtes chanceux, mais vous ignorerez la structure sous-jacente de vos données, qui peut être essentielle pour interpréter les résultats. Et avec un modèle aussi peu robuste vous vous mettez en position de devoir expliquer dans quelques mois pourquoi c’est une toute autre variable qui ressort à présent.

Par conséquent, il est nécessaire de limiter la multicolinéarité des variables utilisées par un modèle, même en Machine Learning. Examinons donc à présent comment réduire efficacement les structures de corrélations.

Les corrélations, matrice brute

Que l’on utilise les corrélations de Pearson (la définition classique de la corrélation) ou des méthodes plus avancées comme la corrélation de Spearman (corrélation des rangs), la question est la même : comment utiliser cette matrice pour mieux comprendre les corrélations dans nos données et retirer des variables intelligemment?

Pour illustrer l’identification des variables corrélées, prenons des données de consommation de 5 supermarchés Supermarket aggr. customer [4]. Ces données permettent de prédire le nombre de supermarchés fréquentés par un foyer en fonction de sa distance aux différents supermarchés et du nombre d’articles qu’il achète.

01 clustering corrélation matrice originale

Figure 1. Matrice de corrélation brute des données de consommation. Cette matrice nous indique de nombreuses corrélations et donc une forte redondance entre variables, ce qui vient du fait que certaines variables sont liées par construction : nombre d’articles achetés, nombre d’articles uniques achetés, montant total des achats etc.

On peut – en faisant quelques efforts – distinguer les groupes de variables corrélées au sein de ces données. Mais sans bénéficier d’une grande lisibilité des groupes. Cette absence de clarté devient fatale dès que le nombre de variables augmente : avec 100 variables et de nombreux patterns, il faut être un pro du rubik’s cube pour trouver les groupes. Et automatiser quoi que ce soit est impossible.

Réordonner les corrélations par clustering

La méthode

Pour mieux visualiser la matrice des corrélations, faisons un clustering. Le principe est ici de définir une distance entre deux variables à partir de leur corrélation. Munis de cette distance, nous pouvons construire un clustering hiérarchique entre les variables. Les variables “proches” dans la hiérarchie sont alors les variables qui sont le plus corrélées. Cette hiérarchie est réutilisable pour définir un ordre et permettre une meilleure visualisation de la matrice de corrélation avec les variables ordonnées.

Distance entre les variables

Pour faire des regroupements au sein desquels l’ensemble des corrélations deux à deux sont supérieures à un minimum, il faut d’abord définir une distance en se basant sur les corrélations. La solution la plus simple est de prendre

\begin{equation*} d(X_i, X_j) = 1 – |corr(X_i, X_j)| \end{equation*}

où :

  • $d$ désigne la distance entre deux variables
  • $X_i$ et $X_j$ désignent respectivement les valeurs prises par les variables $i$ et $j$.
  • et $corr$ désigne la corrélation entre deux variables

Cette formule permet :

  • que les variables parfaitement corrélées (positivement ou négativement) soient à une distance nulle l’une de l’autre.
  • que les variables avec une corrélation nulle soient à la distance maximale, c’est-à-dire 1.

Clustering hiérarchique

Pour répondre à la contrainte de faire des regroupements dont l’ensemble des corrélations deux à deux sont supérieures à un minimum, l’algorithme de clustering le plus adapté est le clustering hiérarchique ascendant avec un critère de liaison de saut maximum (complete linkage). Cet algorithme itératif fonctionne de la façon suivante :

  1. Initialisation : chaque point (ici un point = une variable) correspond à un cluster différent
  2. Récurrence : Pour chaque paire de clusters le critère de liaison est calculé et la paire de clusters dont le critère de liaison est minimal est regroupée en un seul cluster. Dans ce cas, le critère de liaison du saut maximum fait que le critère de liaison entre deux clusters vaut la corrélation maximale entre deux points de chaque cluster.
  3. Critère d’arrêt : La hiérarchie est entièrement construite lorsque tous les points sont regroupés dans un unique cluster.

Avec cette méthode, quel que soit le seuil x choisi pour créer les clusters, au sein de chaque cluster de variables toutes les corrélations deux à deux sont supérieures à 1-x.

02 clustering corrélation clustering hiérarchique

Figure 2. Principe du clustering hiérarchique étape par étape (à noter que dans notre cas, ce n’est pas la distance euclidienne en ordonnée mais la corrélation minimale). Image tirée de [5].

Code et résultats

Mettons la théorie en pratique sous Python. Le temps de calcul de cette méthode dépend surtout du temps de calcul de la matrice de corrélation, les autres opérations étant très rapides.

Avant toute chose, il y a certaines librairies Python à importer :

				
					import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
 
from scipy.cluster import hierarchy
from scipy.spatial.distance import squareform
from collections import defaultdict
				
			
  1. Calcul de la corrélation des éléments de X_num contenant les variables de prédiction (nous prenons la corrélation de Spearman ici) :
				
					corr = spearmanr(X_num, nan_policy = 'omit').correlation

				
			
  1. (Optionnel) Il se peut que le résultat de votre calcul de corrélation ne donne pas une matrice parfaitement symétrique du fait des floating points [5]. Pour passer aux étapes suivantes (dont les fonctions demandent une matrice exactement symétrique), le plus sûr est de symétriser et corriger la diagonale de la matrice :
				
					corr = (corr + corr.T) / 2
np.fill_diagonal(corr, 1.0)

				
			
  1. Définition de la distance :
				
					# Définition de la matrice de distance à partir des corrélations
dist = squareform(1-abs(corr))
				
			
  1. Construction du clustering hiérarchique :
				
					# Réalisation du clustering hiérarchique
corr_linkage = hierarchy.complete(dist)
				
			
  1. Récupération et visualisation de la hiérarchie :
				
					# Récupération du dendrogramme
dendro = hierarchy.dendrogram(
    corr_linkage,
    orientation="right",
    labels=var_selection_for_X_1_unordered,
)
				
			

L’ordre des variables est ensuite disponible dans dendro["leaves"] et les noms des variables correspondantes dans dendro["ivl"].

03 clustering corrélation dendrogramme clustering

Figure 3. Dendrogramme du clustering des données de consommation.

Explication du clustering avec les 3 variables du haut (traits verts) :

    • A l’abscisse 0, les 3 variables sont représentées par 3 traits différents. Cela signifie que parmi ces 3 variables il n’y a aucun couple parfaitement corrélé.
    • A l’abscisse 0.02, les deux premières lignes vertes se rejoignent : amount_purchased et products_purchased sont regroupées car leur corrélation est supérieure à 98% (= 1- 0.02).
    • A l’abscisse 0.04, la ligne verte du premier cluster rejoint la ligne verte de unique_producs_purchased : les trois variables sont regroupées car la corrélation minimale entre ces variables est toujours supérieure à 96%.
  1. Visualisation de la matrice de corrélation réordonnée (c’est exactement la même matrice qu’avant, seul l’ordre change!).
				
					fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plot = ax.pcolor(abs(corr[dendro["leaves"],:][:,dendro["leaves"]]))
dendro_idx = np.arange(0, len(dendro["ivl"]))
ax.set_xticks(dendro_idx)
ax.set_yticks(dendro_idx)
ax.set_xticklabels(dendro["ivl"], rotation='vertical')
ax.set_yticklabels(dendro["ivl"])
 
cbar = fig.colorbar(plot, format=ticker.PercentFormatter(xmax=1))
				
			
04 clustering corrélation matrice ordonnée

Figure 4. Matrice de corrélation réordonnée. Matrice de corrélation des données de consommation réordonnée. La matrice devient beaucoup plus claire, avec deux groupes de variables fortement corrélées : le nombre de produits, le nombre de produits uniques et le montant achetés dans tous les magasins d’une part et les mêmes variables dans le magasin n°1 d’autre part.

En utilisant cet ordre pour afficher la matrice des corrélations, la compréhension et l’interprétation des corrélations sont facilitées. Ci-dessous, on peut observer les améliorations quand le nombre de variables augmente dans nos données.

00 clustering corrélation matrice corrélation

Figure 5. Amélioration de la lisibilité de la matrice de corrélation. Matrice de corrélation avant et après ordonnancement des variables des données de consommation. Dans la version ordonnée de la matrice, les groupes s’identifient beaucoup plus facilement.

Automatisation de la sélection des variables

En choisissant la corrélation minimale au-dessus de laquelle les variables seront considérées comme redondantes, il devient possible de définir des regroupements et de réaliser une sélection des variables de façon automatisée.

Prenons l’exemple où l’on considère que les variables sont redondantes au-delà de 95% de corrélation. Alors il suffit de tracer un trait vertical d’abscisse 5% pour déterminer les clusters de variables. Les clusters formés à gauche de la ligne verticale tracée sont les regroupements retenus. Une illustration est obtenue avec le code suivant :

				
					hierarchy.dendrogram(
    corr_linkage,
    orientation="right",
    labels=X_num.columns,
    color_threshold=0.05
)
				
			

et visualisée dans la figure suivante :

06 clustering corrélation_dendrogramme seuil clustering

Figure 6. Dendrogramme avec seuil de regroupement. Dendrogramme du clustering des données de consommations avec application d’un seuil à 5% pour définir les groupes de variables redondantes.

Chaque trait bleu représente un groupe de variables différent lorsqu’on prend le seuil à 5% visualisé par la ligne noire. Par exemple, amount_purchased, products_purchased et unique_product_purchased sont dans un unique groupe de variables corrélées à plus de 95%.

Il est alors possible d’extraire le noms des colonnes à retirer de nos données :

				
					# Définition du seuil de corrélation
threshold_for_cluster_creation = 0.05
 
# Récupération des clusters à partir de la hiérarchie
cluster_ids = hierarchy.fcluster(corr_linkage, threshold_for_cluster_creation, criterion='distance')
cluster_id_to_feature_ids = defaultdict(list)
for idx, cluster_id in enumerate(cluster_ids):
    cluster_id_to_feature_ids[cluster_id].append(idx)
clusters = [ list(v) for v in cluster_id_to_feature_ids.values() if len(v) >1]
clusters_col = [list(X_num.columns[v]) for v in clusters]
 
# On ne conserve que la première variable de chaque cluster, les autres sont retirées
dropped_features = [ X_num.columns[v[1:]] for v in clusters ]
dropped_features = [item for sublist in dropped_features for item in sublist]
				
			

Où la liste dropped_features contient les variables à supprimer des données.

Conclusion

Utiliser le clustering sur la matrice des corrélations permet d’obtenir des groupes de variables au sein desquels toutes les variables ont une corrélation minimale entre elles. Lorsque cette corrélation est trop élevée, cela signifie que ces différentes variables portent essentiellement la même information, et qu’une seule doit être conservée. Le seuil de corrélation à choisir dépend de vos données, mais peut être choisi empiriquement. En comparant la performance d’un modèle avec toutes les variables et d’un modèle après retrait automatique au seuil de 95%, si vous observez une baisse significative de performance, retentez avec un seuil plus élevé.

Cette technique se base sur deux outils simples : la création d’une distance avec la corrélation et le clustering hiérarchique par saut maximum. Et son temps de calcul est court une fois la matrice de corrélation disponible.

Vous voilà désormais équipés pour filtrer les corrélations de vos variables numériques efficacement et avoir des mesures d’importance de vos variables plus fiables!

Références :

  1. E. Farrar et R. R. Glauber, « Multicollinearity in Regression Analysis: The Problem Revisited », Rev. Econ. Stat., vol. 49, no 1, p. 92, févr. 1967.
  2. « Multicolinéarité dans la régression ». http://larmarange.github.io/analyse-R/multicolinearite.html
  3. T. Chen, T. He, M. Benesty, et Y. Tang, « Understand your dataset with XGBoost », Understand your dataset with XGBoost. https://cran.r-project.org/web/packages/xgboost/vignettes/discoverYourData.html
  4. czuriaga, « Supermarket aggr. Customer », Supermarket aggr. customer | BigML.com. https://bigml.com/user/czuriaga/gallery/dataset/5559c2c6200d5a6570000084
  5. « hierarch.gif (Image GIF, 720 × 324 pixels) ». https://dashee87.github.io/images/hierarch.gif
  6. « 15. Floating Point Arithmetic: Issues and Limitations — Python 3.10.0 documentation ». https://docs.python.org/3/tutorial/floatingpoint.html

Sommaire

Voir aussi

Voir aussi

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.