A travers ce livre, vous apprendrez à :

  • installer Sparklyr et une version récente d’Apache Spark dans votre pc ;

  • construire et évaluer des modèles de Machine Learning avec la librairie tidymodels ;

  • combiner sparklyr et tidymodels ;

  • réaliser une analyse exploratoire des données Big Data en utilisant sparklyr et dplyr ;

  • afficher les requêtes équivalentes de codes dplyr ;

  • construire, entraîner et évaluer un pipeline de Machine Learning en utilisant Spark MLlib ;

  • optimiser un modèle de Machine Learning en réglant ses hyperparamètres ;

  • déployer un modèle de Machine Learning dans une application web.

Prérecquis

Afin de bien comprendre le contenu de ce livre, vous devez :

  • avoir au moins un niveau débutant en programmation avec R et savoir utiliser RStudio ;

  • avoir une compréhension basique du Machine Learning ;

  • avoir des notions basiques en développement d’applications web avec la framework R Shiny.

Pour apprendre à programmer avec R, je vous conseille mon livre intitulé : APPRENDRE À PROGRAMMER AVEC R ET RSTUDIO: MANUEL DE COURS ET EXERCICES CORRIGÉS POUR DÉBUTANTS disponible en version papier et version pdf.

En ce qui concerne le développement d’applications web, il vous faudra aussi un livre 100% pratique axé sur des projets de création d’applications. Mon livre intitulé Développement Web en Data Science avec R Shiny sans HTML, CSS, PHP ni JavaScript vous amènera d’un niveau débutant à un niveau Expert en développement web avec R Shiny.

1. Introduction générale

1.1. Big Data

Au début des années 1990, avoir un ordinateur personnel Apple Macintosh Classic avec un disque dur de 80 mégaoctets était considéré déjà comme un luxe. Aujourd’hui, nous avons des ordinateurs avec 10 téraoctets (125000 fois plus d’espace qu’un disque dur de capacité égale à 80 mégaoctets) de stockage externe et parfois cette capacité n’est pas suffisante pour stocker tous nos fichiers. Donc, lorsqu’on parle de Big Data, la notion de taille est relative et ne peut donc à elle seule définir ce concept. Si vous avez un ordinateur avec un disque dur de 500 Giga, vous ne pourez pas stocker 1 téraoctet de données. Alors qu’une personne disposant de 10 To de capacité pourra facilment stocker ces données dans son ordinateur. Et donc, si nous voulons vraiment réfléchir à ce que nous entendons par big data compte tenu du caractère relatif de la taille, une chose qui est assez cohérente est la définition qui repose sur ce qu’on appelle les trois V du big data : Volume, Vitesse, Variété.

  • Volume : le volume fait référence à la taille des données.

  • Vitesse : cette caractéristique du big data fait référence aux données qui arrivent rapidement dans un système et qui changent fréquemment. Par exemple, plus de 5 milliards de vidéos sont regardées chaque jour sur YouTube. C’est énorme !

  • Variété : cette caractéristique du big data se réfère au fait que les données arrivant dans le système proviennent de sources différentes et sous différents formats (vidéos, photos, audio, textes, données spatiales, etc.).

De par leurs caractéristiques, l’analyse et la modélisation des big data a le potentiel de donner un avantage concurrentiel à une entreprise. De plus, l’utilisation intelligente des big data grâce à la Data Science, au Machine Learning et à l’intelligence artificielle permet aux entreprises de s’adapter dynamiquement en temps réel à leur marché, et pas seulement trimestriellement, mensuellement ou annuellement.

Si l’utilisation appropriée du Big Data présente de nombreux avantages aux organisations/entreprises, il n’en demeurre pas moins qu’elle présente de nombreux défis à relever dont les principaux sont le stockage et la puissance de calcul pour leur traitement. Fort heureusement, il existe des framework performants pour le traitement des big data comme Apache Spark.

1.2. Apache Spark et sparklyr

Apache Spark est un puissant moteur open-source de calcul distribué dédié au traitement de larges volumes de données. Avec Apache Spark, vous pouvez exécuter parallèlement les tâches concernant l’ingénierie des données (Data Engineering), la science des données (Data Science) et l’apprentissage automatique (Machine Learning) sur des machines. Le calcul parallèle, encore appelé calcul distribué, consiste à décomposer une grande tâche en sous-tâches plus petites, puis les répartir entre plusieurs machines et enfin agréger les résultats de chaque machine. Spark est un framework multi-langage, c’est-à-dire qu’il peut s’utiliser à travers plusieurs langages de programmation. Spark possède des interfaces (ou APIs) permettant de l’exécuter avec Scala, Java, SQL, Python et R.

L’interface R de Spark est le package sparklyr qui fait l’objet de ce livre. Sparklyr supporte plusieurs packages connus de l’écosystème R dont dplyr qui est une puissante librairie dédiée à la l’analyse des données. Sparklyr permet :

  • d’interagir avec Apache Spark à l’aide d’interfaces R familières, telles que dplyr, broom et DBI qui est le package permettant de connecter R à des systèmes de gestion de bases de données et de pouvoir ainsi exécuter des requêtes SQL.

  • d’accéder aux bibliothèques d’apprentissage automatique distribuées de Spark comme MLlib, à Structure Streaming et aux pipelines Machine Learning de R.

  • d’étendre votre boîte à outils en ajoutant XGBoost, H2O, Tidymodels à votre analyse Spark plus R.

  • de connecter R partout où Spark s’exécute : Hadoop, Mesos, Kubernetes, Stand Alone et Livy.

  • d’exécuter du code R distribué dans Spark.

Ce livre axé sur pratique vous permettra de comprendre facilement l’utilisation de Apache Spark dans R. Nous allons traiter une problématique concernant la modélisation du risque de crédit en utilisant les fonctionnalités de sparklyr pour l’analyse et la modélisation des données grâce à des algorithmes de Machine Learning.

2. Installation et configuration de l’environnement de travail

2.1. Installer R et RStudio

Au moment où j’écris ce livre, j’utilise la version 4.2.1 de R et la version 2022.07.1 de RStudio. Pour installer R et RStudio dans votre machine, vous pouvez consulter cet article : Comment installer R et RStudio sur son PC ? (Tutoriel complet).

2.2. Installer Java 8

L’installation de sparklyr est très facile que vous utilisez Windows, Mac ou Linux. Tout d’abord, commencez par vérifier si Java 8 est installé dans votre machine en exécutant ce code dans la console de RStudio :

system("java -version")
## [1] 0

Si vous avez une version supérieure ou antérieure à Java 8, je vous conseille de la suppimer et d’installer impérativement Java 8 dans votre machine en suivant les instructions sur cette page web : https://www.java.com/en/download/help/windows_manual_download.html. Assurez-vous aussi que ce soit le chemin de Java 8 qui soit définie comme valeur de la variable environnement JAVA_HOME de votre machine.

2.3. Installer sparklyr et spark

A présent, commençons l’installation de sparklyr. Exécutez le code ci-dessous :

install.packages('sparklyr')

Une fois que l’installation du package est terminée, vous pouvez l’importer :

library(sparklyr)

Trouvez la version de sparklyr en exécutant le code ci-dessous :

packageVersion("sparklyr")
## [1] '1.8.1'

Comme n’importe quel autre framework, plusieurs versions de Spark sont disponibles :

# Versions disponibles de Spark
spark_available_versions()
##    spark
## 1    1.6
## 2    2.0
## 3    2.1
## 4    2.2
## 5    2.3
## 6    2.4
## 7    3.0
## 8    3.1
## 9    3.2
## 10   3.3

A moins que vous ayez des contraintes techniques qui vous forcent à utiliser une version passée de Spark, il est conseillé d’utiliser la dernière version. Donc, à mon niveau je vais installer la version 3.3 qui est la dernière version disponible au moment où j’écris ce livre. Vous pouvez aussi installer cette version dans votre machine ne serait-ce que pour pouvoir reproduire les exemples de ce livre. Par contre, essayez aussi d’installer la dernière version disponible à votre niveau.

spark_install(version = "3.3")

Vous pouvez aussi retrouver les versions de Spark qui sont installées dans votre machine :

spark_installed_versions()
##   spark hadoop                                                              dir
## 1 2.4.3    2.7 C:\\Users\\josue\\AppData\\Local/spark/spark-2.4.3-bin-hadoop2.7
## 2 3.3.0      2   C:\\Users\\josue\\AppData\\Local/spark/spark-3.3.0-bin-hadoop2
## 3 3.3.0      3   C:\\Users\\josue\\AppData\\Local/spark/spark-3.3.0-bin-hadoop3
## 4 3.3.2      2   C:\\Users\\josue\\AppData\\Local/spark/spark-3.3.2-bin-hadoop2

J’ai 3 versions de Spark qui sont installées dans mon PC. Je choisis de les garder toutes. Mais il est possible de supprimer une version de Spark (au cas où vous en avez plusieurs et de très anciennes versions). Le code ci-dessous vous montre comment supprimer une version de Spark :

spark_uninstall(version = "2.3", hadoop = "2.7")

3. Machine Learning

3.1. Intelligence Artificielle et Machine Learning : définitions

L’Intelligence Artificielle, communément désignée par son acronyme IA (ou AI en anglais), est en train de révolutionner profondément notre monde. Elle impacte notre manière de vivre et aussi de travailler et ceci dans presque tous les domaines : Agriculture, Télécom, Énergie, Santé, Industrie, Commerce, Technologies, Transports, etc.

Mais qu’est-ce que réellement l’Intelligence Artificielle ? Qu’est-ce que le Machine Learning ? Globalement, les experts distinguent deux types d’Intelligence Artificielle : L’IA faible et l’IA forte ou généralisée.

L’IA faible est le type d’Intelligence Artificielle où les progrès sont les plus considérables et concrets. Il s’agit de l’IA qui peut effectuer des tâches spécifiques dans des domaines spécifiques en prenant des décisions basées sur des algorithmes entraînés par des données. L’IA faible effectue donc une tâche spécifique. Parmi les tâches que peuvent effectuer l’IA faible à ce jour, nous pouvons citer : le traitement du langage naturel, la détection de visages, la reconnaissance d’images, les voitures autonomes, l’assistance virtuelle, les systèmes de recommandation, etc. Comment l’IA faible peut-elle accomplir ces tâches ? C’est majoritairement grâce à l’Apprentissage Automatique, plus connu sous le nom de Machine Learning.

L’Apprentissage Automatique est un ensemble d’outils basés sur des approches mathématiques et statistiques et qui donnent aux machines la capacité d’apprendre à réaliser une tâche sans être explicitement programmées pour le faire. Par exemple, pour apprendre à un ordinateur à reconnaître un chat, on lui montre plusieurs photos de chat. Le système intègre ces informations en son sein. On le teste ensuite afin de s’assurer qu’il soit capable de distinguer un chat d’un chien par exemple. Pour ce faire, il faut lui montrer des centaines voire des milliers d’images. En effet, plus on dispose de données d’entrées, plus le système apprend mieux et sa performance est élevée. Heureusement, aujourd’hui nous sommes à l’ère du Big Data. Le monde génère chaque jour des milliards de données de tout type. L’exploitation de ces données permet l’entraînement des algorithmes de Machine Learning pour former des modèles prédictifs qui vont conduire au développement d’intelligences artificielles de plus en plus performantes qui nous aident à régler des problèmes de la vie quotidienne.

Il existe déjà plusieurs cas d’apprentissage automatique que nous expérimentons déjà au quotidien et d’autres qui sont en cours de développement et de vulgarisation. On peut citer entres autres :

  • Le classement de nos mails : Par exemple dans la messagerie de Google, nous avons des mails qui viennent dans notre boîte principale, d’autres sont rangés dans la catégorie “Réseaux sociaux” ou “Promotions”. D’autres vont systématiquement dans la catégorie “spam”. Ce n’est pas nous-mêmes qui faisons ce classement. Google a entraîné son système de messagerie à faire ce classement de manière automatique grâce à des modèles de Machine Learning.

  • Les systèmes de reconnaissance d’image : On a entraîné les systèmes à reconnaître une image spécifique. Par exemple, dans les voitures autonomes, le système peut distinguer un panneau stop, une bande piétonne, un feu rouge, etc. Il y a aussi des systèmes de reconnaissance faciale qui peuvent reconnaître le visage d’une personne parmi une multitude d’images.

  • Le diagnostic médical : Sur la base des données de patients, la machine peut dire si un individu est atteint par exemple du cancer.

