Cet article explique les forêts aléatoires (Random Forest) en commentant le cours INTRODUCTION TO RANDOM FORESTS de Jeremy Howard (probablement le meilleur formateur au Machine Learning et au Deep Learning). Le principe de la formation retenue par Jeremy est toujours de partir du code, de l’expliquer, d’arriver ensuite à la théorie. On apprend en codant. Ceci suppose de savoir coder. Si vous ne le savez pas, alors cet article n’est pas pour vous. Le langage utilisé est Python. De préférence, la version 3.x (3.6) actuellement. Le code de l’exemple est ici : https://github.com/fastai/fastai/blob/master/courses/ml1/lesson1-rf.ipynb Anaconda est supposé installé. C’est un must have en machine learning. Vous avez le choix de travailler en local ou d’utiliser les services du Cloud spécialisé en ML/DL. Crestle et Paperspace sont recommandés. AWS est aussi une solution. L’exemple présenté ici est testé en local, sur Mac. Le code proposé par Jeremy ne marche pas sur Mac tel quel. Si vous rencontrez l’erreur : ‘No module names bcolz‘ alors la solution est ici et si vous rencontrez l’erreur « ResolvePackageNotFound: cuda90« , la solution est ici (I commented out cuda90 (=> #cuda90) in environment.yml file and conda env update works successfully) Il est fortement recommandé de lire le Wiki et les Notes. Le code exemple est commenté ci-dessous. Pour bien comprendre, il faut à la fois regarder le code, le cours de Jeremy et cet article. L’idéal est de regarder la vidéo du cours en même temps que cet article et d’avoir le code de l’exemple sous les yeux dans l’environnement Jupyter. Jupyter utilise IPython (commandes en lignes interactives).
IPython is an interactive command-line terminal for Python.

autoreload

autoreload permet de recharger automatiquement tout fichier qui aurait été modifié après le début du lancement de Jupyter. autoreload reloads modules automatically before entering the execution of code typed at the IPython prompt. %autoreload 2
Reload all modules (except those excluded by %aimport) every time before executing the Python code typed.

Imports

Le langage Python recommande un style de programmation PEP 8 . Ce style dit ceci au niveau des imports :
Wildcard imports (from <module> import *) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools
Ce n’est pas ce que fait le code proposé mais l’auteur a ses raisons (on  lui fait confiance !)

Path

La commande !ls permet d’exécuter la commande ls (liste des fichiers du répertoire) En IPython, le  ! indique que la commande suivante sera exécutée par le shell.
When working interactively with the standard Python interpreter, one of the frustrations is the need to switch between multiple windows to access Python tools and system command-line tools. IPython bridges this gap, and gives you a syntax for executing shell commands directly from within the IPython terminal. The magic happens with the exclamation point: anything appearing after ! on a line will be executed not by the Python kernel, but by the system command-line.
Par ailleurs : Communication in the other direction–passing Python variables into the shell–is possible using the {varname} syntax:

Données

Les données sont récupérées sur Kaggle que connait bien l’auteur puisqu’il en a été le président. Il s’agit de prévoir le prix de bulldozers (SalePrice) vendus aux enchères. Oui c’est bizarre mais intéressant. On utilise pandas pour lire les données. Le paramètre parse_dates permet de spécifier qu’un champ est une date.
  • parse_dates : boolean or list of ints or names or list of lists or dict, default False
  • boolean. If True -> try parsing the index. list of ints or names. e.g. If [1, 2, 3] -> try parsing columns 1, 2, 3 each as a separate date column.
f'{PATH}Train.csv’ est du Python 3.x (et non une commande Jupyter). On obtient le contenu de la variable en la mettant entre crochets.
This PEP proposed to add a new string formatting mechanism: Literal String Interpolation. In this PEP, such strings will be referred to as « f-strings », taken from the leading character used to denote such strings, and standing for « formatted strings ». This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms. F-strings provide a way to embed expressions inside string literals, using a minimal syntax. It should be noted that an f-string is really an expression evaluated at run time, not a constant value. In Python source code, an f-string is a literal string, prefixed with ‘f’, which contains expressions inside braces.  
Ne soyez pas surpris si la lecture des données dans le dataframe  prend quelques secondes. Il y a plus de 40 000 lignes. low_memory=false n’est peut-être plus utile, d’après ici.
pandas will guess the data type chunk by chunk if low_memory is True, so each item in a single column might have different types. However, the fix is pretty easy: stating dtype explicitly.
Le choix est de ne pas faire d’EDA (Exploratory Data Analysis) afin d’éviter tout risque d’overfitting.

