Random Forest, tutoriel avec Python

Cela faisait un moment que je voulais vous proposer un tutoriel complet avec Python pour réaliser un projet de Data Science assez simple. Je me lance donc dans cet article avec un tutoriel complet pour utiliser un Random Forest avec Python. Nous allons créer un modèle de prédiction avec un Random Forest en passant par l’ensemble de ces étapes :

  • Chargement des données
  • Exploration et visualisation des données
  • Création d’un échantillon d’apprentissage et de test
  • Phase d’apprentissage avec un algorithme Random Forest
  • Évaluation de la performance sur l’échantillon de test
  • Interprétation des résultats

Pour cela j’ai choisi un dataset disponible sur Kaggle qui contient l’indice de bonheur de chaque pays avec plusieurs variables explicatives.

Bien comprendre l’algorithme Random Forest

Pour commencer, voici quelques liens qui pourront vous être utiles si vous avez besoin de réviser un peu la théorie :

J’ai utilisé des données disponibles sur Kaggle : il s’agit du dataset World Happiness Report il contient plusieurs fichiers, j’ai utilisé celui de 2017 qui semble être le plus complet. Vous pouvez aussi retrouver l’ensemble de mon code sur Kaggle (peut être plus facile à lire que sur le blog)

C’est parti, notre objectif est de prédire l’indice de bonheur Happiness.Score

Utiliser un Random Forest avec Python

Chargement des librairies Python

Premièrement, on charge les librairies Python que nous allons utiliser

import pandas as pd  
import numpy as np
import pandas_profiling
import seaborn as sns
import geopandas as gpd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

Chargement des données

J’ai téléchargé les données, je les ai dézippé et j’ai conservé le fichier concernant l’année 2017. J’utilise la fonction read_csv de la librairie pandas pour charger mes données.

df = pd.read_csv("C:/Users/Happiness_2017.csv")
print("Le fichier a " + str(df.shape[0]) + " lignes et " + str(df.shape[1]) + " colonnes")
Le fichier a 155 lignes et 12 colonnes

Exploration des données

Liste et type de données

On analyse ensuite le contenu du fichier, le nom des colonnes et leur type, on explore les premières lignes du fichier

#Liste des colonnes et leur type 
df.dtypes
# 5 premières lignes du dataset
df.head(5)

Analyse de la qualité des données avec pandas_profiling

On fait un état des lieux de la qualité des données :
– Données manquantes
– Données corrélées
– Valeurs extrêmes
– Statistiques descriptives (moyenne, écart-type, …)
– Distribution des variables

Rien de tel que la librairie pandas_profiling pour calculer tout cela automatiquement

pandas_profiling.ProfileReport(df)

Note : je vous présente ici uniquement une partie de la sortie pandas_profiling mais vous pouvez aller sur Github pour accéder au Notebook et voir le vrai résultat

Bilan pandas_profiling :

  • pandas_profiling a éliminé 2 variables : Whisker.high et Whisker.low qui sont fortement corrélées avec Happiness.Score. Effectivement, quand on regarde la définition de ces 2 variables on voit que ces 2 variables correspondent à l’intervalle de confiance de Happiness.Score. On peut donc les écarter pour notre analyse. On peut également supprimer Happiness.Rank
  • Aucune valeur manquante
  • 9 variables numériques et 1 variable textuelle (on avait déjà calculé cette info un peu plus haut)

Globalement ce dataset est propre. On regarde ensuite dans le détail chaque variable

Exploration & Visualisation des données

Avant de coder l’algorithme de prédiction du score de bonheur nous allons faire un peu d’exploration du jeu de données. L’idée est de mieux comprendre les liens entre les différentes variables et leur lien avec la variable à prédire Happiness.Score. Cette première étape descriptive est importante, elle vous permettra de mieux comprendre les résultats de votre algorithme et vous pourrez vous assurer que tout est cohérent.

Analyse des corrélations