Il y a d’autres exemples comme les logiciels de traduction de langues, reconnaissance vocale, etc. Les exemples de Machine Learning sont légion et d’autres applications sont créés chaque jour. Il existe deux (02) types majeurs d’apprentissage automatique :

  • Apprentissage supervisé (*Supervised Learning** en anglais) : l’apprentissage supervisé fait les prédictions sur la base de données étiquetées. En apprentissage supervisé on a deux (02) types de problème : les problèmes de Régression, lorsqu’il s’agit de prédire une variable quantitative et les problèmes de Classification, lorsqu’il s’agit de prédire une variable qualitative.

  • Apprentissage non supervisé (Unsupervised Learning en anglais) : Contrairement à l’apprentissage supervisé, le but d’un algorithme d’apprentissage non supervisé est de trouver lui-même des structures (ou relations) sous-jacentes dans les données non étiquetées.

Il existe un autre type de Machine Learning moins populaire qui est l’apprentissage par renforcement.

3.2. Implémenter des techniques de Machine Learning avec R

3.2.1. Initiation à la librairie tidymodels

Dans cette section, je vous présente tidymodels qui est une collections de packages R dédiés au Machine Learning. Il est principalement utilisé pour l’apprentissage automatique supervisé, où les algorithmes apprennent des modèles à partir de données étiquetées.

# Installation de tidymodels
install.packages("tidymodels")

# Installation de tidyverse
install.packages("tidyverse")

# Chargement de tidymodels
library(tidymodels)

# Chargement de tidyverse
library(tidyverse)
  • Tâche de classification

Pour illustrer la démarche méthodologique utilisée dans une tâche de classification, nous allons utiliser le jeu de données iris pour prédire une espèce d’iris en fonction de ses caractéristiques.

head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 

Il n’y pas de valeurs manquantes dans l’ensemble de données iris. Il est important de souligner que pour des ensembles de jeux de données réelles, il faut préalablement passer par une étape de nettoyage et de prétraitement des données avant la phase de modélisation. Nous verrons cela dans la partie 3 où nous construirons des pipelines de Machine Learning en utilisant Spark MLlib.

plot(
  iris$Species, 
  main = "Espèces d'iris"
)

Il n’y a pas de déséquilibre de classe dans l’ensemble de données car il y a le même nombre d’observation pour chacune des 3 espèces d’iris.

La première étape de la phase de modélisation consiste à diviser de manière aléatoire les données d’origine en ensemble de données d’entraînement et de test. Cela permet d’éviter un phénomène connu sous le nom de surajustement (overfitting) où un algorithme de machine learning mémorise les schémas dans l’ensemble de données qui a servi à son entraînement, puis fonctionne mal sur de nouvelles données. Autrement dit, il y a overfitting lorsque le modèle a une bonne performance (la performance est mesurée par la métrique choisie en amont du projet) sur les données d’entraînement et une très mauvaise mauvaise performance sur les données de test. On dit dans ce cas que le modèle ne généralise pas bien. Généralement, 75% des données sont affectées à la formation du modèle et 25% à son évaluation.

# Pour s'assurer de la reproductibilité des résultats :
set.seed(123)

# Objet initial_split()
iris_split <- initial_split(
  iris,
  strata = Species
)

La variable cible est utilisée pour la stratification (strata = Species) afin que sa distribution soit la même dans chacun des deux ensembles (entraînement et test) pour éviter le problème de déséquilibre de classes.

# Ensemble d'entraînement et de test
iris_training <- iris_split %>%
  training()

iris_testing <- iris_split %>%
  testing()

print(nrow(iris_training))
## [1] 111
print(nrow(iris_testing))
## [1] 39
plot(iris_training$Species)

plot(iris_testing$Species)

La stratification par la variable cible (variable à prédire) garantit que le processus d’ajustement du modèle est effectué sur un échantillon représentatif des données d’origine. Nous allons utiliser l’algorithme d’arbre de décision.

  • Arbre de décision

Les modèles de Machine Learning sont considérés comme des boîtes noires ce qui constitue très souvent un frein à leur utilisation dans des cas pratiques en entreprises. En effet, les parties prenantes d’un projet ainsi que les décideurs doivent pouvoir bien comprendre le modèle proposé par le Statisticien ou le Data Scientist afin de l’adopter. Lorsqu’il s’agit d’interprétabilité des modèles de Machine Learning, les arbres de décision sont très attractifs. Ils peuvent être utilisés aussi bien pour des tâches de classification et des tâches de régression. Les arbres de décision sont les composantes fondamentales des forêts aléatoires qui sont parmi les algorithmes de Machine Learning les plus puissants connus à ce jour.

La figure ci-dessous montre un exemple de modèle d’arbre de décision capable de prédire si une patiente, sur la base de ses données médicales, sera atteinte d’un cancer du sein (classe M) ou pas (classe B).

Comme le montre la figure ci-dessus, un modèle d’arbre de décision peut être considéré comme une décomposition des données permettant de prendre une décision sur la base d’une série de questions ou conditions. Les modèles d’arbre de décision fournissent des règles de classification simples qui sont compréhensibles et interprétables.

La question principale qui se pose est de savoir comment effectuer chaque division. L’objectif est de trouver le tuple de sélection optimal à chaque nœud compte tenu de l’objectif final, qui est la classification en catégories discrètes (le processus est presque identique pour les régressions). La technique est très similaire à un problème basé sur une fonction de coût qui doit être minimisée, mais, dans ce cas, nous opérons localement, en appliquant une mesure d’impureté proportionnelle à l’hétérogénéité d’un nœud. L’impureté de Gini est une mesure d’impureté très courante.

L’indice de Gini est basé sur la probabilité d’une mauvaise classification si un point de données est catégorisé à l’aide d’une étiquette choisie au hasard dans la distribution du sous-ensemble de nœuds. Une impureté élevée indique que des échantillons appartenant à de nombreuses catégories différentes sont présents, tandis qu’une impureté égale à 0 indique qu’une seule catégorie est présente. Le tuple de sélection doit être choisi de manière à minimiser l’impureté Gini des branches enfants.

Une autre approche utilisée aussi est l’impureté à entropie croisée . L’objectif de cette approche est aussi la minimisation de l’incertitude mais en utilisant cette fois l’entropie croisée. Dans la plupart du temps, cela ne fait aucune différence d’utiliser l’impureté de Gini ou l’entropie de Gini. Toutefois, vous pouvez déterminer le meilleur choix à partir du réglage des hyperparamètres de votre modèle. Soulignons quand même que l’impureté de Gini est rapide dans le calcul et est souvent la valeur par défaut de l’impureté dans la plupart des algorithmes d’arbres de décision.

# Initialisation du modèle
tree_spec <- decision_tree() %>% 
  set_engine("rpart") %>%  # Spécification du moteur de calcul
  set_mode("classification") # Définition du type de modèle

tree_spec
## Decision Tree Model Specification (classification)
## 
## Computational engine: rpart

Ici, nous utilisons le package rpart comme moteur de calcul qui sera utilisé pour ajuster le modèle.

# Entraînement du modèle
model_trained <- tree_spec %>% 
  fit(
    Species ~ ., 
    data = iris_training
  )

# Affichage du modèle
print(model_trained)
## parsnip model object
## 
## n= 111 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 111 74 setosa (0.33333333 0.33333333 0.33333333)  
##   2) Petal.Length< 2.45 37  0 setosa (1.00000000 0.00000000 0.00000000) *
##   3) Petal.Length>=2.45 74 37 versicolor (0.00000000 0.50000000 0.50000000)  
##     6) Petal.Width< 1.75 40  4 versicolor (0.00000000 0.90000000 0.10000000) *
##     7) Petal.Width>=1.75 34  1 virginica (0.00000000 0.02941176 0.97058824) *
# Prédictions

predictions <- predict(
  model_trained,
  new_data = iris_testing
)

head(predictions)
## # A tibble: 6 × 1
##   .pred_class
##   <fct>      
## 1 setosa     
## 2 setosa     
## 3 setosa     
## 4 setosa     
## 5 setosa     
## 6 setosa

Ajoutons les vraies valeurs de la variable cible et créons une matrice de confusion :

predictions_combined <- predictions %>% 
  mutate(true_class = iris_testing$Species)

head(predictions_combined)
## # A tibble: 6 × 2
##   .pred_class true_class
##   <fct>       <fct>     
## 1 setosa      setosa    
## 2 setosa      setosa    
## 3 setosa      setosa    
## 4 setosa      setosa    
## 5 setosa      setosa    
## 6 setosa      setosa
# Matrice de confusion

diabetes_matrix <- conf_mat(
  data = predictions_combined,
  estimate = .pred_class,
  truth = true_class
)

diabetes_matrix
##             Truth
## Prediction   setosa versicolor virginica
##   setosa         13          0         0
##   versicolor      0         13         1
##   virginica       0          0        12

Il existe plusieurs fonctions dans le package yardstick pour cacluler des métriques d’évaluation de modèles de Machine Learning. Ce package fait partie des packages de la librairie tidymodels. Parmi les métriques utilisées pour évaluer les modèles de classification, il y a la précision de la classification (Accuracy en anglais). La précision de la classification est le pourcentage d’instances correctement classées.

library(yardstick)
# Score global du modèle

acc <- accuracy(
  predictions_combined,
  estimate = .pred_class,
  truth = true_class
)

acc
## # A tibble: 1 × 3
##   .metric  .estimator .estimate
##   <chr>    <chr>          <dbl>
## 1 accuracy multiclass     0.974
acc$.estimate
## [1] 0.974359
  • Tâche de régression

Un modèle de régression décrit une variable dépendante continue y comme étant une combinaison linéaire de différents prédicteurs x (variables indépendantes).

La méthode la plus simple pour estimer les paramètres du modèle est la méthode des moindres carrés. Les moindres carrés consistent à minimiser la somme des carrés des différences entre la variable dépendante observée (valeurs de la variable observée) dans l’ensemble de données donné et celles prédites par la fonction linéaire de la variable indépendante.

La démarche en régression est pratiquement la même que pour une tâche de classification. Ici, nous utiliserons le jeu de données mpg qui contient des données sur l’efficacité énergétique de plus de 200 voitures populaires.

head(mpg)
## # A tibble: 6 × 11
##   manufacturer model displ  year   cyl trans      drv     cty   hwy fl    class 
##   <chr>        <chr> <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr> 
## 1 audi         a4      1.8  1999     4 auto(l5)   f        18    29 p     compa…
## 2 audi         a4      1.8  1999     4 manual(m5) f        21    29 p     compa…
## 3 audi         a4      2    2008     4 manual(m6) f        20    31 p     compa…
## 4 audi         a4      2    2008     4 auto(av)   f        21    30 p     compa…
## 5 audi         a4      2.8  1999     6 auto(l5)   f        16    26 p     compa…
## 6 audi         a4      2.8  1999     6 manual(m5) f        18    26 p     compa…
# Tableau de corrélations
mpg_corr <- mpg %>%
  select_if(is.numeric) %>%
  cor() %>%
  round(2)

mpg_corr
##       displ  year   cyl   cty   hwy
## displ  1.00  0.15  0.93 -0.80 -0.77
## year   0.15  1.00  0.12 -0.04  0.00
## cyl    0.93  0.12  1.00 -0.81 -0.76
## cty   -0.80 -0.04 -0.81  1.00  0.96
## hwy   -0.77  0.00 -0.76  0.96  1.00
library(ggcorrplot)
# Corrélations

cor_plot <- ggcorrplot(
  corr = mpg_corr,
  hc.order = TRUE,
  type = "lower",
  lab_size = 3,
  colors = c("red", "white", "green"),
  title = "Matrice de corrélation",
  ggtheme = theme_bw()
)

cor_plot

Construisons un modèle de prédiction de la variable hwy qui représente la consommation moyenne de la voiture sur l’autoroute exprimée en miles par gallon.

# Objet initial_split()
mpg_split <- initial_split(
  mpg,
  prop = 0.75,
  strata = hwy
)

# Ensemble d'entraînement
mpg_training <- training(mpg_split)
print(nrow(mpg_training))
## [1] 173
# Ensemble de test
mpg_testing <- testing(mpg_split) 
print(nrow(mpg_testing))
## [1] 61
# Initialisation de l'algorithme
lm_model <- linear_reg() %>%
  set_engine("lm") %>%
  set_mode("regression")

# Entraînement du modèle
lm_fit <- lm_model %>%
  fit(hwy ~ displ + cyl + cty, 
      data = mpg_training)

