Que sont les arbres de décision?
Les arbres de décision sont un algorithme d'apprentissage automatique polyvalent qui peut effectuer à la fois des tâches de classification et de régression. Ce sont des algorithmes très puissants, capables d'ajuster des ensembles de données complexes. En outre, les arbres de décision sont des composants fondamentaux des forêts aléatoires, qui comptent parmi les algorithmes d'apprentissage automatique les plus puissants disponibles aujourd'hui.
Formation et visualisation d'un arbre de décision
Pour construire votre premier arbre de décision dans l'exemple R, nous allons procéder comme suit dans ce tutoriel sur l'arbre de décision:
- Étape 1: Importez les données
- Étape 2: Nettoyez l'ensemble de données
- Étape 3: Créer un train / ensemble de test
- Étape 4: Construisez le modèle
- Étape 5: Faites des prédictions
- Étape 6: mesurez les performances
- Étape 7: Réglez les hyper-paramètres
Étape 1) Importez les données
Si vous êtes curieux du sort du titanic, vous pouvez regarder cette vidéo sur Youtube. Le but de cet ensemble de données est de prédire quelles personnes sont les plus susceptibles de survivre après la collision avec l'iceberg. L'ensemble de données contient 13 variables et 1309 observations. L'ensemble de données est ordonné par la variable X.
set.seed(678)path <- 'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/titanic_data.csv'titanic <-read.csv(path)head(titanic)
Production:
## X pclass survived name sex## 1 1 1 1 Allen, Miss. Elisabeth Walton female## 2 2 1 1 Allison, Master. Hudson Trevor male## 3 3 1 0 Allison, Miss. Helen Loraine female## 4 4 1 0 Allison, Mr. Hudson Joshua Creighton male## 5 5 1 0 Allison, Mrs. Hudson J C (Bessie Waldo Daniels) female## 6 6 1 1 Anderson, Mr. Harry male## age sibsp parch ticket fare cabin embarked## 1 29.0000 0 0 24160 211.3375 B5 S## 2 0.9167 1 2 113781 151.5500 C22 C26 S## 3 2.0000 1 2 113781 151.5500 C22 C26 S## 4 30.0000 1 2 113781 151.5500 C22 C26 S## 5 25.0000 1 2 113781 151.5500 C22 C26 S## 6 48.0000 0 0 19952 26.5500 E12 S## home.dest## 1 St Louis, MO## 2 Montreal, PQ / Chesterville, ON## 3 Montreal, PQ / Chesterville, ON## 4 Montreal, PQ / Chesterville, ON## 5 Montreal, PQ / Chesterville, ON## 6 New York, NY
tail(titanic)
Production:
## X pclass survived name sex age sibsp## 1304 1304 3 0 Yousseff, Mr. Gerious male NA 0## 1305 1305 3 0 Zabour, Miss. Hileni female 14.5 1## 1306 1306 3 0 Zabour, Miss. Thamine female NA 1## 1307 1307 3 0 Zakarian, Mr. Mapriededer male 26.5 0## 1308 1308 3 0 Zakarian, Mr. Ortin male 27.0 0## 1309 1309 3 0 Zimmerman, Mr. Leo male 29.0 0## parch ticket fare cabin embarked home.dest## 1304 0 2627 14.4583 C## 1305 0 2665 14.4542 C## 1306 0 2665 14.4542 C## 1307 0 2656 7.2250 C## 1308 0 2670 7.2250 C## 1309 0 315082 7.8750 S
À partir de la sortie tête et queue, vous pouvez remarquer que les données ne sont pas mélangées. C'est un gros problème! Lorsque vous diviserez vos données entre un train et un ensemble de test, vous ne sélectionnerez que le passager de la classe 1 et 2 (aucun passager de la classe 3 n'est dans les 80% des observations), ce qui signifie que l'algorithme ne verra jamais le caractéristiques des passagers de classe 3. Cette erreur conduira à une mauvaise prévision.
Pour résoudre ce problème, vous pouvez utiliser la fonction sample ().
shuffle_index <- sample(1:nrow(titanic))head(shuffle_index)
Arbre de décision Code R Explication
- sample (1: nrow (titanic)): Génère une liste aléatoire d'index de 1 à 1309 (c'est-à-dire le nombre maximum de lignes).
Production:
## [1] 288 874 1078 633 887 992
Vous utiliserez cet index pour mélanger l'ensemble de données titanesques.
titanic <- titanic[shuffle_index, ]head(titanic)
Production:
## X pclass survived## 288 288 1 0## 874 874 3 0## 1078 1078 3 1## 633 633 3 0## 887 887 3 1## 992 992 3 1## name sex age## 288 Sutton, Mr. Frederick male 61## 874 Humblen, Mr. Adolf Mathias Nicolai Olsen male 42## 1078 O'Driscoll, Miss. Bridget female NA## 633 Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren) female 39## 887 Jermyn, Miss. Annie female NA## 992 Mamee, Mr. Hanna male NA## sibsp parch ticket fare cabin embarked home.dest## 288 0 0 36963 32.3208 D50 S Haddenfield, NJ## 874 0 0 348121 7.6500 F G63 S## 1078 0 0 14311 7.7500 Q## 633 1 5 347082 31.2750 S Sweden Winnipeg, MN## 887 0 0 14313 7.7500 Q## 992 0 0 2677 7.2292 C
Étape 2) Nettoyez l'ensemble de données
La structure des données montre que certaines variables ont des NA. Le nettoyage des données doit être effectué comme suit
- Supprimer les variables home.dest, cabin, name, X et ticket
- Créer des variables de facteur pour pclass et survivre
- Laissez tomber le NA
library(dplyr)# Drop variablesclean_titanic <- titanic % > %select(-c(home.dest, cabin, name, X, ticket)) % > %#Convert to factor levelmutate(pclass = factor(pclass, levels = c(1, 2, 3), labels = c('Upper', 'Middle', 'Lower')),survived = factor(survived, levels = c(0, 1), labels = c('No', 'Yes'))) % > %na.omit()glimpse(clean_titanic)
Explication du code
- select (-c (home.dest, cabin, name, X, ticket)): Supprime les variables inutiles
- pclass = factor (pclass, levels = c (1,2,3), labels = c ('Upper', 'Middle', 'Lower')): Ajouter une étiquette à la variable pclass. 1 devient supérieur, 2 devient moyen et 3 devient inférieur
- factor (survécu, niveaux = c (0,1), labels = c ('Non', 'Yes')): Ajouter un libellé à la variable survécu. 1 devient non et 2 devient oui
- na.omit (): supprime les observations NA
Production:
## Observations: 1,045## Variables: 8## $ pclassUpper, Lower, Lower, Upper, Middle, Upper, Middle, U… ## $ survived No, No, No, Yes, No, Yes, Yes, No, No, No, No, No, Y… ## $ sex male, male, female, female, male, male, female, male… ## $ age 61.0, 42.0, 39.0, 49.0, 29.0, 37.0, 20.0, 54.0, 2.0,… ## $ sibsp 0, 0, 1, 0, 0, 1, 0, 0, 4, 0, 0, 1, 1, 0, 0, 0, 1, 1,… ## $ parch 0, 0, 5, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 4, 0,… ## $ fare 32.3208, 7.6500, 31.2750, 25.9292, 10.5000, 52.5542,… ## $ embarked S, S, S, S, S, S, S, S, S, C, S, S, S, Q, C, S, S, C…
Étape 3) Créer un train / ensemble de test
Avant d'entraîner votre modèle, vous devez effectuer deux étapes:
- Créez un train et un jeu de test: vous entraînez le modèle sur le train et testez la prédiction sur le jeu de test (c'est-à-dire des données invisibles)
- Installez rpart.plot depuis la console
La pratique courante consiste à diviser les données 80/20, 80% des données servent à entraîner le modèle et 20% à faire des prédictions. Vous devez créer deux blocs de données distincts. Vous ne souhaitez pas toucher l'ensemble de test tant que vous n'avez pas terminé de créer votre modèle. Vous pouvez créer un nom de fonction create_train_test () qui prend trois arguments.
create_train_test(df, size = 0.8, train = TRUE)arguments:-df: Dataset used to train the model.-size: Size of the split. By default, 0.8. Numerical value-train: If set to `TRUE`, the function creates the train set, otherwise the test set. Default value sets to `TRUE`. Boolean value.You need to add a Boolean parameter because R does not allow to return two data frames simultaneously.
create_train_test <- function(data, size = 0.8, train = TRUE) {n_row = nrow(data)total_row = size * n_rowtrain_sample < - 1: total_rowif (train == TRUE) {return (data[train_sample, ])} else {return (data[-train_sample, ])}}
Explication du code
- function (data, size = 0.8, train = TRUE): Ajouter les arguments dans la fonction
- n_row = nrow (data): compte le nombre de lignes dans l'ensemble de données
- total_row = size * n_row: renvoie la nième ligne pour construire l'ensemble de trains
- train_sample <- 1: total_row: Sélectionnez la première ligne jusqu'aux nièmes lignes
- if (train == TRUE) {} else {}: Si la condition est définie sur true, renvoie l'ensemble de trains, sinon l'ensemble de test.
Vous pouvez tester votre fonction et vérifier la dimension.
data_train <- create_train_test(clean_titanic, 0.8, train = TRUE)data_test <- create_train_test(clean_titanic, 0.8, train = FALSE)dim(data_train)
Production:
## [1] 836 8
dim(data_test)
Production:
## [1] 209 8
Le jeu de données train a 1046 lignes tandis que le jeu de données test a 262 lignes.
Vous utilisez la fonction prop.table () combinée à table () pour vérifier si le processus de randomisation est correct.
prop.table(table(data_train$survived))
Production:
#### No Yes## 0.5944976 0.4055024
prop.table(table(data_test$survived))
Production:
#### No Yes## 0.5789474 0.4210526
Dans les deux ensembles de données, le nombre de survivants est le même, environ 40%.
Installez rpart.plot
rpart.plot n'est pas disponible dans les bibliothèques conda. Vous pouvez l'installer depuis la console:
install.packages("rpart.plot")
Étape 4) Construisez le modèle
Vous êtes prêt à construire le modèle. La syntaxe de la fonction d'arbre de décision Rpart est:
rpart(formula, data=, method='')arguments:- formula: The function to predict- data: Specifies the data frame- method:- "class" for a classification tree- "anova" for a regression tree
Vous utilisez la méthode de classe parce que vous prédisez une classe.
library(rpart)library(rpart.plot)fit <- rpart(survived~., data = data_train, method = 'class')rpart.plot(fit, extra = 106
Explication du code
- rpart (): Fonction adaptée au modèle. Les arguments sont:
- survécu ~: Formule des arbres de décision
- data = data_train: ensemble de données
- method = 'class': Ajuster un modèle binaire
- rpart.plot (fit, extra = 106): Tracez l'arbre. Les fonctionnalités supplémentaires sont définies sur 101 pour afficher la probabilité de la 2e classe (utile pour les réponses binaires). Vous pouvez vous référer à la vignette pour plus d'informations sur les autres choix.
Production:
Vous commencez au nœud racine (profondeur 0 sur 3, le haut du graphique):
- En haut, c'est la probabilité globale de survie. Il montre la proportion de passagers qui ont survécu à l'accident. 41 pour cent des passagers ont survécu.
- Ce nœud demande si le sexe du passager est de sexe masculin. Si oui, vous descendez au nœud enfant gauche de la racine (profondeur 2). 63 pour cent sont des hommes avec une probabilité de survie de 21 pour cent.
- Dans le deuxième nœud, vous demandez si le passager masculin a plus de 3,5 ans. Si oui, alors les chances de survie sont de 19%.
- Vous continuez comme ça pour comprendre quelles fonctionnalités ont un impact sur la probabilité de survie.
Notez que l'une des nombreuses qualités des arbres de décision est qu'ils nécessitent très peu de préparation de données. En particulier, ils ne nécessitent pas de mise à l'échelle ou de centrage des caractéristiques.
Par défaut, la fonction rpart () utilise la mesure d'impureté Gini pour diviser la note. Plus le coefficient de Gini est élevé, plus les instances du nœud sont différentes.
Étape 5) Faites une prédiction
Vous pouvez prédire votre jeu de données de test. Pour faire une prédiction, vous pouvez utiliser la fonction prédire (). La syntaxe de base de prédire pour l'arbre de décision R est:
predict(fitted_model, df, type = 'class')arguments:- fitted_model: This is the object stored after model estimation.- df: Data frame used to make the prediction- type: Type of prediction- 'class': for classification- 'prob': to compute the probability of each class- 'vector': Predict the mean response at the node level
Vous voulez prédire quels passagers sont les plus susceptibles de survivre après la collision à partir de l'ensemble de test. Cela signifie que vous saurez parmi ces 209 passagers, lequel survivra ou non.
predict_unseen <-predict(fit, data_test, type = 'class')
Explication du code
- prédire (fit, data_test, type = 'class'): prédire la classe (0/1) de l'ensemble de test
Test du passager qui n'a pas réussi et de ceux qui l'ont fait.
table_mat <- table(data_test$survived, predict_unseen)table_mat
Explication du code
- table (data_test $ survived, predict_unseen): Créez une table pour compter le nombre de passagers classés comme survivants et décédés comparée à la classification correcte de l'arbre de décision dans R
Production:
## predict_unseen## No Yes## No 106 15## Yes 30 58
Le modèle a correctement prédit 106 passagers morts mais a classé 15 survivants comme morts. Par analogie, le modèle a mal classé 30 passagers comme survivants alors qu'ils se sont avérés morts.
Étape 6) Mesurer les performances
Vous pouvez calculer une mesure de précision pour la tâche de classification avec la matrice de confusion :
La matrice de confusion est un meilleur choix pour évaluer les performances de classification. L'idée générale est de compter le nombre de fois où les instances True sont classées comme False.
Chaque ligne d'une matrice de confusion représente une cible réelle, tandis que chaque colonne représente une cible prédite. La première ligne de cette matrice considère les passagers morts (la classe Faux): 106 ont été correctement classés comme morts ( Vrai négatif ), tandis que le reste a été incorrectement classé comme survivant ( Faux positif ). La deuxième ligne considère les survivants, la classe positive était de 58 ( vrai positif ), tandis que le vrai négatif était de 30.
Vous pouvez calculer le test de précision à partir de la matrice de confusion:
C'est la proportion du vrai positif et du vrai négatif sur la somme de la matrice. Avec R, vous pouvez coder comme suit:
accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
Explication du code
- sum (diag (table_mat)): Somme de la diagonale
- sum (table_mat): somme de la matrice.
Vous pouvez imprimer la précision de l'ensemble de test:
print(paste('Accuracy for test', accuracy_Test))
Production:
## [1] "Accuracy for test 0.784688995215311"
Vous avez un score de 78 pour cent pour l'ensemble de test. Vous pouvez répliquer le même exercice avec l'ensemble de données d'entraînement.
Étape 7) Réglez les hyper-paramètres
L'arbre de décision dans R a divers paramètres qui contrôlent les aspects de l'ajustement. Dans la bibliothèque d'arbre de décision rpart, vous pouvez contrôler les paramètres à l'aide de la fonction rpart.control (). Dans le code suivant, vous introduisez les paramètres que vous allez régler. Vous pouvez vous référer à la vignette pour d'autres paramètres.
rpart.control(minsplit = 20, minbucket = round(minsplit/3), maxdepth = 30)Arguments:-minsplit: Set the minimum number of observations in the node before the algorithm perform a split-minbucket: Set the minimum number of observations in the final note i.e. the leaf-maxdepth: Set the maximum depth of any node of the final tree. The root node is treated a depth 0
Nous procéderons comme suit:
- Construire la fonction pour renvoyer la précision
- Réglez la profondeur maximale
- Ajustez le nombre minimum d'échantillons qu'un nœud doit avoir avant de pouvoir se diviser
- Ajustez le nombre minimum d'échantillons qu'un nœud feuille doit avoir
Vous pouvez écrire une fonction pour afficher la précision. Vous enveloppez simplement le code que vous avez utilisé auparavant:
- prédire: predire_unseen <- prédire (ajustement, test_données, type = 'classe')
- Produire une table: table_mat <- table (data_test $ survived, predict_unseen)
- Précision de calcul: precision_Test <- sum (diag (table_mat)) / sum (table_mat)
accuracy_tune <- function(fit) {predict_unseen <- predict(fit, data_test, type = 'class')table_mat <- table(data_test$survived, predict_unseen)accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)accuracy_Test}
Vous pouvez essayer d'ajuster les paramètres et voir si vous pouvez améliorer le modèle par rapport à la valeur par défaut. Pour rappel, vous devez obtenir une précision supérieure à 0,78
control <- rpart.control(minsplit = 4,minbucket = round(5 / 3),maxdepth = 3,cp = 0)tune_fit <- rpart(survived~., data = data_train, method = 'class', control = control)accuracy_tune(tune_fit)
Production:
## [1] 0.7990431
Avec le paramètre suivant:
minsplit = 4minbucket= round(5/3)maxdepth = 3cp=0
Vous obtenez des performances plus élevées que le modèle précédent. Félicitations!
Résumé
On peut résumer les fonctions pour entraîner un algorithme d'arbre de décision en R
Bibliothèque |
Objectif |
fonction |
classer |
paramètres |
des détails |
---|---|---|---|---|---|
rpart |
Arbre de classification des trains en R |
rpart () |
classer |
formule, df, méthode | |
rpart |
Arbre de régression de train |
rpart () |
anova |
formule, df, méthode | |
rpart |
Tracer les arbres |
rpart.plot () |
modèle ajusté | ||
base |
prédire |
prédire() |
classer |
modèle ajusté, type | |
base |
prédire |
prédire() |
prob |
modèle ajusté, type | |
base |
prédire |
prédire() |
vecteur |
modèle ajusté, type | |
rpart |
Paramètres de contrôle |
rpart.control () |
minsplit |
Définissez le nombre minimum d'observations dans le nœud avant que l'algorithme n'effectue un fractionnement |
|
minbucket |
Définissez le nombre minimum d'observations dans la note finale, c'est-à-dire la feuille |
||||
profondeur max |
Définissez la profondeur maximale de n'importe quel nœud de l'arbre final. Le nœud racine est traité d'une profondeur 0 |
||||
rpart |
Modèle de train avec paramètre de contrôle |
rpart () |
formule, df, méthode, contrôle |
Remarque: Entraînez le modèle sur des données d'entraînement et testez les performances sur un ensemble de données invisible, c'est-à-dire un ensemble de test.