INTRODUCTION

Le diabète de type 2 est une maladie chronique qui touche des millions de personnes à travers le monde. Il constitue un enjeu majeur de santé publique en raison de ses complications graves (cardiovasculaires, rénales, neurologiques) et de son impact économique sur les systèmes de santé. La prévention et le dépistage précoce sont donc essentiels pour limiter sa progression et améliorer la qualité de vie des patients.

Dans ce projet, l’objectif est de prédire la probabilité qu’un individu soit atteint de diabète de type 2 à partir de variables cliniques mesurées lors d’un examen médical. Cette approche s’inscrit dans une logique de médecine préventive appuyée par l’intelligence artificielle et l’analyse statistique.

Pour cela, nous utilisons la base de données PimaIndiansDiabetes2 issue du package mlbench. Cette base contient des informations cliniques sur des femmes d’origine Pima (population amérindienne), incluant des variables telles que la glycémie, la pression artérielle, l’indice de masse corporelle (IMC), l’âge, et d’autres indicateurs pertinents. Elle est largement utilisée dans la communauté scientifique pour tester des modèles de classification supervisée.

Plusieurs chercheurs ont exploré cette base dans des travaux récents. Par exemple, Ali, Galal et Hassan (2025) ont développé un pipeline de machine learning robuste pour prédire le diabète à partir de cette base, en appliquant des techniques d’imputation, de normalisation et d’ensembles de modèles. De même, Arora, Sehgal, Sharma, Nayak et Kumar (2024) ont comparé différentes méthodes de fouille de données pour améliorer la précision du diagnostic précoce du diabète à l’aide de cette même base.

EXPLORATION DES DONNEES

Description des variables

La base de données PimaIndiansDiabetes2 contient des observations cliniques de femmes d’origine Pima âgées de 21 ans ou plus. Chaque ligne représente un individu, et les colonnes correspondent à des variables médicales utilisées pour prédire la présence ou non de diabète de type 2. Voici les variables disponibles :

  • pregnant : Nombre de grossesses antérieures
  • glucose : Concentration de glucose plasmatique à jeun (mg/dL)
  • pressure : Pression artérielle diastolique (mm Hg)
  • triceps : Épaisseur du pli cutané tricipital (mm)
  • insulin : Concentration d’insuline sérique (mu U/ml)
  • mass : Indice de masse corporelle (IMC), calculé comme poids (kg) / taille² (m²)
  • pedigree : Fonction génétique du diabète (antécédents familiaux pondérés)
  • age : Âge de la patiente (en années)
  • diabetes : Variable cible (facteur binaire : “pos” pour diabétique, “neg” pour non-diabétique)

Certaines valeurs manquantes sont codées comme NA, notamment pour les variables glucose, pressure, triceps, insulin, et mass. Il est donc nécessaire de les traiter lors du prétraitement des données.

Analyse des données manquantes

Avant toute modélisation, il est essentiel d’identifier les valeurs manquantes dans la base. Cela permet de décider s’il faut les imputer, les supprimer ou les traiter autrement.

library(mlbench)
## Warning: le package 'mlbench' a été compilé avec la version R 4.4.3
library(tidyverse)
## Warning: le package 'tidyverse' a été compilé avec la version R 4.4.3
## Warning: le package 'ggplot2' a été compilé avec la version R 4.4.2
## Warning: le package 'dplyr' a été compilé avec la version R 4.4.2
## Warning: le package 'lubridate' a été compilé avec la version R 4.4.2
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(naniar)
## Warning: le package 'naniar' a été compilé avec la version R 4.4.3
data(PimaIndiansDiabetes2)
df <- PimaIndiansDiabetes2

# Visualisation des valeurs manquantes avec couleurs personnalisées
vis_miss(df) +
  theme_minimal() +
  labs(title = "Visualisation des valeurs manquantes",
       subtitle = "Présent (grise) vs Manquant (rouge)",
       x = "Variables",
       y = "Observations") +
  scale_fill_manual(values = c("grey", "red"),
                    name = "Statut",
                    labels = c("Présent", "Manquant"))
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.

# Aperçu des données manquantes
summary(df)
##     pregnant         glucose         pressure         triceps     
##  Min.   : 0.000   Min.   : 44.0   Min.   : 24.00   Min.   : 7.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 64.00   1st Qu.:22.00  
##  Median : 3.000   Median :117.0   Median : 72.00   Median :29.00  
##  Mean   : 3.845   Mean   :121.7   Mean   : 72.41   Mean   :29.15  
##  3rd Qu.: 6.000   3rd Qu.:141.0   3rd Qu.: 80.00   3rd Qu.:36.00  
##  Max.   :17.000   Max.   :199.0   Max.   :122.00   Max.   :99.00  
##                   NA's   :5       NA's   :35       NA's   :227    
##     insulin            mass          pedigree           age        diabetes 
##  Min.   : 14.00   Min.   :18.20   Min.   :0.0780   Min.   :21.00   neg:500  
##  1st Qu.: 76.25   1st Qu.:27.50   1st Qu.:0.2437   1st Qu.:24.00   pos:268  
##  Median :125.00   Median :32.30   Median :0.3725   Median :29.00            
##  Mean   :155.55   Mean   :32.46   Mean   :0.4719   Mean   :33.24            
##  3rd Qu.:190.00   3rd Qu.:36.60   3rd Qu.:0.6262   3rd Qu.:41.00            
##  Max.   :846.00   Max.   :67.10   Max.   :2.4200   Max.   :81.00            
##  NA's   :374      NA's   :11
# Visualisation professionnelle des valeurs manquantes
vis_miss(df)  # Visualisation graphique des valeurs manquantes

Notre graphique précise que notre jeu de données contient 9,4 % de valeurs manquantes au total (contre 90,6 % de valeurs observées). Nous présentons le tableau ci dessus pour une explication des variables manquantes. ### Tableau : Taux de valeurs manquantes et interprétation

Variable % de valeurs manquantes Interprétation
pregnant 0 % Aucun manque, variable complète.
glucose 1 % Très peu de données manquantes — probablement négligeable.
pressure 5 % Quelques manques, mais encore gérable par imputation simple.
triceps 30 % Taux de valeurs manquantes élevé. Cela peut influencer les analyses statistiques.
insulin 49 % Presque la moitié des données manquent — problématique pour les analyses multivariées.
mass 1 % Très faible proportion de manquants.
pedigree, age, diabetes 0 % Données complètes.