Display

Pour rappel, .T transpose les données et .tail commence par la fin. display est une commande IPython.
display.max_rows : This sets the maximum number of rows pandas should output when printing out various output. For example, this value determines whether the repr() for a dataframe prints out fully or just a summary repr. ‘None’ value means unlimited. display.max_columns : max_rows and max_columns are used in __repr__() methods to decide if to_string() or info() is used to render an object to a string. In case Python/IPython is running in a terminal this is set to 0 by default and pandas will correctly auto-detect the width of the terminal and switch to a smaller format in case all columns would not fit vertically. The IPython notebook, IPython qtconsole, or IDLE do not run in a terminal and hence it is not possible to do correct auto-detection, in which case the default is set to 20. ‘None’ value means unlimited.
  Le résultat :
 401120401121401122401123401124
SalesID63333366333337633333863333416333342
SalePrice10500110001150090007750
MachineID18407021830472188765919035701926965
ModelID2143921439214392143521435
datasource149149149149149
auctioneerID11122
YearMade20052005200520052005
MachineHoursCurrentMeterNaNNaNNaNNaNNaN
UsageBandNaNNaNNaNNaNNaN
saledate2 November 20112 November 20112 November 201125 October 201125 October 2011
fiModelDesc35NX235NX235NX230NX30NX
fiBaseModel3535353030
fiSecondaryDescNXNXNXNXNX
fiModelSeries222NaNNaN
fiModelDescriptorNaNNaNNaNNaNNaN
ProductSizeMiniMiniMiniMiniMini
fiProductClassDescHydraulic Excavator, Track - 3.0 to 4.0 Metric...Hydraulic Excavator, Track - 3.0 to 4.0 Metric...Hydraulic Excavator, Track - 3.0 to 4.0 Metric...Hydraulic Excavator, Track - 2.0 to 3.0 Metric...Hydraulic Excavator, Track - 2.0 to 3.0 Metric...
stateMarylandMarylandMarylandFloridaFlorida
ProductGroupTEXTEXTEXTEXTEX
ProductGroupDescTrack ExcavatorsTrack ExcavatorsTrack ExcavatorsTrack ExcavatorsTrack Excavators
Drive_SystemNaNNaNNaNNaNNaN
EnclosureEROPSEROPSEROPSEROPSEROPS
ForksNaNNaNNaNNaNNaN
Pad_TypeNaNNaNNaNNaNNaN
Ride_ControlNaNNaNNaNNaNNaN
StickNaNNaNNaNNaNNaN
TransmissionNaNNaNNaNNaNNaN
TurbochargedNaNNaNNaNNaNNaN
Blade_ExtensionNaNNaNNaNNaNNaN
Blade_WidthNaNNaNNaNNaNNaN
Enclosure_TypeNaNNaNNaNNaNNaN
Engine_HorsepowerNaNNaNNaNNaNNaN
HydraulicsAuxiliaryStandardAuxiliaryStandardStandard
PushblockNaNNaNNaNNaNNaN
RipperNaNNaNNaNNaNNaN
ScarifierNaNNaNNaNNaNNaN
Tip_ControlNaNNaNNaNNaNNaN
Tire_SizeNaNNaNNaNNaNNaN
CouplerNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or Unspecified
Coupler_SystemNaNNaNNaNNaNNaN
Grouser_TracksNaNNaNNaNNaNNaN
Hydraulics_FlowNaNNaNNaNNaNNaN
Track_TypeSteelSteelSteelSteelSteel
Undercarriage_Pad_WidthNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or Unspecified
Stick_LengthNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or Unspecified
ThumbNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or Unspecified
Pattern_ChangerNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or UnspecifiedNone or Unspecified
Grouser_TypeDoubleDoubleDoubleDoubleDouble
Backhoe_MountingNaNNaNNaNNaNNaN
Blade_TypeNaNNaNNaNNaNNaN
Travel_ControlsNaNNaNNaNNaNNaN
Differential_TypeNaNNaNNaNNaNNaN
Steering_ControlsNaNNaNNaNNaNNaN
La variable dépendante est SalePrice.

