Classifieur naive Bayes en R : théorème de Bayes avec klaR et tidymodels

Prédire l’appartenance à une classe à partir des vraisemblances par variable et des probabilités a priori — ajuster, évaluer l’exactitude et l’AUC, et lire les probabilités a posteriori

Un guide pratique du classifieur naive Bayes en R pour la classification binaire et multiclasse. Découvrez comment le théorème de Bayes transforme les probabilités a priori des classes et les vraisemblances par variable en une probabilité de classe a posteriori, pourquoi l’hypothèse « naïve » d’indépendance conditionnelle le rend rapide et robuste en grande dimension, et où cette hypothèse pose problème. Ajustez-le de deux façons — le workflow moderne tidymodels avec parsnip + le moteur discrim/klaR, et les routes classiques klaR::NaiveBayes / e1071::naiveBayes — et évaluez l’exactitude et l’AUC ROC sur les données PimaIndiansDiabetes2.

Date de publication

25 juin 2026

Modifié

7 juillet 2026

AstucePoints clés
  • Le classifieur naive Bayes utilise le théorème de Bayes pour calculer, pour chaque classe, la probabilité qu’une observation lui appartienne — la probabilité a posteriori — et affecte l’observation à la classe obtenant le score le plus élevé. Il traite aussi bien les problèmes binaires que multiclasses.
  • Il est « naïf » parce qu’il suppose que les prédicteurs sont conditionnellement indépendants sachant la classe. Cette hypothèse n’est presque jamais strictement vraie, et pourtant le classifieur fonctionne étonnamment bien — et elle rend le modèle extrêmement rapide et stable, même avec de nombreux prédicteurs et peu de données.
  • Le score d’une classe est sa probabilité a priori × le produit de la vraisemblance de chaque variable — les probabilités a priori des classes (la fréquence de la classe) multipliées par les vraisemblances par variable (à quel point les valeurs de l’observation sont typiques pour cette classe). Le théorème de Bayes ne fait que les normaliser en probabilités dont la somme vaut un.
  • C’est une base de référence solide et peu coûteuse — le choix de prédilection pour la classification de texte / en grande dimension (le filtrage anti-spam en est l’exemple classique) et un premier modèle judicieux sur tout nouveau problème. Sa principale limite tient justement à l’hypothèse d’indépendance : avec des prédicteurs fortement corrélés, ses probabilités deviennent trop confiantes.
  • Deux routes, un même modèle : le workflow tidymodels moderne (naive_Bayes() |> set_engine("klaR") via le package discrim, évalué avec yardstick), ou les appels classiques klaR::NaiveBayes() / e1071::naiveBayes() que la plupart des utilisateurs de R rencontrent en premier.
Obtenez le livre — Machine Learning Essentials (PDF)

Introduction

Vous disposez d’un jeu de données clinique et d’une question par oui ou non : un patient est-il positif au diabète, étant donné une poignée de mesures — glucose, IMC, âge, pression artérielle, etc. ? Vous voulez un classifieur qui soit rapide à entraîner, qui vous donne une probabilité honnête (et pas seulement une étiquette), et qui reste stable même lorsque vous lui soumettez de nombreux prédicteurs. Le classifieur naive Bayes est conçu exactement pour cela.

Naive Bayes est une méthode probabiliste : pour chaque classe, il se demande « quelle est la vraisemblance du profil de ce patient s’il appartient à cette classe ? », multiplie cela par « à quel point cette classe est-elle fréquente au départ ? », et transforme le résultat — via le théorème de Bayes — en une probabilité a posteriori d’appartenance à la classe. Le patient est affecté à la classe dont la probabilité a posteriori est la plus élevée. C’est simple, rapide, et une base de référence remarquablement solide.

Le mot « naïf » vient d’une hypothèse simplificatrice audacieuse : celle que les prédicteurs sont conditionnellement indépendants sachant la classe — qu’une fois que vous savez qu’un patient est diabétique-positif, connaître son glucose ne vous apprend rien de plus sur son IMC. C’est rarement littéralement vrai, mais le classifieur s’en accommode et prédit bien malgré tout, et c’est pourquoi naive Bayes reste un cheval de bataille pour les problèmes de texte et en grande dimension (filtrage anti-spam, classification de documents) où les variables sont nombreuses et où une base de référence rapide et robuste importe.