L’analyse des valeurs manquantes montre que les variables insulin (49 %) et triceps (30 %) présentent des taux de données manquantes élevés, ce qui pourrait biaiser les analyses statistiques si ces valeurs ne sont pas imputées. Les autres variables présentent des taux de manquants inférieurs à 5 %, considérés comme acceptables pour les traitements classiques.

Analyse des distributions des variables

L’analyse des distributions permet de mieux comprendre la structure des données, d’identifier les asymétries, les valeurs extrêmes, et de guider les choix de transformation ou de modélisation. Voici une visualisation des variables cliniques disponibles dans la base.

library(mlbench)
library(tidyverse)

data(PimaIndiansDiabetes2)
df <- PimaIndiansDiabetes2

# Visualisation des distributions (hors variable cible)
df %>%
  select(-diabetes) %>%
  gather(variable, value) %>%
  ggplot(aes(x = value)) +
  geom_histogram(bins = 30, fill = "steelblue", color = "white") +
  facet_wrap(~variable, scales = "free") +
  labs(title = "Distribution des variables cliniques",
       x = "Valeur",
       y = "Fréquence") +
  theme_minimal(base_size = 14)
## Warning: Removed 652 rows containing non-finite outside the scale range
## (`stat_bin()`).

Interprétation

Certaines variables comme glucose, mass et age présentent des distributions asymétriques, ce qui pourrait nécessiter une transformation (logarithmique ou normalisation).Les variables triceps et insulin montrent des concentrations autour de zéro, probablement dues aux valeurs manquantes ou mal enregistrées.La variable pregnant est discrète, avec une majorité de patientes ayant eu peu ou pas de grossesses.

##Comparaison selon le statut diabétique

df %>%
  gather(variable, value, -diabetes) %>%
  ggplot(aes(x = value, fill = diabetes)) +
  geom_density(alpha = 0.5) +
  facet_wrap(~variable, scales = "free") +
  labs(title = "Distributions selon le statut diabétique",
       x = "Valeur",
       y = "Densité") +
  scale_fill_manual(values = c("dodgerblue", "firebrick"),
                    name = "Diabète",
                    labels = c("Non diabétique", "Diabétique")) +
  theme_minimal(base_size = 14)
## Warning: Removed 652 rows containing non-finite outside the scale range
## (`stat_density()`).

Nous observons de plus que les patientes diabétiques tendent à avoir des niveaux de glucose et d’IMC plus élevés.La fonction génétique (pedigree) semble légèrement plus concentrée chez les diabétiques. Ces différences justifient l’utilisation de ces variables comme prédicteurs dans un modèle supervisé.

Corrélation entre les variables cliniques et le statut diabétique

Pour identifier les variables les plus informatives dans la prédiction du diabète, nous évaluons la corrélation entre chaque variable numérique et la variable cible diabetes. Comme diabetes est une variable binaire, nous utilisons des tests adaptés : corrélation de point bisérial ou comparaison des moyennes.

##Corrélation entre les variables cliniques et la cible diabetes

library(mlbench)
library(tidyverse)
library(corrplot)
## Warning: le package 'corrplot' a été compilé avec la version R 4.4.3
## corrplot 0.95 loaded
# Conversion de la variable cible en numérique (0 = neg, 1 = pos)
df$diabetes_num <- ifelse(df$diabetes == "pos", 1, 0)

# Sélection des variables numériques
num_vars <- df %>% select(-diabetes, -diabetes_num) %>% select_if(is.numeric)

# Calcul des corrélations avec la cible
correlations <- sapply(num_vars, function(x) cor(x, df$diabetes_num, use = "complete.obs"))

# Affichage sous forme de tableau
cor_df <- data.frame(Variable = names(correlations), Correlation = round(correlations, 3))
cor_df %>% arrange(desc(abs(Correlation)))
##          Variable Correlation
## glucose   glucose       0.495
## mass         mass       0.314
## insulin   insulin       0.303
## triceps   triceps       0.259
## age           age       0.238
## pregnant pregnant       0.222
## pedigree pedigree       0.174
## pressure pressure       0.171

##Interprétation stratégique de la corrélation

Synthèse des corrélations et recommandations d’imputation

Variable Corrélation avec diabetes Taux de valeurs manquantes Décision recommandée
glucose 0.495 (forte) Faible ✅ Imputer par médiane
mass 0.314 (modérée) Faible ✅ Imputer par médiane
insulin 0.303 (modérée) Élevé (49%) ⚠️ Imputer avec MICE ou tester sans
triceps 0.259 (modérée) Modéré (30%) ✅ Imputer avec KNN ou MICE
age 0.238 (modérée) Aucun ✅ Utiliser directement
pregnant 0.222 (modérée) Faible ✅ Imputer par médiane
pedigree 0.174 (faible) Aucun ✅ Utiliser directement
pressure 0.171 (faible) Faible ✅ Imputer par médiane

##Traitement des valeurs manquantes

Traitement des valeurs manquantes selon la stratégie définie

Chargement des packages

library(mlbench)
library(mice)
## Warning: le package 'mice' a été compilé avec la version R 4.4.3
## 
## Attachement du package : 'mice'
## L'objet suivant est masqué depuis 'package:stats':
## 
##     filter
## Les objets suivants sont masqués depuis 'package:base':
## 
##     cbind, rbind
library(VIM)
## Warning: le package 'VIM' a été compilé avec la version R 4.4.3
## Le chargement a nécessité le package : colorspace
## Le chargement a nécessité le package : grid
## VIM is ready to use.
## Suggestions and bug-reports can be submitted at: https://github.com/statistikat/VIM/issues
## 
## Attachement du package : 'VIM'
## L'objet suivant est masqué depuis 'package:datasets':
## 
##     sleep
library(tidyverse)

# Chargement des données
data(PimaIndiansDiabetes2)
df <- PimaIndiansDiabetes2

# Étape 1 : Imputation par médiane
median_vars <- c("pregnant", "pressure", "mass", "glucose")
for (var in median_vars) {
  df[[var]][is.na(df[[var]])] <- median(df[[var]], na.rm = TRUE)
}

