Créer un arbre de décision

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

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
    

Le jeu de données Palmer Penguins

Ce 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 les espèces de manchots en fonction des données du jeu de données sur les manchots de Palmer. Voici les manchots:

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 l'ensemble 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 les manchots de Palmer

espèce island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex year
0 Adélie Tørgersen 39,1 18,7 181,0 3750,0 male 2007
1 Adélie Tørgersen 39,5 17,4 186,0 3800,0 female 2007
2 Adélie Tørgersen 40,3 18.0 195,0 3250,0 female 2007

L'ensemble de données complet contient une combinaison de caractéristiques numériques (par exemple, bill_depth_mm), catégorielles (par exemple, island) et manquantes. Contrairement aux réseaux de neurones, les forêts de décision sont compatibles de manière native avec tous ces types de caractéristiques. Vous n'avez donc pas à effectuer d'encodage one-hot, de normalisation ou de caractéristique supplémentaire "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 les hyperparamètres par défaut

Vous pouvez entraîner votre premier arbre de décision avec l'algorithme d'apprentissage CART (arbres de classification et de régression) (également appelé "apprenant") 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 davantage sur le fonctionnement de ce type de modèle plus tard dans le cours.

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

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

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

model.plot_tree()

Dans Colab, vous pouvez utiliser la souris pour afficher des détails sur des éléments spécifiques, tels que la répartition des classes dans chaque nœud.

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

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

Colab indique que la condition racine contient 243 exemples. Cependant, n'oubliez pas que l'ensemble de données d'entraînement contenait 272 exemples. Les 29 autres exemples ont été réservés automatiquement pour la validation et l'élagage.

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èce Likelihood
Adélie (rouge) 8 %
Gentoo (bleu) 58 %
Jugulaire (vert) 36 %

 

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

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

bill_depth_mm est une caractéristique numérique. Par conséquent, la valeur 42,3 a été obtenue à l'aide de l'algorithme de scission exacte pour la classification binaire avec des caractéristiques numériques.

Si bill_depth_mm ≥ 42.3 est défini sur "True", des tests supplémentaires visent à déterminer si flipper_length_mm ≥ 207.5 peut séparer presque parfaitement les Gentoos et les Gentoos et Adelie.

Le code suivant fournit l'entraînement et la précision 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 justesse du test soit supérieure à la justesse de l'entraînement. Dans ce cas, l'ensemble de test est peut-être différent de l'ensemble d'entraînement. Cependant, ce n'est pas le cas ici, car l'entraînement et le test ont été divisés 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), donc l'estimation de la justesse comporte du bruit.

En pratique, pour un ensemble de données aussi petit, il est préférable d'utiliser la validation croisée, car elle permet de calculer des valeurs de métriques d'évaluation plus précises. Toutefois, dans cet exemple, nous poursuivons l'entraînement et les tests par souci 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 apprenant plus puissant, tel qu'une forêt aléatoire ou un modèle d'arbres à boosting de gradient. Ces algorithmes d'apprentissage sont expliqués sur la page suivante.

  2. Optimiser l'hyperparamètre à l'aide de vos observations et de votre intuition Le guide d'amélioration de modèle peut vous être utile.

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

Comme nous n'avons pas encore vu l'algorithme des arbres à boosting de gradient et de forêt aléatoire, et comme le nombre d'exemples est trop faible pour un réglage automatique des hyperparamètres, vous allez améliorer manuellement le modèle.

L'arbre de décision illustré ci-dessus est petit, et la feuille avec 61 exemple contient un mélange d'étiquettes Adelie et Chinstrap. Pourquoi l'algorithme n'a-t-il pas encore divisé cette feuille ? 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 observez les résultats:

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

Un 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 intéressant 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 a augmenté, avec une justesse de test passant de 0,9167 à 0,97222. Ce changement d'hyperparamètre était une bonne idée.

Précédente des forêts de décision

En continuant à améliorer les hyperparamètres, nous pourrions probablement atteindre une précision parfaite. Toutefois, 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(pandas_train_dataset)
print("Test accuracy: ", model.evaluate(pandas_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 indiqué précédemment, un arbre de décision unique est souvent de moins bonne qualité que les méthodes modernes de machine learning, telles que les forêts d'arbres décisionnels, 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.
  • En cas de compromis entre qualité et interprétabilité du modèle.
  • en tant que proxy pour l'interprétation du modèle de forêts de décision, que nous étudierons plus tard dans le cours.