# Matrice des corrélations : 
cor = df.corr() 
sns.heatmap(cor, square = True, cmap="coolwarm",linewidths=.5,annot=True )
#Pour choisr la couleur du heatmap : https://matplotlib.org/examples/color/colormaps_reference.html

Le heatmap permet de représenter visuellement les corrélations entre les variables.
Plus la valeur est proche de 1 (couleur rouge foncé) plus la corrélation est positive et forte. Au contraire plus la corrélation est proche de 0 (bleu foncé) plus la corrélation est négative et forte.

Constats :

Corrélations avec la variable cible Happiness.score :

  • Happiness.score est correlé positivement avec Economy.GDP.per.Capita., Family et Health..Life.Expectancy. (donc globalement quand l’indicateur family augmente, Happiness.score augmente aussi)
  • Happiness.score est correlé négativement avec Generosity
  • En revanche pour les autres variables la corrélation est plus faible

Corrélations entre les autres variables :

  • 2 variables semblent assez correlées positivement : Health..Life.Expectancy. et Economy..GDP.per.Capita.
  • Générosite et Dystopia.Residual sont correlées négativement avec la plupart des variables

Géolocalisation

#Chargement du fonds de carte 
# Dispo ici https://tapiquen-sig.jimdofree.com/english-version/free-downloads/world/
map_df = gpd.read_file('C:/Users/World_Countries.shp')
#Jointure avec nos données (on ne conserve que Country et Happiness.Rank)
map_df = map_df.set_index('COUNTRY').join(df[['Country','Happiness.Score']].set_index('Country'))
map_df.dropna(inplace=True)
map_df.reset_index(inplace=True)
#Préparation de la carte
# on fixe les seuils pour la couleur
vmin, vmax = 0, 8
# création de la figure et des axes
fig, ax = plt.subplots(1, figsize=(18, 5))
# Création de la carte
map_df.plot(column='Happiness.Score', cmap='Blues', linewidth=0.8, ax=ax, edgecolor='0.8')
# On supprime l'axe des abscisses
ax.axis('off')
# On ajoute un titre
ax.set_title('Happiness.Score par pays', fontdict={'fontsize': '16', 'fontweight' : '2'})
# On créé la légende
sm = plt.cm.ScalarMappable(cmap='Blues', norm=plt.Normalize(vmin=vmin, vmax=vmax))
sm._A = []
# On ajoute la légende
cbar = fig.colorbar(sm)

Data prep avant d’utiliser un Random Forest

Le Dataset est de bonne qualité, il y a peu de travail à faire ici :

  • Transformer country en index puisqu’il s’agit de l’identifiant unique
  • Supprimer Happiness.Rank, Whisker.high et Whisker.low
# On transforme Country en index
pd.DataFrame.set_index(df, 'Country',inplace=True)
# On supprime 3 colonnes
df.drop(columns =['Happiness.Rank','Whisker.high', 'Whisker.low' ], inplace=True)

Modélisation : Training Random Forest

On transforme les données en Numpy arrays pour pouvoir les utiliser dans le modèle

#On stocke Happiness.Score (la variable à prédire) dans cible
cible = np.array(df['Happiness.Score'])
#On supprime Happiness.Score du dataset
df= df.drop('Happiness.Score', axis = 1)
#On conserve les noms de variable à part
liste_variables = list(df.columns)
#On convertit le dataset en array
df = np.array(df)

Split du dataset en train et test

On choisit de faire l’apprentissage sur un échantillon d’apprentissage de 75% des données et de faire le test sur 25% des données. On va également séparer la variable à prédire Happiness.Score des variables de prédiction

#On créé 4 dataset : 
#   - x_train contient 75% de x  
#   - y_train contient le appiness.Score associé à x_train
# => x_train et y_train permettront d'entraîner l'algorithme
#
#   - x_test contient 25% de x  
#   - y_test contient le appiness.Score associé à x_test
# => x_test et y_test permettront d'évaluer la performance de l'algorithme une fois entrainé sur le train
x_train,x_test,y_train,y_test=train_test_split(df,cible,test_size=0.25, random_state=2020)