Describe

Pandas permet de présenter les statistiques descriptives qui résument les formes de la distribution. Le résultat :
countuniquetopfreqfirstlastmeanstdmin0.250.50.75max 
SalesID401125NaNNaNNaNNaNNaN1.91971e+069090211.13925e+061.41837e+061.63942e+062.24271e+066.33334e+06
SalePrice401125NaNNaNNaNNaNNaN31099.723036.94750145002400040000142000
MachineID401125NaNNaNNaNNaNNaN1.2179e+0644099201.0887e+061.27949e+061.46807e+062.48633e+06
ModelID401125NaNNaNNaNNaNNaN6889.76221.782832594604872437198
datasource401125NaNNaNNaNNaNNaN134.6668.96224121132132136172
auctioneerID380989NaNNaNNaNNaNNaN6.5560416.9768012499
YearMade401125NaNNaNNaNNaNNaN1899.16291.79710001985199520002013
MachineHoursCurrentMeter142765NaNNaNNaNNaNNaN3457.9627590.300030252.4833e+06
UsageBand696393Medium33985NaNNaNNaNNaNNaNNaNNaNNaNNaN
saledate401125391916 February 2009193217 January 198930 December 2011NaNNaNNaNNaNNaNNaNNaN
fiModelDesc4011254999310G5039NaNNaNNaNNaNNaNNaNNaNNaNNaN
fiBaseModel401125195058019798NaNNaNNaNNaNNaNNaNNaNNaNNaN
fiSecondaryDesc263934175C43235NaNNaNNaNNaNNaNNaNNaNNaNNaN
fiModelSeries56908122II13202NaNNaNNaNNaNNaNNaNNaNNaNNaN
fiModelDescriptor71919139L15875NaNNaNNaNNaNNaNNaNNaNNaNNaN
ProductSize1903506Medium62274NaNNaNNaNNaNNaNNaNNaNNaNNaN
fiProductClassDesc40112574Backhoe Loader - 14.0 to 15.0 Ft Standard Digg...56166NaNNaNNaNNaNNaNNaNNaNNaNNaN
state40112553Florida63944NaNNaNNaNNaNNaNNaNNaNNaNNaN
ProductGroup4011256TEX101167NaNNaNNaNNaNNaNNaNNaNNaNNaN
ProductGroupDesc4011256Track Excavators101167NaNNaNNaNNaNNaNNaNNaNNaNNaN
Drive_System1043614Two Wheel Drive46139NaNNaNNaNNaNNaNNaNNaNNaNNaN
Enclosure4008006OROPS173932NaNNaNNaNNaNNaNNaNNaNNaNNaN
Forks1920772None or Unspecified178300NaNNaNNaNNaNNaNNaNNaNNaNNaN
Pad_Type791344None or Unspecified70614NaNNaNNaNNaNNaNNaNNaNNaNNaN
Ride_Control1486063No77685NaNNaNNaNNaNNaNNaNNaNNaNNaN
Stick791342Standard48829NaNNaNNaNNaNNaNNaNNaNNaNNaN
Transmission1832308Standard140328NaNNaNNaNNaNNaNNaNNaNNaNNaN
Turbocharged791342None or Unspecified75211NaNNaNNaNNaNNaNNaNNaNNaNNaN
Blade_Extension252192None or Unspecified24692NaNNaNNaNNaNNaNNaNNaNNaNNaN
Blade_Width25219614'9615NaNNaNNaNNaNNaNNaNNaNNaNNaN
Enclosure_Type252193None or Unspecified21923NaNNaNNaNNaNNaNNaNNaNNaNNaN
Engine_Horsepower252192No23937NaNNaNNaNNaNNaNNaNNaNNaNNaN
Hydraulics320570122 Valve141404NaNNaNNaNNaNNaNNaNNaNNaNNaN
Pushblock252192None or Unspecified19463NaNNaNNaNNaNNaNNaNNaNNaNNaN
Ripper1041374None or Unspecified83452NaNNaNNaNNaNNaNNaNNaNNaNNaN
Scarifier252302None or Unspecified12719NaNNaNNaNNaNNaNNaNNaNNaNNaN
Tip_Control252193None or Unspecified16207NaNNaNNaNNaNNaNNaNNaNNaNNaN
Tire_Size9471817None or Unspecified46339NaNNaNNaNNaNNaNNaNNaNNaNNaN
Coupler2139523None or Unspecified184582NaNNaNNaNNaNNaNNaNNaNNaNNaN
Coupler_System434582None or Unspecified40430NaNNaNNaNNaNNaNNaNNaNNaNNaN
Grouser_Tracks433622None or Unspecified40515NaNNaNNaNNaNNaNNaNNaNNaNNaN
Hydraulics_Flow433623Standard42784NaNNaNNaNNaNNaNNaNNaNNaNNaN
Track_Type991532Steel84880NaNNaNNaNNaNNaNNaNNaNNaNNaN
Undercarriage_Pad_Width9987219None or Unspecified79651NaNNaNNaNNaNNaNNaNNaNNaNNaN
Stick_Length9921829None or Unspecified78820NaNNaNNaNNaNNaNNaNNaNNaNNaN
Thumb992883None or Unspecified83093NaNNaNNaNNaNNaNNaNNaNNaNNaN
Pattern_Changer992183None or Unspecified90255NaNNaNNaNNaNNaNNaNNaNNaNNaN
Grouser_Type991533Double84653NaNNaNNaNNaNNaNNaNNaNNaNNaN
Backhoe_Mounting786722None or Unspecified78652NaNNaNNaNNaNNaNNaNNaNNaNNaN
Blade_Type7983310PAT38612NaNNaNNaNNaNNaNNaNNaNNaNNaN
Travel_Controls798347None or Unspecified69923NaNNaNNaNNaNNaNNaNNaNNaNNaN
Differential_Type694114Standard68073NaNNaNNaNNaNNaNNaNNaNNaNNaN
Steering_Controls693695Conventional68679NaNNaNNaNNaNNaNNaNNaNNaNNaN