print(lm_fit)
## parsnip model object
## 
## 
## Call:
## stats::lm(formula = hwy ~ displ + cyl + cty, data = data)
## 
## Coefficients:
## (Intercept)        displ          cyl          cty  
##     -0.7404      -0.3022       0.3384       1.3739
# Obtention des paramètres du modèle
tidy(lm_fit)
## # A tibble: 4 × 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)   -0.740    1.77      -0.418 6.76e- 1
## 2 displ         -0.302    0.292     -1.04  3.02e- 1
## 3 cyl            0.338    0.240      1.41  1.61e- 1
## 4 cty            1.37     0.0585    23.5   3.93e-55
# Prédictions
hwy_preds <- lm_fit %>%
  predict(new_data = mpg_testing) %>%
  mutate(true_hwy = mpg_testing$hwy)

head(hwy_preds)
## # A tibble: 6 × 2
##   .pred true_hwy
##   <dbl>    <int>
## 1  24.8       29
## 2  28.9       30
## 3  22.4       26
## 4  24.8       26
## 5  22.1       25
## 6  26.1       27

Les valeurs de la colonne .pred semblent raisonnables.

Parmi les métriques d’évaluation des modèles de régression, il y a l’erreur quadratique moyenne (RMSE : Root Mean Squared Error).

# Calcul de RMSE
rmse <- rmse(
  hwy_preds,
  estimate = .pred,
  truth = true_hwy
)

rmse$.estimate
## [1] 1.547823

On peut dire que l’erreur de prédiction moyenne de notre modèle est d’environ 1,78 miles par gallon pour les valeurs estimées d’efficacité énergétique.

Pour rationaliser le processus d’ajustement et d’évaluation d’un modèle, vous pouvez utiliser la fonction last_fit() de tidymodels. Cette fonction crée des ensembles de données d’entraînement et de test, adapte le modèle aux données d’entraînement, calcule les métriques et les prédictions sur les données de test et renvoie un objet avec tous les résultats.

lm_last_fit <- lm_model %>%
  last_fit(hwy ~ displ + cyl + cty, 
           split = mpg_split)
lm_last_fit$.metrics
## [[1]]
## # A tibble: 2 × 4
##   .metric .estimator .estimate .config             
##   <chr>   <chr>          <dbl> <chr>               
## 1 rmse    standard       1.55  Preprocessor1_Model1
## 2 rsq     standard       0.939 Preprocessor1_Model1
# Récupération des métriques sur les données de test
lm_last_fit %>%
  collect_metrics()
## # A tibble: 2 × 4
##   .metric .estimator .estimate .config             
##   <chr>   <chr>          <dbl> <chr>               
## 1 rmse    standard       1.55  Preprocessor1_Model1
## 2 rsq     standard       0.939 Preprocessor1_Model1

Nous obtenons les mêmes mesures de performance sur les données de test mpg_test qu’auparavant, mais avec beaucoup moins de travail. Notez que la métrique rsq est le coefficient de détermination (R²).

Nous pouvons aussi récupérer les prédictions :

# Récupération des prédictions sur les données de test
lm_last_fit %>%
  collect_predictions() %>%
  head()
## # A tibble: 6 × 5
##   id               .pred  .row   hwy .config             
##   <chr>            <dbl> <int> <int> <chr>               
## 1 train/test split  24.8     1    29 Preprocessor1_Model1
## 2 train/test split  28.9     4    30 Preprocessor1_Model1
## 3 train/test split  22.4     5    26 Preprocessor1_Model1
## 4 train/test split  24.8     8    26 Preprocessor1_Model1
## 5 train/test split  22.1     9    25 Preprocessor1_Model1
## 6 train/test split  26.1    11    27 Preprocessor1_Model1

La fonction last_fit est très intéressante en ce sens où elle condense toutes les étapes de la modélisation. C’est une sorte de pipeline. Dans la section 4.4 , nous verrons comment automatiser les workflow en Data Science en construisant des pipelines de Machine Learning grâce à la puissance de Spark MLlib.

3.2.2. Intégration de tidymodels dans Spark

Dans le chapitre 2 concernant l’installation et la configuration de l’environnement de travail, vous avez appris à installer spark et sparklyr dans votre machine. Mais pour utiliser spark vous devez vous connecter à un cluster. Je précise que dans le cadre de ce livre, nous allons utiliser un cluster spark local. Néanmoins, il est possible de se connecter à un cluster en ligne notamment dans le Cloud.

# Connection au cluster local de Spark
sc <- spark_connect(master = "local", version = "3.0")

Commençons par copier l’ensemble de données mpg dans notre cluster local Spark en utilisant la fonction copy_to() :

spark_mpg <- copy_to(sc, mpg)
head(spark_mpg)
## # Source: spark<?> [?? x 11]
##   manufacturer model displ  year   cyl trans      drv     cty   hwy fl    class 
##   <chr>        <chr> <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr> 
## 1 audi         a4      1.8  1999     4 auto(l5)   f        18    29 p     compa…
## 2 audi         a4      1.8  1999     4 manual(m5) f        21    29 p     compa…
## 3 audi         a4      2    2008     4 manual(m6) f        20    31 p     compa…
## 4 audi         a4      2    2008     4 auto(av)   f        21    30 p     compa…
## 5 audi         a4      2.8  1999     6 auto(l5)   f        16    26 p     compa…
## 6 audi         a4      2.8  1999     6 manual(m5) f        18    26 p     compa…

Construisons un modèle de régression pour prédire la variable hwy en utilisant cette fois-ci un moteur Spark :

mpg_model <- linear_reg() %>%
  set_engine("spark") %>%
  set_mode("regression") %>%
  fit(hwy ~ displ + cyl + cty, 
      data = spark_mpg)

mpg_model
## parsnip model object
## 
## Formula: hwy ~ displ + cyl + cty
## 
## Coefficients:
## (Intercept)       displ         cyl         cty 
##   0.0347868  -0.3430756   0.3127413   1.3497128
# Performance du modèle
glance(mpg_model)
## # A tibble: 1 × 5
##   explained.variance mean.absolute.error mean.squared.error r.squared root.mea…¹
##                <dbl>               <dbl>              <dbl>     <dbl>      <dbl>
## 1               32.3                1.35               3.01     0.915       1.74
## # … with abbreviated variable name ¹​root.mean.squared.error

Intégrer Spark et tidymodels est très simple. Tout ce que vous avez à faire est de spéfier “spark” comme moteur de calcul (set_engine("spark")) dans l’initialisation de votre modèle. Une fois que vous avez obtenu le modèle, vous pouvez réaliser toutes les étapes de la section 3.2.1

4. Projet réel : Analyse et modélisation du risque de crédit (Credit Scoring) avec Spark

La meilleure manière d’apprendre de nouvelles compétences en Data Science est de réaliser un projet de bout en bout. So, let’s go!

4.1. Compréhension de la problématique business

Lorsqu’une banque prête de l’argent à une personne, elle prend le risque que cette dernière ne rembourse pas cet argent dans le délai convenu. Ce risque est appelé Risque de Crédit. Alors avant d’octroyer un crédit, les banques vérifient si le client (ou la cliente) qui demandent un prêt sera capable ou pas de le rembourser. Cette vérification se fait grâce à l’analyse de plusieurs paramètres tels que les revenus, les biens, les dépenses actuelles du client, etc. Cette analyse est encore effectuée manuellement par plusieurs banques. Ainsi, elle est très consommatrice en temps et en ressources financières.

Grâce au Machine Learning, il est possible d’automatiser cette tâche et de pouvoir prédire avec plus de précision les clients qui seront en défaut de paiement.

Dans ce projet, nous allons construire un modèle capable de prédire si une personne sera en défaut de paiement ou pas (1 : défaut, 0 : non-défaut). Il s’agit donc d’un problème de classification car nous voulons prédire une variable discrète (binaire pour être précis).

En ce qui concerne les données, il s’agit des informations collectées sur d’anciens clients ayant contracté des prêts qui sont utilisées pour prédire le comportement des nouveaux clients.

Deux (02) types de données peuvent être utilisés pour modéliser la probabilité de défaut de paiement :

Données liées à la demande de crédit ;

Données comportementales décrivant le bénéficiaire du prêt.

Dans la pratique, les banques utilisent un mélange de ces deux types de données pour construire leur modèle de scoring appliqué à la gestion du risque de crédit.

4.2. Importation des données

4.2.1. Les données

Les données que nous utiliserons pour illustrer les fonctionnalités de sparklyr proviennent de Kaggle qui est la plus célèbre plateforme de compétitions en Data Science. Téléchargez ces données en cliquant ici

# Importation des données
df <- spark_read_csv(
  sc = sc,
  name = "credit_risk_dataset",
  path = 'credit_risk_dataset.csv', # Chemin du fichier csv des données
  header = TRUE,
  infer_schema = TRUE,
  delimiter = ","
)

N.B : Pour ne pas avoir des coucis de chemin de vos données, placez le fichier csv dans le répertoire principal de votre script R.

class(df)
## [1] "tbl_spark" "tbl_sql"   "tbl_lazy"  "tbl"

df n’est pas un objet R. Il s’agit d’une table Spark. Mais fort heureusement, nous pouvons lui appliquer certaines fonctions de R et surtout de dplyr.

# Affichage des cinq premières observations
df %>%
  head()
## # Source: spark<?> [?? x 12]
##   person_age person_in…¹ perso…² perso…³ loan_…⁴ loan_…⁵ loan_…⁶ loan_…⁷ loan_…⁸
##        <int>       <int> <chr>     <dbl> <chr>   <chr>     <int>   <dbl>   <int>
## 1         22       59000 RENT        123 PERSON… D         35000   16.0        1
## 2         21        9600 OWN           5 EDUCAT… B          1000   11.1        0
## 3         25        9600 MORTGA…       1 MEDICAL C          5500   12.9        1
## 4         23       65500 RENT          4 MEDICAL C         35000   15.2        1
## 5         24       54400 RENT          8 MEDICAL C         35000   14.3        1
## 6         21        9900 OWN           2 VENTURE A          2500    7.14       1
## # … with 3 more variables: loan_percent_income <dbl>,
## #   cb_person_default_on_file <chr>, cb_person_cred_hist_length <int>, and
## #   abbreviated variable names ¹​person_income, ²​person_home_ownership,
## #   ³​person_emp_length, ⁴​loan_intent, ⁵​loan_grade, ⁶​loan_amnt, ⁷​loan_int_rate,
## #   ⁸​loan_status
# Structure de la table
df %>%
  glimpse()
## Rows: ??
## Columns: 12
## Database: spark_connection
## $ person_age                 <int> 22, 21, 25, 23, 24, 21, 26, 24, 24, 21, 22,…
## $ person_income              <int> 59000, 9600, 9600, 65500, 54400, 9900, 7710…
## $ person_home_ownership      <chr> "RENT", "OWN", "MORTGAGE", "RENT", "RENT", …
## $ person_emp_length          <dbl> 123, 5, 1, 4, 8, 2, 8, 5, 8, 6, 6, 2, 2, 4,…
## $ loan_intent                <chr> "PERSONAL", "EDUCATION", "MEDICAL", "MEDICA…
## $ loan_grade                 <chr> "D", "B", "C", "C", "C", "A", "B", "B", "A"…
## $ loan_amnt                  <int> 35000, 1000, 5500, 35000, 35000, 2500, 3500…
## $ loan_int_rate              <dbl> 16.02, 11.14, 12.87, 15.23, 14.27, 7.14, 12…
## $ loan_status                <int> 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0…
## $ loan_percent_income        <dbl> 0.59, 0.10, 0.57, 0.53, 0.55, 0.25, 0.45, 0…
## $ cb_person_default_on_file  <chr> "Y", "N", "N", "N", "Y", "N", "N", "N", "N"…
## $ cb_person_cred_hist_length <int> 3, 2, 3, 2, 4, 2, 3, 4, 2, 3, 4, 2, 2, 4, 4…
# Nombre d'observations
sdf_nrow(df)
## [1] 32581