Cette leçon ajuste naive Bayes de deux façons — le workflow tidymodels moderne (parsnip::naive_Bayes() avec le moteur discrim/klaR) et les routes classiques klaR::NaiveBayes() / e1071::naiveBayes() — lit les probabilités a posteriori en langage clair, et évalue l’exactitude et l’AUC ROC sur un échantillon de test mis de côté. Pour un autre classifieur probabiliste qui traite plusieurs classes, voir l’analyse discriminante ; pour l’histoire complète de la matrice de confusion et de la courbe ROC/AUC, voir l’évaluation des modèles de classification.

NoteQuand y recourir

Recourez à naive Bayes lorsque vous voulez une base de référence rapide et solide — surtout avec de nombreux prédicteurs relativement à votre taille d’échantillon (texte, génomique, données creuses en grande dimension), ou lorsque vous avez besoin d’un modèle qui s’entraîne en millisecondes et donne des probabilités suffisamment calibrées. Il est indulgent sur les petits jeux de données. Soyez prudent lorsque les prédicteurs sont fortement corrélés (l’hypothèse d’indépendance est alors violée et les probabilités a posteriori deviennent trop confiantes) — là, un modèle logistique ou discriminant fera peut-être mieux.

Les données

Nous utilisons le jeu de données PimaIndiansDiabetes2 du package mlbench : 768 femmes d’origine Pima, avec pour objectif de prédire diabetes (une issue binaire pos/neg) à partir de huit prédicteurs cliniques — le nombre de grossesses (pregnant), le glucose plasmatique, la pressure artérielle, l’épaisseur du pli cutané du triceps, l’insulin sérique, l’indice de mass corporelle, la fonction pedigree du diabète, et l’age.

Cette version comporte des valeurs manquantes (enregistrées comme NA là où une mesure est invraisemblable, p. ex. un glucose nul). À la suite de l’analyse source, nous supprimons les lignes incomplètes, ce qui laisse 392 enregistrements complets, puis nous partageons les données en un échantillon d’entraînement (80 %, pour l’ajustement) et un échantillon de test (20 %, mis de côté pour juger le classifieur honnêtement). Nous stratifions sur diabetes afin que les deux échantillons conservent le même équilibre positif/négatif, et fixons une graine pour la reproductibilité :

library(rsample)
data("PimaIndiansDiabetes2", package = "mlbench")

# Drop rows with missing measurements (keep complete cases)
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
split      <- initial_split(pima, prop = 0.80, strata = diabetes)
train_data <- training(split)
test_data  <- testing(split)

c(complete = nrow(pima), train = nrow(train_data), test = nrow(test_data))
complete    train     test 
     392      313       79 
# Class balance is preserved by the stratified split
prop.table(table(train_data$diabetes))

      neg       pos 
0.6677316 0.3322684 
head(pima, 4)
  pregnant glucose pressure triceps insulin mass pedigree age diabetes
4        1      89       66      23      94 28.1    0.167  21      neg
5        0     137       40      35     168 43.1    2.288  33      pos
7        3      78       50      32      88 31.0    0.248  26      pos
9        2     197       70      45     543 30.5    0.158  53      pos

Environ 313 patients pour apprendre et 79 mis de côté pour faire office de juge, avec à peu près un tiers de diabétiques-positifs — un problème de classification modérément déséquilibré mais exploitable. L’issue diabetes est un facteur à deux niveaux, neg puis pos ; pos est l’événement que nous voulons détecter.

Le workflow tidymodels : ajuster naive Bayes

Dans tidymodels, naive Bayes correspond à parsnip::naive_Bayes(), fourni par le package discrim et propulsé par le moteur klaR. Le modèle n’a besoin d’aucun réglage pour démarrer, donc le workflow est court : un recipe (que nous gardons minimal — naive Bayes n’est pas sensible à l’échelle comme le sont les modèles pénalisés ou discriminants), la spécification du modèle, et un fit().

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(klaR)
library(yardstick)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
split      <- initial_split(pima, prop = 0.80, strata = diabetes)
train_data <- training(split)
test_data  <- testing(split)

# A minimal recipe — naive Bayes handles raw predictors fine
nb_rec <- recipe(diabetes ~ ., data = train_data)

# The model spec: naive Bayes via the discrim/klaR engine
nb_spec <- naive_Bayes() |>
  set_engine("klaR") |>
  set_mode("classification")

nb_wf <- workflow() |>
  add_recipe(nb_rec) |>
  add_model(nb_spec)

# Fit on the training set
nb_fit <- fit(nb_wf, data = train_data)
nb_fit
══ Workflow [trained] ══════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: naive_Bayes()