Apprentissage

J’ai choisi d’utiliser un algorithme Random Forest.

#On importe l'algorithme à partir de sklearn
from sklearn.ensemble import RandomForestRegressor
#On créé un Random Forest de 100 arbres 
rf = RandomForestRegressor(n_estimators = 100, random_state = 2020)
#Et on lance le training sur notre dataset de train
rf.fit(x_train, y_train)

Test

#On applique le modèle que l'on vient 
#d'entraîner sur l'échantillon de test
predictions = rf.predict(x_test)
#On va calculer plusieurs erreurs entre la valeur prédite et le score de bonheur réel (que nous avions stocké dans y_test)
#     - MAE : Mean Asolute Error
#     - MAPE : Mean Absolute Percentage Error 
# MAE 
erreurs = abs(predictions - y_test)
print('Mean Absolute Error:', round(np.mean(erreurs), 2))
Mean Absolute Error: 0.32

La moyenne des erreurs est de 0,32 donc en moyenne on arrive à prédire le score de bonheur à 0.32 près

# MAPE
mape = 100 * (erreurs / y_test)
print('Mean Absolute Percentage Error :', round(np.mean(mape), 2), '%.')
Mean Absolute Percentage Error : 6.13 %.

Interprétation des résultats

On calcule les variables d’importance du modèle, c’est à dire celles qui contribuent le plus.

importances = rf.feature_importances_
indices = np.argsort(importances)
# style du graphique 
plt.style.use('fivethirtyeight')
%matplotlib inline
plt.figure(1)
plt.title('Feature Importances')
plt.barh(range(len(indices)), importances[indices], color='b', align='center')
plt.yticks(range(len(indices)), [liste_variables[i] for i in indices])
plt.xlabel('Relative Importance')

Ce dernier graphique nous apprend que les 2 variables qui contribuent le plus à notre modèle sont Economy..GDP.per.Capita et Health..Life.Expectancy

Voilà si vous êtes allé jusqu’au bout de ce tutoriel vous avez intégralement prédit le score Happiness.Score grâce à un algorithme Random Forest avec Python en commençant par l’exploration des données, la data prep, la modélisation, le test et l’interprétation des résultats.

Et si vous voulez varier les plaisirs vous pouvez aussi coder un Random Forest avec R