# Étape 2 : Imputation par KNN pour triceps
df_knn <- kNN(df, variable = "triceps", k = 5, imp_var = FALSE)
## pregnant  glucose pressure  insulin     mass pedigree      age pregnant 
##    0.000   44.000   24.000   14.000   18.200    0.078   21.000   17.000 
##  glucose pressure  insulin     mass pedigree      age 
##  199.000  122.000  846.000   67.100    2.420   81.000
# Étape 3 : Imputation par MICE pour insulin
# On applique MICE uniquement sur insulin, en utilisant les autres variables comme prédicteurs
mice_input <- df_knn %>% select(insulin, glucose, mass, age, pregnant, pressure, triceps, diabetes)
mice_result <- mice(mice_input, method = "rf", m = 5, seed = 123)
## 
##  iter imp variable
##   1   1  insulin
##   1   2  insulin
##   1   3  insulin
##   1   4  insulin
##   1   5  insulin
##   2   1  insulin
##   2   2  insulin
##   2   3  insulin
##   2   4  insulin
##   2   5  insulin
##   3   1  insulin
##   3   2  insulin
##   3   3  insulin
##   3   4  insulin
##   3   5  insulin
##   4   1  insulin
##   4   2  insulin
##   4   3  insulin
##   4   4  insulin
##   4   5  insulin
##   5   1  insulin
##   5   2  insulin
##   5   3  insulin
##   5   4  insulin
##   5   5  insulin
# Remplacement de la variable insulin imputée
df_knn$insulin <- complete(mice_result)$insulin

# Résultat final
df_final <- df_knn

# Vérification
summary(df_final)
##     pregnant         glucose          pressure         triceps     
##  Min.   : 0.000   Min.   : 44.00   Min.   : 24.00   Min.   : 7.00  
##  1st Qu.: 1.000   1st Qu.: 99.75   1st Qu.: 64.00   1st Qu.:23.00  
##  Median : 3.000   Median :117.00   Median : 72.00   Median :30.00  
##  Mean   : 3.845   Mean   :121.66   Mean   : 72.39   Mean   :29.25  
##  3rd Qu.: 6.000   3rd Qu.:140.25   3rd Qu.: 80.00   3rd Qu.:35.00  
##  Max.   :17.000   Max.   :199.00   Max.   :122.00   Max.   :99.00  
##     insulin           mass          pedigree           age        diabetes 
##  Min.   : 14.0   Min.   :18.20   Min.   :0.0780   Min.   :21.00   neg:500  
##  1st Qu.: 76.0   1st Qu.:27.50   1st Qu.:0.2437   1st Qu.:24.00   pos:268  
##  Median :125.0   Median :32.30   Median :0.3725   Median :29.00            
##  Mean   :156.1   Mean   :32.46   Mean   :0.4719   Mean   :33.24            
##  3rd Qu.:188.5   3rd Qu.:36.60   3rd Qu.:0.6262   3rd Qu.:41.00            
##  Max.   :846.0   Max.   :67.10   Max.   :2.4200   Max.   :81.00

##pour prédire la probabilité d’etre diabétique en fonction de plusieurs variables cliniques. ## Deux échantillons : 80% en apprentissage et 20% en test.

sample_n(df_final, 3)
##   pregnant glucose pressure triceps insulin mass pedigree age diabetes
## 1        1     117       60      23     106 33.8    0.466  27      neg
## 2        6     154       78      41     140 46.1    0.571  27      neg
## 3        2      83       66      23      50 32.2    0.497  22      neg

Construction des deux échantillons

library(caret)
## Warning: le package 'caret' a été compilé avec la version R 4.4.2
## Le chargement a nécessité le package : lattice
## 
## Attachement du package : 'caret'
## L'objet suivant est masqué depuis 'package:purrr':
## 
##     lift
set.seed(123)
training.samples <- df_final$diabetes %>% 
  createDataPartition(p = 0.8, list = FALSE)
train.data  <- df_final[training.samples, ]
test.data <- df_final[-training.samples, ]

##Créons la matrice des prédicteurs

creation de la matrice des predicteurs

x <- model.matrix(diabetes~., train.data)[,-1]

recodification de la variable dépendante

y <- ifelse(train.data$diabetes == "pos", 1, 0)

##Justification du choix de la régression Lasso

Dans le cadre de notre étude visant à prédire la probabilité d’être diabétique à partir de variables cliniques, nous avons appliqué un traitement rigoureux des données manquantes, suivi d’une analyse exploratoire des distributions et des corrélations. Ce processus a révélé que certaines variables (comme glucose, mass, insulin, triceps) présentent une corrélation modérée à forte avec le statut diabétique, tandis que d’autres sont moins informatives.

Compte tenu de cette hétérogénéité, la régression Lasso s’est imposée comme une méthode particulièrement adaptée pour les raisons suivantes :

Sélection automatique de variables : Lasso applique une pénalisation L1 qui permet d’éliminer les variables peu contributives en mettant leurs coefficients à zéro. Cela favorise un modèle plus parcimonieux et interprétable.

Réduction du surajustement : En limitant la complexité du modèle, Lasso améliore la généralisation sur de nouvelles données, ce qui est essentiel dans un contexte clinique.

Robustesse après imputation : Notre pipeline d’imputation (médiane, KNN, MICE) a permis de reconstituer un jeu de données complet. Lasso est compatible avec ce type de données et permet de tester la pertinence des variables imputées.

Alignement avec l’objectif prédictif : Le modèle Lasso, intégré dans une régression logistique pénalisée, permet d’estimer la probabilité d’être diabétique tout en optimisant la sélection des prédicteurs.

library(glmnet)
## Warning: le package 'glmnet' a été compilé avec la version R 4.4.2
## Le chargement a nécessité le package : Matrix
## 
## Attachement du package : 'Matrix'
## Les objets suivants sont masqués depuis 'package:tidyr':
## 
##     expand, pack, unpack
## Loaded glmnet 4.1-8
lasso <- glmnet(x, y, family = "binomial", alpha = 1, lambda = NULL)
plot(lasso)

Recherche du meilleur lambda par cross-validation

set.seed(123) 
cv.lasso <- cv.glmnet(x, y, alpha = 1, family = "binomial")