L’ensemble des données compte 12 variables et 32581 observations (lignes) historiques. Chaque observation correspond à une personne ayant contracté un prêt. On a des variables qui décrivent le prêt (montant, statut, taux d’intérêt, etc.) et d’autres variables qui décrivent la personne ayant contracté ce prêt (age, revenu, etc.). Nous allons donc utiliser ces données historiques afin de construire le modèle de scoring qui va prédire le statut des nouveaux candidats à un crédit.
Il est très important de comprendre les variables de notre jeu de données :

  • person_age : variable indiquant l’âge de la personne ;

  • person_income : variable indiquant le revenu annuel (ou encore le salaire) de la personne ;

  • person_home_ownership : variable indiquant le statut de la personne par rapport à son lieu d’habitation (popriétaire, locataire, etc.) ;

  • person_emp_length : variable indiquant la durée (en mois) depuis laquelle la personne est en activité professionnelle ;

  • loan_intent : variable indiquant le motif du crédit ;

  • loan_grade : Notation de la solvabilité du client. classes de A à G avec A indiquant la classe de solvabilité la plus élevée et G la plus basse ;

  • loan_amnt : variable indiquant le montant du prêt ;

  • loan_int_rate : variable indiquant le taux d’intérêt du crédit ;

  • loan_status : c’est la variable d’intérêt. Elle indique si la personne est en défaut de paiement (1) ou pas (0) ;

  • loan_percent_income : variable indiquant le pourcentage du crédit par rapport au revenu (ratio dette / revenu) ;

  • cb_person_default_on_file : variable indiquant si la personne a été en défaut de paiement ou pas dans le passé ;

  • cb_person_cred_hist_length : variable indiquant la durée des antécédents de crédits.

4.2.2. dplyr VS SQL

Il est important de souligner qu’avec sparklyr, vous pouvez utiliser SQL ou dplyr pour manipuler vos données. Mais dplyr permet d’écrire moins de code et il est plus facile et consistant que SQL. Par exemple, le code dplyr ci-dessous permet de sélectionner les vaiables numériques et de calculer leur médiane :

# Moyenne de chaque variable numérique
df %>%
  select_if(is.numeric) %>%
  summarise_all(median, na.rm = TRUE)
## # Source: spark<?> [?? x 8]
##   person_age person_income person_emp_…¹ loan_…² loan_…³ loan_…⁴ loan_…⁵ cb_pe…⁶
##        <dbl>         <dbl>         <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
## 1         26         55000             4    8000    11.0       0    0.15       4
## # … with abbreviated variable names ¹​person_emp_length, ²​loan_amnt,
## #   ³​loan_int_rate, ⁴​loan_status, ⁵​loan_percent_income,
## #   ⁶​cb_person_cred_hist_length
library(DBI)

Pour obtenir le même résultat en SQL, on doit écrire :

query = "SELECT
  AVG(`person_age`) AS `person_age`,
  AVG(`person_income`) AS `person_income`,
  AVG(`person_emp_length`) AS `person_emp_length`,
  AVG(`loan_amnt`) AS `loan_amnt`,
  AVG(`loan_int_rate`) AS `loan_int_rate`,
  AVG(`loan_status`) AS `loan_status`,
  AVG(`loan_percent_income`) AS `loan_percent_income`,
  AVG(`cb_person_cred_hist_length`) AS `cb_person_cred_hist_length`
FROM (
  SELECT
    `person_age`,
    `person_income`,
    `person_emp_length`,
    `loan_amnt`,
    `loan_int_rate`,
    `loan_status`,
    `loan_percent_income`,
    `cb_person_cred_hist_length`
  FROM `credit_risk_dataset`
) "

dbGetQuery(sc, query)
##   person_age person_income person_emp_length loan_amnt loan_int_rate
## 1    27.7346      66074.85          4.789686  9589.371      11.01169
##   loan_status loan_percent_income cb_person_cred_hist_length
## 1    0.218164           0.1702035                   5.804211

Cette petite démonstration montre que le code dplyr est beaucoup plus simple et consistant que le code SQL. De plus, vous pouvez retrouver la requête SQL équivalente à un code dplyr en utilisant la fonction show_query() de dplyr :

df %>%
  select_if(is.numeric) %>%
  summarise_all(mean, na.rm = TRUE)
## # Source: spark<?> [?? x 8]
##   person_age person_income person_emp_…¹ loan_…² loan_…³ loan_…⁴ loan_…⁵ cb_pe…⁶
##        <dbl>         <dbl>         <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
## 1       27.7        66075.          4.79   9589.    11.0   0.218   0.170    5.80
## # … with abbreviated variable names ¹​person_emp_length, ²​loan_amnt,
## #   ³​loan_int_rate, ⁴​loan_status, ⁵​loan_percent_income,
## #   ⁶​cb_person_cred_hist_length
df %>%
  select_if(is.numeric) %>%
  summarise_all(mean, na.rm = TRUE) %>%
  show_query()
## <SQL>
## SELECT
##   AVG(`person_age`) AS `person_age`,
##   AVG(`person_income`) AS `person_income`,
##   AVG(`person_emp_length`) AS `person_emp_length`,
##   AVG(`loan_amnt`) AS `loan_amnt`,
##   AVG(`loan_int_rate`) AS `loan_int_rate`,
##   AVG(`loan_status`) AS `loan_status`,
##   AVG(`loan_percent_income`) AS `loan_percent_income`,
##   AVG(`cb_person_cred_hist_length`) AS `cb_person_cred_hist_length`
## FROM (
##   SELECT
##     `person_age`,
##     `person_income`,
##     `person_emp_length`,
##     `loan_amnt`,
##     `loan_int_rate`,
##     `loan_status`,
##     `loan_percent_income`,
##     `cb_person_cred_hist_length`
##   FROM `credit_risk_dataset`
## ) `q01`

La plupart des opérations de transformation de données mises à disposition par dplyr pour fonctionner avec des DataFrames locales peuvent également être utilisées avec une connexion Spark. Cela signifie que vous pouvez d’abord vous concentrer sur l’apprentissage de dplyr, puis réutiliser cette compétence lorsque vous travaillez avec Spark.

4.3. Analyse exploratoire des données

Passons à présent à l’analyse exploratoire des données qui nous permettra de mieux les comprendre.

# Résumé statistique
sdf_describe(df)
## # Source: spark<?> [?? x 13]
##   summary person_age     perso…¹ perso…² perso…³ loan_…⁴ loan_…⁵ loan_…⁶ loan_…⁷
##   <chr>   <chr>          <chr>   <chr>   <chr>   <chr>   <chr>   <chr>   <chr>  
## 1 count   32581          32581   32581   31686   32581   32581   32581   29465  
## 2 mean    27.7345999201… 66074.… <NA>    4.7896… <NA>    <NA>    9589.3… 11.011…
## 3 stddev  6.34807841922… 61983.… <NA>    4.1426… <NA>    <NA>    6322.0… 3.2404…
## 4 min     20             4000    MORTGA… 0.0     DEBTCO… A       500     5.42   
## 5 max     144            6000000 RENT    123.0   VENTURE G       35000   23.22  
## # … with 4 more variables: loan_status <chr>, loan_percent_income <chr>,
## #   cb_person_default_on_file <chr>, cb_person_cred_hist_length <chr>, and
## #   abbreviated variable names ¹​person_income, ²​person_home_ownership,
## #   ³​person_emp_length, ⁴​loan_intent, ⁵​loan_grade, ⁶​loan_amnt, ⁷​loan_int_rate
  • Nous remarquons que les moyennes et les écart-types sont très différents d’une variable à une autre. Cela indique que les données ne sont pas à la même échelle. Il faudra probablement normaliser les données avant de les modéliser. en effet, certains algoritmes de Machine Learning nécessitent une normalisation des données pour un meilleur résultat.

  • De plus, il y a des valeurs manquantes au niveau des variables person_emp_length et loan_int_rate. Ces deux variables contiennent probablement des valeurs aberantes vu la différence très importante entre leur 3è quartile et leur maximum. Les valeurs aberantes sont très distantes des autres valeurs et ne sont donc pas représentatives de l’ensemble des données. Elles peuvent causer d’importatantes erreurs de modélisation.

Dans la partie consacrée au nettoyage des données, nous aurons principalement à traiter les valeurs aberrantes (outliers) et les valeurs manquantes.

Passons maintenat à l’analyse de la variable cible (loan_status).

# Variable cible
df %>%
  group_by(loan_status) %>%
  tally() %>%
  mutate(fraction = n / sum(n))
## Warning: Missing values are always removed in SQL aggregation functions.
## Use `na.rm = TRUE` to silence this warning
## This warning is displayed once every 8 hours.
## # Source: spark<?> [?? x 3]
##   loan_status     n fraction
##         <int> <dbl>    <dbl>
## 1           1  7108    0.218
## 2           0 25473    0.782
ggplot(df, aes(loan_status)) +
  geom_histogram(na.rm = TRUE)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Ces résultats montrent qu’il y un déséquilibre de classe très importants dans les données. En effet, seulement environ 22% de clients sont en défaut de paiement contre un peu plus de 78% de bons clients.

Le déséquilibre de classe est souvent observé dans les données de crédit. la majorité des demandeurs de crédit sont incités à ne pas être en défaut de paiement car plus ils remboursent le crédit dans les délais, plus leurs scores de crédit augmentent et donc ils peuvent à nouveau emprunter pour effectuer d’autres investissements.

Si le déséquilibre observé ici est tout à fait normal, il n’en demeurre moins que cela représente un grand défi de performance pour les algorithmes de Machine Learning.

Analysons à présent les corrélations entre chaque variable indépendante et la variable cible.

# Fonction de contruction d'un graphique montrant la relation 
    #entre une variable indépendante numérique et la variable cible

show_relation <- function(feature) {
  df %>%
    ggplot(aes(x = "", y = {{ feature }}, fill = as.factor(loan_status))) +
    geom_boxplot(na.rm = TRUE) +
    xlab("") +
    guides(fill = guide_legend(title = "loan_status"))
}
col_names <- quos(
  person_age, person_income, 
  person_emp_length, 
  loan_amnt, loan_int_rate, 
  loan_percent_income, 
  cb_person_cred_hist_length
)

map(col_names, show_relation)
## [[1]]

## 
## [[2]]

## 
## [[3]]

## 
## [[4]]

## 
## [[5]]

## 
## [[6]]

## 
## [[7]]

A partir de ces graphiques, nous pouvons tirer les conclusions ci-dessous :

  • Le ratio moyen dette/revenu (variable loan_percent_income) est plus élevé chez les clients en défaut de paiement que chez les bons clients. En effet, lorsque le ration dette / revenu est très élévé, cela veut dire tout simplement que le crédit est trop élevé par rapport aux revenus de la personne. Et lorsqu’une personne a un crédit trop élevé par rapport à ses revenus, le risque qu’elle soit en défaut de paiement est logiquement et naturellement important.

  • Les personnes qui ont été en défaut de paiement ont en moyenne un montant de crédit (variable loan_amnt) plus élevé que les autres.

  • Les personnes qui ont été en défaut de paiement ont en moyenne un revenu annuel (variable *person_income) inférieur à celui des bons emprunteurs.

  • Les personnes en défaut de paiement ont en moyenne un taux d’intérêt plus élevé que les personnes qui ne sont pas en défaut de paiement. Ce résultat vient confirmer les résultats précédents sur le comportement des personnes en défaut de paiement. En effet, nous avons vu que ces personnes empruntent beaucoup plus de grosses sommes que les autres donc des crédits à forts taux d’intérêt.

  • Il apparaît que les personnes en défaut de paiement ont en moyenne une durée d’activité professionnelle inférieure à celle des autres.

  • Il semble que l’âge n’a aucune influence sur le remboursement ou non d’un crédit.

Construisons l’histogramme de la variable indiquant le montant du crédit :

# Histogramme du montant du crédit
df %>%
  ggplot(aes(x = loan_amnt)) +
  geom_histogram(na.rm = TRUE) +
  ggtitle(label = "Montant du crédit")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