16 réflexions sur “Random Forest, tutoriel avec Python”

  1. Ping : Random Forest, comment ça marche? – Lovely Analytics

  2. Bonjour !
    Je vous remercie pour cet tutoriel super.
    J’aurais une difficulté concernant pandas_profiling , je n’arrive pas à l’importer sur mon Jupiter . Je voudrais savoir s’il y une chose particulière à faire avant de l’importer?

    Merci

    1. Hello, je n’ai pas rencontré de problème particulier pour installer pandas_profiling.
      J’utilise anaconda et je l’avais chargé grâce à la commande : conda install -c conda-forge/label/cf202003 pandas-profiling

      Est ce que le problème apparaît dans le notebook ou avant au moment du chargement?

      1. Voilci le message affiché lorsque j’essaie de l’installer sur mon notebook:
         » File «  », line 5
        conda install -c conda-forge/label/cf202003 pandas-profiling
        ^
        SyntaxError: invalid syntax  »

        J’ai même essayé le code: pip install pandas-profiling ….. il me renvoie le même message.

        1. En fait il y a 2 choses à faire.
          Tout d’abord il faut installer le package avec une commande pip (ou conda si on utilise anaconda). Le code d’installation qui commence par pip doit être exécuté dans l’invit de commande windows.
          Une fois que cette partie est faite on charge le package dans le notebook avec la ligne « import pandas_profiling »
          Est ce que tu as le même problème avec les autres package?

          Je n’ai pas accès à mon PC pendant plusieurs semaines mais si besoin je pourrai te faire des captures d’écran à mon retour.

          1. D’accord je vais essayer ces deux cas, je vous remercie encore pour votre gentillesse j’attends quand même la capture d’écran.
            L’importation marche généralement pour les autres packages sauf pour geopandas et pandas_profiling au sujet de l’installation. Je pense si je résous le problème l’un ça marchera pour l’autre.

            Merci encore

  3. Bonjour,

    Vous indiquez :

    Mean Absolute Error: 0.32

    La moyenne des erreurs est de 0,32 donc en moyenne on arrive à prédire le score de bonheur à 0.32 près.

    Puis ensuite :

    Mean Absolute Percentage Error : 6.13 %.

    Mais le dataset possède 155 lignes, 0.32/155 n’est pas égal à 6.13%. Comment faut-il comprendre vos résultats ?

    Merci pour votre réponse.

    A+ 😉

    1. Hello,
      Je vais essayer d’expliquer dans mon commentaire et je compléterai peut-être le tutoriel si ce n’est pas clair.
      Le Mean Absolute Error calcule l’erreur moyenne entre chaque prédiction et sa valeur réelle. Cet indicateur dépend donc de la nature des données (par exemple si on prédit une hauteur en mètre, le MAE sera exprimé en metre).
      Le Mean Absolute Percentage Error permet d’avoir la même information mais sous forme de pourcentage. Pour chaque individu de l’échantillon de test on fait (valeur reelle-valeur predite)/valeur réelle. Puis on calcule ensuite la moyenne pour tous les individus et on transforme la valeur en pourcentage en multipliant par 100.

      Donc en fait dans le code la partie errors correspond aux valeurs (valeur reelle-valeur predite) et ytest correspond aux valeurs réelles (il s’agit d’un vecteur avec toutes les valeurs y du dataset de test et non pas la taille du dataset).

      Voilà j’espère avoir pu aider, n’hésite pas à me dire si ce n’est pas clair.

    1. Bonjour,

      Vous pouvez mettre la valeur de votre choix pour le random_state. Il vous permet juste de réutiliser les mêmes tirages aléatoires à chaque exécution. Grâce à lui vous aurez toujours le même X_train et X_test.

  4. Hedi Jabnouni

    Bonjour,
    J’ai un TP à réaliser concernant mes études.

    Le but est de coder un programme avec python concerne la segmentation d’images par la technique Random Forest.
    Votre tutoriel s’applique sur des données.

    Pouvez vous m’expliquer comment modifier votre code afin de l’utiliser avec des images, et c’est pour les trois phases : l’apprentissage, le test et l’évaluation selon les critères d’évaluation indiqués dans ce fichier :
    https://drive.google.com/file/d/1w4wzRfUN9UgY-jCdlEymBeoSnz2GuQyF/view?usp=sharing

    Merci d’avance.

  5. Mohamed Mahand Baba

    Bonjour,

    Je vous remercie pour l’analyse bien détaillé mais par contre j’arrive pas à importer la librairie geopandas !!
    il m’affiche toujours : ModuleNotFoundError: No module named ‘geopandas’

    Merci !

    1. Bonjour,
      J’utilise Anaconda, pour installer geopandas j’ai utilisé conda install -c conda-forge geopandas dans la console (Anaconda Prompt).
      Sinon si vous n’utilisez pas Anaconda c’est simplement pip install geopandas à saisir dans la console.

  6. Bonjour et merci pour votre tuto très clair et détaillé!
    J’aimerais savoir s’il y a un moyen de faire du randomforest avec des variables d’entrée de type « catégories » (=string)
    Merci
    Héloïse

    1. Bonjour,

      Il me semble que cela dépend des outils. Avec Scikit-learn il est nécessaire de convertir les variables catégorielles en numériques. Il existe plusieurs manière de le faire en fonction de la variable. Soit avec un one hot encoding (chaque modalité de la variable est transformée en indicatrice) soit avec un ordinal encoder (s’il est possible de classer les modalités de la variables catégorielle).

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *