You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
686 lines
33 KiB
686 lines
33 KiB
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Construire un modèle de régression logistique - Leçon 4\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"#### **[Quiz avant la leçon](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/15/)**\n",
|
|
"\n",
|
|
"#### Introduction\n",
|
|
"\n",
|
|
"Dans cette dernière leçon sur la régression, l'une des techniques *classiques* de base en apprentissage automatique, nous allons examiner la régression logistique. Vous utiliseriez cette technique pour découvrir des modèles permettant de prédire des catégories binaires. Ce bonbon est-il au chocolat ou non ? Cette maladie est-elle contagieuse ou non ? Ce client choisira-t-il ce produit ou non ?\n",
|
|
"\n",
|
|
"Dans cette leçon, vous apprendrez :\n",
|
|
"\n",
|
|
"- Les techniques de régression logistique\n",
|
|
"\n",
|
|
"✅ Approfondissez votre compréhension de ce type de régression dans ce [module d'apprentissage](https://learn.microsoft.com/training/modules/introduction-classification-models/?WT.mc_id=academic-77952-leestott)\n",
|
|
"\n",
|
|
"## Prérequis\n",
|
|
"\n",
|
|
"Après avoir travaillé avec les données sur les citrouilles, nous sommes maintenant suffisamment familiers avec elles pour réaliser qu'il existe une catégorie binaire sur laquelle nous pouvons travailler : `Color`.\n",
|
|
"\n",
|
|
"Construisons un modèle de régression logistique pour prédire, à partir de certaines variables, *quelle couleur une citrouille donnée est susceptible d'avoir* (orange 🎃 ou blanche 👻).\n",
|
|
"\n",
|
|
"> Pourquoi parlons-nous de classification binaire dans une leçon sur la régression ? Uniquement pour des raisons linguistiques, car la régression logistique est [en réalité une méthode de classification](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), bien qu'elle soit basée sur des modèles linéaires. Découvrez d'autres façons de classifier des données dans le prochain groupe de leçons.\n",
|
|
"\n",
|
|
"Pour cette leçon, nous aurons besoin des packages suivants :\n",
|
|
"\n",
|
|
"- `tidyverse` : Le [tidyverse](https://www.tidyverse.org/) est une [collection de packages R](https://www.tidyverse.org/packages) conçue pour rendre la science des données plus rapide, plus facile et plus amusante !\n",
|
|
"\n",
|
|
"- `tidymodels` : Le [framework tidymodels](https://www.tidymodels.org/) est une [collection de packages](https://www.tidymodels.org/packages/) pour la modélisation et l'apprentissage automatique.\n",
|
|
"\n",
|
|
"- `janitor` : Le [package janitor](https://github.com/sfirke/janitor) fournit des outils simples pour examiner et nettoyer des données désordonnées.\n",
|
|
"\n",
|
|
"- `ggbeeswarm` : Le [package ggbeeswarm](https://github.com/eclarke/ggbeeswarm) propose des méthodes pour créer des graphiques de type \"beeswarm\" en utilisant ggplot2.\n",
|
|
"\n",
|
|
"Vous pouvez les installer avec :\n",
|
|
"\n",
|
|
"`install.packages(c(\"tidyverse\", \"tidymodels\", \"janitor\", \"ggbeeswarm\"))`\n",
|
|
"\n",
|
|
"Alternativement, le script ci-dessous vérifie si vous avez les packages nécessaires pour compléter ce module et les installe pour vous s'ils sont manquants.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n",
|
|
"\n",
|
|
"pacman::p_load(tidyverse, tidymodels, janitor, ggbeeswarm)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## **Définir la question**\n",
|
|
"\n",
|
|
"Pour nos besoins, nous exprimerons cela comme un binaire : 'Blanc' ou 'Non Blanc'. Il existe également une catégorie 'rayée' dans notre ensemble de données, mais elle contient peu d'exemples, donc nous ne l'utiliserons pas. De toute façon, elle disparaît une fois que nous supprimons les valeurs nulles de l'ensemble de données.\n",
|
|
"\n",
|
|
"> 🎃 Petit fait amusant, nous appelons parfois les citrouilles blanches des citrouilles 'fantômes'. Elles ne sont pas très faciles à sculpter, donc elles ne sont pas aussi populaires que les citrouilles orange, mais elles ont un look sympa ! On pourrait donc reformuler notre question comme : 'Fantôme' ou 'Non Fantôme'. 👻\n",
|
|
"\n",
|
|
"## **À propos de la régression logistique**\n",
|
|
"\n",
|
|
"La régression logistique diffère de la régression linéaire, que vous avez apprise précédemment, de plusieurs manières importantes.\n",
|
|
"\n",
|
|
"#### **Classification binaire**\n",
|
|
"\n",
|
|
"La régression logistique n'offre pas les mêmes fonctionnalités que la régression linéaire. La première permet de prédire une `catégorie binaire` (\"orange ou non orange\"), tandis que la seconde est capable de prédire des `valeurs continues`, par exemple, étant donné l'origine d'une citrouille et le moment de la récolte, *de combien son prix augmentera*.\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"### Autres classifications\n",
|
|
"\n",
|
|
"Il existe d'autres types de régression logistique, notamment multinomiale et ordinale :\n",
|
|
"\n",
|
|
"- **Multinomiale**, qui implique d'avoir plus d'une catégorie - \"Orange, Blanc et Rayée\".\n",
|
|
"\n",
|
|
"- **Ordinale**, qui implique des catégories ordonnées, utile si nous voulons ordonner nos résultats de manière logique, comme nos citrouilles classées par un nombre fini de tailles (mini,petite,moyenne,grande,très grande,énorme).\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"#### **Les variables N'ONT PAS besoin d'être corrélées**\n",
|
|
"\n",
|
|
"Vous vous souvenez que la régression linéaire fonctionnait mieux avec des variables plus corrélées ? La régression logistique est l'inverse - les variables n'ont pas besoin d'être alignées. Cela fonctionne pour ces données qui présentent des corrélations relativement faibles.\n",
|
|
"\n",
|
|
"#### **Vous avez besoin de beaucoup de données propres**\n",
|
|
"\n",
|
|
"La régression logistique donnera des résultats plus précis si vous utilisez davantage de données ; notre petit ensemble de données n'est pas optimal pour cette tâche, donc gardez cela à l'esprit.\n",
|
|
"\n",
|
|
"✅ Réfléchissez aux types de données qui se prêtent bien à la régression logistique.\n",
|
|
"\n",
|
|
"## Exercice - nettoyer les données\n",
|
|
"\n",
|
|
"Commencez par nettoyer un peu les données, en supprimant les valeurs nulles et en sélectionnant uniquement certaines colonnes :\n",
|
|
"\n",
|
|
"1. Ajoutez le code suivant :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Load the core tidyverse packages\n",
|
|
"library(tidyverse)\n",
|
|
"\n",
|
|
"# Import the data and clean column names\n",
|
|
"pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\") %>% \n",
|
|
" clean_names()\n",
|
|
"\n",
|
|
"# Select desired columns\n",
|
|
"pumpkins_select <- pumpkins %>% \n",
|
|
" select(c(city_name, package, variety, origin, item_size, color)) \n",
|
|
"\n",
|
|
"# Drop rows containing missing values and encode color as factor (category)\n",
|
|
"pumpkins_select <- pumpkins_select %>% \n",
|
|
" drop_na() %>% \n",
|
|
" mutate(color = factor(color))\n",
|
|
"\n",
|
|
"# View the first few rows\n",
|
|
"pumpkins_select %>% \n",
|
|
" slice_head(n = 5)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Vous pouvez toujours jeter un coup d'œil à votre nouveau dataframe en utilisant la fonction [*glimpse()*](https://pillar.r-lib.org/reference/glimpse.html) comme indiqué ci-dessous :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"pumpkins_select %>% \n",
|
|
" glimpse()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Confirmons que nous allons effectivement traiter un problème de classification binaire :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Subset distinct observations in outcome column\n",
|
|
"pumpkins_select %>% \n",
|
|
" distinct(color)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Visualisation - graphique catégoriel\n",
|
|
"À ce stade, vous avez de nouveau chargé les données sur les citrouilles et les avez nettoyées afin de conserver un ensemble de données contenant quelques variables, y compris la couleur. Visualisons le dataframe dans le notebook en utilisant la bibliothèque ggplot.\n",
|
|
"\n",
|
|
"La bibliothèque ggplot propose des moyens astucieux de visualiser vos données. Par exemple, vous pouvez comparer les distributions des données pour chaque variété et couleur dans un graphique catégoriel.\n",
|
|
"\n",
|
|
"1. Créez un tel graphique en utilisant la fonction geombar, en utilisant nos données sur les citrouilles, et en spécifiant une correspondance de couleur pour chaque catégorie de citrouille (orange ou blanche) :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "python"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Specify colors for each value of the hue variable\n",
|
|
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
|
|
"\n",
|
|
"# Create the bar plot\n",
|
|
"ggplot(pumpkins_select, aes(y = variety, fill = color)) +\n",
|
|
" geom_bar(position = \"dodge\") +\n",
|
|
" scale_fill_manual(values = palette) +\n",
|
|
" labs(y = \"Variety\", fill = \"Color\") +\n",
|
|
" theme_minimal()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"En observant les données, vous pouvez voir comment les données de Couleur sont liées à la Variété.\n",
|
|
"\n",
|
|
"✅ Étant donné ce graphique catégoriel, quelles explorations intéressantes pouvez-vous envisager ?\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Prétraitement des données : encodage des caractéristiques\n",
|
|
"\n",
|
|
"Notre ensemble de données sur les citrouilles contient des valeurs sous forme de chaînes pour toutes ses colonnes. Travailler avec des données catégorielles est intuitif pour les humains, mais pas pour les machines. Les algorithmes d'apprentissage automatique fonctionnent mieux avec des nombres. C'est pourquoi l'encodage est une étape très importante dans la phase de prétraitement des données, car il nous permet de transformer des données catégorielles en données numériques, sans perdre d'informations. Un bon encodage permet de construire un bon modèle.\n",
|
|
"\n",
|
|
"Pour l'encodage des caractéristiques, il existe deux principaux types d'encodeurs :\n",
|
|
"\n",
|
|
"1. Encodeur ordinal : il convient bien aux variables ordinales, qui sont des variables catégorielles dont les données suivent un ordre logique, comme la colonne `item_size` dans notre ensemble de données. Il crée une correspondance où chaque catégorie est représentée par un numéro, correspondant à l'ordre de la catégorie dans la colonne.\n",
|
|
"\n",
|
|
"2. Encodeur catégoriel : il convient bien aux variables nominales, qui sont des variables catégorielles dont les données ne suivent pas un ordre logique, comme toutes les caractéristiques autres que `item_size` dans notre ensemble de données. Il s'agit d'un encodage en one-hot, ce qui signifie que chaque catégorie est représentée par une colonne binaire : la variable encodée est égale à 1 si la citrouille appartient à cette variété, et 0 sinon.\n",
|
|
"\n",
|
|
"Tidymodels propose un autre package pratique : [recipes](https://recipes.tidymodels.org/) - un package pour le prétraitement des données. Nous allons définir une `recipe` qui spécifie que toutes les colonnes prédictives doivent être encodées en un ensemble d'entiers, la `prep` pour estimer les quantités et statistiques nécessaires à toute opération, et enfin la `bake` pour appliquer les calculs aux nouvelles données.\n",
|
|
"\n",
|
|
"> En général, recipes est souvent utilisé comme préprocesseur pour la modélisation, où il définit les étapes à appliquer à un ensemble de données afin de le préparer à la modélisation. Dans ce cas, il est **fortement recommandé** d'utiliser un `workflow()` plutôt que d'estimer manuellement une recette avec prep et bake. Nous verrons tout cela dans un instant.\n",
|
|
">\n",
|
|
"> Cependant, pour l'instant, nous utilisons recipes + prep + bake pour spécifier les étapes à appliquer à un ensemble de données afin de le préparer à l'analyse des données, puis extraire les données prétraitées avec les étapes appliquées.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Preprocess and extract data to allow some data analysis\n",
|
|
"baked_pumpkins <- recipe(color ~ ., data = pumpkins_select) %>%\n",
|
|
" # Define ordering for item_size column\n",
|
|
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
|
|
" # Convert factors to numbers using the order defined above (Ordinal encoding)\n",
|
|
" step_integer(item_size, zero_based = F) %>%\n",
|
|
" # Encode all other predictors using one hot encoding\n",
|
|
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE) %>%\n",
|
|
" prep(data = pumpkin_select) %>%\n",
|
|
" bake(new_data = NULL)\n",
|
|
"\n",
|
|
"# Display the first few rows of preprocessed data\n",
|
|
"baked_pumpkins %>% \n",
|
|
" slice_head(n = 5)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"✅ Quels sont les avantages d'utiliser un encodeur ordinal pour la colonne Taille de l'Article ?\n",
|
|
"\n",
|
|
"### Analyser les relations entre les variables\n",
|
|
"\n",
|
|
"Maintenant que nous avons pré-traité nos données, nous pouvons analyser les relations entre les caractéristiques et l'étiquette afin de comprendre dans quelle mesure le modèle sera capable de prédire l'étiquette à partir des caractéristiques. La meilleure façon de réaliser ce type d'analyse est de représenter les données graphiquement. \n",
|
|
"Nous utiliserons à nouveau la fonction ggplot geom_boxplot_ pour visualiser les relations entre Taille de l'Article, Variété et Couleur dans un graphique catégoriel. Pour mieux représenter les données, nous utiliserons la colonne Taille de l'Article encodée et la colonne Variété non encodée.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Define the color palette\n",
|
|
"palette <- c(ORANGE = \"orange\", WHITE = \"wheat\")\n",
|
|
"\n",
|
|
"# We need the encoded Item Size column to use it as the x-axis values in the plot\n",
|
|
"pumpkins_select_plot<-pumpkins_select\n",
|
|
"pumpkins_select_plot$item_size <- baked_pumpkins$item_size\n",
|
|
"\n",
|
|
"# Create the grouped box plot\n",
|
|
"ggplot(pumpkins_select_plot, aes(x = `item_size`, y = color, fill = color)) +\n",
|
|
" geom_boxplot() +\n",
|
|
" facet_grid(variety ~ ., scales = \"free_x\") +\n",
|
|
" scale_fill_manual(values = palette) +\n",
|
|
" labs(x = \"Item Size\", y = \"\") +\n",
|
|
" theme_minimal() +\n",
|
|
" theme(strip.text = element_text(size = 12)) +\n",
|
|
" theme(axis.text.x = element_text(size = 10)) +\n",
|
|
" theme(axis.title.x = element_text(size = 12)) +\n",
|
|
" theme(axis.title.y = element_blank()) +\n",
|
|
" theme(legend.position = \"bottom\") +\n",
|
|
" guides(fill = guide_legend(title = \"Color\")) +\n",
|
|
" theme(panel.spacing = unit(0.5, \"lines\"))+\n",
|
|
" theme(strip.text.y = element_text(size = 4, hjust = 0)) \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Utiliser un swarm plot\n",
|
|
"\n",
|
|
"Étant donné que Color est une catégorie binaire (Blanc ou Non), elle nécessite 'une [approche spécialisée](https://github.com/rstudio/cheatsheets/blob/main/data-visualization.pdf) pour la visualisation'.\n",
|
|
"\n",
|
|
"Essayez un `swarm plot` pour montrer la distribution de la couleur par rapport à item_size.\n",
|
|
"\n",
|
|
"Nous utiliserons le [package ggbeeswarm](https://github.com/eclarke/ggbeeswarm), qui propose des méthodes pour créer des graphiques de type beeswarm à l'aide de ggplot2. Les graphiques beeswarm permettent de représenter des points qui se chevaucheraient normalement en les disposant côte à côte.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create beeswarm plots of color and item_size\n",
|
|
"baked_pumpkins %>% \n",
|
|
" mutate(color = factor(color)) %>% \n",
|
|
" ggplot(mapping = aes(x = color, y = item_size, color = color)) +\n",
|
|
" geom_quasirandom() +\n",
|
|
" scale_color_brewer(palette = \"Dark2\", direction = -1) +\n",
|
|
" theme(legend.position = \"none\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Maintenant que nous avons une idée de la relation entre les catégories binaires de couleur et le groupe plus large des tailles, explorons la régression logistique pour déterminer la couleur probable d'une citrouille donnée.\n",
|
|
"\n",
|
|
"## Construisez votre modèle\n",
|
|
"\n",
|
|
"Sélectionnez les variables que vous souhaitez utiliser dans votre modèle de classification et divisez les données en ensembles d'entraînement et de test. [rsample](https://rsample.tidymodels.org/), un package de Tidymodels, fournit une infrastructure pour une division et un rééchantillonnage efficaces des données :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Split data into 80% for training and 20% for testing\n",
|
|
"set.seed(2056)\n",
|
|
"pumpkins_split <- pumpkins_select %>% \n",
|
|
" initial_split(prop = 0.8)\n",
|
|
"\n",
|
|
"# Extract the data in each split\n",
|
|
"pumpkins_train <- training(pumpkins_split)\n",
|
|
"pumpkins_test <- testing(pumpkins_split)\n",
|
|
"\n",
|
|
"# Print out the first 5 rows of the training set\n",
|
|
"pumpkins_train %>% \n",
|
|
" slice_head(n = 5)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"🙌 Nous sommes maintenant prêts à entraîner un modèle en ajustant les caractéristiques d'entraînement à l'étiquette d'entraînement (couleur).\n",
|
|
"\n",
|
|
"Nous allons commencer par créer une recette qui spécifie les étapes de prétraitement à effectuer sur nos données pour les préparer à la modélisation, c'est-à-dire : encoder les variables catégoriques en un ensemble d'entiers. Tout comme `baked_pumpkins`, nous créons une `pumpkins_recipe` mais nous ne faisons pas de `prep` ni de `bake`, car cela sera intégré dans un workflow, comme vous le verrez dans quelques étapes.\n",
|
|
"\n",
|
|
"Il existe plusieurs façons de spécifier un modèle de régression logistique dans Tidymodels. Voir `?logistic_reg()`. Pour l'instant, nous allons spécifier un modèle de régression logistique via le moteur par défaut `stats::glm()`.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create a recipe that specifies preprocessing steps for modelling\n",
|
|
"pumpkins_recipe <- recipe(color ~ ., data = pumpkins_train) %>% \n",
|
|
" step_mutate(item_size = ordered(item_size, levels = c('sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo'))) %>%\n",
|
|
" step_integer(item_size, zero_based = F) %>% \n",
|
|
" step_dummy(all_nominal(), -all_outcomes(), one_hot = TRUE)\n",
|
|
"\n",
|
|
"# Create a logistic model specification\n",
|
|
"log_reg <- logistic_reg() %>% \n",
|
|
" set_engine(\"glm\") %>% \n",
|
|
" set_mode(\"classification\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Maintenant que nous avons une recette et une spécification de modèle, nous devons trouver un moyen de les regrouper dans un objet qui prétraitera d'abord les données (prep+bake en arrière-plan), ajustera le modèle sur les données prétraitées et permettra également des activités de post-traitement potentielles.\n",
|
|
"\n",
|
|
"Dans Tidymodels, cet objet pratique s'appelle un [`workflow`](https://workflows.tidymodels.org/) et contient commodément vos composants de modélisation.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Bundle modelling components in a workflow\n",
|
|
"log_reg_wf <- workflow() %>% \n",
|
|
" add_recipe(pumpkins_recipe) %>% \n",
|
|
" add_model(log_reg)\n",
|
|
"\n",
|
|
"# Print out the workflow\n",
|
|
"log_reg_wf\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Après qu'un workflow a été *spécifié*, un modèle peut être `entraîné` en utilisant la fonction [`fit()`](https://tidymodels.github.io/parsnip/reference/fit.html). Le workflow estimera une recette et prétraitera les données avant l'entraînement, ce qui nous évitera de le faire manuellement avec prep et bake.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Train the model\n",
|
|
"wf_fit <- log_reg_wf %>% \n",
|
|
" fit(data = pumpkins_train)\n",
|
|
"\n",
|
|
"# Print the trained workflow\n",
|
|
"wf_fit\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Le modèle affiche les coefficients appris pendant l'entraînement.\n",
|
|
"\n",
|
|
"Maintenant que nous avons entraîné le modèle avec les données d'entraînement, nous pouvons faire des prédictions sur les données de test en utilisant [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html). Commençons par utiliser le modèle pour prédire les étiquettes de notre ensemble de test ainsi que les probabilités pour chaque étiquette. Lorsque la probabilité est supérieure à 0,5, la classe prédite est `WHITE`, sinon c'est `ORANGE`.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Make predictions for color and corresponding probabilities\n",
|
|
"results <- pumpkins_test %>% select(color) %>% \n",
|
|
" bind_cols(wf_fit %>% \n",
|
|
" predict(new_data = pumpkins_test)) %>%\n",
|
|
" bind_cols(wf_fit %>%\n",
|
|
" predict(new_data = pumpkins_test, type = \"prob\"))\n",
|
|
"\n",
|
|
"# Compare predictions\n",
|
|
"results %>% \n",
|
|
" slice_head(n = 10)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Très bien ! Cela offre des perspectives supplémentaires sur le fonctionnement de la régression logistique.\n",
|
|
"\n",
|
|
"### Meilleure compréhension grâce à une matrice de confusion\n",
|
|
"\n",
|
|
"Comparer chaque prédiction avec sa valeur réelle \"vérité terrain\" correspondante n'est pas une méthode très efficace pour évaluer la qualité des prédictions du modèle. Heureusement, Tidymodels a quelques astuces supplémentaires dans sa manche : [`yardstick`](https://yardstick.tidymodels.org/) - un package utilisé pour mesurer l'efficacité des modèles à l'aide de métriques de performance.\n",
|
|
"\n",
|
|
"Une métrique de performance associée aux problèmes de classification est la [`matrice de confusion`](https://wikipedia.org/wiki/Confusion_matrix). Une matrice de confusion décrit la performance d'un modèle de classification. Elle répertorie combien d'exemples de chaque classe ont été correctement classés par un modèle. Dans notre cas, elle vous montrera combien de citrouilles orange ont été classées comme orange et combien de citrouilles blanches ont été classées comme blanches ; la matrice de confusion indique également combien ont été classées dans les catégories **erronées**.\n",
|
|
"\n",
|
|
"La fonction [**`conf_mat()`**](https://tidymodels.github.io/yardstick/reference/conf_mat.html) de yardstick calcule cette table croisée des classes observées et prédites.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Confusion matrix for prediction results\n",
|
|
"conf_mat(data = results, truth = color, estimate = .pred_class)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Interprétons la matrice de confusion. Notre modèle doit classer les citrouilles entre deux catégories binaires, la catégorie `blanche` et la catégorie `non-blanche`.\n",
|
|
"\n",
|
|
"- Si votre modèle prédit qu'une citrouille est blanche et qu'elle appartient réellement à la catégorie 'blanche', on appelle cela un `vrai positif`, représenté par le chiffre en haut à gauche.\n",
|
|
"\n",
|
|
"- Si votre modèle prédit qu'une citrouille n'est pas blanche et qu'elle appartient réellement à la catégorie 'blanche', on appelle cela un `faux négatif`, représenté par le chiffre en bas à gauche.\n",
|
|
"\n",
|
|
"- Si votre modèle prédit qu'une citrouille est blanche et qu'elle appartient réellement à la catégorie 'non-blanche', on appelle cela un `faux positif`, représenté par le chiffre en haut à droite.\n",
|
|
"\n",
|
|
"- Si votre modèle prédit qu'une citrouille n'est pas blanche et qu'elle appartient réellement à la catégorie 'non-blanche', on appelle cela un `vrai négatif`, représenté par le chiffre en bas à droite.\n",
|
|
"\n",
|
|
"| Vérité |\n",
|
|
"|:-----:|\n",
|
|
"\n",
|
|
"\n",
|
|
"| | | |\n",
|
|
"|---------------|--------|-------|\n",
|
|
"| **Prédit** | BLANC | ORANGE |\n",
|
|
"| BLANC | VP | FP |\n",
|
|
"| ORANGE | FN | VN |\n",
|
|
"\n",
|
|
"Comme vous l'avez probablement deviné, il est préférable d'avoir un plus grand nombre de vrais positifs et de vrais négatifs, et un plus petit nombre de faux positifs et de faux négatifs, ce qui implique que le modèle fonctionne mieux.\n",
|
|
"\n",
|
|
"La matrice de confusion est utile car elle donne naissance à d'autres métriques qui peuvent nous aider à mieux évaluer les performances d'un modèle de classification. Passons en revue certaines d'entre elles :\n",
|
|
"\n",
|
|
"🎓 Précision : `VP/(VP + FP)` définie comme la proportion de positifs prédits qui sont réellement positifs. Aussi appelée [valeur prédictive positive](https://en.wikipedia.org/wiki/Positive_predictive_value \"Positive predictive value\").\n",
|
|
"\n",
|
|
"🎓 Rappel : `VP/(VP + FN)` défini comme la proportion de résultats positifs parmi le nombre d'échantillons qui étaient réellement positifs. Aussi connu sous le nom de `sensibilité`.\n",
|
|
"\n",
|
|
"🎓 Spécificité : `VN/(VN + FP)` définie comme la proportion de résultats négatifs parmi le nombre d'échantillons qui étaient réellement négatifs.\n",
|
|
"\n",
|
|
"🎓 Exactitude : `VP + VN/(VP + VN + FP + FN)` Le pourcentage d'étiquettes prédites correctement pour un échantillon.\n",
|
|
"\n",
|
|
"🎓 F-Mesure : Une moyenne pondérée de la précision et du rappel, avec un maximum de 1 et un minimum de 0.\n",
|
|
"\n",
|
|
"Calculons ces métriques !\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Combine metric functions and calculate them all at once\n",
|
|
"eval_metrics <- metric_set(ppv, recall, spec, f_meas, accuracy)\n",
|
|
"eval_metrics(data = results, truth = color, estimate = .pred_class)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Visualiser la courbe ROC de ce modèle\n",
|
|
"\n",
|
|
"Faisons une dernière visualisation pour observer la fameuse [`courbe ROC`](https://en.wikipedia.org/wiki/Receiver_operating_characteristic) :\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Make a roc_curve\n",
|
|
"results %>% \n",
|
|
" roc_curve(color, .pred_ORANGE) %>% \n",
|
|
" autoplot()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Les courbes ROC sont souvent utilisées pour visualiser les performances d'un classificateur en termes de vrais positifs par rapport aux faux positifs. Les courbes ROC présentent généralement le `Taux de Vrais Positifs`/Sensibilité sur l'axe Y, et le `Taux de Faux Positifs`/1-Spécificité sur l'axe X. Ainsi, la pente de la courbe et l'espace entre la ligne médiane et la courbe sont importants : vous voulez une courbe qui monte rapidement et dépasse la ligne. Dans notre cas, il y a des faux positifs au départ, puis la courbe monte et dépasse correctement.\n",
|
|
"\n",
|
|
"Enfin, utilisons `yardstick::roc_auc()` pour calculer la véritable Aire Sous la Courbe. Une façon d'interpréter l'AUC est comme la probabilité que le modèle classe un exemple positif aléatoire plus haut qu'un exemple négatif aléatoire.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "r"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Calculate area under curve\n",
|
|
"results %>% \n",
|
|
" roc_auc(color, .pred_ORANGE)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Le résultat est d'environ `0,975`. Étant donné que l'AUC varie de 0 à 1, vous voulez obtenir un score élevé, car un modèle qui fait des prédictions 100 % correctes aura une AUC de 1 ; dans ce cas, le modèle est *plutôt bon*.\n",
|
|
"\n",
|
|
"Dans les prochaines leçons sur les classifications, vous apprendrez comment améliorer les scores de votre modèle (comme gérer les données déséquilibrées dans ce cas).\n",
|
|
"\n",
|
|
"## 🚀Défi\n",
|
|
"\n",
|
|
"Il y a beaucoup à découvrir sur la régression logistique ! Mais la meilleure façon d'apprendre est d'expérimenter. Trouvez un jeu de données qui se prête à ce type d'analyse et construisez un modèle avec celui-ci. Qu'apprenez-vous ? astuce : essayez [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) pour trouver des jeux de données intéressants.\n",
|
|
"\n",
|
|
"## Révision & Étude personnelle\n",
|
|
"\n",
|
|
"Lisez les premières pages de [cet article de Stanford](https://web.stanford.edu/~jurafsky/slp3/5.pdf) sur certaines utilisations pratiques de la régression logistique. Réfléchissez aux tâches qui conviennent mieux à l'un ou l'autre type de régression parmi celles que nous avons étudiées jusqu'à présent. Qu'est-ce qui fonctionnerait le mieux ?\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**Avertissement** : \nCe document a été traduit à l'aide du service de traduction automatique [Co-op Translator](https://github.com/Azure/co-op-translator). Bien que nous nous efforcions d'assurer l'exactitude, veuillez noter que les traductions automatisées peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue d'origine doit être considéré comme la source faisant autorité. Pour des informations critiques, il est recommandé de faire appel à une traduction humaine professionnelle. Nous déclinons toute responsabilité en cas de malentendus ou d'interprétations erronées résultant de l'utilisation de cette traduction.\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"anaconda-cloud": "",
|
|
"kernelspec": {
|
|
"display_name": "R",
|
|
"langauge": "R",
|
|
"name": "ir"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": "r",
|
|
"file_extension": ".r",
|
|
"mimetype": "text/x-r-source",
|
|
"name": "R",
|
|
"pygments_lexer": "r",
|
|
"version": "3.4.1"
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "feaf125f481a89c468fa115bf2aed580",
|
|
"translation_date": "2025-09-04T01:21:13+00:00",
|
|
"source_file": "2-Regression/4-Logistic/solution/R/lesson_4-R.ipynb",
|
|
"language_code": "fr"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 1
|
|
} |