Bob a créé sa propre entreprise de téléphonie mobile. Il veut mener une lutte acharnée contre les grandes entreprises comme Apple, Samsung, etc.

Il ne sait pas comment estimer le prix des téléphones portables que son entreprise crée. Sur ce marché concurrentiel de la téléphonie mobile, on ne peut pas se contenter d’hypothèses. Pour résoudre ce problème, il recueille des données sur les ventes de téléphones portables de différentes entreprises.

Bob souhaite établir une relation entre les caractéristiques d’un téléphone portable (RAM, mémoire interne, etc.) et son prix de vente. Mais il n’est pas très doué avec les algorithmes de classification. Il a donc besoin de votre aide pour résoudre ce problème.

Dans ce problème, vous ne devez pas prédire le prix réel mais une fourchette de prix indiquant à quel niveau se situe le prix.

library(dplyr)
library(ggplot2)
library(rpart)
library(rpart.plot)
library(yardstick)
library(DataExplorer)

1 Jeu de données

1.1 Des concurents

Le jeu de données est disponible sur le site Kaggle, attention prenez bien le train.csv pour cette section et le test.csv pour la section suivante.

data <- read.csv("C:/Users/kermo/Documents/UPPA/Cours/master SIGLIS/Dataviz 2/CART_RF/TD_arbre/train.csv")

1.2 Des téléphones de Bob

Prenez le jeu de données test.csv

data_bob <- read.csv("C:/Users/kermo/Documents/UPPA/Cours/master SIGLIS/Dataviz 2/CART_RF/TD_arbre/test.csv")

2 Visualisation des données et des liens entre les variables

plot_histogram(data)

plot_correlation(data)

La corrélation la plus forte est entre le prix et la RAM, on verra bien si la RAM ressortira avec les arbres

zoom sur la variable price_range :

summary(data$price_range)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00    0.75    1.50    1.50    2.25    3.00

R défini automatiquement price_range comme une quantitative puisque 0,1,2,3 sont des chiffres. Sauf que, ici, c’est une qualitative ordinale avec 4 possibilités. Il faut le spécifier à R, les qualitatives sous R font appelées des facteurs.

data$price_range <- as.factor(data$price_range)
summary(data$price_range)
##   0   1   2   3 
## 500 500 500 500

Les graphiques suivant sont utilisés pour étudier les liens deux à deux entre les différentes variables du jeu de données :

plot_histogram(data_bob)

plot_correlation(data_bob)

3 Arbre de classification CART

Dans cet exemple, on parle d’arbre de classification puisque la variable à expliquer est une variable qualitative. Lorsque la variable à expliquer est quantitative, on parle d’arbre de régression.

3.1 Création de l’arbre

dt01 <- rpart(price_range ~  ., data)
rpart.plot(dt01)

Le paramètre de complexité cp permet de contrôler le degré de précision d’un arbre rpart et donc sa probabilité d’être surajusté. Toute division qui ne diminue pas le manque d’ajustement global d’un facteur de cp n’est pas tentée. De petites valeurs de cp créeront de grands arbres et de grandes valeurs peuvent ne produire aucun arbre. La valeur par défaut de cp est de 0,01. Voyons le résultat d’une augmentation de cp d’un ordre de grandeur 1 :

dt02 <- rpart(price_range ~  ., data, cp = 0.1)
rpart.plot(dt02)

Si l’arbre résultant est trop grand pour être tracé on peut utiliser la fonction predict avec type = “class” pour obtenir les valeurs prédites pour chaque élément de l’échantillon.

rpart offre une mesure de l’importance de la variable égale à la somme des mesures de la qualité du fractionnement pour chaque fractionnement pour lequel elle était la variable principale :

dt02$variable.importance
##           ram battery_power     px_height          sc_w    int_memory 
##   760.9412261    14.1714705    11.8661275    10.9715698    10.3660928 
##      px_width            fc            pc          sc_h     mobile_wt 
##     7.3192737     4.8688247     2.9277095     2.4768265     1.9518063 
##   clock_speed 
##     0.8256088

