Créer un arbre de décision

Dans ce module, vous allez utiliser la bibliothèque YDF (Yggdrasil Decision Forest) pour entraîner et interpréter un arbre de décision.

Ce module s'inspire du tutoriel 🧭 Premiers pas avec YDF.

Préliminaires

Avant d'étudier l'ensemble de données, procédez comme suit :

  1. Créez un notebook Colab.
  2. Installez la bibliothèque YDF en plaçant et en exécutant la ligne de code suivante dans votre nouveau notebook Colab :
    !pip install ydf -U
  3. Importez les bibliothèques suivantes :
    import ydf
    import numpy as np
    import pandas as pd

Ensemble de données Palmer Penguins

Ce notebook Colab utilise l'ensemble de données Palmer Penguins, qui contient des mesures de taille pour trois espèces de manchots :

  • Jugulaire
  • Gentoo
  • Adélie

Il s'agit d'un problème de classification : l'objectif est de prédire l'espèce de manchot en fonction des données de l'ensemble de données Palmer's Penguins. Voici les pingouins :

Trois espèces de manchots différentes.

Figure 16. Trois espèces de manchots différentes. Image de @allisonhorst

 

Le code suivant appelle une fonction pandas pour charger le jeu de données Palmer Penguins en mémoire :

path = "https://storage.googleapis.com/download.tensorflow.org/data/palmer_penguins/penguins.csv"
dataset = pd.read_csv(path)
label = "species"

# Display the first 3 examples.
dataset.head(3)

Le tableau suivant met en forme les trois premiers exemples de l'ensemble de données Palmer Penguins :

Tableau 3. Les trois premiers exemples dans Palmer Penguins

espèce island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex année
0 Adélie Torgersen 39.1 18,7 181.0 3750,0 male 2007
1 Adélie Torgersen 39,5 17,4 186.0 3800,0 female 2007
2 Adélie Torgersen 40.3 18.0 195,0 3 250,0 female 2007

L'ensemble de données complet contient un mélange de caractéristiques numériques (par exemple, bill_depth_mm), catégorielles (par exemple, island) et manquantes. Contrairement aux réseaux neuronaux, les forêts de décision sont compatibles avec tous ces types de caractéristiques de manière native. Vous n'avez donc pas besoin d'effectuer d'encodage one-hot, de normalisation ni d'ajouter de caractéristique is_present.

La cellule de code suivante divise l'ensemble de données en un ensemble d'entraînement et un ensemble de test :

# Use the ~20% of the examples as the testing set
# and the remaining ~80% of the examples as the training set.
np.random.seed(1)
is_test = np.random.rand(len(dataset)) < 0.2

train_dataset = dataset[~is_test]
test_dataset = dataset[is_test]

print("Training examples: ", len(train_dataset))
# >> Training examples: 272

print("Testing examples: ", len(test_dataset))
# >> Testing examples: 72

Entraîner un arbre de décision avec des hyperparamètres par défaut

Vous pouvez entraîner votre premier arbre de décision avec l'algorithme d'apprentissage CART (Classification and Regression Trees), également appelé "learner", sans spécifier d'hyperparamètres. En effet, l'apprenant ydf.CartLearner fournit de bonnes valeurs d'hyperparamètres par défaut. Vous en apprendrez plus sur le fonctionnement de ce type de modèle plus loin dans le cours.

model = ydf.CartLearner(label=label).train(train_dataset)

L'appel précédent n'a pas spécifié les colonnes à utiliser comme caractéristiques d'entrée. Par conséquent, chaque colonne de l'ensemble d'entraînement est utilisée. L'appel n'a pas non plus spécifié la sémantique (par exemple, numérique, catégorielle, textuelle) des caractéristiques d'entrée. Par conséquent, la sémantique des caractéristiques est déduite automatiquement.

Appelez model.plot_tree() pour afficher l'arbre de décision résultant :

model.plot_tree()

Dans Colab, vous pouvez utiliser la souris pour afficher des informations sur des éléments spécifiques, comme la distribution des classes dans chaque nœud.

Arbre de décision entraîné avec des hyperparamètres par défaut.

Figure 17. Arbre de décision entraîné avec des hyperparamètres par défaut.

Colab indique que la condition racine contient 243 exemples. Toutefois, vous vous souvenez peut-être que l'ensemble de données d'entraînement contenait 272 exemples. Les 29 exemples restants ont été réservés automatiquement pour la validation et l'élagage de l'arbre.

La première condition teste la valeur de bill_depth_mm. Les tableaux 4 et 5 indiquent la probabilité de différentes espèces en fonction du résultat de la première condition.

Tableau 4. Probabilité de différentes espèces si bill_depth_mm ≥ 42.3

Espèces Likelihood
Adélie (rouge) 8 %
Gorfou (bleu) 58 %
Jugulaire (vert) 36 %

 

Tableau 5. Probabilité de différentes espèces si bill_depth_mm < 42.3