── Preprocessor ────────────────────────────────────────────────────────────────
0 Recipe Steps

── Model ───────────────────────────────────────────────────────────────────────
$apriori
grouping
      neg       pos 
0.6677316 0.3322684 

$tables
$tables$pregnant
$tables$pregnant$neg

Call:
    density.default(x = xx)

Data: xx (209 obs.);    Bandwidth 'bw' = 0.6922

       x                y            
 Min.   :-2.077   Min.   :6.175e-05  
 1st Qu.: 2.212   1st Qu.:6.023e-03  
 Median : 6.500   Median :2.516e-02  
 Mean   : 6.500   Mean   :5.817e-02  
 3rd Qu.:10.788   3rd Qu.:8.290e-02  
 Max.   :15.077   Max.   :2.288e-01  

$tables$pregnant$pos

Call:
    density.default(x = xx)

Data: xx (104 obs.);    Bandwidth 'bw' = 1.425

       x                y            
 Min.   :-4.276   Min.   :3.012e-05  
 1st Qu.: 2.112   1st Qu.:5.446e-03  
 Median : 8.500   Median :2.873e-02  
 Mean   : 8.500   Mean   :3.905e-02  
 3rd Qu.:14.888   3rd Qu.:6.412e-02  
 Max.   :21.276   Max.   :1.112e-01  


$tables$glucose
$tables$glucose$neg

Call:
    density.default(x = xx)

Data: xx (209 obs.);    Bandwidth 'bw' = 7.383

       x                y            
 Min.   : 45.85   Min.   :4.121e-06  
 1st Qu.: 88.17   1st Qu.:6.283e-04  
 Median :130.50   Median :3.673e-03  

...
and 544 more lines.

Voilà tout le modèle. naive_Bayes() a estimé, pour chaque classe, la probabilité a priori (la fréquence de pos par rapport à neg dans les données d’entraînement) et une vraisemblance pour chaque prédicteur (une densité lisse des valeurs de ce prédicteur au sein de chaque classe). Pour classer un nouveau patient, il multiplie les probabilités a priori par les vraisemblances par variable et retient la plus grande probabilité a posteriori — le théorème de Bayes, calculé sous l’hypothèse naïve d’indépendance.

Prédire et évaluer sur l’échantillon de test

Naive Bayes renvoie une probabilité pour chaque classe, et pas seulement une étiquette. Nous demandons les deux : la classe prédite et les probabilités a posteriori, puis nous évaluons le modèle sur l’échantillon de test intact avec yardstick :

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(klaR)
library(yardstick)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
split      <- initial_split(pima, prop = 0.80, strata = diabetes)
train_data <- training(split)
test_data  <- testing(split)

nb_rec  <- recipe(diabetes ~ ., data = train_data)
nb_spec <- naive_Bayes() |> set_engine("klaR") |> set_mode("classification")
nb_fit  <- fit(workflow() |> add_recipe(nb_rec) |> add_model(nb_spec), data = train_data)

# Predicted class + posterior probabilities for the test set
nb_pred <- predict(nb_fit, test_data)
nb_prob <- predict(nb_fit, test_data, type = "prob")
results <- cbind(nb_pred, nb_prob, diabetes = test_data$diabetes)
head(results, 4)
  .pred_class  .pred_neg .pred_pos diabetes
1         neg 0.52821342 0.4717866      neg
2         pos 0.19187730 0.8081227      neg
3         pos 0.14907452 0.8509255      pos
4         pos 0.03692151 0.9630785      neg
# Accuracy and ROC AUC (pos is the second factor level — the event)
accuracy(results, truth = diabetes, estimate = .pred_class)
# A tibble: 1 × 3
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy binary         0.709
roc_auc(results, truth = diabetes, .pred_pos, event_level = "second")
# A tibble: 1 × 3
  .metric .estimator .estimate
  <chr>   <chr>          <dbl>
1 roc_auc binary         0.777

Lisez les chiffres (la performance honnête de votre classifieur, hors échantillon) :

  • Exactitude ≈ 0.71 — le modèle donne le bon verdict sur le diabète environ 71 % du temps pour des patients qu’il n’a jamais vus pendant l’ajustement. Une base de référence solide pour un modèle aussi simple et aussi rapide, mais à lire conjointement avec l’AUC car l’exactitude peut flatter un modèle sur une issue déséquilibrée.
  • AUC ROC ≈ 0.78 — la probabilité que le modèle attribue un score plus élevé à un patient positif tiré au hasard qu’à un négatif tiré au hasard. 0.5 équivaut à un tirage à pile ou face, 1.0 est parfait ; 0.78 signifie que les probabilités a posteriori classent les patients de manière utile. Comme l’AUC est indépendante du seuil, elle juge le classement du modèle, et non le seuil arbitraire de 0.5 utilisé pour les étiquettes.