D’après le graphique ci-dessus, la distribution variable indiquant le montant du crédit est asymétrique positive (étalée vers la droite donc ne suit probablement pas une loi normale.

Plusiuers algorithmes de Machine Learning sont conçus pour fonctionner avec des données gaussiennes. Donc, pour ne pas avoir des résultats biaisés, il est indispensable de vérifier l’asymétrie de chaque variable quantitative et d’effectuer si besoin une transformation de variable avant la phase de modélisation.

Il est intéressant de visualiser la distribution de la variable indiquant le montant du crédit chez les personnes en défaut de paiement et chez les autres afin de pouvoir effectuer une comparaison.

# Histogramme de 'loan_amnt' discrétisé par 'loan_status'

ggplot(df, aes(x=loan_amnt)) +
  geom_histogram(color="red", fill="red", bins=50) +
  facet_wrap(~ loan_status, scales="free", ncol=2)

Les deux histogrammes semblent être identiques mais en observant très bien on constate on remarque par exemple que les barres au niveau des montants très élevés sont plus longues chez les personnes en défaut de paiement que chez les autres. Cela veut dire qu’il y a beaucoup plus de personnes en défaut de paiement qui ont emprunté de grosses sommes d’argent en comparaison aux personnes qui ne sont pas en défaut de paiement.

# Histogramme des revenus annuels
df %>%
  ggplot(aes(x = person_income)) +
  geom_histogram() +
  ggtitle(label = "Histogramme du Revenu annuel")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

L’histogramme des revenus annuels a une seule grande barre ce qui montre qu’il y a une certaine anomalie au niveau des valeurs de cette variable. En effet, le résumé statistique de la variable person_income ainsi que son histogramme révèlent la présence de valeurs aberrantes (outliers) au niveau de cette variable. Nous pouvons aussi voir ces ouliers en traçant un nuage de points :

# Revenu annuel

df %>%
  ggplot(aes(y = person_income)) +
  geom_boxplot() +
  ylab("Revenu annuel")

Le graphique ci-dessus confirme bel et bien la présence de valeurs aberrantes au niveau de la variable indiquant le revenu annuel. Il y a un salaire énorme de 6 millions de dollars alors que le salaire médian est de 55000$.

df %>%
  ggplot(aes(x = loan_int_rate)) +
  geom_histogram(na.rm = TRUE) +
  ggtitle(label = "Taux d'intérêt du crédit")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Tous les crédits ont un taux d’intérêt supérieur à 5% et très peu de crédits ont un taux d’intérêt supérieur à 20%.

# Variable 'person_home_ownership'

df %>%
    ggplot(aes(x=person_home_ownership, fill = person_home_ownership)) +
    geom_bar() 

# person_home_ownership discrétisée selon le statut du crédit

df %>%
    ggplot(aes(x=person_home_ownership, fill = person_home_ownership)) +
    geom_bar() +
    theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
    facet_wrap(~ loan_status, scales = "free", ncol = 2)

# Motif de l'emprunt

df %>%
  ggplot(aes(x=loan_intent, fill = loan_intent)) +
  geom_bar() +
  coord_flip()

# Motif de l'emprunt discrétisé selon la variable cible

df %>%
  ggplot(aes(x=loan_intent, fill = loan_intent)) +
  geom_bar() +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
  facet_wrap(~ loan_status, scales = "free", ncol = 2)

Ceux qui ont été en défaut de paiement empruntent majoritairement pour motif médical alors que les autres empruntent majoritairement pour motif d’éducation.

L’analyse exploratoire réalisée avec ggplot2 et dplyr prouve davantage qu’on peut utiliser les fonctionnalités de la suite Tidyverse pour manipuler les objets tbl_spark. Si vous voulez maîtriser la visualisation des données avec ggplot2, je vous recommande ma formation gratuite Visualisation avancée et interactive avec ggplot2 et plotly

Bien que les visualisations soient indispensables, vous pouvez compléter l’analyse des données à l’aide de modèles statistiques pour obtenir des informations encore plus approfondies sur nos données. Avant d’aborder le Machine Learning avec Spark, vous devez d’abord comprendre ses notions fondamentales. Ainsi, dans la section suivante, je vous introduit les concepts fondamentaux du Machine Learning avec R.

4.4. Pipelines de Machine Learning avec Spark

Les pipelines ML de Spark permettent de combiner facilement plusieurs transformations et algorithmes de ML en un seul workflow, ou pipeline. En outre, un pipeline facilite également la collaboration entre les équipes de Data Science et de Big Data Engineering en ce sens qu’ils permettent de déployer efficacement des modèles dans des systèmes de production, des applications Web, des applications mobiles, etc.

Pour illustrer cette section,reprenons l’ensemble de données sur le risque de crédit.

# Nombre de valeurs manquantes par colonne
df %>%
  mutate_all(is.na) %>%
  mutate_all(as.numeric) %>%
  summarise_all(sum) %>%
  collect() # pour retourner le résultat sous forme de tibble
## # A tibble: 1 × 12
##   person_age person_in…¹ perso…² perso…³ loan_…⁴ loan_…⁵ loan_…⁶ loan_…⁷ loan_…⁸
##        <dbl>       <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
## 1          0           0       0     895       0       0       0    3116       0
## # … with 3 more variables: loan_percent_income <dbl>,
## #   cb_person_default_on_file <dbl>, cb_person_cred_hist_length <dbl>, and
## #   abbreviated variable names ¹​person_income, ²​person_home_ownership,
## #   ³​person_emp_length, ⁴​loan_intent, ⁵​loan_grade, ⁶​loan_amnt, ⁷​loan_int_rate,
## #   ⁸​loan_status
# Données d'entraînement et de test

seed = 42

data_splits <- sdf_random_split(
  df,
  training = 0.8,
  testing = 0.2,
  seed = seed
)

train <- data_splits$training
test <- data_splits$testing
# Vérification de la distribution de la variable cible au niveau de chaque ensemble

train %>%
  group_by(loan_status) %>%
  tally() %>%
  mutate(fraction = n / sum(n))
## # Source: spark<?> [?? x 3]
##   loan_status     n fraction
##         <int> <dbl>    <dbl>
## 1           1  5730    0.220
## 2           0 20362    0.780
test %>%
  group_by(loan_status) %>%
  tally() %>%
  mutate(fraction = n / sum(n))
## # Source: spark<?> [?? x 3]
##   loan_status     n fraction
##         <int> <dbl>    <dbl>
## 1           1  1378    0.212
## 2           0  5111    0.788

La variable cible loan_status a la même distribution dans les ensembles d’entraînement et de test.

4.4.1. Construction d’un pipeline

Un pipeline Spark est composé d’étapes de Transformateurs (commençant souvent par ft_) et d’estimateurs (commençant souvent par ml_) qui sont des algorithmes de Machine Learning. Comme transformateurs, il y a par exemple l’imputation des valeurs manquantes, la transformation de variables catégorielles en variables numériques, la standardisation, etc.

Pour cosntruire un pipeline Spark, vous pouvez initialiser un objet pipeline avec la fonction ml_pipeline() puis ajouter sucessivement les étapes de transformation qui vous permettront de partir des données brutes jusqu’à l’obtention d’un ensemble de données propres. La dernière étape du pipeline est celle de l’estimateur qui sera appliqué aux données transformées.

# Pipeline

pipeline <- ml_pipeline(sc) %>%
  
  # imputation des valeurs manquantes par la médiane
  ft_imputer(
    input_cols = c("person_emp_length", 
                   "loan_int_rate"),
    output_cols = c("imputer_person_emp_length", 
                    "imputer_loan_int_rate"),
    strategy = "median"
  ) %>%
  
  # transformation des variables catégorielles en variables numériques
  ft_string_indexer(
    input_col = "person_home_ownership", 
    output_col = "person_home_ownership_indexed"
  ) %>%
  ft_string_indexer(
    input_col = "loan_intent", 
    output_col = "loan_intent_indexed"
  ) %>%
  ft_string_indexer(
    input_col = "loan_grade", 
    output_col = "loan_grade_indexed"
  ) %>%
  ft_string_indexer(
    input_col = "cb_person_default_on_file", 
    output_col = "cb_person_default_on_file_indexed"
  ) %>%
  
  ft_one_hot_encoder(
    input_cols = c("person_home_ownership_indexed", 
                   "loan_intent_indexed", 
                   "loan_grade_indexed", 
                   "cb_person_default_on_file_indexed"),
    output_cols = c("person_home_ownership_encoded", 
                    "loan_intent_encoded", 
                    "loan_grade_encoded", 
                    "cb_person_default_on_file_encoded")
  ) %>%
  
  # Création d'un vecteur features
  ft_vector_assembler(
    input_cols = c(
      "person_age", "person_income", 
      "person_home_ownership_encoded", 
      "imputer_person_emp_length", 
      "loan_intent_encoded",
      "loan_grade_encoded", "loan_amnt", 
      "imputer_loan_int_rate", "loan_percent_income", 
      "cb_person_default_on_file_encoded",
      "cb_person_cred_hist_length"
    ),
    output_col = "features"
  ) %>%
  
  # Standardisation
  ft_standard_scaler(
    input_col = "features",
    output_col = "features_scaled",
    with_mean = TRUE
  ) %>%
  
  # Estimateur : Modèle de forêt aléatoire pour la classification
  ml_random_forest_classifier(
    features_col = "features_scaled",
    label_col = "loan_status",
    seed = seed
  )

Le code du pipeline ci-dessus est peut-être long mais il est très simple et facile à comprendre.

  • La première étape a consisté en l’imputation des valeurs manquantes par la médiane ;

  • La deuxième étape du pipeline est l’encodage des variables catégorielles avec la fonction ft_one_hot_encoder(). Mais avant d’utiliser cette fonction, chaque variable catégorielle doit être indexée ce qui a été faite avec la fonction ft_string_indexer().

  • La troisième étape est l’assemblage des variables numériques (dont celles qui ont subi les imputations) et des variables obtenues après l’application de ft_one_hot_encoder en utilisant la fonction ft_vector_assembler(). Ainsi, on obtient le vecteur des variables indépendantes (features) qui seront utilisés dans l’algorithme de ML.

  • La quatrième étape est la standardisation des features afin que toutes les variables indépendantes soient à la même échelle.

  • La dernière étape est celle de l’estimateur. Ici, nous voulons construire un modèle de Forêt aléatoire donc nous utilisons ml_random_forest_classifier().

Forêts aléatoires

Les algorithmes de forêts aléatoires font partie des méthodes d’ensembles. Dans le jargon de l’Apprentissage Automatique, un Ensemble est un groupe de prédicteurs. En agrégeant les prédictions de plusieurs algorithmes individuels, on obtient très souvent de meilleures prédictions. Dans le cas d’un modèle de forêt aléatoire, les algorithmes individuels sont les arbres de décision qui constituent cette forêt. Les modèles de forêts aléatoires sont l’un des algorithmes d’apprentissage automatique les plus puissants disponibles aujourd’hui. De plus, ils sont très efficaces pour résoudre le problème de surajustement (overfitting).

L’implémentation d’un algorithme de forêt aléatoire se fait en 04 étapes simples :

  • Choix d’un échantillon bootstrap aléatoire (échantillonnage avec remise) de taille n à partir de l’ensemble de données d’apprentissage ;

  • Construction d’un arbre de décision à partir de l’échantillon bootstrap ;

  • Répétition des deux étapes précédentes un certain nombre k de fois ;

  • Agrégation des prédictions des k arbres de décision pour l’attribution de l’étiquette de classe par la règle du vote majoritaire.

Le concept de vote majoritaire est très simple à comprendre. Soit par exemple un Ensemble de trois algorithmes de classification pour prédire une variable binaire (0 et 1). Pour la prédiction d’un exemple donné, deux parmi les 3 modèles prédisent la classe 0 et le dernier algorithme prédit la classe 1. Alors d’après le vote majoritaire, si les poids des prédictions des trois algorithmes sont égaux, alors la classe prédite par l’Ensemble est la classe 0.

L’un des hyperparamètres les plus importants d’un algorithme de forêt aléatoire est le nombre d’arbres de décision. Généralement plus ce nombre est grand, plus le modèle est performant mais attention au surapprentissage (overfitting).

Les modèles basés sur les arbres de décision permettent de calculer l’importance de chaque prédicteur encore appelée importance de Gini.

La question qui se pose est comment peut-on connnaître les étapes indispensables à mettre dans un pipeline de Machine Learning. La réponse est simple : réaliser une bonne analyse exploratoire des données.

class(pipeline)
## [1] "ml_pipeline"       "ml_estimator"      "ml_pipeline_stage"
# Affichage du pipeline
pipeline

Après avoir construit votre pipeline, vous pouvez maintenant l’entraîner afin d’objenir un modèle :

# Entraînement du pipeline 
pipeline_model <- ml_fit(pipeline, train)
# Affichage du pipeline modèle
pipeline_model
# Prédictions sur les données de test
predictions <- ml_predict(
  pipeline_model,
  test
)
names(predictions)
## [1] "src"                "lazy_query"         "sdf_cache_state"   
## [4] "spark_dataframe"    "schema_cache_state" "schema"

Cette table contient plusieurs attributs.

predictions %>%
  sdf_separate_column("probability", c("p0", "p1")) %>%
  select(loan_status, p0, p1, prediction) %>%
  head(10)
## # Source: spark<?> [?? x 4]
##    loan_status    p0     p1 prediction
##          <int> <dbl>  <dbl>      <dbl>
##  1           0 0.889 0.111           0
##  2           0 0.924 0.0764          0
##  3           0 0.925 0.0752          0
##  4           0 0.920 0.0801          0
##  5           1 0.132 0.868           1
##  6           1 0.198 0.802           1
##  7           1 0.346 0.654           1
##  8           0 0.768 0.232           0
##  9           1 0.501 0.499           0
## 10           1 0.185 0.815           1

Comment lire ces valeurs ?

Première ligne : le statut de crédit est 0 donc ce client n’est pas en défaut de paiement. Selon le modèle, la probabilité que ce client ne soit pas en défaut de paiement (P0) est égale à environ 0.89 et la probabilité qu’il soit en défaut de paiement (p1) est de 0.11. Le odèle prédit donc que ce client n’est pas en défaut de paiment.

Les valeurs prédictes sembles correctes. Mais il faut une métrique d’évaluation de la performance de notre modèle.

4.4.2. Evaluation de la performance du pipeline modèle

  • Choix de la métrique d’évaluation

Nous sommes dans une tâche de classification binaire. Les métriques d’évaluation de ce type de modèle sont calculées pour la plupart à partir de la matrice de confusion. La matrice de confusion est une matrice carrée qui rapporte le nombre de vrais positifs (True Positives ou TP), vrais négatifs (True Négatives ou TN), faux positifs (False Positive ou FP) et faux négatifs (False Negatives ou FN).

Dans notre cas, la classe positive est 1 : le client est en défaut de paiement et la classe négative est 0 : le client n’est pas en défaut de paiement.

  • TP : le client est en défaut de paiement et le modèle prédit qu’il est en défaut de paiement ;

  • TN : le client n’est pas en défaut de paiement et le modèle prédit qu’il n’est pas en défaut de paiement ;

Les 2 cas ci-dessus (TP et TN) sont les bons cas. Mais FP et FN sont les mauvais cas :

  • FP : le client n’est pas en défaut de paiement mais le modèle prédit qu’il est en défaut de paiement ;

  • FN : le client est en défaut de paiement mais le modèle prédit qu’il n’est pas en défaut de paiement.

A partir de la matrice de confusion, vous pouvez calculer certaines métriques pour évaluer la performance du modèle.

# Matrice de confusion
credit_matrix <- table(
  pull(predictions, loan_status),
  pull(predictions, prediction)
)

credit_matrix
##    
##        0    1
##   0 5023   88
##   1  499  879
  • La précision de la classification (Accuracy en anglais) est le pourcentage d’instances correctement classées, c’est-à-dire la somme du nombre de vrais négatifs et de vrais positifs divisée par le nombre total des observations. Elle se calcule donc par la formule ci-dessous :

\[Accuracy = \frac{TN + TP}{(TN + FN + FP + TP)}\]

  • La sensibilité du modèle (Sensitivity en anglais) se calcule par la formule ci-dessous :

\[Sensitivity = \frac{TP}{(FN + TP)}\]

Dans le cas présent, la sensibilité se traduit par le pourcentage de clients en défaut de paiement (classe positive) qui ont été classés comme tel par le modèle. Une sensibilité élevée est meilleure.

  • La spécificité du modèle (Specificity en anglais) se calcule par la formule ci-dessous :

\[Specificity = \frac{TN}{(TN + FP)}\]

Ici, la spécificité est le pourcentage de clients qui ne sont pas en défauts de paiement (classe négative) et qui ont été classés comme tel par le modèle.

Une spécificité élevée est meilleure. Mais il faudra un compromis entre la sensibilité du modèle et la spécificité car l’amélioration de la sensibilité diminue la spécificité et l’amélioration de la spécificité diminue la sensibilité.

Il faut faire attention à la précision globale. Une forte précision globale ne signifie pas forcément que le modèle est performant. Le choix de la métrique pour quantifier la performance du modèle doit se faire en fonction du contexte de l’étude, c’est-à-dire de la problématique qu’on veut résoudre.

Dans la pratique, pour les modèles de classification binaire on calcule l’AUC (Area Under the Curve). Plus cette mesure est élevée, meilleure est le modèle pour prédire une classe négative comme négative et une classe positive comme positive. La valeur de cette métrique varie entre 0 et 1.

  • Calcul et interprétation de métriques d’évaluation
# Calcul de l'AUC
ml_binary_classification_evaluator(
  x = predictions,
  label_col = "loan_status"
)
## [1] 0.891446

L’AUC de ce modèle est égal à 0,89 ce qui signifie que ce modèle une probabilité de 89% pour distinguer correctement une classe négative (client qui n’est pas en défaut de paiement) d’une classe positive (client en défaut de paiement).

4.5 Réglage des hyperparamètres

Une façon de d’optimiser la performance d’un modèle de Machine Learning consiste à ajuster les hyperparamètres, ce qui signifie optimiser les paramètres pour ce modèle spécifique. Dans cette section, je vous montrerai comment utiliser la fonction ml_cross_validator() pour régler les hyperparamètres d’un modèle.

Mais avant de passer au réglage des hyperparamètres, il est important de comprendre la différence entre paramètres et hyperparamètres d’un modèle. En effet, pour créer un modèle on entraîne un algorithme de Machine Learning avec l’ensemble des données d’ajustement. Les résultats du modèle ajusté donnent les paramètres du modèle. Par exemple, les paramètres d’un modèle de régression linéaire simple sont la pente et l’interception (ordonnée à l’origine). Ainsi, les paraètres du modèles sont le résultat de l’ajustement de l’algorithme de ML. Autrement dit, les paramètres du modèle sont ou trouvés pendant la formation du modèle.

Les hyperparamètres quant à eux sont définis avant l’apprentissage. Ils précisent comment la formation est censée se dérouler. Par exemple, parmi les hyperparamètres de l’algorithme de forêt aléatoire, on peut citer :

  • num_trees : Nombre d’arbres dans la forêt ;

  • max_depth : profondeur maximale d’un arbre.

Chaque hyperparamètre peut prendre une plage de valeurs. Le but du réglage des hyperparamètres et donc de trouver la meilleure combinaison de valeurs afin que notre modèle soit aussi performant que possible.

grid <- list(
  random_forest = list(
    num_trees = c(20, 50, 100),
    max_depth = c(3, 5, 10),
    impurity = c("entropy", "gini")
  )
)

cv <- ml_cross_validator(
  sc,
  estimator = pipeline,
  estimator_param_maps = grid,
  evaluator = ml_binary_classification_evaluator(
    sc, label_col = "loan_status"
  ),
  num_folds = 5,
  parallelism = 4
)

cv
## CrossValidator (Estimator)
## <cross_validator__64379984_99aa_4722_86c1_a34d358c2606> 
##  (Parameters -- Tuning)
##   estimator: Pipeline
##              <pipeline__0827daa3_ee2f_4704_bc4c_6ffd4cdeb542> 
##   evaluator: BinaryClassificationEvaluator
##              <binary_classification_evaluator__54f54b68_1363_476e_9be1_25c29d608183> 
##     with metric areaUnderROC 
##   num_folds: 5 
##   [Tuned over 18 hyperparameter sets]

Le réglage des hyperparamètres est une phase très importante dans la modélisation. Il n’y a pas d’autre secret pour réussir cette phase en dehors de la lecture de la documentation de l’algorithme de ML que vous utilisez. De plus, avec l’expérience, vous saurez quels ont les hyperparamètres pertinents à régler.

cv_model <- ml_fit(cv, train)
# Résultats de la validation croisée
ml_validation_metrics(cv_model) %>%
  arrange(-areaUnderROC)
##    areaUnderROC impurity_1 num_trees_1 max_depth_1
## 1     0.9159072    entropy         100          10
## 2     0.9153013    entropy          50          10
## 3     0.9139552    entropy          20          10
## 4     0.9138801       gini         100          10
## 5     0.9133208       gini          50          10
## 6     0.9126416       gini          20          10
## 7     0.8970262    entropy         100           5
## 8     0.8955541       gini         100           5
## 9     0.8949153    entropy          50           5
## 10    0.8944590    entropy          20           5
## 11    0.8938309       gini          50           5
## 12    0.8931669       gini          20           5
## 13    0.8829618       gini         100           3
## 14    0.8815983    entropy         100           3
## 15    0.8809254    entropy          20           3
## 16    0.8805599       gini          50           3
## 17    0.8800893    entropy          50           3
## 18    0.8777260       gini          20           3
# Meilleur modèle
cv_model
## CrossValidatorModel (Transformer)
## <cross_validator__64379984_99aa_4722_86c1_a34d358c2606> 
##  (Parameters -- Tuning)
##   estimator: Pipeline
##              <pipeline__0827daa3_ee2f_4704_bc4c_6ffd4cdeb542> 
##   evaluator: BinaryClassificationEvaluator
##              <binary_classification_evaluator__54f54b68_1363_476e_9be1_25c29d608183> 
##     with metric areaUnderROC 
##   num_folds: 5 
##   [Tuned over 18 hyperparameter sets]
##  (Best Model)
##   PipelineModel (Transformer) with 9 stages
##   <pipeline__0827daa3_ee2f_4704_bc4c_6ffd4cdeb542> 
##     Stages 
##     |--1 ImputerModel (Transformer)
##     |    <imputer__6554253b_c603_4e0f_85d0_4bdd4a6855fb> 
##     |     (Parameters -- Column Names)
##     |      input_cols: person_emp_length, loan_int_rate
##     |      output_col: imputer__6554253b_c603_4e0f_85d0_4bdd4a6855fb__output
##     |      output_cols: imputer_person_emp_length, imputer_loan_int_rate
##     |--2 StringIndexerModel (Transformer)
##     |    <string_indexer__5f0a7fa6_ab2a_40d5_a057_af3180e00aa4> 
##     |     (Parameters -- Column Names)
##     |      input_col: person_home_ownership
##     |      output_col: person_home_ownership_indexed
##     |     (Transformer Info)
##     |      labels:  chr [1:4] "RENT" "MORTGAGE" "OWN" "OTHER" 
##     |--3 StringIndexerModel (Transformer)
##     |    <string_indexer__d0f4c8de_5452_4a6c_b6d2_05d86b1cbb86> 
##     |     (Parameters -- Column Names)
##     |      input_col: loan_intent
##     |      output_col: loan_intent_indexed
##     |     (Transformer Info)
##     |      labels:  chr [1:6] "EDUCATION" "MEDICAL" "VENTURE" "PERSONAL" "DEBTCONSOLIDATION" ... 
##     |--4 StringIndexerModel (Transformer)
##     |    <string_indexer__c85d4565_baeb_41d1_8f65_6229fd9d4055> 
##     |     (Parameters -- Column Names)
##     |      input_col: loan_grade
##     |      output_col: loan_grade_indexed
##     |     (Transformer Info)
##     |      labels:  chr [1:7] "A" "B" "C" "D" "E" "F" "G" 
##     |--5 StringIndexerModel (Transformer)
##     |    <string_indexer__38dd8937_1e26_4a41_aaac_1b3beea51327> 
##     |     (Parameters -- Column Names)
##     |      input_col: cb_person_default_on_file
##     |      output_col: cb_person_default_on_file_indexed
##     |     (Transformer Info)
##     |      labels:  chr [1:2] "N" "Y" 
##     |--6 OneHotEncoderModel (Transformer)
##     |    <one_hot_encoder__9f200c47_1a4e_4ff6_bd6d_719a4cee7514> 
##     |     (Parameters -- Column Names)
##     |      input_cols: person_home_ownership_indexed, loan_intent_indexed, loan_grade_indexed, cb_person_default_on_file_indexed
##     |      output_col: one_hot_encoder__9f200c47_1a4e_4ff6_bd6d_719a4cee7514__output
##     |      output_cols: person_home_ownership_encoded, loan_intent_encoded, loan_grade_encoded, cb_person_default_on_file_encoded
##     |     (Transformer Info)
##     |      category_sizes:  int [1:4] 4 6 7 2 
##     |--7 VectorAssembler (Transformer)
##     |    <vector_assembler__3f110ba3_84aa_4a90_a84a_6d9a04012453> 
##     |     (Parameters -- Column Names)
##     |      input_cols: person_age, person_income, person_home_ownership_encoded, imputer_person_emp_length, loan_intent_encoded, loan_grade_encoded, loan_amnt, imputer_loan_int_rate, loan_percent_income, cb_person_default_on_file_encoded, cb_person_cred_hist_length
##     |      output_col: features
##     |--8 StandardScalerModel (Transformer)
##     |    <standard_scaler__36efb7b1_b594_411f_a834_4090b1446246> 
##     |     (Parameters -- Column Names)
##     |      input_col: features
##     |      output_col: features_scaled
##     |     (Transformer Info)
##     |      mean:  num [1:22] 2.77e+01 6.60e+04 5.05e-01 4.12e-01 8.01e-02 ... 
##     |      std:  num [1:22] 6.37 6.51e+04 5.00e-01 4.92e-01 2.71e-01 ... 
##     |--9 RandomForestClassificationModel (Transformer)
##     |    <random_forest_classifier__164a5dee_53f6_412f_9db0_df46e370b112> 
##     |     (Parameters -- Column Names)
##     |      features_col: features_scaled
##     |      label_col: loan_status
##     |      prediction_col: prediction
##     |      probability_col: probability
##     |      raw_prediction_col: rawPrediction
##     |     (Transformer Info)
##     |      feature_importances: <function> 
##     |      num_classes:  int 2 
##     |      num_features:  int 22 
##     |      total_num_nodes: <function> 
##     |      tree_weights: <function> 
##     |      trees: <function>
# Prédictions sur les données de test
predictions <- ml_predict(
  cv_model,
  test
)
predictions %>%
  select(loan_status, prediction) %>%
  head()
## # Source: spark<?> [?? x 2]
##   loan_status prediction
##         <int>      <dbl>
## 1           0          0
## 2           0          0
## 3           0          0
## 4           0          0
## 5           1          1
## 6           1          1
predictions %>%
  group_by(loan_status, prediction) %>%
  tally() %>%
  collect()
## # A tibble: 4 × 3
##   loan_status prediction     n
##         <int>      <dbl> <dbl>
## 1           1          1   943
## 2           0          0  5094
## 3           1          0   435
## 4           0          1    17
# Sauvegarde du pipeline modèle
ml_save(
  cv_model,
  "credit_risk_model",
  overwrite = TRUE
)

On peut aussi sauvegarder le pipeline qui n’a pas été entraîné :

ml_save(
  pipeline,
  "credit_risk_pipeline",
  overwrite = TRUE
)

On peut utiliser un PipelineModel existant pour effectuer des prédictions sur de nouvelles données

# Chargement d'un PipelineModel existant
reloaded_model <- ml_load(
  sc, 
  "credit_risk_model"
)

supposons que nous avons de nouvelles observations :

# Nouvelles données 
new_df <- df %>%
  filter(loan_intent == "MEDICAL", person_age >= 60)
new_df
## # Source: spark<?> [?? x 12]
##    person_age person_i…¹ perso…² perso…³ loan_…⁴ loan_…⁵ loan_…⁶ loan_…⁷ loan_…⁸
##         <int>      <int> <chr>     <dbl> <chr>   <chr>     <int>   <dbl>   <int>
##  1         66      60000 RENT          4 MEDICAL C         27050   NA          1
##  2         62      68375 RENT          4 MEDICAL C         24250   12.7        1
##  3         61      51000 RENT          2 MEDICAL D         20000   14.1        1
##  4         78      48000 RENT         41 MEDICAL A          3000    7.51       0
##  5         70      39996 RENT         NA MEDICAL C          3600   15.2        0
##  6         66      38400 RENT         14 MEDICAL A         11000    5.42       0
##  7         69      37000 RENT          6 MEDICAL D         10750   14.6        0
##  8         69      80000 RENT         12 MEDICAL C          4800   14.8        0
##  9         70      30000 RENT          1 MEDICAL B          5000   11.0        0
## 10         69      24000 RENT          3 MEDICAL A          6000    6.62       0
## # … with more rows, 3 more variables: loan_percent_income <dbl>,
## #   cb_person_default_on_file <chr>, cb_person_cred_hist_length <int>, and
## #   abbreviated variable names ¹​person_income, ²​person_home_ownership,
## #   ³​person_emp_length, ⁴​loan_intent, ⁵​loan_grade, ⁶​loan_amnt, ⁷​loan_int_rate,
## #   ⁸​loan_status
# Scoring des nouvelles observations :
new_predictions <- ml_predict(reloaded_model, new_df)
new_predictions %>%
  group_by(loan_status, prediction) %>%
  tally() %>%
  collect()
## # A tibble: 4 × 3
##   loan_status prediction     n
##         <int>      <dbl> <dbl>
## 1           1          1     4
## 2           0          0    17
## 3           1          0     1
## 4           0          1     2

Il est aussi possible de charger un simple pipeline (qui n’a pas été entraîné) afin de l’entraîner sur de nouvelles données.

reloaded_pipeline <- ml_load(
  sc, 
  "credit_risk_pipeline"
)

Lorsque vous avez fini votre modélisation, n’oubliez pas de vous déconnecter au cluster Spark.

# Déconnection du cluster Spark
spark_disconnect(sc = sc)

5. Déploiement du pipeline modèle dans une application web R Shiny

5.1. Qu’est-ce que le déploiement de modèle de Machine Learning ?

Vous avez fini de construire, évaluer et enregistrez votre modèle de Machine learning. Est-ce que votre travail s’arrête la ? Il est vrai que dans de nombreux cas, un projet de modélisation des données peut se terminer par une préentation powerpoint où le Data Scientist présente les résultats de son étude ainsi que des recommandations pour améliorer le business de l’entreprise. Mais dans de nombreux cas, l’entreprise a besoin de réaliser des prédictions sur de nouvelles données et souvent en temps réel. Par exemple, dans le cadre de notre projet réel traité à la section 4, cette banque a besoin de scorer des nouveaux demandeurs de prêts afin de savoir lesquels sont susceptibles d’être en défaut de paiement. Ceci peut se faire en intégrant le modèle construit dans une application.

Ce processus consistant à prendre un modèle de Machine learning et à le transformer en un service prédictif que d’autres peuvent consommer est généralement appelé déploiement ou mise en production. Pour mieux comprendre cette notion très importante du déploiement de modèles de Machine learning je vous invite à regarder ma vidéo intitulée Déploiement de modèles de Machine Learning en Entreprise ? | Défis et Solutions | Josué AFOUDA

Dans la section 5.2, nous construirons une application web R Shiny dans laquelle sera intégré notre modèle de prédiction du risque de crédit.

5.2. Intégration d’un pipeline Spark ML dans une application R Shiny

Shiny est un package de R qui permet de créer des applications web en utilisant du code R. Avec R Shiny, tu n’auras pas besoin de savoir coder en HTML, PHP ni JavaScript pour développer de suberbes applications. Ici, je ne te ferai pas un cours sur R Shiny. Si tu veux apprendre cet magnifique outil très demandé en entreprises, je te conseille cet ouvrage 100% pratique : Développement Web en Data Science avec R Shiny sans HTML, CSS, PHP ni JavaScript.

Ci-dessous, le code de l’application :

library(sparklyr)
library(shiny)
library(shinydashboard)

sc <- spark_connect(
  master = "local", 
  version = "3.0"
)


model <- ml_load(
  sc, 
  "credit_risk_model"
)

# Interface utilisateur
ui <- dashboardPage(
  
  dashboardHeader(
    title = "Credit Scoring"
  ),
  
  dashboardSidebar(),
  
  dashboardBody(
    tabName = "features",
    fluidRow(
      box(
        valueBoxOutput("score_prediction")
      ),
      box(
        numericInput(
          "var1", 
          label = "Age du demandeur de credit", 
          value = 20, 
          min = 18
        )
      )
    ),
    
    fluidRow(
      box(
        numericInput(
          "var2", 
          label = "Revenu annuel du demandeur de credit", 
          value = 10000, 
          min = 0
        )
      ),
      box(
        selectInput(
          'var3', 
          label = "Proprieté immobilière", 
          choices = c('MORTGAGE', 'OWN', 'RENT', 'OTHER')
        )
      )
    ),
    
    fluidRow(
      box(
        numericInput(
          "var4", 
          label = "Depuis quand le demandeur de credit 
          est-il en activité professionnelle ?", 
          value = 1, 
          min = 0
        )
      ),
      box(
        selectInput(
          'var5', 
          label = "Motif du prêt bancaire", 
          choices = c("PERSONAL", "EDUCATION", "MEDICAL", 
                      "VENTURE", "HOMEIMPROVEMENT", 
                      "DEBTCONSOLIDATION")
        )
      )
    ),
    
    fluidRow(
      box(
        selectInput(
          'var6', 
          label = "Catégorie du crédit", 
          choices = c("A", "B", "C", "D", "E", "F", "G")
        )
      ),
      box(
        numericInput(
          "var7", 
          label = "Montant du crédit", 
          value = 2000, 
          min = 0
        )
      )
    ),
    
    fluidRow(
      box(
        numericInput(
          "var8", 
          label = "Taux dintérêt du crédit (%)", 
          value = 5, 
          min = 0
        )
      ),
      box(
        numericInput(
          "var9", 
          label = "Ratio Dette/Revenu du demandeur 
          de crédit (valeur entre 0 et 1)", 
          value = 0.4, 
          min = 0, 
          max = 1
        )
      )
    ),
    
    fluidRow(
      box(
        selectInput(
          'var10', 
          label = "Le demandeur de crédit 
          est-il à découvert bancaire ?", 
          choices = c("Y", "N")
        )
      ),
      box(
        numericInput(
          "var11", 
          label = "Echénace des crédits 
          en cours (en nombre d'années)", 
          value = 3, 
          min = 0
        )
      )
    )
    
  )
  
)

# Serveur
server <- function(input, output) {
  
  # Nouvelles observations dont on veut les prédictions
  new_df <- reactive({
    
    data.frame(
      "person_age" = input$var1,
      "person_income" = input$var2,
      "person_home_ownership" = input$var3,
      "person_emp_length" = input$var4,
      "loan_intent" = input$var5,
      "loan_grade" = input$var6,
      "loan_amnt" = input$var7,
      "loan_int_rate" = input$var8,
      "loan_percent_income" = input$var9,
      "cb_person_default_on_file" = input$var10,
      "cb_person_cred_hist_length" = input$var11
    )
    
  })
  
  # Copier les nouvelles observations dans le cluster Spark
  spark_new_df <- reactive({
    
    copy_to(
      sc,
      new_df()
    )
    
  })
  
  # Prédictions
  new_prediction_tbl <- reactive({
    ml_predict(
      model,
      spark_new_df()
    ) %>%
      sdf_separate_column("probability", c("p0", "p1")) %>%
      select(p0, p1, prediction)
  })
  
  # Prédictions : O ou 1
  pred_outcome <- reactive({
    new_prediction_tbl() %>%
      select(prediction) %>%
      collect()
  })
  
  # Expliciter la prédiction
  prediction_label <- reactive({
    ifelse(
      pred_outcome()$prediction == 0, 
      "Eligible au crédit", "Non éligible au crédit"
    )
  })
  
  # Probabilité de défaut de paiement
  prediction_prob <- reactive({
    new_prediction_tbl() %>%
      select(p1) %>%
      collect()
  })
  
  # Couleur pour distinguer le résultat 
  prediction_color <- reactive({
    ifelse(pred_outcome()$prediction == 0, "green", "red")
  })
  
  output$score_prediction <- renderValueBox({
    valueBox(
      value = paste(round(100 * prediction_prob()$p1, 0), "%"),
      subtitle = prediction_label(),
      color = prediction_color(),
      icon = icon('hand-holding-usd')
    )
  })
  
}

# Run the application 
shinyApp(ui = ui, server = server)

Vous pouvez maintenant déployer l’application en ligne. La dernière section du chapitre 3 de mon livre Développement Web en Data Science avec R Shiny sans HTML, CSS, PHP ni JavaScript traite du déploiement des applications web R Shiny dans le cloud.

6. Mes autres livres

Ci-dessous quelques livres qui vous permettront de développer des compétences nécessaires en Data Science :

Statistique et Simulation avec Python : Cours et Exercices corrigés

Broché : 288 pages ISBN-13 : 979-8591390259

La Statistique est présente partout dans notre quotidien. Vous ne pouvez pas y échapper. La Statistique est la fondation de la Data Science.

Ce livre vous donnera beaucoup de plaisir à réaliser des analyses statistiques avec le langage Python. Il n’est pas du tout comme la plupart des livres de Statistique retrouvés sur le marché qui sont remplis de théories et de formules mathématiques tellement complexes que cela ne donne pas envie de les lire. Mon livre à moi est écrit dans un langage très simple et accessible à tout le monde. Nul besoin d’avoir un Master ou un Doctorat en Mathématiques pour comprendre tous les concepts présentés dans ce livre. Chaque notion est présentée sous forme d’activité résolue avec cas pratique. Le code est écrit de manière très simple avec des commentaires. De plus, des exercices sont glissés après chaque concept introduit pour vous aider à pratiquer au fur à mesure ce que vous apprenez. Tous les exercices sont entièrement résolus au dernier chapitre pour vous aider en cas de blocage. Vous pouvez donc utiliser ce livre en toute autonomie pour apprendre la Statistique avec Python.

A travers ce livre, vous apprendrez à :

✅ Calculer des mesures de tendance centrale et des mesures de dispersion afin de décrire les données ;

✅ créer et interpréter des graphiques de visualisation des données en utilisant Python ainsi que les librairies Matplotlib et Seaborn ;

✅ effectuer des analyses multivariées afin d’examiner les relations existant entre plusieurs variables ;

✅ penser de manière probabiliste afin de réaliser des inférences statistiques pour tirer des conclusions à partir d’échantillons de données ;

✅ simuler des données afin d’estimer la probabilité d’un événement ;

✅ rééchantilloner les données à l’aide de techniques comme le Bootstrapping et visualiser les échantillons bootstrap ;

✅ calculer les intervalles de confiance des statistiques récapitulatives d’une population ;

✅ identifier, effectuer et interpréter les tests d’hypothèse appropriés à utiliser pour les ensembles de données ;

✅ appliquer des techniques de modélisation statistique aux données (régression linéaire et régression logistique) ;

✅ interpréter les résultats d’une modélisation statistique et évaluer la qualité des modèles ;

✅ comprendre l’apprentissage automatique ainsi que ses différences avec la modélisation statistique ;- construire et évaluer des modèles de Machine Learning (classification et régression).

Savoir programmer avec le langage Python appliqué à l’analyse des données: Cours, Exercices corrigés et Projets réels

Broché : 101 pages ISBN-13 : 979-8664840995

Un livre génial destiné aux personnes désireuses d’apprendre à programmer. Même si vous n’aviez jamais écrit auparavant une seule ligne de code, grâce à sa syntaxe intuitive et très facile à comprendre, Python vous fera entrer dans le monde passionnant de la programmation informatique appliquée à la Science des données (Data Science) qui offre d’immenses opportunités.

Avec plus de 15 ans d’expérience en programmation informatique, je vous guiderai pas à pas à travers mes explications simples, précises et efficaces pour vous permettre d’acquérir les fondamentaux du langage Python. Chaque notion est expliquée par une activité résolue puis il y a un exercice d’application pour vous permettre de pratiquer au fur et à mesure. Tous les exercices d’application sont entièrement corrigés avec les codes complets et les commentaires dans le but de vous aider à apprendre efficacement et en toute autonomie.

A travers ce livre, vous apprendrez à :

✅ configurer votre environnement Python pour un travail efficace ;

✅ écrire du code propre et concis avec Python 3 incluant des structures conditionnelles et des boucles ;

✅ écrire des programmes Python qui interagissent avec les utilisateurs et traite leurs entrées afin de générer les sorties souhaitées ;

✅ automatiser des tâches en écrivant des fonctions ;

✅ utiliser certains outils modernes comme les fonctions lambda, les listes de compréhension, les fonctions map() et filter() ;

✅ stocker l’information dans des structures de données et générer des statistiques ;

✅ effectuer une analyse des données avec des fonctionnalités de Numpy et de Pandas ;

✅ analyser de réels jeux de données.

Analyse financière et Gestion des Risques avec Python: Application à la création et l’optimisation des Portefeuilles d’Actions

Broché : 103 pages ISBN-13 : 979-8567677681

Le monde de la Finance en général et le secteur de la Bourse en particulier ont connu une révolution depuis quelques années grâce à l’apport de l’Intelligence Artificielle et à l’utilisation d’outils puissants et performants. Python a été largement adopté aussi bien par les professionnels des marchés boursiers qui l’utilisent dans leurs tâches quotidiennes que par les chercheurs, étudiants ou autres personnes intéressées par la Bourse.

Ce livre est une introduction à l’analyse technique et quantitative avec Python dans le secteur boursier.

A travers ce livre, vous apprendrez à :

✅ Importer automatiquement des données boursières à partir du Web et à les stocker en tant que dataframe ;

✅ Traiter et nettoyer des données financières (Séries Temporelles) ;✅

Créer et analyser des graphiques interactifs avec la librairie Plotly ;✅Calculer les rendements des titres (actions et du marché ;

✅Analyser statistiquement les rendements des actions ;✅

✅ Calculer de diverses manières le Risque d’un investissement financier (Volatilité Standard, VaR, CVaR, Matrice de Covariance, etc.) ;

✅Calculer des rendements ajustés au Risque (Ratio de Sharpe, Ratio de Sortino, etc.) ;✅

Effectuer des simulations Monte-Carlo pour l’estimation du Risque ;

✅Modéliser les facteurs influençant les rendements des actions afin de calculer les paramètres Alpha et Bêta ;

✅Calculer le rendement attendu d’un investissement (Action ou Portefeuille) en utilisant le modèle d’évaluation des actifs financiers (Capital Asset Pricing Model ou CAPM en Anglais) ;

✅Créer et Analyser différents types de Portefeuilles d’Actions ;✅

Générer automatiquement le rapport complet d’analyse de performance d’un portefeuille en utilisant l’outil Pyfolio ;

✅Utiliser la théorie d’Harry Markowitz pour le calcul de Portefeuille optimal ;✅

Générer de milliers de Portefeuilles avec la méthode Monte-Carlo et Sélectionner le Portefeuille à ratio de Sharpe maximum et le Portefeuille à volatilité minimale ;

✅Optimiser un Portefeuille en utilisant l’outil PyPortfolioOpt de la société Quantopian ;✅

Modéliser les cours des actions en vue de la prédiction de futurs prix grâce à de ‘simples techniques’ comme l’estimation par la moyenne, la moyenne mobile, les lissages exponentiels simple, double et triple.Les Chapitres :

✅ CHAPITRE 1 : GENERALITES ET DEFINITIONSDans ce chapitre, je vous explique ce qu’est une série temporelle et pourquoi il est très important de savoir manipuler ce type de données. Ensuite je vous explique quelques notions sur le marché boursier, les tendances en matière d’analyses de données dans ce secteur ainsi que les composantes d’une bonne analyse des données boursières.

✅CHAPITRE 2 : IMPORTATION ET ANALYSE EXPLORATOIRE DES DONNÉESDans ce chapitre, vous apprendrez comment collecter automatiquement de données boursières sur des plateformes comme Yahoo Finance sans quitter un instant votre notebook. Nous ferons le traitement et le nettoyage de ces données pour les mettre dans une forme qui facilitera nos futures analyses. Nous finirons par une analyse exploratoire des données pour mieux les comprendre.

✅CHAPITRE 3 : RENDEMENTS ET RISQUESDans ce chapitre, vous apprendrez des concepts tels les rendements, les risques, le ratio de Sharpe, le ratio de Sortino, CAPM (Capital Asset Price Management), etc. et comment les calculer. Par ailleurs, vous apprendrez à écrire des fonctions afin de mieux structurer votre code.

✅ CHAPITRE 4 : CRÉATION, ANALYSE ET OPTIMISATION D’UN PORTEFEUILLE D’ACTIONS DANS PYTHONIci, Vous apprendrez à créer différents types de portefeuilles. Vous apprendrez aussi comment optimiser un portefeuille en trouvant des pondérations risque-rendement qui sont optimales.

✅ CHAPITRE 5 : MODÈLES SIMPLESIci, vous apprendrez comment modéliser les prix des actions en utilisant l’estimation par la moyenne, les moyennes mobiles et différents types de lissages exponentiels.

Machine Learning par la pratique avec Python: Projets réels dans les Finances, l’Immobilier, le Trading, la Santé, le Marketing, etc.

Broché : 230 pages ISBN-13 : 979-8671731064

L’apprentissage automatique (Machine Learning en anglais) est un domaine de l’Intelligence artificielle qui se fonde sur des approches mathématiques et statistiques pour donner aux ordinateurs la capacité d’ apprendre à partir de données, c’est-à-dire d’améliorer leurs performances à résoudre des tâches sans être explicitement programmés pour chacune de ces tâches. Plus largement, il concerne la conception, l’analyse, l’optimisation, le développement et l’implémentation de telles méthodes.

Ce livre est purement pratique afin de vous permettre d’acquérir rapidement et efficacement les compétences nécessaires pour créer des systèmes d’apprentissage automatique (Machine Learning) dans son domaine d’intervention. Les projets couvrent plusieurs domaines. Vous apprendrez à modéliser vos données avec des algorithmes de régression, de classification, de clustering, etc. De plus, vous apprendrez à évaluer les performances des modèles créés.

A travers ce livre, vous apprendrez à :

✅ Nettoyer un jeu de données et la rendre prête pour la modélisation (Traitement des valeurs manquantes, Détection et suppression des outliers, Encodage des variables catégorielles, Normalisation des données, etc.) ;

✅ Construire un modèle de classification (LogisticRegression, RandomForestClassifier, DecisionTreeClassifier, KNeighborsClassifier, etc.) et d’un modèle de régression (LinearRegression, RandomForestRegressor, DecisionTreeRegressor, KNeighborsRegressor, etc.) ;

✅ Evaluer la performance d’un modèle (Données d’entraînement et d’évaluation, Choix de la métrique, Validation croisée, Robustesse du modèle, etc.)

✅ effectuer des prédictions ;

✅ modéliser des séries temporelles et effectuer des prévisions ;

✅ rechercher les hyperparamètres optimaux d’un modèle en utilisant les méthodes Grid Search et Random Search ;

✅ automatiser la sélection du meilleur modèle avec l’outil TPOT ;

✅ automatiser le flux de travail de vos projets de Machine Learning ;

✅ effectuer des segmentations avec des algorithmes comme KMeans ;

✅ réduire la dimension de grand ensembles de données en utilisant l’ACP, …etc.

APPRENDRE À PROGRAMMER AVEC R ET RSTUDIO: MANUEL DE COURS ET EXERCICES CORRIGÉS POUR DÉBUTANTS

Broché : 226 pages ISBN-13 : 979-8790793295

R est l’un des langages informatiques les plus utilisés. Plus qu’un langage, R est un environnement intégré et complet pour la conception, la réalisation et la vulgarisation d’un projet concernant l’analyse des données. R peut être utilisé pour des tâches telles que la modélisation statistique, la visualisation des données, l’apprentissage automatique (Machine Learning), l’analyse des séries temporelles, les études économétriques, l’analyse quantitative, le traitement des données textuelles, etc.

A travers ce livre, vous apprendrez à :

✅ nstaller et Configurer votre environnement de travail pour pouvoir écrire du code R ;

✅ écrire votre premier programme (‘Hello World’) et effectuer des opérations basiques (Addition, Soustraction, Multipication, Division, Exponentiel, Modulo, etc.) ;

✅ afficher les résultats d’un code en utilisant de différentes manières les fonctions print(), paste() et cat() ;

✅ créer des variables et à les réutiliser ;

✅ manipuler différents types de données tels que les entiers naturels, les booléens, les chaînes de caractères, les nombres décimaux, les matrices, les vecteurs, les listes, les dataframes, etc.

✅ créer une dataframe et recueillir des informations concernant sa structure et son résumé statistique ;

✅ combiner des booléens, des opérateurs logiques et des opérateurs de comparaison ;

✅ écrire du code propre et concis incluant des structures conditionnelles if, if…else, if…else if…else, des boucles for et while ;

✅ utiliser les fonctions de la famille apply tels que lapply(), sapply() et vapply() ;

✅ créer vos propres fonctions et les optimiser afin d’automatiser certaines tâches et rendre votre code réutilisable ;

✅ créer des listes de compréhension vous permettant d’écrire des boucles for plus ou moins complexes en une seule ligne de code ;

✅ importer différents types de fichiers tels que Excel, CSV, txt, TSV, …;

✅ importer des données provenant du web à partir des API (Application Programing Interface) et du WebScraping ;

✅ manipuler les données à la manière de Tidyverse avec les fonctions filter(), arrange(), mutate(), select(), summarise() et group_by() ;

✅ créer des graphiques tels que les nuages de points (avec droite de régression), les diagrammes à barres, les courbes, les histogrammes, les boîtes à moustache ainsi que des subplots (sous-graphiques) ;

✅ traiter les variables catégorielles en utilisant les fonctionnalités de la librairie forcats ;

✅ effectuer des jointures de tables (jointure interne, à gauche, à droite, complète ainsi qu’une semi-jointure et une anti-jointure) avec la librairie dplyr.

Ce livre est également disponible en version PDF : https://buy.stripe.com/aEU7wu1kW4EG94A6ov

Mes livres sont disponibles en vente sur Amazon aussi en versions papier (broché) et numérique (kindle) : https://www.amazon.fr/Josu%C3%A9-AFOUDA/e/B08F17S1V8/ref=dp_byline_cont_pop_book_1

N’oublier pas lorsque vous acheter un de mes livres de laisser un petit commentaire et aussi 5 étoiles :) sur le site d’achat. Ceci est vraiment encourageant pour continuer cette mission de démocratisation de la connaissance en Science des données. Merci.