Métrique

La métrique est imposée.
The evaluation metric for this competition is the RMSLE (root mean squared log error) between the actual and predicted auction prices.
Tout ça paraît logique :
The reason we use log is because generally, you care not so much about missing by $10 but missing by 10%. So if it was $1000,000 item and you are $100,000 off or if it was a $10,000 item and you are $1,000 off — we would consider those equivalent scale issues.
L’objectif est d’obtenir un modèle qui minimise les écarts de log. On s’intéresse au log du prix et non au prix lui même tout simplement parce qu’un écart en % a plus de sens dans notre cas qu’un écart en valeur absolue. Le ratio est plus significatif que l’écart de prix. Pour cela, on utilise NumPy. log est ici le logarithme népérien.

RandomForestRegressor

Avant d’expliquer Random Forest, le cours démonte deux idées reçues : En résumé, utiliser beaucoup de colonnes n’est pas un problème et les données ne sont pas si aléatoires qu’on l’imagine. RandomForestRegressor est en fait sklearn.ensemble.RandomForestRegressor. n_jobs=-1pour utiliser tous les processeurs. Si vous ne pouvez pas attendre pour en savoir plus sur RandomForestRegressor, RdV ici pour la fonction et lisez le commentaire pour les forêts aléatoires :

Random forest is a universal machine learning technique.

  • It can predict something that can be of any kind — it could be a category (classification), a continuous variable (regression).
  • It can predict with columns of any kind — pixels, zip codes, revenues, etc (i.e. both structured and unstructured data).
  • It does not generally overfit too badly, and it is very easy to stop it from overfitting.
  • You do not need a separate validation set in general. It can tell you how well it generalizes even if you only have one dataset.
  • It has few, if any, statistical assumptions. It does not assume that your data is normally distributed, the relationship is linear, or you have specified interactions.
  • It requires very few pieces of feature engineering. For many different types of situation, you do not have to take the log of the data or multiply interactions together.
  • RandomForestRegressor — regressor is a method for predicting continuous variables (i.e. regression)
  • RandomForestClassifier — classifier is a method for predicting categorical variables (i.e. classification)

fit

Everything in scikit-learn has the same form.