str(cv.lasso)
## List of 12
##  $ lambda    : num [1:59] 0.232 0.211 0.192 0.175 0.16 ...
##  $ cvm       : num [1:59] 1.29 1.26 1.23 1.2 1.18 ...
##  $ cvsd      : num [1:59] 0.0225 0.0234 0.0228 0.0229 0.0233 ...
##  $ cvup      : num [1:59] 1.32 1.28 1.25 1.22 1.2 ...
##  $ cvlo      : num [1:59] 1.27 1.24 1.2 1.18 1.15 ...
##  $ nzero     : Named int [1:59] 0 1 1 1 1 1 1 1 2 2 ...
##   ..- attr(*, "names")= chr [1:59] "s0" "s1" "s2" "s3" ...
##  $ call      : language cv.glmnet(x = x, y = y, alpha = 1, family = "binomial")
##  $ name      : Named chr "Binomial Deviance"
##   ..- attr(*, "names")= chr "deviance"
##  $ glmnet.fit:List of 13
##   ..$ a0        : Named num [1:59] -0.621 -0.984 -1.316 -1.621 -1.904 ...
##   .. ..- attr(*, "names")= chr [1:59] "s0" "s1" "s2" "s3" ...
##   ..$ beta      :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
##   .. .. ..@ i       : int [1:334] 1 1 1 1 1 1 1 1 5 1 ...
##   .. .. ..@ p       : int [1:60] 0 0 1 2 3 4 5 6 7 9 ...
##   .. .. ..@ Dim     : int [1:2] 8 59
##   .. .. ..@ Dimnames:List of 2
##   .. .. .. ..$ : chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. .. .. ..$ : chr [1:59] "s0" "s1" "s2" "s3" ...
##   .. .. ..@ x       : num [1:334] 0.00297 0.00566 0.00813 0.01041 0.01252 ...
##   .. .. ..@ factors : list()
##   ..$ df        : int [1:59] 0 1 1 1 1 1 1 1 2 2 ...
##   ..$ dim       : int [1:2] 8 59
##   ..$ lambda    : num [1:59] 0.232 0.211 0.192 0.175 0.16 ...
##   ..$ dev.ratio : num [1:59] -6.18e-15 3.08e-02 5.63e-02 7.75e-02 9.54e-02 ...
##   ..$ nulldev   : num 796
##   ..$ npasses   : int 364
##   ..$ jerr      : int 0
##   ..$ offset    : logi FALSE
##   ..$ classnames: chr [1:2] "0" "1"
##   ..$ call      : language glmnet(x = x, y = y, alpha = 1, family = "binomial")
##   ..$ nobs      : int 615
##   ..- attr(*, "class")= chr [1:2] "lognet" "glmnet"
##  $ lambda.min: num 0.00321
##  $ lambda.1se: num 0.0476
##  $ index     : int [1:2, 1] 47 18
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "min" "1se"
##   .. ..$ : chr "Lambda"
##  - attr(*, "class")= chr "cv.glmnet"

modele avec le lambda optimal sur apprentissage

model <- glmnet(x, y, alpha = 1, family = "binomial",
                lambda = cv.lasso$lambda.min)
str(model)
## List of 13
##  $ a0        : Named num -8.38
##   ..- attr(*, "names")= chr "s0"
##  $ beta      :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
##   .. ..@ i       : int [1:8] 0 1 2 3 4 5 6 7
##   .. ..@ p       : int [1:2] 0 8
##   .. ..@ Dim     : int [1:2] 8 1
##   .. ..@ Dimnames:List of 2
##   .. .. ..$ : chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. .. ..$ : chr "s0"
##   .. ..@ x       : num [1:8] 0.094856 0.034971 -0.006537 0.014832 0.000129 ...
##   .. ..@ factors : list()
##  $ df        : int 8
##  $ dim       : int [1:2] 8 1
##  $ lambda    : num 0.00321
##  $ dev.ratio : num 0.262
##  $ nulldev   : num 796
##  $ npasses   : int 30
##  $ jerr      : int 0
##  $ offset    : logi FALSE
##  $ classnames: chr [1:2] "0" "1"
##  $ call      : language glmnet(x = x, y = y, family = "binomial", alpha = 1, lambda = cv.lasso$lambda.min)
##  $ nobs      : int 615
##  - attr(*, "class")= chr [1:2] "lognet" "glmnet"

Coeffs de regression

coef(model)
## 9 x 1 sparse Matrix of class "dgCMatrix"
##                        s0
## (Intercept) -8.3751350342
## pregnant     0.0948555492
## glucose      0.0349713795
## pressure    -0.0065374804
## triceps      0.0148321673
## insulin      0.0001293714
## mass         0.0685062734
## pedigree     0.7843532950
## age          0.0104174307

Predictions sur données test