Regardez les premières lignes ci-dessus : chacune porte .pred_neg et .pred_pos, les probabilités a posteriori dont la somme vaut un. La classe prédite .pred_class est simplement la plus grande des deux. Un patient avec .pred_pos proche de 0.85 est un patient pour lequel le modèle est confiant ; un patient proche de 0.50 est un cas limite — exactement les patients qu’un seuil de probabilité différent de 0.5 réétiquetterait.

Lire les probabilités a posteriori

La probabilité a posteriori est au cœur de naive Bayes — bien plus informative que la simple étiquette. Représenter la distribution de .pred_pos, séparée selon la vraie classe du patient, montre d’un coup d’œil le pouvoir discriminant du modèle :

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(klaR)
library(ggpubr)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
split      <- initial_split(pima, prop = 0.80, strata = diabetes)
train_data <- training(split)
test_data  <- testing(split)

nb_spec <- naive_Bayes() |> set_engine("klaR") |> set_mode("classification")
nb_fit  <- fit(workflow() |> add_recipe(recipe(diabetes ~ ., data = train_data)) |>
                 add_model(nb_spec), data = train_data)

# Posterior probability of "pos", paired with each patient's true class
post <- predict(nb_fit, test_data, type = "prob")
plot_df <- data.frame(prob_pos = post$.pred_pos, diabetes = test_data$diabetes)

ggdensity(
  plot_df, x = "prob_pos",
  color = "diabetes", fill = "diabetes",
  palette = "jco", alpha = 0.4,
  xlab = "Posterior probability of diabetes (pos)",
  ylab = "Density"
) +
  geom_vline(xintercept = 0.5, linetype = "dashed", color = "gray40") +
  theme_minimal()

Density plot of the naive Bayes posterior probability of being diabetes-positive on the Pima test set, with two overlaid curves coloured by the patient's true class. True-negative patients pile up near a posterior of zero, true-positive patients lean toward one, and the two curves overlap in the middle around 0.5 where the classifier is least certain.

Lisez-le comme deux histoires que le classifieur sépare en grande partie. Les patients neg (une couleur) s’accumulent vers une faible probabilité a posteriori — le modèle pense à juste titre qu’ils sont peu susceptibles d’être diabétiques. Les patients pos (l’autre couleur) penchent vers une probabilité a posteriori élevée. Ils se chevauchent autour de la ligne pointillée à 0.5, et ce chevauchement est l’erreur du classifieur : les patients dont le profil paraît ambigu pour le modèle. Plus la séparation entre les deux courbes est nette, meilleure est l’AUC — ici elle est bonne mais pas parfaite, ce qui correspond au 0.78 que nous avons mesuré.

La matrice de confusion

Où exactement le modèle trébuche-t-il ? La matrice de confusion décompose l’exactitude en quatre issues — correctes et incorrectes, pour chaque classe :

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(klaR)
library(yardstick)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
split      <- initial_split(pima, prop = 0.80, strata = diabetes)
train_data <- training(split)
test_data  <- testing(split)

nb_spec <- naive_Bayes() |> set_engine("klaR") |> set_mode("classification")
nb_fit  <- fit(workflow() |> add_recipe(recipe(diabetes ~ ., data = train_data)) |>
                 add_model(nb_spec), data = train_data)

nb_pred <- predict(nb_fit, test_data)
results <- cbind(nb_pred, diabetes = test_data$diabetes)

conf_mat(results, truth = diabetes, estimate = .pred_class)
          Truth
Prediction neg pos
       neg  39   9
       pos  14  17

Lisez le tableau par colonne (la vérité). Le modèle étiquette correctement la plupart des vrais négatifs et capture une bonne part des vrais positifs, mais il manque certains positifs — les faux négatifs qui se trouvent dans la zone de chevauchement du graphique de densité. Pour une issue clinique comme le diabète, ces positifs manqués comptent souvent plus que l’exactitude globale, et c’est pourquoi on lit la matrice de confusion et la courbe ROC plutôt que de s’arrêter au chiffre de l’exactitude.

Les routes classiques : klaR et e1071