Create an instance of an object for the machine learning model Call fit by passing in the independent variables (the things you are going to use to predict) and dependent variable (the thing you want to predict). axis=1 means remove columns.
Le code proposé présente à la suite une ligne qui génère une erreur : fit est une méthode qui crée une forêt à partir de données. fit(X, y[, sample_weight])Build a forest of trees from the training set (X, y). drop (pandas – DataFrame) supprime une ligne ou une colonne dans un tableau de données. En l’occurence, c’est la colonne SalePrice. Le tableau de données des variables indépendantes est tout le tableau moins la colonne SalePrice et la variable dépendante est la colonne SalePrice. Ce code génère une erreur car toutes les données ne sont pas numériques.

Dates

Comme on ne peut pas utiliser la date de la vente telle quelle, alors on crée d’autres champs, comme par exemple : saleDayofweek, saleDayofyear.

train_cats

Il ne suffit pas de remplacer les dates par d’autre champs. Il faut le faire pour toutes les strings. Fastai propose pour cela train_cats.
Pandas has a concept of a category data type, but by default it would not turn anything into a category for you. Fast.ai provides a function called train_cats which creates categorical variables for everything that is a String. Behind the scenes, it creates a column that is an integer and it is going to store a mapping from the integers to the strings. train_cats is called “train” because it is training data specific. It is important that validation and test sets will use the same category mappings (in other words, if you used 1 for “high” for a training dataset, then 1 should also be for “high” in validation and test datasets).
 

df_raw.UsageBand.cat.categories

On fait ici le remplacement de catégories.
df_raw.UsageBand.cat — Similar tofld.dt.year , .cat gives you access to things assuming something is a category. The order does not matter too much, but since we are going to be creating a decision tree that split things at a single point (i.e. High vs. Low and Medium , High and Low vs. Medium ) which is a little bit weird. To order them in a sensible manner, you can do the following: inplace will ask Pandas to change the existing dataframe rather than returning a new one. There is a kind of categorical variable called “ordinal”. An ordinal categorical variable has some kind of order (e.g. “Low” < “Medium” < “High”). Random forests are not terribly sensitive for that fact, but it is worth noting.
Ce code n’est pas commenté ici car il n’apporte rien à la compréhension de Random Forests.

Valeurs manquantes

En exécutant la commande suivante, on constate qu’il existe de nombreuses valeurs manquantes.

Sauvegarde

Pour sauvegarder et relire les données : Le format utilisé est feather format, disponible ici.
Feather provides binary columnar serialization for data frames. It is designed to make reading and writing data frames efficient, and to make sharing data across data analysis languages easy.

Fin de la mise à jour des données

On obtient cette fois des données qui peuvent être exploitées.
We will replace categories with their numeric codes, handle missing continuous values, and split the dependent variable into a separate variable.

Random ForestRegressor

Cette fois on peut recommencer RandomForest – avec des données nettoyées.

score

La méthode score de sklearn.ensemble.RandomForestRegressor retourne le coefficient de détermination R^2 de la prédiction.
En statistique, le coefficient de détermination, noté R2 ou r2, est une mesure de la qualité de la prédiction d’une régression linéaire.
score(X, y[, sample_weight]) La valeur calculée est 0.9829

Création d’un jeu de données de validation

A partir d’ici, le cours de Jeremy est le #2. Les données sont désormais réparties de la façon suivante :

RMSE

Le modèle est-il bon ?

Nous obtenons les résultats :

Un seul arbre

Une forêt est composée d’arbres. Voyons ce que ça donne avec un seul arbre. n_estimators = 1 veut dire un seul arbre. Le résultat obtenu n’est pas terrible. mais on peut l’afficher. On peut faire mieux en approfondissant l’arbre : mais on overfits.

Bagging

L’idée est de travailler sur un échantillon des données, d’effectuer un TreeClassier profond qui fera de l’overfit, et d’itérer de nombreuses fois sur différents échantillons. Par défaut, le nombre d’arbres est 10. le résultat :

Prédiction sur chaque arbre

Le résultat : On peut constater que plus il y a d’arbres, meilleur est r2

Augmentation du nombre d’arbres

Augmenter le nombre d’arbres dans la forêt est efficace…jusqu’à un certain point : Avec 20 arbres : Avec 40 arbres : Avec 80 arbres Ce 1er cours s’arrête ici – ce qui correspond à 1:12 de la vidéo de la lesson 2. Les autres points, plus techniques seront abordés dans le prochain article.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *