{"id":425,"date":"2015-06-09T16:11:26","date_gmt":"2015-06-09T14:11:26","guid":{"rendered":"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=425"},"modified":"2017-07-20T15:40:39","modified_gmt":"2017-07-20T13:40:39","slug":"classification-par-forets-aleatoires","status":"publish","type":"post","link":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/classification-par-forets-aleatoires\/","title":{"rendered":"Classification par for\u00eats al\u00e9atoires"},"content":{"rendered":"<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Random_forest\/Lise_Vaudor_headband-1.png\" alt=\"\" \/><\/p>\n<h1>Qu&rsquo;est-ce que c&rsquo;est ?<\/h1>\n<p>Il y a quelques mois, je vous proposais un billet sur les <a href=\"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=247\">arbres d\u00e9cisionnels<\/a>. Comme on dit, c&rsquo;\u00e9tait l&rsquo;arbre qui cachait la for\u00eat (ha!ha! quelle joie d&rsquo;avoir un blog pour pouvoir faire de tels jeux de mots). Voici donc la suite naturelle de ce billet,cette fois sur les <strong>for\u00eats d&rsquo;arbres d\u00e9cisionnels<\/strong> ou <strong>for\u00eats al\u00e9atoires<\/strong> (alias <strong>\u00ab\u00a0random forests\u00a0\u00bb<\/strong> en anglais).<\/p>\n<p>Les for\u00eats al\u00e9atoires sont compos\u00e9es (comme le terme \u00ab\u00a0for\u00eat\u00a0\u00bb l&rsquo;indique) d&rsquo;un ensemble d&rsquo;arbres d\u00e9cisionnels. Ces arbres se distinguent les uns des autres par le <strong>sous-\u00e9chantillon de donn\u00e9es sur lequel ils sont entra\u00een\u00e9s<\/strong>. Ces sous-\u00e9chantillons sont tir\u00e9s au hasard (d&rsquo;o\u00f9 le terme \u00ab\u00a0al\u00e9atoire\u00a0\u00bb) dans le jeu de donn\u00e9es initial.<\/p>\n<p>On va utiliser le package <code>randomForest<\/code>.<\/p>\n<pre><code>require(randomForest)\n<\/code><\/pre>\n<p>On utilise le jeu de donn\u00e9es iris:<\/p>\n<pre><code>data(iris)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Random_forest\/plot_simple-1.png\" alt=\"\" \/><\/p>\n<p>Dans ce jeu de donn\u00e9es, des iris de trois esp\u00e8ces diff\u00e9rentes sont d\u00e9crits par :<\/p>\n<ul>\n<li>leur appartenance \u00e0 l&rsquo;esp\u00e8ce <em>setosa<\/em> (en gris ci-dessus), <em>versicolor<\/em> (en rose), ou <em>virginica<\/em> (en jaune)<\/li>\n<li>la longueur des s\u00e9pales (les sortes de petites feuilles \u00e0 la base des corolles de fleurs)<\/li>\n<li>la largeur des s\u00e9pales<\/li>\n<li>la longueur des p\u00e9tales<\/li>\n<li>la largeur des p\u00e9tales<\/li>\n<\/ul>\n<h1>Construction d&rsquo;une for\u00eat al\u00e9atoire<\/h1>\n<p>Pour produire une for\u00eat al\u00e9atoire (ici sans modifier les param\u00e8tres par d\u00e9faut) \u00e0 l&rsquo;aide de la fonction randomForest, rien de plus simple:<\/p>\n<pre><code>iris.rf &lt;- randomForest(iris[,1:4], iris$Species)\nprint(iris.rf)\n\n## \n## Call:\n##  randomForest(x = iris[, 1:4], y = iris$Species) \n##                Type of random forest: classification\n##                      Number of trees: 500\n## No. of variables tried at each split: 2\n## \n##         OOB estimate of  error rate: 4.67%\n## Confusion matrix:\n##            setosa versicolor virginica class.error\n## setosa         50          0         0        0.00\n## versicolor      0         47         3        0.06\n## virginica       0          4        46        0.08\n<\/code><\/pre>\n<p>Ici la fonction print nous permet d&rsquo;afficher quelques caract\u00e9ristiques de l&rsquo;objet produit. On apprend ainsi que la for\u00eat est compos\u00e9e de 500 arbres, qu&rsquo;\u00e0 chaque noeud l&rsquo;algorithme fait un essai sur 2 variables, que le taux d&rsquo;erreur est de 4%. La <strong>matrice de confusion<\/strong> est \u00e9galement affich\u00e9e (on y reviendra tr\u00e8s bient\u00f4t!).<\/p>\n<p>Chaque arbre de la for\u00eat est construit sur une fraction (\u00ab\u00a0in bag\u00a0\u00bb) des donn\u00e9es (c&rsquo;est la fraction qui sert \u00e0 l&rsquo;<strong>entra\u00eenement<\/strong> de l&rsquo;algorithme. Alors pour chacun des individus de la fraction restante (\u00ab\u00a0out of bag\u00a0\u00bb) l&rsquo;arbre peut pr\u00e9dire une classe.<\/p>\n<p>Pour ce qui est de la construction de l&rsquo;arbre lui-m\u00eame, je vous renvoie une fois encore \u00e0 <a href=\"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=247\">ce billet<\/a>.<\/p>\n<p>Par d\u00e9faut, la fonction <code>randomForest<\/code> tire au hasard n individus parmi les n (avec remplacement, ce qui devrait correspondre, en moyenne, \u00e0 l&rsquo;\u00e9chantillonnage au hasard de 63.2% des individus). Ainsi sur les <em>n<\/em>\u2004=\u2004500 arbres, chaque individu fera partie de la fraction \u00ab\u00a0in bag\u00a0\u00bb et \u00ab\u00a0out of bag\u00a0\u00bb en moyenne 0.632\u2005<em>\u2005500\u2004=\u2004316 et 0.368\u2005<\/em>\u2005500\u2004=\u2004184 fois (en moyenne, mais pas forc\u00e9ment exactement, du fait de l&rsquo;al\u00e9a d&rsquo;\u00e9chantillonnage).<\/p>\n<p>On peut ainsi acc\u00e9der au nombre de fois o\u00f9 chaque individu est \u00ab\u00a0out of bag\u00a0\u00bb de la mani\u00e8re suivante (ici je n&rsquo;affiche que les dix premiers individus):<\/p>\n<pre><code>print(iris.rf$oob.times[1:10])\n\n##  [1] 178 182 183 178 195 177 185 187 200 176\n<\/code><\/pre>\n<p>Sur l&rsquo;ensemble des arbres sur lesquels les individus ont \u00e9t\u00e9 \u00ab\u00a0out of bag\u00a0\u00bb, on peut s&rsquo;int\u00e9resser \u00e0 la proportion de <strong>votes<\/strong> que chaque classe a recueilli. Ici, par exemple, je m&rsquo;int\u00e9resse \u00e0 un sous-\u00e9chantillon de trois individus:<\/p>\n<pre><code>sous_echant=c(25,75,135)\niris$Species[sous_echant]\n\n## [1] setosa     versicolor virginica \n## Levels: setosa versicolor virginica\n\niris.rf$oob.times[sous_echant]\n\n## [1] 185 197 189\n\niris.rf$votes[sous_echant,]\n\n##     setosa versicolor   virginica\n## 25       1  0.0000000 0.000000000\n## 75       0  0.9949239 0.005076142\n## 135      0  0.5026455 0.497354497\n<\/code><\/pre>\n<p>Pour les trois individus affich\u00e9s ci-dessus:<\/p>\n<ul>\n<li>la for\u00eat al\u00e9atoire a class\u00e9 le 1er individu en \u00ab\u00a0setosa\u00a0\u00bb (donc correctement) dans 100% des 185 arbres o\u00f9 il \u00e9tait \u00ab\u00a0out of bag\u00a0\u00bb<\/li>\n<li>la for\u00eat al\u00e9atoire a class\u00e9 le 2\u00e8me individu en \u00ab\u00a0versicolor\u00a0\u00bb (donc correctement) dans 99% des 197 arbres o\u00f9 il \u00e9tait \u00ab\u00a0out of bag\u00a0\u00bb.<\/li>\n<li>la for\u00eat al\u00e9atoire a class\u00e9 le 3\u00e8me individu en \u00ab\u00a0virginica\u00a0\u00bb (donc correctement) dans seulement 50% des 189 arbres o\u00f9 il \u00e9tait \u00ab\u00a0out of bag\u00a0\u00bb, et en versicolor dans les 50% de cas restants.<\/li>\n<\/ul>\n<p>Ainsi, pour identifier les individus qui tendent \u00e0 poser probl\u00e8me, on peut utiliser la <strong>marge<\/strong>. Pour un individu donn\u00e9, qui appartient \u00e0 la classe <em>i<\/em>, on note <em>P<\/em><sub><em>j<\/em><\/sub> la proportion de votes pour la classe <em>j<\/em>. Alors la marge correspond \u00e0:<\/p>\n<pre><code>    $$ P_i-max_{j\\neq i}(P_j)\n    $$\n<\/code><\/pre>\n<p>Il s&rsquo;agit ainsi de la diff\u00e9rence entre la proportion de votes <strong>pour la classe correcte<\/strong> (<em>i<\/em>) et la proportion de votes <strong>pour la classe sortie majoritaire parmi les autres classes<\/strong> (<em>j<\/em>\u2004\u2260\u2004<em>i<\/em>).<\/p>\n<pre><code>m=margin(iris.rf)\nprint(m[sous_echant])                                                                                                                                                                     \n\n##       setosa   versicolor    virginica \n##  1.000000000  0.989847716 -0.005291005\n<\/code><\/pre>\n<p>Ainsi, <strong>plus la marge est proche de 1 et plus la confiance accord\u00e9e \u00e0 la pr\u00e9diction est grande<\/strong>&#8230; Au contraire, quand la marge est faible ou m\u00eame n\u00e9gative, la confiance \u00e0 accorder \u00e0 la classification pour l&rsquo;individu consid\u00e9r\u00e9 est faible.<\/p>\n<h1>Pr\u00e9diction<\/h1>\n<p>La classe pr\u00e9dite est pour chaque individu est, par d\u00e9faut, celle qui recueille le plus de votes sur l&rsquo;ensemble des arbres o\u00f9 l&rsquo;individu est \u00ab\u00a0out of bag\u00a0\u00bb.<\/p>\n<p>Voici comment la r\u00e9cup\u00e9rer sous R<\/p>\n<pre><code>print(iris.rf$predicted[1:10])\n\n##      1      2      3      4      5      6      7      8      9     10 \n## setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa \n## Levels: setosa versicolor virginica\n<\/code><\/pre>\n<p>On peut bien \u00e9videmment comparer la classe observ\u00e9e et la classe pr\u00e9dite:<\/p>\n<pre><code>table(iris$Species, iris.rf$predicted)\n\n##             \n##              setosa versicolor virginica\n##   setosa         50          0         0\n##   versicolor      0         47         3\n##   virginica       0          4        46\n<\/code><\/pre>\n<p>Surprise! on retrouve la matrice de confusion, que l&rsquo;on peut aussi afficher de la mani\u00e8re suivante:<\/p>\n<pre><code>iris.rf$confusion\n\n##            setosa versicolor virginica class.error\n## setosa         50          0         0        0.00\n## versicolor      0         47         3        0.06\n## virginica       0          4        46        0.08\n<\/code><\/pre>\n<p>Le taux d&rsquo;erreur correspond \u00e0 la proportion de cas o\u00f9 la pr\u00e9diction est incorrecte:<\/p>\n<pre><code>error_rate=1-sum(diag(iris.rf$confusion))\/sum(iris.rf$confusion)\nprint(error_rate)\n\n## [1] 0.04755561\n<\/code><\/pre>\n<p>Il est ici d&rsquo;environ 5%.<\/p>\n<h1>Pr\u00e9diction sur un nouveau jeu de donn\u00e9es<\/h1>\n<p>Imaginons maintenant que nous disposions d&rsquo;un jeu de donn\u00e9es dans lequel figurent les descripteurs des individus (longueur et largeur des s\u00e9pales, longueur et largeur des p\u00e9tales) mais pas leur esp\u00e8ce. Par exemple, les donn\u00e9es disponibles <a href=\"..\/..\/lise.vaudor\/Rdata\/Random_forest\/Species_to_predict.csv\">ici<\/a><\/p>\n<p>Je peux alors r\u00e9utiliser ma for\u00eat al\u00e9atoire comme classificateur:<\/p>\n<pre><code>predicted=predict(iris.rf,newdata=Species_to_predict)\nprint(predicted[1:5])\n\n##          1          2          3          4          5 \n## versicolor  virginica  virginica  virginica  virginica \n## Levels: setosa versicolor virginica\n<\/code><\/pre>\n<h1>Importance des variables<\/h1>\n<p>L&rsquo;importance d&rsquo;une variable dans la classification correspond \u00e0 la <strong>diminution moyenne de l&rsquo;impuret\u00e9<\/strong> qu&rsquo;elle permet. Pour chaque arbre, la diminution totale de l&rsquo;impuret\u00e9 li\u00e9e \u00e0 une variable correspond \u00e0 la diminution de l&rsquo;impuret\u00e9 cumul\u00e9e sur l&rsquo;ensemble des noeuds qu&rsquo;elle r\u00e9git. Cette diminution est ensuite moyenn\u00e9e sur l&rsquo;ensemble des arbres.<\/p>\n<p>Pour rappel, l&rsquo;impuret\u00e9 est mesur\u00e9es par l&rsquo;index de Gini (cf <a href=\"http:\/\/perso.ens-lyon.fr\/lise.vaudor\/?p=247\">ce billet<\/a> sur les arbres d\u00e9cisionnels).<\/p>\n<pre><code>iris.rf$importance\n\n##              MeanDecreaseGini\n## Sepal.Length         9.714378\n## Sepal.Width          2.290949\n## Petal.Length        44.439867\n## Petal.Width         42.828712\n\nvarImpPlot(iris.rf)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Random_forest\/variable_importance-1.png\" alt=\"\" \/><\/p>\n<p>Ici les deux variables qui ont clairement le plus d&rsquo;importance dans la classification des esp\u00e8ces sont la longueur et la largeur de p\u00e9tales.<\/p>\n<h1>Param\u00e9trisation de la for\u00eat<\/h1>\n<p>Dans la construction de chacun des arbres il y a une part d&rsquo;al\u00e9a li\u00e9e \u00e0 la fraction du jeu de donn\u00e9e consid\u00e9r\u00e9e pour l&rsquo;entra\u00eenement de l&rsquo;algorithme&#8230; Le taux d&rsquo;erreur observ\u00e9 pour chaque arbre est donc al\u00e9atoire. Plus on construit d&rsquo;arbres, et plus le taux d&rsquo;erreur \u00ab\u00a0moyen\u00a0\u00bb va converger vers une valeur fixe (ici 5%).<\/p>\n<p>Observons ainsi le taux d&rsquo;erreur si l&rsquo;on s&rsquo;int\u00e8gre les votes de 1, 2, 3, &#8230;. 5000 arbres parmi ceux construits par la fonction randomForest (le nombre d&rsquo;arbres peut \u00eatre modifi\u00e9 par le param\u00e8tre ntree):<\/p>\n<pre><code>iris.rf=randomForest(iris[,1:4], iris$Species, ntree=5000) \nplot(iris.rf$err.rate[,1], type=\"l\")\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"..\/..\/lise.vaudor\/Rfigures\/Random_forest\/error_rate-1.png\" alt=\"\" \/><\/p>\n<p>On observe que le taux d&rsquo;erreur se stabilise autour de 4% (soit 6 erreurs de classement sur 150 individus) quand le nombre d&rsquo;arbres atteint 3000 environ. Mais en produisant une for\u00eat qui ne compte \u00ab\u00a0que\u00a0\u00bb 500 arbres, on a un taux d&rsquo;erreur qui tourne autour de 6\/150 avec parfois un \u00ab\u00a0bond\u00a0\u00bb \u00e0 7\/150 donc ce n&rsquo;est pas non plus l&rsquo;horreur&#8230;<\/p>\n<p>On peut \u00e9galement \u00e9valuer (entre autres) l&rsquo;effet du param\u00e8tre <code>sampsize<\/code> qui fixe la taille de l&rsquo;\u00e9chantillon \u00ab\u00a0in bag\u00a0\u00bb, ou encore l&rsquo;effet du param\u00e8tre <code>maxnodes<\/code>, qui limite le nombre de noeuds de chaque arbre:<\/p>\n<pre><code>iris.rf2=randomForest(iris[,1:4], iris$Species, sampsize=140) \niris.rf3=randomForest(iris[,1:4], iris$Species, maxnodes=5) \n<\/code><\/pre>\n<p>Les valeur des param\u00e8tres sont fix\u00e9es par d\u00e9faut d&rsquo;une mani\u00e8re qui permet \u00ab\u00a0raisonnablement\u00a0\u00bb\u00a0\u00bb d&rsquo;esp\u00e9rer atteindre la convergence pour 500 arbres&#8230; mais rien n&#8217;emp\u00eache de s&rsquo;en assurer, empiriquement, \u00e0 travers le genre de graphique pr\u00e9sent\u00e9 ci-dessus&#8230;<\/p>\n<p>Pour une discussion plus approfondie de ces param\u00e8tres, rendez-vous sur la page d&rsquo;aide de la fonction randomForest, ou bien allez voir l&rsquo;article de Liaw and Wiener (2002)!<\/p>\n<h2>R\u00e9f\u00e9rences<\/h2>\n<p>Liaw, Andy, and Matthew Wiener. 2002. \u201cClassification and Regression by randomForest.\u201d <em>R News<\/em> 2 (3): 18\u201322. <a href=\"http:\/\/CRAN.R-project.org\/doc\/Rnews\/\">http:\/\/CRAN.R-project.org\/doc\/Rnews\/<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Qu&rsquo;est-ce que c&rsquo;est ? Il y a quelques mois, je vous proposais un billet sur les arbres d\u00e9cisionnels. Comme on dit, c&rsquo;\u00e9tait l&rsquo;arbre qui cachait la for\u00eat (ha!ha! quelle joie d&rsquo;avoir un blog pour pouvoir faire de tels jeux de mots). Voici donc la suite naturelle de ce billet,cette fois sur les for\u00eats d&rsquo;arbres d\u00e9cisionnels ou for\u00eats al\u00e9atoires (alias \u00ab\u00a0random forests\u00a0\u00bb en anglais). Les for\u00eats al\u00e9atoires sont compos\u00e9es (comme le.. <a href=\"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/classification-par-forets-aleatoires\/\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-425","post","type-post","status-publish","format-standard","hentry","category-tous-les-posts"],"_links":{"self":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/425","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/comments?post=425"}],"version-history":[{"count":13,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/425\/revisions"}],"predecessor-version":[{"id":794,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/posts\/425\/revisions\/794"}],"wp:attachment":[{"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/media?parent=425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/categories?post=425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/perso.ens-lyon.fr\/lise.vaudor\/wp-json\/wp\/v2\/tags?post=425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}