La plupart des utilisateurs de R rencontrent naive Bayes directement via klaR::NaiveBayes() ou e1071::naiveBayes() — bon à connaître car ils sont omniprésents dans le code et les tutoriels plus anciens, et ils donnent le modèle identique. Voici la route klaR (le même moteur que tidymodels a utilisé ci-dessus), avec un partage entraînement/test en base R :

library(klaR)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
# Stratified 80/20 split with base R: sample within each class
neg <- which(pima$diabetes == "neg")
pos <- which(pima$diabetes == "pos")
train_idx <- c(sample(neg, 0.8 * length(neg)), sample(pos, 0.8 * length(pos)))
train_data <- pima[train_idx, ]
test_data  <- pima[-train_idx, ]

# Fit naive Bayes the classic way
nb_model    <- NaiveBayes(diabetes ~ ., data = train_data)
predictions <- predict(nb_model, test_data)

# predict() returns $class (the label) and $posterior (the class probabilities)
head(predictions$posterior, 4)
          neg       pos
19 0.82655465 0.1734454
21 0.44445782 0.5555422
32 0.30123007 0.6987699
55 0.01611919 0.9838808
# Test-set accuracy
mean(predictions$class == test_data$diabetes)
[1] 0.721519

La sortie reflète celle de tidymodels : predictions$class est l’étiquette prédite et predictions$posterior est la matrice des probabilités a posteriori — exactement les colonnes .pred_neg / .pred_pos d’avant. L’exactitude se situe dans le même ordre de grandeur (la petite différence n’est due qu’au partage aléatoire). Le package e1071 propose le même modèle avec un appel encore plus concis — e1071::naiveBayes(diabetes ~ ., data = train_data) puis predict(model, test_data) — c’est la version que vous verrez le plus souvent dans la nature.

NoteklaR ou e1071 — lequel utiliser ?

Les deux ajustent le même modèle naive Bayes. e1071::naiveBayes() est le plus léger et le plus courant (vraisemblance gaussienne pour les prédicteurs numériques). klaR::NaiveBayes() ajoute une option de densité par noyau (usekernel = TRUE) pour les prédicteurs numériques dont la distribution n’est pas gaussienne — pratique quand une variable est asymétrique — et c’est le moteur que le package discrim de tidymodels enveloppe. Pour une base de référence rapide, l’un ou l’autre convient ; recourez à klaR avec usekernel = TRUE quand vos prédicteurs numériques sont clairement non normaux.

Naive Bayes face aux autres classifieurs : une base de référence rapide et honnête

L’intérêt de naive Bayes n’est pas de remporter chaque concours — c’est de vous donner un résultat solide en millisecondes, avec presque aucun réglage, comme étalon pour des modèles plus sophistiqués. Sur les données Pima, il atteint environ 71 % d’exactitude et 0.78 d’AUC — juste derrière une régression logistique pénalisée (≈0.78 d’exactitude) sur le même partage, pour une fraction de l’effort. C’est le bon plan naive Bayes : si un modèle lourdement réglé ne parvient pas à battre nettement la base de référence naive Bayes de 30 secondes, la complexité supplémentaire ne mérite pas son coût. Ajustez toujours d’abord la base de référence peu coûteuse.

Naive Bayes affecte une observation \(x = (x_1, \dots, x_p)\) à la classe \(k\) ayant la plus forte probabilité a posteriori \(P(C_k \mid x)\). Le théorème de Bayes réécrit cette probabilité a posteriori en fonction de quantités que nous pouvons estimer à partir des données d’entraînement :

\[ P(C_k \mid x) = \frac{P(C_k)\; P(x \mid C_k)}{P(x)} . \]

Ici \(P(C_k)\) est la probabilité a priori de la classe (la fréquence de la classe \(k\) — estimée par sa fréquence dans l’échantillon d’entraînement), \(P(x \mid C_k)\) est la vraisemblance d’observer les valeurs des variables de cette observation dans la classe \(k\), et le dénominateur \(P(x)\) est le même pour chaque classe, de sorte qu’il ne fait que normaliser les probabilités a posteriori pour que leur somme vaille un — nous pouvons l’ignorer lorsqu’on retient la plus grande.

La partie difficile est \(P(x \mid C_k)\) — la vraisemblance jointe des \(p\) variables à la fois, qui nécessiterait une quantité énorme de données pour être estimée. L’hypothèse « naïve » est que les variables sont conditionnellement indépendantes sachant la classe, ce qui permet à la vraisemblance jointe de se factoriser en un simple produit de vraisemblances par variable :

