class: center, middle, inverse, title-slide # Les forêts aléatoires ## 🌳🎄🌴🌱🌵
alias random forests ### Cyrille Conord
cyrille.conord@univ-st-etienne.fr
### 2019/02/27 (màj: 2019-03-25) --- class: center, middle, inverse # Introduction --- # Idée de base .center[ <video width="320" height="240" controls> <source src="vids/video_pesquet.mp4" type="video/mp4"> </video> ] --- class: clear, center, middle background-image: url(images/single-tree.gif) background-size: cover .font300.white[Arbres de décision] ??? Image credit: [giphy](https://giphy.com/gifs/tree-U85Z0lxOwDoys?utm_source=media-link&utm_medium=landing&utm_campaign=Media%20Links&utm_term=) --- # Principe <img src="images/dt-01.png" width="90%" height="90%" style="display: block; margin: auto;" /> .center[.content-box-gray[.bold[Est-ce qu'un client du supermarché va dépenser sa cagnotte?]]] --- # Un modèle fondé sur .red[un jeu de règles] <img src="images/dt-03.png" width="90%" height="90%" style="display: block; margin: auto;" /> --- # Terminologie <img src="images/dt-02-french.png" width="90%" height="90%" style="display: block; margin: auto;" /> --- # Faire pousser un arbre .pull-left[ ### Algorithmes - ID3 - C4.5 - CART (Classification And Regression Tree) - CHAID - MARS - Conditional Inference Trees - ... ] --- # Faire pousser un arbre .pull-left[ ### Algorithmes - ID3 - C4.5 - .bold.blue[CART (Classification And Regression Tree)] - CHAID - MARS - Conditional Inference Trees - ... ] .pull-right[ ### Qu'a donc CART dans son caddie ?
<i class="fas fa-shopping-cart faa-passing animated faa-slow "></i>
- Classification and regression trees - Variable continues et catégorielles - Partitionnement - Divisif - Divisions binaires (conduit souvent à de grands arbres) - Arbres de régression: réduction de la variance - Arbres de classification: critère de pureté de Gini - Elagage possible selon la complexité - [
<i class="ai ai-google-scholar faa-tada animated-hover "></i>(Breiman, 1984)
](https://www.taylorfrancis.com/books/9781351460491) ] <br> .center[.content-box-gray[.bold[C'est l'algorithme d'arbre de décision le plus commun]]] --- # Trouver le meilleur partitionnement .red[
binaire
] .pull-left[ .center.font130.bold[Arbre de régression] <img src="images/regression-partition.png" width="90%" style="display: block; margin: auto;" /> ] .pull-right[ .center.font130.bold[Arbre de classification] <img src="images/classification-partition.png" width="90%" style="display: block; margin: auto;" /> ] <br> .center[.content-box-gray[.bold[Objectif: Minimiser la dissimilarité dans les noeuds terminaux]]] --- # Trouver le meilleur partitionnement .red[binaire] .pull-left[ <br> - __Variable numérique__: partition numérique minimisant une fonction de coût <br><br><br><br> - __Variable binaire__: partition catégorielle minimisant une fonction de coût <br><br><br><br> - __Variable multi-classes__: Ordonner les classes par la moyenne de la variable cible (régr.) ou par la proportion dans les classes (classif.) et choisir la partition minimisant une fonction de coût ([
<i class="ai ai-google-scholar faa-tada animated-hover "></i>Voir Elements of Statistical Learning, section 9.2.4
](https://web.stanford.edu/~hastie/ElemStatLearn/)). ] .pull-right[ <img src="images/splitting-rules.png" width="55%" height="55%" style="display: block; margin: auto;" /> ] --- # Jusqu'où faire pousser un arbre ? Disons que l'on dispose des données suivantes issues de la fonction sous-jacente .blue["réelle"] <br><br> le code
<i class="fab fa-r-project faa-pulse animated faa-slow " style=" color:steelblue;"></i>
```r set.seed(1112) # pour la reproductibilité df <- tibble::tibble( x = seq(from = 0, to = 2 * pi, length = 500), y = sin(x) + rnorm(length(x), sd = 0.5), truth = sin(x) ) library(rpart) ctrl <- list(cp = 0, minbucket = 5, maxdepth = 1) fit <- rpart(y ~ x, data = df, control = ctrl) df %>% mutate(pred = predict(fit, df)) %>% ggplot(aes(x, y)) + geom_point(alpha = .3, size = 2) + geom_line(aes(x, y = truth), color = "blue", size = 1) ``` --- # Jusqu'où faire pousser un arbre ? Disons que l'on dispose des données suivantes issues de la fonction sous-jacente .blue["réelle"] <br><br> <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-8-1.png" style="display: block; margin: auto;" /> --- # Profondeur = 1 (.red[souche] de décision
<img src="images/stump.png" style="height:1em; width:auto; "/>
) .scrollable90[ .pull-left[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-9-1.png" width="100%" style="display: block; margin: auto;" /> ``` ## ## Model formula: ## y ~ x ## ## Fitted party: ## [1] root ## | [2] x >= 3.07863: -0.665 (n = 255, err = 95.5) ## | [3] x < 3.07863: 0.640 (n = 245, err = 75.9) ## ## Number of inner nodes: 1 ## Number of terminal nodes: 2 ``` ] .pull-right[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-10-1.png" style="display: block; margin: auto;" /> ] ] --- # Profondeur = 3
<img src="images/small-tree-icon.png" style="height:1em; width:auto; "/>
.scrollable90[ .pull-left[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-11-1.png" width="100%" style="display: block; margin: auto;" /> ``` ## ## Model formula: ## y ~ x ## ## Fitted party: ## [1] root ## | [2] x >= 3.07863 ## | | [3] x >= 3.65785 ## | | | [4] x < 5.53399: -0.948 (n = 149, err = 40.0) ## | | | [5] x >= 5.53399: -0.316 (n = 60, err = 15.6) ## | | [6] x < 3.65785 ## | | | [7] x < 3.20455: -0.476 (n = 10, err = 0.9) ## | | | [8] x >= 3.20455: -0.130 (n = 36, err = 9.0) ## | [9] x < 3.07863 ## | | [10] x < 0.52255 ## | | | [11] x < 0.28331: 0.142 (n = 23, err = 4.8) ## | | | [12] x >= 0.28331: 0.390 (n = 19, err = 5.1) ## | | [13] x >= 0.52255 ## | | | [14] x >= 2.26018: 0.440 (n = 65, err = 13.7) ## | | | [15] x < 2.26018: 0.852 (n = 138, err = 36.6) ## ## Number of inner nodes: 7 ## Number of terminal nodes: 8 ``` ] .pull-right[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-12-1.png" style="display: block; margin: auto;" /> ] ] --- # Profondeur = 20 (.red[arbre complexe]
<img src="images/large-tree-icon.png" style="height:1em; width:auto; "/>
) .scrollable90[ .pull-left[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-13-1.png" height="100%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-14-1.png" style="display: block; margin: auto;" /> ] ] --- # Frontières de décision .center[ <img src="images/learning.png" style="width: 105%" /> ] --- # Frontières de décision avec .red[deux variables prédictrices] .pull-left[ ### Problème de classification: jeu de données Iris <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-15-1.png" style="display: block; margin: auto;" /> ] --- # Frontières de décision avec .red[deux variables prédictrices] .pull-left[ ### Problème de classification: jeu de données Iris <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-16-1.png" style="display: block; margin: auto;" /> ] .pull-right[ ### Arbre de Classification <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-17-1.png" height="100%" style="display: block; margin: auto;" /> ] --- # Un arbre en action http://www.r2d3.us/visual-intro-to-machine-learning-part-1/ --- # Le pour, le contre... .pull-left[ ### Forces - .green[Les arbres courts sont faciles à interpréter] - .green[Les arbres s'adaptent bien à de grands _N_] (rapidement) = "scalabilité" - .green[Possibilité d'utiliser des données de tous types] (i.e., requière peu ou pas de "pre-processing") - .green[Sélection des variables automatique] - .green[Tolérance aux données manquantes] - .green[Totalement non-paramètrique] ] -- .pull-right[ ### Faiblesses - .red[Les grands arbres sont plus difficiles à interpréter] - .red[Chaque branchaison *"split"* dépend des précédentes] (détecter les interactions entre variables
<i class="fas fa-thumbs-up faa-FALSE animated " style=" color:green;"></i>
; modèle additif
<i class="fas fa-thumbs-down faa-FALSE animated " style=" color:red;"></i>
) - .red[Les arbres se comportent comme des fonctions étagées] (i.e., partitions binaires) - .red[Un arbre seul est un faible prédicteur] - .red[Un arbre seul montre une grande variance] (sur-apprentissage des données) ] --- # Sur-apprentissage ? <br><br> <img src="images/overfitting.png" width="600px" style="display: block; margin: auto;" /> --- # Minimiser le sur-apprentissage / overfitting .pull-left[ .font110[Il faur équilibrer la longueur(profondeur) et la complexité de l'arbre pour .bold[généraliser / extrapoler] à des données inédites] 2 stratégies: * Arrêter la croissance de l'arbre * limiter la profondeur * limiter la taille des noeuds * Elaguer ] .pull-right[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-19-1.png" style="display: block; margin: auto;" /> .center[.content-box-gray[.bold[Les arbres ont tendance à sur-apprendre]]] ] --- class: clear, center, middle background-image: url(images/baggy.jpg) background-size: cover -- .font300.white[Le Baggy !???!] <br> -- .font300.black[Non, le Bagging !!] ??? Image credit: [LeMonde.fr](http://s1.lemde.fr/image/2013/03/28/534x0/3149306_5_021a_illustration_be6072959b8bf65fd0345fa812999817.jpg) --- # Le problème avec les arbres pris isoléments .pull-left[ .center[.font120[.bold[Les arbres solo élagués sont nuls en prédiction]]] <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-20-1.png" style="display: block; margin: auto;" /> ] .pull-right[ .center[.font120[.bold[Les arbres solo trops profonds sont bruités]]] <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-21-1.png" style="display: block; margin: auto;" /> ] .center[.content-box-gray[Le Bagging utilise cette grande variance comme une force
<i class="fas fa-arrow-up faa-FALSE animated " style=" color:red;"></i>
]] --- # .red[B]ootstrap .red[Agg]regat.red[ing] .pull-left[ 1. Echantillonner des cas avec remplacement ("bootstraper" les données d'apprentissage) 2. .white[Calculer un arbre sur-dimensionné sur les données recomposées] 3. .white[Moyenner les prédictions] ] .pull-right[ <img src="images/bagging-fig1.png" width="1379" style="display: block; margin: auto;" /> ] --- # .red[B]ootstrap .red[Agg]regat.red[ing] .pull-left[ 1. .opacity[.grey[Echantillonner des cas avec remplacement ("bootstraper" les données d'apprentissage)]] 2. .white[Calculer un arbre
sur-dimensionné
sur les données recomposées] 3. .white[Moyenner les prédictions] ] .pull-right[ <img src="images/bagging-fig2.png" width="1384" style="display: block; margin: auto;" /> ] --- # .red[B]ootstrap .red[Agg]regat.red[ing] .pull-left[ 1. .opacity[.grey[Echantillonner des cas avec remplacement ("bootstraper" les données d'apprentissage)]] 2. Calculer un arbre
sur-dimensionné
sur les données recomposées 3. .white[Moyenner les prédictions] ] .pull-right[ <img src="forets_aleatoires_lbvpam_files/figure-html/unnamed-chunk-24-1.png" style="display: block; margin: auto;" /> ] --- # .red[B]ootstrap .red[Agg]regat.red[ing] .pull-left[ 1. .opacity[.grey[Sample records with replacement (aka "bootstrap" the training data)]] 2. .opacity[.grey[Calculer un arbre "sur-dimensionné" sur les données recomposées]] 3. Moyenner les prédictions ] .pull-right[ <img src="images/bagging-fig3.png" width="1385" style="display: block; margin: auto;" /> ] --- # .red[B]ootstrap .red[Agg]regat.red[ing] .pull-left[ .font120.bold[Plus on ajoute d'arbres...]  ] .pull-right[ .font120.bold[plus l'erreur de prédiction décroît]  ] --- # Cependant, .red[il reste un problème] .bold[Le bagging crée des arbres dont la réponse est corrélée...] <img src="images/tree-correlation-1.png" width="70%" style="display: block; margin: auto;" /> .center[.content-box-gray[.bold[ce qui empêche justement le bagging de réduire la variance des valeurs prédites]]] --- class: clear, center, middle background-image: url(images/oil-palm-plantation-vl.jpg) background-size: cover .font300.white[Pb des arbres qui se ressemblent...] --- class: clear, center, middle background-image: url(images/primary_forest.jpg) background-size: cover .font300.white[Random Forests] --- # Principe .pull-left[ ### Randomisation de la variable de partitionnement * .font120[Un processus similaire au bagging mais... ] ] .pull-right[ <img src="images/bagged-trees-illustration.png" width="1484" style="display: block; margin: auto;" /> .center[.content-box-gray[.bold[Bagging => n arbres corrélés]]] ] --- # Principe .pull-left[ ### Randomisation de la variable de partitionnement * Un processus similaire au bagging mais... * à chaque partition, la variable à choisir l'est dans .blue[un sous-jeu limité *m* parmi les *p* variables] - arbres de régression: `\(m = \frac{p}{3}\)` - arbres de classification: `\(m = \sqrt{p}\)` - `\(m\)` is commonly referred to as .blue[___mtry___] .white[ * Le Bagging introduit l'aléatoire dans les rangées du dataset * Random forest introduit l'aléatoire dans les rangées et les colonnes du dataset ] ] .pull-right[ <img src="images/rf-trees-illustration.png" width="1491" style="display: block; margin: auto;" /> .center[.content-box-gray[.bold[Random Forests => n arbres uniques]]] ] --- # Bagging contre Random Forest .pull-left[ .opacity[ ### Randomisation de la variable de partitionnement * Un processus similaire au bagging mais... * à chaque partition, la variable est tirée dans .blue[un sous-jeu *m* parmi les *p* variables] ] * Bagging introduit .red[l'aléatoire] dans les rangées du dataset * Random forest introduit .red[l'aléatoire] dans rangées *et* colonnes du dataset ] .pull-right[  ] .center[.bold[.green[La combinaison produit un jeu d'arbres plus diversifié qui réduit encore l'erreur de prédiction.]]] --- # Out-of-bag
<i class="fas fa-shopping-bag faa-pulse animated-hover " style=" color:red;"></i>
.pull-left[ .font75[ * Pour un N suffisamment grand, 63.21% des observations sont incluses dans un échantillon bootstrappé * En gros, 36.79% des observations ne sont pas utilisées pour construire un arbre donné * Ces observations sont dites .red[out-of-bag (OOB)] et peuvent être utilisées pur une évaluation efficace des performances du modèle (.bold[= cross-validation (validation croisée) non structurée mais gratuite]) ] .font75[.blue[Au doigt mouillé]: - Pour un N petit, OOB est moins fiable que la validation - N augmentant, OOB devient plus efficace qu'une CV à *k-feuillets* - Quand le nombre d'arbres est 3x le nombre pour que l'erreur de la forêt se stabilise, alors l'erreur estimée par OOB error est équivalente à une erreur de validation leave-one-out. ]] .pull-right[  ] --- # Applications ? .pull-left[ * __Cartographie de biotopes__ ] .pull-right[ <iframe width="850" height="650" frameborder="0" style="border:0" src="https://websig.univ-st-etienne.fr/cyrille/index.php/view/embed/?repository=loirepoc&project=proj_pocloiret_lizmap&layers=B0TTTT&bbox=-69758.954411%2C5885969.21613%2C508104.979345%2C6150135.585847&crs=EPSG%3A3857" allowfullscreen></iframe> ] --- # Applications ? .pull-left[ * __Cartographie de biotopes__ ] .pull-right[ * Projet CarHAB: Cartographie des Habitats (Stratégie Nationale pour la Biodiversité) * MESR, IGN, MNHN, AFB, IRSTEA, URennes, UJM * Réseau des CBN: CBN Massif Central, CBN Bassin Parisien, CBN Bailleul, CBN Aalpin, CBN Brest, CBN Corse, CBN SE Atlantique * Géocomputation (reprodutible) * Ex: Loiret & Cher: un tableau de données avec 43 millions de lignes ] --- # Applications ? .pull-left[ * Cartographie de biotopes * Analyse de __données compositionnelles en écologie-chimique__ ] .pull-right[  .center[ .font80[ *...[RF] is robust against almost all violations of common statistical assumptions, needs notransformation and also provides an additional graphicalMDS output based on the classification results.* ] ] ] --- # Applications ? .pull-left[ * Cartographie de biotopes * Analyse de données compositionnelles en écologie-chimique * Marqueurs sous sélection en génétique des populations * Classement des données de RNA-Seq * ... ] .pull-right[  .font80[ *...[RF] is robust against almost all violations of common statistical assumptions, needs notransformation and also provides an additional graphicalMDS output based on the classification results.* ] ] --- class: center, middle, inverse # Les deux cultures --- # Breiman 2001 .pull-left[  ] .pull-right[ Prédiction / Information ] -- .pull-left[  ] .pull-right[ Validation: oui / non, goodness-of-fit & examen des résidus ] -- .pull-left[ *  ] .pull-right[ * Validation: par précision du modèle (succès) ] --- # Un algo pour tous les problèmes ? .center[ <img src="images/do_we_need_hundred.png" style="height: 80" /> * 179 classifieurs * 17 familles d'algorithmes * 121 jeux de données (UCI database) ] -- .bold[ .blue[ *The random forest is clearly the best family of classifiers (3 out of 5 bests classifiers are RF),followed by SVM (4 classifiers in the top-10), neural networks and boosting ensembles (5and 3 members in the top-20, respectively)* ] ] --- # Ensemblisme contre Rasoir d'Ockham ? ## Wisdom of crowds Galton et l'estimation du poids du boeuf... -- Epicure et son principe des explication multiples: *"si plus d'une théorie est en accord avec les données, alors il faut toutes les garder"* -- Si plusieurs explications sont en accord, alors il peut être possible d'arriver à un plus grand niveau de précision en les utilisant __conjointement__ Cf méthodes de combinaisons de décision: * bagging * boosting * ... -- Nouveaux modèles de démocratie participative ??? --- # Penser ces choses-là en français ? <br><br><br> .center[  ] --- # J'ai pillé * Bradley Boehmke bradleyboehmke.github.io grâce au __code__ de sa présentation __reproductible__ https://bradleyboehmke.github.io/random-forest-training/