Espèces Likelihood
Adélie (rouge) 97 %
Gorfou (bleu) 2 %
Jugulaire (vert) 0 %

bill_depth_mm est une caractéristique numérique. La valeur 42, 3 a donc été trouvée à l'aide de l'algorithme Exact splitting for binary classification with numerical features (Fractionnement exact pour la classification binaire avec des caractéristiques numériques).

Si bill_depth_mm ≥ 42.3 est défini sur "True", d'autres tests sont effectués pour déterminer si flipper_length_mm ≥ 207.5 peut presque parfaitement séparer les Gentoos des Gentoos+Adelie.

Le code suivant fournit la précision de l'entraînement et du test du modèle :

train_evaluation = model.evaluate(train_dataset)
print("train accuracy:", train_evaluation.accuracy)
# >> train accuracy:  0.9338

test_evaluation = model.evaluate(test_dataset)
print("test accuracy:", test_evaluation.accuracy)
# >> test accuracy:  0.9167

Il est rare, mais possible, que la précision du test soit supérieure à celle de l'entraînement. Dans ce cas, l'ensemble de test peut différer de l'ensemble d'entraînement. Cependant, ce n'est pas le cas ici, car les ensembles d'entraînement et de test ont été répartis de manière aléatoire. Une explication plus probable est que l'ensemble de données de test est très petit (seulement 72 exemples), de sorte que l'estimation de la précision est bruyante.

En pratique, pour un ensemble de données aussi petit, il serait préférable d'utiliser la validation croisée, car elle permettrait de calculer des valeurs de métriques d'évaluation plus précises. Toutefois, dans cet exemple, nous continuons avec un entraînement et un test pour plus de simplicité.

Améliorer les hyperparamètres du modèle

Le modèle est un arbre de décision unique qui a été entraîné avec des valeurs d'hyperparamètres par défaut. Pour obtenir de meilleures prédictions, vous pouvez :

  1. Utilisez un modèle d'apprentissage plus puissant, tel qu'un modèle random forest ou gradient boosted trees. Ces algorithmes d'apprentissage seront expliqués sur la page suivante.

  2. Optimisez l'hyperparamètre en utilisant vos observations et votre intuition. Le guide d'amélioration des modèles peut vous être utile.

  3. Utilisez le réglage des hyperparamètres pour tester automatiquement un grand nombre d'hyperparamètres possibles.

Comme nous n'avons pas encore vu l'algorithme de forêt aléatoire et d'arbres de régression boostés par gradient, et que le nombre d'exemples est trop petit pour effectuer un réglage automatique des hyperparamètres, vous allez améliorer manuellement le modèle.

L'arbre de décision ci-dessus est petit, et la feuille contenant 61 exemples contient un mélange de libellés Adélie et Manchot à jugulaire. Pourquoi l'algorithme n'a-t-il pas divisé cette feuille davantage ? Il y a deux raisons possibles à cela :

  • Le nombre minimal d'échantillons par feuille (min_examples=5 par défaut) a peut-être été atteint.
  • L'arbre a peut-être été divisé, puis élagué pour éviter le surapprentissage.

Réduisez le nombre minimal d'exemples à 1 et examinez les résultats :

model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()

Arbre de décision entraîné avec min_examples=1.

Figure 18. Arbre de décision entraîné avec min_examples=1.

 

Le nœud feuille contenant 61 exemples a été divisé plusieurs fois.

Pour déterminer s'il est utile de diviser davantage le nœud, nous évaluons la qualité de ce nouveau modèle sur l'ensemble de données de test :

print(model.evaluate(test_dataset).accuracy)
# >> 0.97222

La qualité du modèle s'est améliorée, la précision des tests passant de 0,9167 à 0,97222. Cette modification de l'hyperparamètre était une bonne idée.

Aperçu des forêts de décision

En continuant à améliorer les hyperparamètres, nous pourrions probablement atteindre une précision parfaite. Cependant, au lieu de ce processus manuel, nous pouvons entraîner un modèle plus puissant tel qu'une forêt aléatoire et voir s'il fonctionne mieux.

model = ydf.RandomForestLearner(label=label).train(train_dataset)
print("Test accuracy: ", model.evaluate(test_dataset).accuracy)
# >> Test accuracy: 0.986111

La précision de la forêt aléatoire est meilleure que celle de notre arbre simple. Vous découvrirez pourquoi dans les pages suivantes.

Utilisation et limites

Comme mentionné précédemment, un seul arbre de décision est souvent de qualité inférieure aux méthodes de machine learning modernes telles que les forêts aléatoires, les arbres à boosting de gradient et les réseaux de neurones. Toutefois, les arbres de décision restent utiles dans les cas suivants :

  • Comme référence simple et peu coûteuse pour évaluer des approches plus complexes.
  • Lorsqu'il existe un compromis entre la qualité et l'interprétabilité du modèle.
  • En tant que proxy pour l'interprétation du modèle de forêts de décision, que le cours explorera plus tard.