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 :
- Créez un notebook Colab.
- 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
- 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 :
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.
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 :
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.
Optimisez l'hyperparamètre en utilisant vos observations et votre intuition. Le guide d'amélioration des modèles peut vous être utile.
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()
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.