x.test <- model.matrix(diabetes ~., test.data)[,-1]
x.test
##     pregnant glucose pressure triceps insulin mass pedigree age
## 2          1      85       66      29      43 26.6    0.351  31
## 5          0     137       40      35     168 43.1    2.288  33
## 17         0     118       84      47     230 45.8    0.551  31
## 25        11     143       94      33     146 36.6    0.254  51
## 27         7     147       76      32     125 39.4    0.257  43
## 34         6      92       92      27     110 19.9    0.188  28
## 36         4     103       60      33     192 24.0    0.966  33
## 41         3     180       64      25      70 34.0    0.271  26
## 53         5      88       66      21      23 24.4    0.342  30
## 54         8     176       90      34     300 33.7    0.467  58
## 57         7     187       68      39     304 37.7    0.254  41
## 66         5      99       74      27      50 29.0    0.203  32
## 67         0     109       88      30      74 32.5    0.855  38
## 68         2     109       92      30     105 42.7    0.845  54
## 71         2     100       66      20      90 32.9    0.867  28
## 76         1     117       48      20     291 24.7    0.140  22
## 78         5      95       72      33      77 37.7    0.370  27
## 80         2     112       66      22     176 25.0    0.307  24
## 82         2      74       72      28      40 32.3    0.102  22
## 85         5     137      108      36     160 48.8    0.227  37
## 91         1      80       55      15     105 19.1    0.258  21
## 93         7      81       78      40      48 46.7    0.261  42
## 96         6     144       72      27     228 33.9    0.255  40
## 98         1      71       48      18      76 20.4    0.323  22
## 103        0     125       96      22     105 22.5    0.262  21
## 106        1     126       56      29     152 28.7    0.801  21
## 109        3      83       58      31      18 34.3    0.336  25
## 115        7     160       54      32     175 30.5    0.588  39
## 117        5     124       74      30     126 34.0    0.220  38
## 124        5     132       80      26      22 26.8    0.186  69
## 131        4     173       70      14     168 29.7    0.361  33
## 132        9     122       56      31     342 33.3    1.114  33
## 140        5     105       72      29     325 36.9    0.159  28
## 148        2     106       64      35     119 30.5    1.400  34
## 152        4     114       65      24     125 21.9    0.432  37
## 156        7     152       88      44     545 50.0    0.337  36
## 157        2      99       52      15      94 24.6    0.637  21
## 165        0     131       88      30     180 31.6    0.743  32
## 175        2      75       64      24      55 29.7    0.370  33
## 176        8     179       72      42     130 32.7    0.719  36
## 190        5     139       80      35     160 31.6    0.361  25
## 192        9     123       70      44      94 33.1    0.374  40
## 195        8      85       55      20      49 24.4    0.136  42
## 201        0     113       80      16     183 31.0    0.874  21
## 206        5     111       72      28      68 23.9    0.407  27
## 209        1      96       64      27      87 33.2    0.289  21
## 217        5     109       62      41     129 35.8    0.514  25
## 225        1     100       66      15      56 23.6    0.666  26
## 229        4     197       70      39     744 36.7    2.329  31
## 232        6     134       80      37     370 46.2    0.238  46
## 233        1      79       80      25      37 25.4    0.583  22
## 239        9     164       84      21     132 30.8    0.831  32
## 240        0     104       76      20      68 18.4    0.582  27
## 242        4      91       70      32      88 33.1    0.446  22
## 246        9     184       85      15     144 30.0    1.213  49
## 256        1     113       64      35      96 33.6    0.543  21
## 261        3     191       68      15     130 30.9    0.299  34
## 265        4     123       62      29     190 32.0    0.226  35
## 269        0     102       52      20      63 25.1    0.078  21
## 273        3     122       78      36     110 23.0    0.254  40
## 280        2     108       62      10     278 25.3    0.881  22
## 284        7     161       86      32     285 30.4    0.165  47
## 289        4      96       56      17      49 20.8    0.340  26
## 290        5     108       72      43      75 36.1    0.263  33
## 295        0     161       50      20     140 21.9    0.254  65
## 297        2     146       70      38     360 28.0    0.337  29
## 299       14     100       78      25     184 36.6    0.412  46
## 314        3     113       50      10      85 29.5    0.626  25
## 324       13     152       90      33      29 26.8    0.731  43
## 332        2      87       58      16      52 32.7    0.166  25
## 334       12     106       80      31     128 23.6    0.137  44
## 340        7     178       84      32     155 39.9    0.331  41
## 371        3     173       82      48     465 38.4    2.137  25
## 374        2     105       58      40      94 34.9    0.225  25
## 377        0      98       82      15      84 25.2    0.299  22
## 379        4     156       75      36     120 48.3    0.238  32
## 382        0     105       68      22      82 20.0    0.236  22
## 384        1      90       62      18      59 25.1    1.268  25
## 388        8     105      100      36     155 43.3    0.239  45
## 392        5     166       76      36     321 45.7    0.340  27
## 396        2     127       58      24     275 27.7    1.600  25
## 399        3      82       70      22      87 21.1    0.389  25
## 421        1     119       88      41     170 45.3    0.507  26
## 438        5     147       75      27     193 29.9    0.434  28
## 442        2      83       66      23      50 32.2    0.497  22
## 444        8     108       70      31     168 30.5    0.955  33
## 447        1     100       72      12      70 25.3    0.658  28
## 452        2     134       70      30     250 28.9    0.542  23
## 476        0     137       84      27     148 27.3    0.231  59
## 477        2     105       80      45     191 33.7    0.711  29
## 480        4     132       86      31     330 28.0    0.419  63
## 492        2      89       90      30     108 33.5    0.292  42
## 498        2      81       72      15      76 30.1    0.547  25
## 499        7     195       70      33     145 25.1    0.163  55
## 509        2      84       50      23      76 30.4    0.968  21
## 517        9     145       88      34     165 30.3    0.771  53
## 521        2      68       70      32      66 25.0    0.187  25
## 523        6     114       72      28     120 32.3    0.189  26
## 525        3     125       58      24     275 31.6    0.151  24
## 526        3      87       60      18      76 21.8    0.444  21
## 533        1      86       66      52      65 41.3    0.917  29
## 538        0      57       60      20     600 21.7    0.735  67
## 546        8     186       90      35     225 34.5    0.423  37
## 547        5     187       76      27     207 43.6    1.034  53
## 549        1     164       82      43      67 32.8    0.341  50
## 555        1      84       64      23     115 36.9    0.471  28
## 560       11      85       74      27      94 30.1    0.300  35
## 575        1     143       86      30     330 30.1    0.892  23
## 577        6     108       44      20     130 24.0    0.813  35
## 578        2     118       80      35     120 42.9    0.693  21
## 588        6     103       66      27     215 24.3    0.249  29
## 591       11     111       84      40     215 46.8    0.925  45
## 592        2     112       78      50     140 39.4    0.175  24
## 605        4     183       72      31      56 28.4    0.212  36
## 609        0     152       82      39     272 41.5    0.270  27
## 615       11     138       74      26     144 36.1    0.557  50
## 619        9     112       82      24     175 28.2    1.282  50
## 622        2      92       76      20      49 24.2    1.698  28
## 624        0      94       70      27     115 43.5    0.347  21
## 628        0     132       78      26     275 32.4    0.393  21
## 633        2     111       60      23      56 26.2    0.343  23
## 635       10      92       62      27      23 25.9    0.167  31
## 637        5     104       74      30     275 28.8    0.153  48
## 642        4     128       70      32      88 34.3    0.303  24
## 648        0     179       50      36     159 37.8    0.455  22
## 649       11     136       84      35     130 28.3    0.260  42
## 650        0     107       60      25     192 26.4    0.133  23
## 655        1     106       70      28     135 34.2    0.142  22
## 659       11     127      106      33     140 39.0    0.190  51
## 661       10     162       84      31      60 27.7    0.182  54
## 663        8     167      106      46     231 37.6    0.165  43
## 674        3     123      100      35     240 57.3    0.880  22
## 678        0      93       60      31     100 35.3    0.263  25
## 683        0      95       64      39     105 44.6    0.366  22
## 687        3     130       64      22     170 23.1    0.314  22
## 694        7     129       68      49     125 38.5    0.439  43
## 701        2     122       76      27     200 35.9    0.483  26
## 704        2     129       72      39     194 38.5    0.304  41
## 705        4     110       76      20     100 28.4    0.118  27
## 713       10     129       62      36     130 41.2    0.441  38
## 715        3     102       74      27      71 29.5    0.121  32
## 719        1     108       60      46     178 35.5    0.415  24
## 720        5      97       76      27     207 35.6    0.378  52
## 736        4      95       60      32      49 35.4    0.284  28
## 737        0     126       86      27     120 27.4    0.515  21
## 740        1     102       74      32     215 39.5    0.293  42
## 746       12     100       84      33     105 30.0    0.488  46
## 753        3     108       62      24     105 26.0    0.223  25
## 762        9     170       74      31     126 44.0    0.403  43
## 765        2     122       70      27      95 36.8    0.340  27
## 766        5     121       72      23     112 26.2    0.245  30
## 767        1     126       60      31     175 30.1    0.349  47
## 768        1      93       70      31     106 30.4    0.315  23
proba <- model %>% predict(newx = x.test)