Dans cet arbre, la variable la plus importante pour expliquer le prix des téléphones est la variable “RAM”.

3.2 Predictions

On peut utiliser l’arbre que l’on a crée sur les données d’entraînement pour prédire les prix des téléphones de Bob (jeu de données data_bob) :

predictions <-predict(dt02, data_bob)
data_final <- cbind(data_bob, predictions)
head(data_final)

En regardant les dernières colonnes de ce tableau, on observe les probabilité de classement de chaque téléphone (=ligne) dans chacune des 4 classes de prix.

4 Pour aller plus loin, les forêts aléatoires

Le random forest est un algorithme incontournable en machine learning. Random forest signifie « forêt aléatoire ». Proposé par Leo Breiman en 2001, c’est un algorithme qui se base sur l’assemblage d’arbres de décision. Il est assez intuitif à comprendre, rapide à entraîner et il produit des résultats généralisables. Seul bémol, le random forest est une boîte noire qui donne des résultats peu lisibles, c’est-à-dire peu explicatifs.

Un random forest est constitué d’un ensemble d’arbres de décision indépendants.

Chaque arbre dispose d’une vision parcellaire du problème du fait d’un double tirage aléatoire :

A la fin, tous ces arbres de décisions indépendants sont assemblés. La prédiction faite par le random forest pour des données inconnues est alors la moyenne (ou le vote, dans le cas d’un problème de classification) de tous les arbres.

En résumé; le Random Forest est un algorythme qui produit plein de petits arbres de classification sur une fraction aléatoire des données puis il les fait voter. De ce vote sont déduits l’ordre et l’importance des variables explicatives.

source : static.javatpoint.com
source : static.javatpoint.com
set.seed(123)
library(randomForest)
RF <- randomForest(as.factor(price_range) ~  ., data, ntree = 750)
RF
## 
## Call:
##  randomForest(formula = as.factor(price_range) ~ ., data = data,      ntree = 750) 
##                Type of random forest: classification
##                      Number of trees: 750
## No. of variables tried at each split: 4
## 
##         OOB estimate of  error rate: 10.8%
## Confusion matrix:
##     0   1   2   3 class.error
## 0 473  27   0   0       0.054
## 1  36 424  40   0       0.152
## 2   0  48 425  27       0.150
## 3   0   0  38 462       0.076

OOB

out-of-bag

L’out of bag error est une mesure de l’erreur de prédiction de Random Forest. Chaque arbre de la forêt est construit sur une fraction (“in bag”) des données (c’est la fraction qui sert à l’entraînement de l’algorithme. Alors pour chacun des individus de la fraction restante (“out of bag”) l’arbre peut prédire une classe.

Le but du jeu est d’obtenir l’OOB le plus petit possible. Pour minimiser cette valeur, on peut régler deux éléments : le nombre d’arbres construits par l’algorithme (ntree) et le nombre de variables testées à chaque division (mtry).

Matrice de confusion

Il s’agit d’un tableau présentant en ligne les données observées et en colonnes les données prédites par l’algorithme. On trouve sur sa diagonale le nombre d’individus bien classés c’est-à-dire les individus dont la prédiction de l’algorithme correspond aux données observées. Les autres valeurs correspondent aux individus mal classés par l’algorithme.

Importance des variables explicatives

varImpPlot(RF)

Le graphique suivant est une visualisation intéressante de l’importance de chaque variable dans la forêt aléatoire. Les couleurs indiquent la profondeur d’apparition de la variable dans chaque arbre de la forêt (si la variable arrive dans les premiers nœuds dans tous les arbres, alors elle est considérée comme importante). L’étiquette indique la profondeur moyenne d’apparition de la variable.

library(randomForestExplainer)
plot_min_depth_distribution(RF)