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

Jeu de données sur les manchots de Palmer

Ce Colab utilise le jeu de données Penguins Palmer, qui contient des mesures de taille pour trois espèces de manchots:

  • Jugulaire
  • Gentoo
  • Adelie

Il s'agit d'un problème de classification. L'objectif est de prédire l'espèce de manchot à partir des données de l'ensemble de données "Manchots de Palmer". 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 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 Palmer Penguins

espèce island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex année
0 Adelie Torgersen 39.1 18,7 181.0 3750,0 male 2007
1 Adelie Torgersen 39,5 17,4 186.0 3800,0 female 2007
2 Adelie 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 de neurones, les forêts de décision prennent en charge tous ces types de fonctionnalités en mode natif. Vous n'avez donc pas besoin d'effectuer d'encodage one-hot, de normalisation ni de fonctionnalité is_present supplémentaire.

La cellule de code suivante divise l'ensemble de données en ensemble d'entraînement et 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 des arbres 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 (Classification and Regression Trees) (également appelé apprenant) sans spécifier de paramètres 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 tard 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 éléments géographiques 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, texte) des éléments géographiques d'entrée. Par conséquent, la sémantique des éléments géographiques est automatiquement inférée.

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 informations détaillées sur des éléments spécifiques, tels que 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 les hyperparamètres par défaut.

Colab indique que la condition racine contient 243 exemples. Cependant, 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'arborescence.

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é d'espèces différentes si bill_depth_mm ≥ 42.3

Espèces Probabilité
Adelie (rouge) 8 %
Gentoo (bleu) 58 %
Manchot à jugulaire (vert) 36 %

 

Tableau 5. Probabilité d'espèces différentes si : bill_depth_mm < 42.3

Espèces Probabilité
Adelie (rouge) 97 %
Gentoo (bleu) 2 %
Manchot à 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 partitionnement exact pour la classification binaire avec des caractéristiques numériques.

Si bill_depth_mm ≥ 42.3 est défini sur "True", effectuez des tests supplémentaires pour déterminer si flipper_length_mm ≥ 207.5 peut presque parfaitement séparer les manchots et les manchots+manchots adelie.

Le code suivant fournit la justesse d'entraînement et de 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 justesse 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 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), de sorte que l'estimation de la justesse est bruyante.

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étrique d'évaluation plus précises. Toutefois, dans cet exemple, nous continuons avec un entraînement et des tests par souci de simplicité.

Améliorer les hyperparamètres du modèle

Le modèle est un arbre de décision unique 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'un random forest ou un modèle d'arbre de décision à boosting de gradient. Ces algorithmes d'apprentissage seront expliqués sur la page suivante.

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

  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 boostés par gradient, et que le nombre d'exemples est trop faible pour effectuer un réglage automatique des hyperparamètres, vous allez améliorer manuellement le modèle.

L'arbre de décision présenté ci-dessus est petit, et la feuille avec l'exemple 61 contient un mélange de libellés Adelie et Chinstrap. Pourquoi l'algorithme n'a-t-il pas divisé cette feuille plus loin ? Il y a deux raisons possibles à cela :

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

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 de feuille contenant 61 exemples a été divisé plusieurs fois.

Pour déterminer si la division du nœud est utile, 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.

Aperçu d'une forêt 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(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 indiqué précédemment, un seul arbre de décision est souvent de moins bonne qualité que les méthodes de machine learning modernes, telles que les forêts d'arbres aléatoires, les arbres de décision à boosting de gradient et les réseaux de neurones. Toutefois, les arbres de décision restent utiles dans les cas suivants:

  • En tant que référence simple et peu coûteuse pour évaluer des approches plus complexes.
  • Lorsque vous devez trouver 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êt d'arbres décisionnels, que le cours explorera plus tard.