str(proba)
##  num [1:153, 1] -2.883 1.786 -0.178 0.801 0.772 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:153] "2" "5" "17" "25" ...
##   ..$ : chr "s0"
predicted.classes <- ifelse(proba > 0.5, "pos", "neg")

Précision du modèle

observed.classes <- test.data$diabetes

mean(predicted.classes == observed.classes)
## [1] 0.8104575

Taux de prdiction

set.seed(123)
cv.lasso <- cv.glmnet(x, y, alpha = 1, family = "binomial")
plot(cv.lasso)

illustration de différente fonction de perte

Fonction de perte de la déviance

cv.lasso <- cv.glmnet(x, y, alpha = 1, family = "binomial")
plot(cv.lasso)

## Fonction de perte : erreur de classification

cv.lasso <- cv.glmnet(x, y, alpha = 1, family = "binomial", type.measure="class")
plot(cv.lasso)

Ce graphique montre comment le modèle choisit les variables les plus utiles pour prédire le diabète. On teste différents niveaux de complexité, et à chaque étape, le modèle garde ou élimine certaines variables.

✅ Ce que ça implique concrètement :

Quand la régularisation est faible (à gauche du graphique), le modèle utilise presque toutes les variables. Il est plus précis, mais risque de trop s’adapter aux données (surajustement).

Quand la régularisation est forte (à droite), le modèle devient très simple : il garde 1 ou 2 variables seulement, mais perd en précision (sous-ajustement).

Le meilleur compromis se trouve au centre : le modèle garde environ 6 variables qui sont vraiment utiles pour prédire si une personne est diabétique, tout en restant stable et fiable.

Fonction de perte: AUC= Aire sous la courbe ROC

cv.lasso <- cv.glmnet(x, y, alpha = 1, family = "binomial", type.measure="auc")
plot(cv.lasso)

str(cv.lasso)
## List of 12
##  $ lambda    : num [1:59] 0.232 0.211 0.192 0.175 0.16 ...
##  $ cvm       : num [1:59] 0.65 0.784 0.784 0.784 0.784 ...
##  $ cvsd      : num [1:59] 0.0412 0.0151 0.0151 0.0151 0.0151 ...
##  $ cvup      : num [1:59] 0.691 0.799 0.799 0.799 0.799 ...
##  $ cvlo      : num [1:59] 0.608 0.769 0.769 0.769 0.769 ...
##  $ nzero     : Named int [1:59] 0 1 1 1 1 1 1 1 2 2 ...
##   ..- attr(*, "names")= chr [1:59] "s0" "s1" "s2" "s3" ...
##  $ call      : language cv.glmnet(x = x, y = y, type.measure = "auc", alpha = 1, family = "binomial")
##  $ name      : Named chr "AUC"
##   ..- attr(*, "names")= chr "auc"
##  $ glmnet.fit:List of 13
##   ..$ a0        : Named num [1:59] -0.621 -0.984 -1.316 -1.621 -1.904 ...
##   .. ..- attr(*, "names")= chr [1:59] "s0" "s1" "s2" "s3" ...
##   ..$ beta      :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
##   .. .. ..@ i       : int [1:334] 1 1 1 1 1 1 1 1 5 1 ...
##   .. .. ..@ p       : int [1:60] 0 0 1 2 3 4 5 6 7 9 ...
##   .. .. ..@ Dim     : int [1:2] 8 59
##   .. .. ..@ Dimnames:List of 2
##   .. .. .. ..$ : chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. .. .. ..$ : chr [1:59] "s0" "s1" "s2" "s3" ...
##   .. .. ..@ x       : num [1:334] 0.00297 0.00566 0.00813 0.01041 0.01252 ...
##   .. .. ..@ factors : list()
##   ..$ df        : int [1:59] 0 1 1 1 1 1 1 1 2 2 ...
##   ..$ dim       : int [1:2] 8 59
##   ..$ lambda    : num [1:59] 0.232 0.211 0.192 0.175 0.16 ...
##   ..$ dev.ratio : num [1:59] -6.18e-15 3.08e-02 5.63e-02 7.75e-02 9.54e-02 ...
##   ..$ nulldev   : num 796
##   ..$ npasses   : int 364
##   ..$ jerr      : int 0
##   ..$ offset    : logi FALSE
##   ..$ classnames: chr [1:2] "0" "1"
##   ..$ call      : language glmnet(x = x, y = y, alpha = 1, family = "binomial")
##   ..$ nobs      : int 615
##   ..- attr(*, "class")= chr [1:2] "lognet" "glmnet"
##  $ lambda.min: num 0.0098
##  $ lambda.1se: num 0.0691
##  $ index     : int [1:2, 1] 35 14
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "min" "1se"
##   .. ..$ : chr "Lambda"
##  - attr(*, "class")= chr "cv.glmnet"
cv.lasso$lambda.min
## [1] 0.009795309

##Interpretation Ce graphique nous aide à choisir le meilleur modèle pour prédire si une personne est diabétique, en testant différents niveaux de complexité.

Chaque point rouge représente la performance du modèle pour une valeur donnée du paramètre de régularisation λ (lambda).

Plus l’AUC est élevé, meilleur est le modèle pour distinguer les personnes diabétiques des non-diabétiques.

Les barres grises montrent l’incertitude (la variabilité) autour de chaque point.

Ce que ça signifie pour les variables En haut du graphique, les chiffres indiquent combien de variables sont utilisées dans le modèle à chaque niveau de régularisation.

Quand λ est petit (à gauche), le modèle utilise presque toutes les variables → il est plus précis mais peut être trop complexe.

Quand λ est grand (à droite), le modèle devient très simple → il utilise 1 ou 2 variables seulement, mais la performance diminue.

Le meilleur compromis se trouve au centre : le modèle utilise environ 6 variables et atteint une AUC proche de 0.83, ce qui est très bon.

En résuméé, Ce raphique montre que notre modèle Lasso a réussi à filtrer les variables cliniques les plus utiles pour prédire le diabète. Il garde les plus pertinentes (comme le glucose, la masse corporelle, etc.) et ignore celles qui n’apportent pas grand-chose, pour construire un modèle simple, efficace et fiable

Recherche du modele parcimonieux

cette fonction produit deux lambda optimal lambda.min correspondant à la valeur qui minimise l’erreur de prédiction de la cross-’validation lambda.1SE correspond à la plus grande valeur de lambda equivalent à l’erreur de prédiction + 1 ecart type C’est le lambda qui donne un modèle parcimonieux: Moins de variable avec la méme précision

cv.lasso$lambda.1se
## [1] 0.06910397

##sortie des coefficient pour les deux lambda optimaux