\[ P(x \mid C_k) = \prod_{j=1}^{p} P(x_j \mid C_k) . \]

Le score de la classe \(k\) est donc simplement sa probabilité a priori multipliée par le produit de la vraisemblance de chaque variable :

\[ P(C_k \mid x) \;\propto\; P(C_k) \prod_{j=1}^{p} P(x_j \mid C_k) . \]

Chaque \(P(x_j \mid C_k)\) est estimée séparément — une densité gaussienne (ou par noyau) pour une variable numérique, une table de fréquences pour une variable catégorielle. L’hypothèse d’indépendance est ce qui rend ceci rapide et stable (vous estimez \(p\) densités unidimensionnelles simples au lieu d’une seule densité à \(p\) dimensions), et c’est aussi ce qui le rend naïf — quand les variables sont fortement corrélées, le produit compte deux fois l’information partagée et les probabilités a posteriori deviennent trop confiantes. Remarquablement, le classement des classes survit souvent à cette mauvaise calibration, et c’est pourquoi naive Bayes classe bien même lorsque ses probabilités sont imparfaites.

Vous venez de caret ? La correspondance

Si vous avez appris naive Bayes avec le train(method = "nb") de caret, les idées se transposent directement — seuls les verbes changent. Le moteur klaR sous-jacent est le même :

caret tidymodels
train(..., method = "nb") naive_Bayes() \|> set_engine("klaR")
trControl = trainControl("cv", number = 10) vfold_cv(v = 10) + fit_resamples()
tuneGrid = expand.grid(usekernel, laplace, adjust) naive_Bayes(smoothness, Laplace) \|> ... \|> tune_grid()
predict(model, test, type = "prob") predict(fit, test, type = "prob")
confusionMatrix(pred, truth) yardstick::conf_mat() + accuracy() / roc_auc()

Les leviers usekernel/adjust du moteur klaR apparaissent dans parsnip sous le nom de smoothness, et la correction de Laplace sous le nom de Laplace — tous deux réglables via le même enchaînement tune_grid() que vous connaissez déjà du workflow tidymodels.

🟢 Avec un agent IA

Vous avez un problème de classification avec base de référence rapide — texte, grande dimension, ou simplement un premier modèle ? Demandez à Prova « ajuste un classifieur naive Bayes à ces données, montre-moi les probabilités a posteriori, et donne-moi l’exactitude et l’AUC ROC » — elle répond avec du code tidymodels + klaR que vous pouvez exécuter sur vos propres données, puis vous aide à lire les probabilités a posteriori, la matrice de confusion, et à savoir si l’hypothèse d’indépendance vous nuit. The runtime is the judge. Ask Prova →

Problèmes courants

  • Des prédicteurs fortement corrélés rendent les probabilités trop confiantes. L’hypothèse d’indépendance compte deux fois l’information partagée, de sorte que deux variables fortement corrélées poussent la probabilité a posteriori vers 0 ou 1 trop fort. Les étiquettes survivent souvent, mais les probabilités sont mal calibrées — supprimez ou combinez les prédicteurs redondants, ou utilisez un modèle qui gère la corrélation (logistique / discriminant).
  • Une vraisemblance nulle élimine une classe (le problème de la « fréquence zéro »). Avec des prédicteurs catégoriels, une valeur de variable jamais vue dans une classe pendant l’entraînement donne à cette classe une vraisemblance exactement nulle, et le produit s’effondre à zéro. Corrigez cela avec un lissage de Laplace (additif)e1071::naiveBayes(..., laplace = 1), ou l’argument Laplace dans parsnip — qui ajoute un petit comptage à chaque catégorie.
  • Un prédicteur numérique asymétrique brise l’hypothèse gaussienne. e1071 suppose que chaque variable numérique est normale au sein d’une classe. Si une variable est clairement asymétrique, utilisez klaR::NaiveBayes(..., usekernel = TRUE) (une densité par noyau au lieu d’une gaussienne), ou transformez la variable (log) avant l’ajustement.
  • Les valeurs manquantes provoquent une erreur ou sont silencieusement supprimées. Naive Bayes doit évaluer une vraisemblance pour chaque variable. Supprimez les lignes incomplètes avec na.omit() (comme ici) ou imputez-les dans un recipe (step_impute_median()) ; voir l’ingénierie des variables avec les recipes.

Questions fréquentes