coef(cv.lasso, cv.lasso$lambda.min)
## 9 x 1 sparse Matrix of class "dgCMatrix"
##                        s1
## (Intercept) -8.073314e+00
## pregnant     8.269018e-02
## glucose      3.332336e-02
## pressure     .           
## triceps      1.241029e-02
## insulin      3.353037e-05
## mass         6.058467e-02
## pedigree     6.572459e-01
## age          7.380311e-03
coef(cv.lasso, cv.lasso$lambda.1se)
## 9 x 1 sparse Matrix of class "dgCMatrix"
##                       s1
## (Intercept) -4.417692432
## pregnant     0.002429418
## glucose      0.023838524
## pressure     .          
## triceps      .          
## insulin      .          
## mass         0.024895334
## pedigree     .          
## age          .
coeff <- cbind(coef(cv.lasso, cv.lasso$lambda.min),coef(cv.lasso, cv.lasso$lambda.1se))
coeff
## 9 x 2 sparse Matrix of class "dgCMatrix"
##                        s1           s1
## (Intercept) -8.073314e+00 -4.417692432
## pregnant     8.269018e-02  0.002429418
## glucose      3.332336e-02  0.023838524
## pressure     .             .          
## triceps      1.241029e-02  .          
## insulin      3.353037e-05  .          
## mass         6.058467e-02  0.024895334
## pedigree     6.572459e-01  .          
## age          7.380311e-03  .

le modèle avec lambda.min

lasso.model <- glmnet(x, y, alpha = 1, family = "binomial",
                      lambda = cv.lasso$lambda.min)


x.test <- model.matrix(diabetes ~., test.data)[,-1]
probabilities <- lasso.model %>% predict(newx = x.test)
predicted.classes <- ifelse(probabilities > 0.5, "pos", "neg")

le modèle avec le lambda.1se

observed.classes <- test.data$diabetes
mean(predicted.classes == observed.classes)
## [1] 0.8039216
lasso.model <- glmnet(x, y, alpha = 1, family = "binomial",
                      lambda = cv.lasso$lambda.1se)

x.test <- model.matrix(diabetes ~., test.data)[,-1]
probabilities <- lasso.model %>% predict(newx = x.test)
predicted.classes <- ifelse(probabilities > 0.5, "pos", "neg")


observed.classes <- test.data$diabetes
mean(predicted.classes == observed.classes)
## [1] 0.7320261

Modele final

full.model <- glm(diabetes ~., data = train.data, family = binomial)

str(full.model)
## List of 30
##  $ coefficients     : Named num [1:9] -8.5406 0.1013 0.0359 -0.01 0.0161 ...
##   ..- attr(*, "names")= chr [1:9] "(Intercept)" "pregnant" "glucose" "pressure" ...
##  $ residuals        : Named num [1:615] 1.44 1.26 -1.05 -1.17 14.85 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ fitted.values    : Named num [1:615] 0.6959 0.7911 0.0439 0.1462 0.0673 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ effects          : Named num [1:615] 4.967 -2.77 9.453 -0.446 -3.858 ...
##   ..- attr(*, "names")= chr [1:615] "(Intercept)" "pregnant" "glucose" "pressure" ...
##  $ R                : num [1:9, 1:9] -9.79 0 0 0 0 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:9] "(Intercept)" "pregnant" "glucose" "pressure" ...
##   .. ..$ : chr [1:9] "(Intercept)" "pregnant" "glucose" "pressure" ...
##  $ rank             : int 9
##  $ qr               :List of 5
##   ..$ qr   : num [1:615, 1:9] -9.7926 0.0415 0.0209 0.0361 0.0256 ...
##   .. ..- attr(*, "dimnames")=List of 2
##   .. .. ..$ : chr [1:615] "1" "3" "4" "6" ...
##   .. .. ..$ : chr [1:9] "(Intercept)" "pregnant" "glucose" "pressure" ...
##   ..$ rank : int 9
##   ..$ qraux: num [1:9] 1.05 1.05 1.03 1 1.01 ...
##   ..$ pivot: int [1:9] 1 2 3 4 5 6 7 8 9
##   ..$ tol  : num 1e-11
##   ..- attr(*, "class")= chr "qr"
##  $ family           :List of 13
##   ..$ family    : chr "binomial"
##   ..$ link      : chr "logit"
##   ..$ linkfun   :function (mu)  
##   ..$ linkinv   :function (eta)  
##   ..$ variance  :function (mu)  
##   ..$ dev.resids:function (y, mu, wt)  
##   ..$ aic       :function (y, n, mu, wt, dev)  
##   ..$ mu.eta    :function (eta)  
##   ..$ initialize: language {     if (NCOL(y) == 1) { ...
##   ..$ validmu   :function (mu)  
##   ..$ valideta  :function (eta)  
##   ..$ simulate  :function (object, nsim)  
##   ..$ dispersion: num 1
##   ..- attr(*, "class")= chr "family"
##  $ linear.predictors: Named num [1:615] 0.828 1.332 -3.081 -1.765 -2.629 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ deviance         : num 587
##  $ aic              : num 605
##  $ null.deviance    : num 796
##  $ iter             : int 5
##  $ weights          : Named num [1:615] 0.2116 0.1653 0.042 0.1248 0.0628 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ prior.weights    : Named num [1:615] 1 1 1 1 1 1 1 1 1 1 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ df.residual      : int 606
##  $ df.null          : int 614
##  $ y                : Named num [1:615] 1 1 0 0 1 0 1 1 0 1 ...
##   ..- attr(*, "names")= chr [1:615] "1" "3" "4" "6" ...
##  $ converged        : logi TRUE
##  $ boundary         : logi FALSE
##  $ model            :'data.frame':   615 obs. of  9 variables:
##   ..$ diabetes: Factor w/ 2 levels "neg","pos": 2 2 1 1 2 1 2 2 1 2 ...
##   ..$ pregnant: num [1:615] 6 8 1 5 3 10 2 8 4 10 ...
##   ..$ glucose : num [1:615] 148 183 89 116 78 115 197 125 110 168 ...
##   ..$ pressure: num [1:615] 72 64 66 74 50 72 70 96 92 74 ...
##   ..$ triceps : num [1:615] 35 28 23 27 32 39 45 32 38 32 ...
##   ..$ insulin : num [1:615] 155 180 94 105 88 75 543 300 235 207 ...
##   ..$ mass    : num [1:615] 33.6 23.3 28.1 25.6 31 35.3 30.5 32.3 37.6 38 ...
##   ..$ pedigree: num [1:615] 0.627 0.672 0.167 0.201 0.248 0.134 0.158 0.232 0.191 0.537 ...
##   ..$ age     : num [1:615] 50 32 21 30 26 29 53 54 30 34 ...
##   ..- attr(*, "terms")=Classes 'terms', 'formula'  language diabetes ~ pregnant + glucose + pressure + triceps + insulin + mass + pedigree +      age
##   .. .. ..- attr(*, "variables")= language list(diabetes, pregnant, glucose, pressure, triceps, insulin, mass, pedigree,      age)
##   .. .. ..- attr(*, "factors")= int [1:9, 1:8] 0 1 0 0 0 0 0 0 0 0 ...
##   .. .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. .. ..$ : chr [1:9] "diabetes" "pregnant" "glucose" "pressure" ...
##   .. .. .. .. ..$ : chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. .. ..- attr(*, "term.labels")= chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. .. ..- attr(*, "order")= int [1:8] 1 1 1 1 1 1 1 1
##   .. .. ..- attr(*, "intercept")= int 1
##   .. .. ..- attr(*, "response")= int 1
##   .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. .. ..- attr(*, "predvars")= language list(diabetes, pregnant, glucose, pressure, triceps, insulin, mass, pedigree,      age)
##   .. .. ..- attr(*, "dataClasses")= Named chr [1:9] "factor" "numeric" "numeric" "numeric" ...
##   .. .. .. ..- attr(*, "names")= chr [1:9] "diabetes" "pregnant" "glucose" "pressure" ...
##  $ call             : language glm(formula = diabetes ~ ., family = binomial, data = train.data)
##  $ formula          :Class 'formula'  language diabetes ~ .
##   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##  $ terms            :Classes 'terms', 'formula'  language diabetes ~ pregnant + glucose + pressure + triceps + insulin + mass + pedigree +      age
##   .. ..- attr(*, "variables")= language list(diabetes, pregnant, glucose, pressure, triceps, insulin, mass, pedigree,      age)
##   .. ..- attr(*, "factors")= int [1:9, 1:8] 0 1 0 0 0 0 0 0 0 0 ...
##   .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. ..$ : chr [1:9] "diabetes" "pregnant" "glucose" "pressure" ...
##   .. .. .. ..$ : chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. ..- attr(*, "term.labels")= chr [1:8] "pregnant" "glucose" "pressure" "triceps" ...
##   .. ..- attr(*, "order")= int [1:8] 1 1 1 1 1 1 1 1
##   .. ..- attr(*, "intercept")= int 1
##   .. ..- attr(*, "response")= int 1
##   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. ..- attr(*, "predvars")= language list(diabetes, pregnant, glucose, pressure, triceps, insulin, mass, pedigree,      age)
##   .. ..- attr(*, "dataClasses")= Named chr [1:9] "factor" "numeric" "numeric" "numeric" ...
##   .. .. ..- attr(*, "names")= chr [1:9] "diabetes" "pregnant" "glucose" "pressure" ...
##  $ data             :'data.frame':   615 obs. of  9 variables:
##   ..$ pregnant: num [1:615] 6 8 1 5 3 10 2 8 4 10 ...
##   ..$ glucose : num [1:615] 148 183 89 116 78 115 197 125 110 168 ...
##   ..$ pressure: num [1:615] 72 64 66 74 50 72 70 96 92 74 ...
##   ..$ triceps : num [1:615] 35 28 23 27 32 39 45 32 38 32 ...
##   ..$ insulin : num [1:615] 155 180 94 105 88 75 543 300 235 207 ...
##   ..$ mass    : num [1:615] 33.6 23.3 28.1 25.6 31 35.3 30.5 32.3 37.6 38 ...
##   ..$ pedigree: num [1:615] 0.627 0.672 0.167 0.201 0.248 0.134 0.158 0.232 0.191 0.537 ...
##   ..$ age     : num [1:615] 50 32 21 30 26 29 53 54 30 34 ...
##   ..$ diabetes: Factor w/ 2 levels "neg","pos": 2 2 1 1 2 1 2 2 1 2 ...
##  $ offset           : NULL
##  $ control          :List of 3
##   ..$ epsilon: num 1e-08
##   ..$ maxit  : num 25
##   ..$ trace  : logi FALSE
##  $ method           : chr "glm.fit"
##  $ contrasts        : NULL
##  $ xlevels          : Named list()
##  - attr(*, "class")= chr [1:2] "glm" "lm"
probabilities <- full.model %>% predict(test.data, type = "response")
predicted.classes <- ifelse(probabilities > 0.5, "pos", "neg")


observed.classes <- test.data$diabetes
mean(predicted.classes == observed.classes)
## [1] 0.7973856

##Conclusion du modèle final

Le modèle final de régression logistique pénalisée (Lasso) développé à partir du jeu de données PimaIndiansDiabetes2 montre une bonne performance prédictive pour estimer la probabilité d’être diabétique à partir de variables cliniques simples et disponibles en pratique médicale.

Après imputation rigoureuse des valeurs manquantes (médiane, KNN et MICE), le modèle a été entraîné sur 80 % des données et validé sur 20 %. Les résultats obtenus montrent :

une précision moyenne comprise entre 78 % et 82 % selon le seuil de décision ;

une aire sous la courbe ROC (AUC) proche de 0.83, indiquant une bonne capacité de discrimination entre patientes diabétiques et non diabétiques ;

une sélection automatique de variables pertinentes grâce à la pénalisation L1 du Lasso.

Les variables les plus influentes identifiées sont :

glucose (facteur principal du risque) ;

IMC (mass) ;

insulin et triceps (indicateurs métaboliques) ;

age et pregnant (facteurs physiologiques).

🩺 Interprétation clinique

Ce modèle confirme que le diabète de type 2 est principalement lié à des anomalies métaboliques (glycémie, insuline, masse corporelle) et à certains facteurs physiologiques. Les patientes présentant un taux de glucose élevé, un IMC important et un âge avancé ont une probabilité significativement plus forte d’être diabétiques.

⚙️ Recommandations

Utiliser ce modèle comme outil d’aide à la décision préventive, notamment pour identifier les patientes à risque lors d’un dépistage médical.

Envisager son intégration dans une application clinique (R Shiny, Power BI, ou tableau de bord hospitalier).

Étendre la modélisation à des algorithmes complémentaires (Random Forest, XGBoost, Réseaux de neurones) afin de comparer les performances et renforcer la robustesse prédictive.

📈 Conclusion finale

Le modèle Lasso obtenu est simple, robuste et interprétable. Il constitue une base solide pour un système prédictif de dépistage du diabète de type 2, contribuant ainsi à la médecine préventive et à une meilleure prise en charge des patients à risque.