Deux routes faciles. Classique : library(klaR); model <- NaiveBayes(y ~ ., data = train), puis predict(model, test)$class pour les étiquettes et predict(model, test)$posterior pour les probabilités — ou la version plus concise e1071::naiveBayes(y ~ ., data = train). tidymodels : naive_Bayes() |> set_engine("klaR") |> set_mode("classification") à l’intérieur d’un workflow(), ajusté avec fit(), et évalué avec yardstick::accuracy() / roc_auc().

C’est un classifieur probabiliste construit sur le théorème de Bayes. Pour chaque classe, il multiplie la probabilité a priori de la classe (la fréquence de la classe) par la vraisemblance des valeurs des variables de l’observation dans cette classe, donnant une probabilité a posteriori ; l’observation est affectée à la classe ayant la plus forte probabilité a posteriori. Il est naïf parce qu’il suppose que les variables sont conditionnellement indépendantes sachant la classe, ce qui permet à la vraisemblance jointe de se factoriser en un simple produit de vraisemblances par variable.

Parce qu’il fait une hypothèse délibérément simpliste : que tous les prédicteurs sont conditionnellement indépendants sachant la classe — que connaître une variable ne vous apprend rien de plus sur une autre, une fois la classe fixée. C’est presque jamais strictement vrai (les vraies variables sont corrélées), et pourtant le classifieur prédit bien malgré tout, et l’hypothèse est ce qui le rend si rapide et robuste. Le nom signale l’hypothèse, pas un défaut dans les résultats.

e1071::naiveBayes() est le plus léger et le plus courant (vraisemblance gaussienne pour les variables numériques). klaR::NaiveBayes() ajoute une option de densité par noyau (usekernel = TRUE) pour les variables numériques non gaussiennes et c’est le moteur que le package discrim de tidymodels enveloppe. Le package naivebayes est une alternative rapide et moderne avec la même interface. Pour une base de référence rapide, n’importe lequel des trois convient ; choisissez klaR quand vos prédicteurs numériques sont clairement non normaux.

Il fonctionne très bien comme base de référence rapide pour les problèmes en grande dimension — classification de texte, filtrage anti-spam, génomique — où les variables sont nombreuses et où un modèle qui s’entraîne en millisecondes importe. Il est indulgent sur les petits jeux de données. Il peine lorsque les prédicteurs sont fortement corrélés (l’hypothèse d’indépendance est violée et les probabilités a posteriori deviennent trop confiantes) — là, la régression logistique ou l’analyse discriminante classent souvent mieux.

Testez vos connaissances

En utilisant les données PimaIndiansDiabetes2 (mlbench, avec na.omit()), ajustez un modèle naive Bayes avec klaR::NaiveBayes() (pas tidymodels) : faites un partage 80/20, ajustez NaiveBayes(diabetes ~ ., …) sur l’échantillon d’entraînement, prédisez sur l’échantillon de test, rapportez l’exactitude, et affichez les probabilités a posteriori pour les trois premiers patients de test. Que signifie une probabilité a posteriori de, disons, 0.85 pour pos ?

La forme reflète le bloc klaR de la leçon. predict(model, test_data) renvoie une liste avec $class (l’étiquette) et $posterior (la matrice de probabilités). L’exactitude est mean(predict(model, test_data)$class == test_data$diabetes) ; les probabilités a posteriori sont predict(model, test_data)$posterior.

library(klaR)
data("PimaIndiansDiabetes2", package = "mlbench")
pima <- na.omit(PimaIndiansDiabetes2)

set.seed(123)
neg <- which(pima$diabetes == "neg"); pos <- which(pima$diabetes == "pos")
train_idx  <- c(sample(neg, 0.8 * length(neg)), sample(pos, 0.8 * length(pos)))
train_data <- pima[train_idx, ]
test_data  <- pima[-train_idx, ]

nb_model    <- NaiveBayes(diabetes ~ ., data = train_data)
predictions <- predict(nb_model, test_data)

mean(predictions$class == test_data$diabetes)   # accuracy
head(predictions$posterior, 3)                  # posterior probabilities

Vous obtiendrez une exactitude autour de 0.71 et une matrice de probabilités a posteriori dont les lignes somment à un. Une probabilité a posteriori de 0.85 pour pos signifie que le modèle estime une probabilité de 85 % que ce patient soit diabétique-positif étant donné ses mesures — il l’étiquette alors pos parce que 0.85 > 0.5. La probabilité est plus utile que la simple étiquette : elle vous dit à quel point le modèle est confiant.

Vérification rapide. Deux de vos prédicteurs — glucose et insulin — sont fortement corrélés. Votre modèle naive Bayes étiquette les patients à peu près aussi précisément qu’une régression logistique, mais ses probabilités prédites sont poussées bien plus près de 0 et de 1. Que se passe-t-il, et cela invalide-t-il le modèle ?

L’hypothèse d’indépendance conditionnelle est violée : glucose et insulin portent une information qui se recoupe, mais naive Bayes les traite comme indépendantes et multiplie donc ce signal partagé deux fois. Le résultat est des probabilités a posteriori trop confiantes — poussées vers 0 et 1 — même si le classement des patients (et donc les étiquettes et l’AUC) reste souvent correct. Cela n’invalide pas le modèle en tant que classifieur : les étiquettes restent utiles. Mais ne faites pas confiance aux probabilités comme estimations calibrées ; si vous avez besoin de probabilités bien calibrées, supprimez l’un des prédicteurs corrélés ou calibrez le modèle.

Conclusion

Vous avez construit un classifieur naive Bayes de bout en bout sur les données PimaIndiansDiabetes2 : le théorème de Bayes transforme les probabilités a priori des classes multipliées par les vraisemblances par variable en une probabilité a posteriori d’appartenance à une classe, et le modèle affecte chaque patient à la classe ayant la plus forte probabilité a posteriori. L’hypothèse « naïve » d’indépendance conditionnelle est ce qui lui permet de se factoriser en un simple produit — rapide, stable, solide en grande dimension — et c’est aussi là qu’elle pose problème quand les prédicteurs sont corrélés. Vous l’avez ajusté à la fois de la manière moderne (naive_Bayes() |> set_engine("klaR") évalué avec yardstick) et par les routes classiques klaR::NaiveBayes() / e1071::naiveBayes(), lu les probabilités a posteriori et la matrice de confusion, et obtenu ~71 % d’exactitude et 0.78 d’AUC. La règle pratique : ajustez naive Bayes d’abord comme une base de référence peu coûteuse et honnête, lisez les probabilités a posteriori et pas seulement les étiquettes, et surveillez l’hypothèse d’indépendance quand vos prédicteurs sont corrélés.

Ensuite, apprenez à repérer quels patients sont mal classés et comment choisir le seuil de probabilité dans l’évaluation des modèles de classification, ou découvrez un classifieur probabiliste apparenté dans l’analyse discriminante.

Leçons connexes

Vous préférez un livre ? Machine Learning Essentials est disponible en PDF téléchargeable — toutes les leçons de cette série, hors ligne et à vous.

Obtenir le livre (PDF) →Les leçons restent gratuites en ligne.
Cette page vous a-t-elle été utile ?

Prouvez que vous savez le faire. Maîtrisez toute la série Classification en R — suivez votre parcours, construisez des projets et obtenez un certificat.

Commencer gratuitement →

Passez à Pro — Prova illimité sur vos propres données et un certificat vérifiable qui atteste la compétence.

dès 15 $/mois facturé annuellement

Passer à Pro →

✓ Vous êtes Pro — continuez. The runtime is the judge.

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN
Note

Cette leçon est reproductible : chaque probabilité, métrique et figure a été produite par le code montré — copiez n’importe quel bloc et exécutez-le pour les reproduire. The runtime is the judge.

Références

  • James, G., Witten, D., Hastie, T., & Tibshirani, R. (2014). An Introduction to Statistical Learning, with Applications in R. Springer. (Chapitre 4 — Classification : naive Bayes.)
  • Weihs, C., Ligges, U., Luebke, K., & Raabe, N. (2005). klaR — Analyzing German Business Cycles. In Data Analysis and Decision Support. Springer. (Le package klaRNaiveBayes().)
  • Meyer, D., Dimitriadou, E., Hornik, K., Weingessel, A., & Leisch, F. e1071: Misc Functions of the Department of Statistics, TU Wien. (Le package e1071naiveBayes().)
  • Kuhn, M., & Silge, J. Tidy Modeling with R. Disponible gratuitement en ligne (CC BY-NC-SA). (L’interface tidymodels / discrim.)

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Classifieur naive Bayes en R : théorème de Bayes avec klaR et
    tidymodels},
  date = {2026-06-25},
  url = {https://www.datanovia.com/learn/machine-learning/classification/naive-bayes},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Classifieur naive Bayes en R : théorème de Bayes avec klaR et tidymodels.” 2026. June 25. https://www.datanovia.com/learn/machine-learning/classification/naive-bayes.