Analyse discriminante en R : LDA & QDA avec MASS et tidymodels

Classez plusieurs groupes avec les discriminants linéaires et quadratiques — ajustez, projetez et évaluez sur un jeu de test

Un guide pratique de l’analyse discriminante en R : analyse discriminante linéaire (LDA, covariance commune, frontières linéaires) et analyse discriminante quadratique (QDA, covariance par classe, frontières courbes), avec un bref tour de MDA, FDA et RDA. Ajustez-les de deux façons — la méthode classique MASS::lda() / MASS::qda() (avec le graphique de projection LD1–LD2 emblématique) et la voie moderne tidymodels discrim — lisez les moyennes de groupe et les fonctions discriminantes en langage clair, et mesurez l’exactitude de classification sur un jeu de test mis de côté. Sur le jeu de données intégré iris.

Date de publication

25 juin 2026

Modifié

7 juillet 2026

AstucePoints clés
  • L’analyse discriminante prédit à quelle classe appartient une observation à partir d’un ou plusieurs prédicteurs continus. Elle excelle sur les problèmes multiclasses (trois groupes ou plus) et est plus stable que la régression logistique lorsque les classes se séparent nettement.
  • La LDA (analyse discriminante linéaire) suppose que chaque classe partage la même matrice de covariance — ses frontières de décision sont donc des droites. C’est le choix par défaut sûr, surtout sur de petits jeux de données.
  • La QDA (analyse discriminante quadratique) laisse chaque classe avoir sa propre covariance — ses frontières se courbent donc. Plus flexible, mais elle a besoin de plus de données pour estimer toutes ces covariances.
  • Standardisez d’abord les prédicteurs. L’analyse discriminante est sensible à l’échelle ; centrez et réduisez chaque prédicteur (step_normalize(), ou un redimensionnement caret/manuel) avant l’ajustement.
  • La projection LDA — chaque observation positionnée sur les discriminants linéaires LD1, LD2 — est le graphique emblématique : elle ramène plusieurs prédicteurs à la vue en 2D qui sépare le mieux les groupes.
  • Deux voies, un même modèle : la méthode classique MASS::lda() / MASS::qda() (moyennes de groupe, la trace en %, la projection intégrée), ou le workflow moderne tidymodels (discrim_linear() / discrim_quad() via le moteur discrim, évalué avec yardstick).
Obtenez le livre — Machine Learning Essentials (PDF)

Introduction

Vous avez mesuré quatre caractéristiques sur un lot de fleurs d’iris — longueur de sépale, largeur de sépale, longueur de pétale, largeur de pétale — et vous voulez une règle qui prédit l’espèce d’une nouvelle fleur à partir de ces quatre nombres. C’est une question de classification supervisée et multiclasse : une variable de sortie étiquetée (Species, trois classes) et plusieurs prédicteurs continus.

L’analyse discriminante est conçue exactement pour cela. Elle trouve les directions, dans l’espace des prédicteurs, qui séparent le mieux les classes, puis affecte chaque observation à la classe à laquelle elle ressemble le plus. Comparée à la régression logistique — la plus naturelle pour deux classes — l’analyse discriminante gère trois classes ou plus avec aisance et tend à être plus stable lorsque les groupes sont bien séparés. Toutes deux savent faire de la classification binaire ; l’analyse discriminante est l’outil à privilégier quand vous avez plusieurs classes.

Cette leçon couvre les deux outils de référence — la LDA (frontières linéaires) et la QDA (frontières courbes) — ainsi qu’un bref aperçu de leurs extensions (MDA, FDA, RDA). Nous les ajustons de deux façons : la méthode classique MASS::lda() / MASS::qda() que la plupart des utilisateurs de R apprennent en premier (et qui donne le graphique de projection emblématique), et le workflow tidymodels moderne via le moteur discrim. Pour le contexte plus large du machine learning, voir construire des modèles avec tidymodels ; pour la technique de réduction de dimension apparentée qui trouve les directions de variance (et non de séparation des classes), voir l’analyse en composantes principales.

NoteQuand y recourir

Recourez à l’analyse discriminante lorsque vous avez une variable de sortie multiclasse et des prédicteurs continus à peu près distribués normalement au sein de chaque classe. Utilisez la LDA par défaut (et quand le jeu d’entraînement est petit) ; passez à la QDA quand vous avez beaucoup de données et que les classes ont clairement des dispersions/formes différentes. Pour deux classes avec un accent sur l’interprétation des cotes, préférez la régression logistique.

Les données

Nous utilisons le jeu de données intégré iris — 150 fleurs, 50 de chacune des trois espèces (setosa, versicolor, virginica), avec quatre mesures chacune. C’est l’exemple classique d’analyse discriminante parce que les espèces forment trois nuages raisonnablement séparés dans l’espace des caractéristiques.

Nous divisons les données en un jeu d’entraînement (80 %, pour l’ajustement) et un jeu de test (20 %, mis de côté pour juger honnêtement le modèle), stratifié sur Species afin que chaque jeu conserve l’équilibre d’un tiers par espèce, et nous fixons une graine pour la reproductibilité :

library(rsample)
data("iris")

# 150 flowers, 3 species (50 each), 4 continuous predictors
set.seed(123)
split      <- initial_split(iris, prop = 0.80, strata = Species)
train_data <- training(split)
test_data  <- testing(split)

c(train = nrow(train_data), test = nrow(test_data))
train  test 
  120    30 
head(iris, 4)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa

Environ 120 fleurs pour apprendre, 30 mises de côté pour servir de juge.

NoteStandardisez avant d’ajuster

L’analyse discriminante est affectée par l’échelle des prédicteurs ; il est donc de bonne pratique de les centrer et réduire d’abord (moyenne 0, écart-type 1). Dans la voie tidymodels ci-dessous, c’est une seule étape de recipe, step_normalize() ; dans la voie classique MASS, vous pouvez réduire les colonnes vous-même. Sur iris, les quatre mesures sont déjà sur une échelle similaire, donc cela change peu ici — mais prenez-en l’habitude, car sur des données réelles cela compte.

Analyse discriminante linéaire (LDA)

La LDA trouve des discriminants linéaires — des combinaisons linéaires des prédicteurs — qui maximisent la séparation entre les classes par rapport à la dispersion au sein des classes. Elle suppose que les prédicteurs sont à peu près normaux au sein de chaque classe et que toutes les classes partagent une seule matrice de covariance ; c’est précisément cette hypothèse de dispersion commune qui rend les frontières de décision droites.

Ajuster à la manière classique : MASS::lda()

La voie classique est MASS::lda(). Nous réduisons les prédicteurs, ajustons sur le jeu d’entraînement, et affichons le modèle pour en lire les trois pièces maîtresses :

library(MASS)
data("iris")

set.seed(123)
# Hold out the same 20% as a test set (base-R index split, stratified by construction on iris's blocks)
idx        <- c(sample(1:50, 40), sample(51:100, 40), sample(101:150, 40))
train_data <- iris[idx, ]
test_data  <- iris[-idx, ]

# Center + scale the four predictors (fit scaling on TRAIN, reuse on TEST)
pred_cols <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
means     <- colMeans(train_data[, pred_cols])
sds       <- apply(train_data[, pred_cols], 2, sd)
train_data[, pred_cols] <- scale(train_data[, pred_cols], center = means, scale = sds)
test_data[, pred_cols]  <- scale(test_data[, pred_cols],  center = means, scale = sds)

# Fit LDA
lda_model <- lda(Species ~ ., data = train_data)
lda_model
Call:
lda(Species ~ ., data = train_data)

Prior probabilities of groups:
    setosa versicolor  virginica 
 0.3333333  0.3333333  0.3333333 

Group means:
           Sepal.Length Sepal.Width Petal.Length Petal.Width
setosa       -1.0112835  0.78048647   -1.2900001  -1.2453195
versicolor    0.1014181 -0.68674658    0.2566029   0.1472614
virginica     0.9098654 -0.09373989    1.0333972   1.0980581

Coefficients of linear discriminants:
                    LD1         LD2
Sepal.Length  0.6794973  0.04463786
Sepal.Width   0.6565085 -1.00330120
Petal.Length -3.8365047  1.44176147
Petal.Width  -2.2722313 -1.96516251

Proportion of trace:
   LD1    LD2 
0.9902 0.0098 

Lire la sortie — trois blocs, chacun avec un sens clair :

  • Prior probabilities of groups — la part des fleurs d’entraînement dans chaque espèce. Ici c’est 1/3 pour chacune (nous avons construit une division équilibrée), donc le modèle démarre sans favoriser aucune classe.
  • Group means — la moyenne de chaque prédicteur au sein de chaque espèce, sur l’échelle standardisée. C’est le « centre de gravité » de chaque classe : setosa se situe bien en dessous des autres sur Petal.Length et Petal.Width (grandes moyennes négatives), ce qui explique pourquoi elle se sépare si nettement.
  • Coefficients of linear discriminants — la recette de LD1 et LD2, les nouveaux axes que le modèle construit. Chacun est une somme pondérée des quatre prédicteurs ; LD1 est l’unique direction qui sépare le mieux les espèces, LD2 la meilleure direction restante orthogonale à celle-ci. La Proportion of trace au bas vous indique quelle part de la séparation entre classes chaque discriminant capture — LD1 en porte l’écrasante majorité, si bien qu’une vue en 1D raconte presque toute l’histoire.

Le graphique emblématique : la projection LDA

L’image qui définit la LDA est la projection : positionnez chaque fleur sur LD1 et LD2, puis tracez ces deux nouvelles coordonnées colorées par espèce. Elle comprime quatre prédicteurs dans la vue en 2D qui sépare le mieux les groupes — bien plus utile ici que de tracer deux mesures brutes :

library(MASS)
library(ggpubr)
data("iris")

set.seed(123)
idx        <- c(sample(1:50, 40), sample(51:100, 40), sample(101:150, 40))
train_data <- iris[idx, ]
pred_cols  <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
train_data[, pred_cols] <- scale(train_data[, pred_cols])

lda_model <- lda(Species ~ ., data = train_data)

# predict() on the training data returns the LD scores in $x — bind them back for plotting
lda_scores <- cbind(train_data, predict(lda_model)$x)

ggscatter(
  lda_scores, x = "LD1", y = "LD2",
  color = "Species", palette = "jco",
  ellipse = TRUE, ellipse.type = "norm",
  size = 2, alpha = 0.8,
  xlab = "First linear discriminant (LD1)",
  ylab = "Second linear discriminant (LD2)"
) + theme_minimal()

Scatter plot of the iris training flowers projected onto the first two linear discriminants LD1 and LD2, coloured by species. Setosa forms a tight cluster well to one side along LD1, while versicolor and virginica sit closer together but are still mostly separated.

Lisez-le de gauche à droite le long de LD1 : setosa se situe loin d’un côté, complètement séparée — le score LD1 d’une fleur décide à lui seul, ou presque, si elle est setosa. Versicolor et virginica se chevauchent un peu mais restent pour l’essentiel distinctes. Le modèle classe une nouvelle fleur en calculant ses scores LD1/LD2 et en l’affectant au centre de groupe le plus proche. Ce seul graphique explique pourquoi l’analyse discriminante est tant appréciée : elle transforme un problème de classification à quatre dimensions en une image que vous pouvez réellement voir.

Prédire et évaluer sur le jeu de test

La LDA calcule, pour chaque fleur, la probabilité a posteriori d’appartenir à chaque espèce et l’affecte à la plus élevée. Nous prédisons sur le jeu de test intact et mesurons l’exactitude :

library(MASS)
data("iris")

set.seed(123)
idx        <- c(sample(1:50, 40), sample(51:100, 40), sample(101:150, 40))
train_data <- iris[idx, ]
test_data  <- iris[-idx, ]
pred_cols  <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
means      <- colMeans(train_data[, pred_cols])
sds        <- apply(train_data[, pred_cols], 2, sd)
train_data[, pred_cols] <- scale(train_data[, pred_cols], center = means, scale = sds)
test_data[, pred_cols]  <- scale(test_data[, pred_cols],  center = means, scale = sds)

lda_model   <- lda(Species ~ ., data = train_data)
predictions <- predict(lda_model, test_data)

# predict() returns: $class (the prediction), $posterior (class probabilities), $x (LD scores)
names(predictions)
[1] "class"     "posterior" "x"        
# Test-set accuracy: the share of flowers classified correctly
mean(predictions$class == test_data$Species)
[1] 0.9666667

La sortie de predict() regroupe trois choses : $class (l’espèce prédite), $posterior (la probabilité de chaque classe — le modèle retient la plus grande), et $x (les scores LD1/LD2 que nous avons tracés). L’exactitude est la fraction de fleurs mises de côté correctement étiquetées.

Lire le nombre : le modèle LDA classe correctement environ 97 % des fleurs mises de côté — il ne manque que l’occasionnelle fleur versicolor/virginica dans leur zone de chevauchement, et ne confond jamais setosa. Pour une règle linéaire de quatre lignes, c’est excellent. Une vue plus complète (quelles classes sont confondues, la précision par classe) provient de la matrice de confusion.

La manière moderne : tidymodels avec discrim

La même LDA s’intègre proprement dans le workflow tidymodels via le paquet discrim, qui ajoute discrim_linear() (LDA) et discrim_quad() (QDA) à parsnip. L’avantage : la standardisation vit dans la recipe, et l’évaluation utilise les mêmes métriques yardstick que tous les autres modèles du pilier — vous pouvez ainsi comparer l’analyse discriminante à la régression logistique ou à un arbre via une seule interface cohérente :

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(yardstick)
data("iris")

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

# Standardize predictors in the recipe — fit on train, reused on test automatically
iris_rec <- recipe(Species ~ ., data = train_data) |>
  step_normalize(all_numeric_predictors())

# LDA model spec via the discrim engine
lda_spec <- discrim_linear() |>
  set_engine("MASS") |>
  set_mode("classification")

lda_wf <- workflow() |>
  add_recipe(iris_rec) |>
  add_model(lda_spec)

lda_fit <- fit(lda_wf, data = train_data)

# Predict on the test set and score accuracy
lda_pred <- predict(lda_fit, test_data)
lda_pred <- cbind(lda_pred, Species = test_data$Species)
accuracy(lda_pred, truth = Species, estimate = .pred_class)
# A tibble: 1 × 3
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy multiclass     0.967

Même modèle, même exactitude d’environ 97 % — mais désormais le prétraitement est intégré au modèle (la recipe s’applique automatiquement à toute nouvelle donnée), et la métrique est un tableau yardstick ordonné que vous pouvez aligner contre d’autres classifieurs. C’est le workflow que chaque leçon supervisée de ce pilier réutilise ; ici, vous avez simplement substitué discrim_linear().

Analyse discriminante quadratique (QDA)

La QDA assouplit la plus grande hypothèse de la LDA. Au lieu de forcer toutes les classes à partager une matrice de covariance, la QDA laisse chaque classe avoir la sienne — une classe étroitement regroupée et une classe dispersée sont ainsi modélisées chacune selon ses propres termes. Le prix de cette flexibilité, ce sont des frontières de décision courbes (quadratiques). Passer de la LDA à la QDA est une modification d’un seul mot :

library(rsample)
library(recipes)
library(parsnip)
library(workflows)
library(discrim)
library(yardstick)
data("iris")

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

iris_rec <- recipe(Species ~ ., data = train_data) |>
  step_normalize(all_numeric_predictors())

# QDA: per-class covariance, quadratic boundaries — change only the spec
qda_spec <- discrim_quad() |>
  set_engine("MASS") |>
  set_mode("classification")

qda_wf  <- workflow() |> add_recipe(iris_rec) |> add_model(qda_spec)
qda_fit <- fit(qda_wf, data = train_data)

qda_pred <- predict(qda_fit, test_data)
qda_pred <- cbind(qda_pred, Species = test_data$Species)
accuracy(qda_pred, truth = Species, estimate = .pred_class)
# A tibble: 1 × 3
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy multiclass     0.967

Sur iris, la QDA obtient à peu près les mêmes ~97 % que la LDA — ce qui est en soi un constat utile. Quand le modèle plus simple (LDA) fait jeu égal avec le plus flexible (QDA), préférez le modèle plus simple : il a moins de paramètres à estimer et risque moins de surajuster. La QDA justifie sa complexité quand les classes ont réellement des dispersions différentes et que vous avez assez de données pour estimer de façon fiable toutes ces covariances distinctes. La méthode classique MASS::qda(Species ~ ., data = train_data) donne le modèle identique si vous préférez l’appel en base R.

NoteLDA ou QDA ? Une règle rapide
  • LDA — le choix par défaut. Moins de paramètres, plus stable sur de petits jeux d’entraînement, frontières droites. Choisissez-la quand les classes ont une dispersion à peu près égale.
  • QDA — plus flexible (covariance par classe, frontières courbes). Choisissez-la quand vous avez un grand jeu d’entraînement et que les classes diffèrent clairement en dispersion/forme, rendant l’hypothèse de covariance commune intenable.
  • Égalité ? Livrez la LDA — le modèle plus simple généralise au moins aussi bien pour moins de risque.

Au-delà de la LDA et de la QDA : MDA, FDA, RDA

La LDA et la QDA couvrent la plupart des besoins, mais trois extensions traitent les cas plus difficiles. Vous y recourez rarement en premier, mais il est utile de savoir qu’elles existent :

  • MDA (mixture discriminant analysis) — suppose que chaque classe est elle-même un mélange de plusieurs sous-classes gaussiennes plutôt qu’un seul amas. Utile quand une classe contient en réalité des sous-groupes distincts. (mda::mda().)
  • FDA (flexible discriminant analysis) — remplace les combinaisons linéaires par des combinaisons non linéaires (des splines, par exemple), de sorte à pouvoir modéliser des formes de classes courbes et non normales. (mda::fda().)
  • RDA (regularized discriminant analysis) — un compromis entre la LDA et la QDA : elle resserre les covariances QDA distinctes vers la covariance LDA commune. Cela stabilise l’estimation quand vous avez beaucoup de prédicteurs corrélés ou moins d’échantillons que de prédicteurs. (klaR::rda().)

Chacune est un remplacement d’une ligne de la fonction de modèle sur les mêmes données ; n’y recourez que lorsque les hypothèses de la LDA/QDA échouent clairement.

Les deux méthodes affectent une observation à la classe ayant la plus forte probabilité a posteriori. Par la règle de Bayes, la probabilité a posteriori de la classe \(k\) est proportionnelle à la probabilité a priori de la classe \(\pi_k\) multipliée par la densité intra-classe \(f_k(x)\). La LDA comme la QDA modélisent chaque densité de classe \(f_k\) par une loi normale multivariée de moyenne de classe \(\mu_k\) et de covariance \(\Sigma_k\) — la différence tient à une seule hypothèse sur la covariance. La LDA force toute classe à partager une covariance unique, \(\Sigma_k = \Sigma\) ; la QDA laisse chaque classe garder la sienne, \(\Sigma_k\).

En injectant la densité normale dans la règle de Bayes, le logarithme de la probabilité a posteriori donne à chaque classe un score discriminant \(\delta_k(x)\) ; l’observation va à la classe au plus grand score. Sous l’hypothèse de covariance commune (LDA), ce score est :

\[ \delta_k(x) = x^{\top}\Sigma^{-1}\mu_k - \tfrac{1}{2}\mu_k^{\top}\Sigma^{-1}\mu_k + \log \pi_k . \]

Parce que \(\Sigma\) est commune, le terme quadratique en \(x\) s’annule entre les classes, laissant \(\delta_k\) linéaire en \(x\) — d’où des discriminants linéaires et des frontières droites. En QDA, chaque classe garde sa propre \(\Sigma_k\), le terme quadratique ne s’annule pas, et le score reste quadratique en \(x\) — d’où des frontières courbes. Le coût : la QDA doit estimer une matrice de covariance complète par classe (bien plus de paramètres), elle a donc besoin de plus de données. L’hypothèse de normalité intra-classe est aussi la raison pour laquelle standardiser les prédicteurs et (au besoin) transformer ceux qui sont asymétriques améliore les deux méthodes.

🟢 Avec un agent IA

Vous cherchez à déterminer quel classifieur convient à vos propres données multiclasses ? Demandez à Prova « ajuste une LDA et une QDA sur ces données, montre-moi la projection discriminante, et dis-moi laquelle classe le jeu de test avec le plus d’exactitude » — elle répond avec du code MASS + tidymodels que vous pouvez exécuter sur vos propres données, puis vous aide à lire les moyennes de groupe, le graphique de projection et l’exactitude. The runtime is the judge. Ask Prova →

Problèmes courants

  • Vous avez oublié de standardiser les prédicteurs. L’analyse discriminante est sensible à l’échelle — un prédicteur mesuré dans de grandes unités peut dominer les discriminants sans bonne raison. Centrez et réduisez d’abord (step_normalize(all_numeric_predictors()) dans une recipe, ou scale() sur les colonnes), en apprenant le redimensionnement sur le jeu d’entraînement et en le réutilisant sur le jeu de test.
  • qda() échoue avec « rank deficiency in group … ». La QDA a besoin de plus d’observations que de prédicteurs dans chaque classe pour estimer chaque covariance de classe. Si une classe est petite, repliez-vous sur la LDA (qui met en commun une covariance) ou sur la RDA (klaR::rda(), qui régularise).
  • La spécification discrim_linear() est introuvable. discrim_linear() / discrim_quad() vivent dans le paquet discrim, pas dans le parsnip de base — library(discrim) d’abord, et gardez MASS installé (c’est le moteur d’ajustement).
  • Les prédictions semblent aléatoires / l’exactitude est proche du hasard. Vérifiez que les prédicteurs sont continus et à peu près normaux au sein de chaque classe. Des prédicteurs fortement asymétriques brisent l’hypothèse de normalité — transformez-les par logarithme ou Box-Cox (step_log() / step_BoxCox()) avant l’ajustement.

Questions fréquentes

Utilisez MASS::lda() : model <- lda(Species ~ ., data = train_data), puis predict(model, test_data)$class pour les classes prédites. Standardisez d’abord les prédicteurs. En tidymodels, utilisez discrim_linear() |> set_engine("MASS") dans un workflow avec step_normalize(), ajustez avec fit(), et évaluez avec yardstick::accuracy(). La LDA suppose que les classes partagent une seule matrice de covariance, donnant des frontières de décision linéaires.

Identique à la LDA mais avec MASS::qda() (ou discrim_quad() en tidymodels). La QDA laisse chaque classe avoir sa propre matrice de covariance, de sorte que ses frontières de décision se courbent. Elle est plus flexible que la LDA mais a besoin de plus de données — chaque classe doit avoir plus d’observations que de prédicteurs, sinon qda() échoue avec un message de déficience de rang.

Les deux supposent que les prédicteurs sont distribués normalement au sein de chaque classe. La LDA force toutes les classes à partager une seule matrice de covariance, donc ses frontières de décision sont droites (linéaires) et elle a moins de paramètres — ce qui la rend stable sur de petits jeux de données. La QDA laisse chaque classe avoir sa propre covariance, donc ses frontières se courbent (quadratiques) — plus flexible, mais elle a besoin d’un jeu d’entraînement plus grand. Utilisez la LDA par défaut ; ne passez à la QDA qu’avec beaucoup de données et des dispersions de classes nettement différentes.

Recourez à l’analyse discriminante quand votre variable de sortie a trois classes ou plus — elle gère les problèmes multiclasses avec aisance, tandis que la régression logistique est la plus naturelle pour deux. L’analyse discriminante est aussi plus stable lorsque les classes se séparent nettement. Pour un problème à deux classes où vous voulez interpréter des odds ratios, préférez la régression logistique. Toutes deux savent faire de la classification binaire.

Oui, c’est recommandé. L’analyse discriminante est affectée par l’échelle des prédicteurs ; centrez et réduisez-les donc (moyenne 0, écart-type 1) avant l’ajustement — step_normalize() dans une recipe tidymodels, ou scale() sur les colonnes. Apprenez le redimensionnement à partir du jeu d’entraînement et réutilisez-le sur le jeu de test afin qu’aucune information de test ne fuite. Standardiser rend aussi les coefficients discriminants comparables comme mesure approximative de l’importance des variables.

La projection LDA positionne chaque observation par ses scores sur les discriminants linéaires LD1 et LD2 — les nouveaux axes que la LDA construit pour séparer au mieux les classes. Elle comprime plusieurs prédicteurs dans la vue en 2D où les groupes s’écartent le plus, si bien que des classes bien séparées forment des regroupements distincts, souvent nettement délimités. La Proportion of trace dans la sortie du modèle indique quelle part de séparation chaque discriminant capture.

Testez vos connaissances

À l’aide des données iris, ajustez un modèle QDA avec MASS::qda() (pas tidymodels) : divisez 80/20, standardisez les quatre prédicteurs, ajustez qda(Species ~ ., …) sur le jeu d’entraînement, prédisez sur le jeu de test, et rapportez l’exactitude. Comment se compare-t-elle à la LDA de la leçon ?

La structure est identique au workflow MASS::lda() de la leçon — ne changez que lda() en qda(). Réduisez d’abord les prédicteurs (apprenez colMeans()/sd() sur le jeu d’entraînement, appliquez aux deux), puis mean(predict(model, test_data)$class == test_data$Species).

library(MASS)
data("iris")

set.seed(123)
idx        <- c(sample(1:50, 40), sample(51:100, 40), sample(101:150, 40))
train_data <- iris[idx, ]
test_data  <- iris[-idx, ]
pred_cols  <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
means      <- colMeans(train_data[, pred_cols]); sds <- apply(train_data[, pred_cols], 2, sd)
train_data[, pred_cols] <- scale(train_data[, pred_cols], center = means, scale = sds)
test_data[, pred_cols]  <- scale(test_data[, pred_cols],  center = means, scale = sds)

qda_model <- qda(Species ~ ., data = train_data)
mean(predict(qda_model, test_data)$class == test_data$Species)

Vous obtiendrez une exactitude d’environ 0.97 — essentiellement la même que la LDA sur ces données. Parce que les deux font jeu égal, c’est la LDA, plus simple, qu’il faut livrer ; la flexibilité supplémentaire de la QDA ne paie que lorsque les classes ont des dispersions nettement différentes et que vous avez plus de données.

Vérification rapide. Vous avez une variable de sortie à 5 classes avec seulement 12 observations dans la plus petite classe et 6 prédicteurs. qda() échoue avec « rank deficiency ». Quelle méthode devriez-vous utiliser à la place, et pourquoi ?

Utilisez la LDA (ou la RDA). La QDA estime une matrice de covariance distincte pour chaque classe, ce qui exige plus d’observations que de prédicteurs dans chaque classe — avec seulement 12 cas et 6 prédicteurs dans la petite classe, il n’y a pas assez de données, d’où l’erreur de déficience de rang. La LDA met en commun une covariance partagée unique pour toutes les classes (bien moins de paramètres), elle s’ajuste donc de façon stable ; la RDA (klaR::rda()) est le terrain d’entente qui resserre les covariances QDA vers celle de la LDA.

Conclusion

Vous avez exécuté l’analyse discriminante de bout en bout sur les données iris : la LDA suppose une seule covariance partagée et trace des frontières droites ; la QDA donne à chaque classe sa propre covariance et des frontières courbes ; MDA / FDA / RDA les étendent pour les mélanges, la non-linéarité et la régularisation en haute dimension. Vous les avez ajustées à la fois de la manière classique (MASS::lda() / qda(), avec la projection LD1–LD2 emblématique) et de la manière moderne tidymodels (discrim_linear() / discrim_quad() évaluées avec yardstick), lu les moyennes de groupe et la proportion de trace en langage clair, et obtenu une exactitude de ~97 % sur un jeu de test mis de côté. La règle pratique : standardisez d’abord, commencez par la LDA, et ne passez à la QDA que lorsque vous avez les données et que les classes diffèrent clairement en dispersion.

Ensuite, apprenez à lire quelles classes sont confondues et comment mettre en balance la précision et le rappel dans l’évaluation des modèles de classification, ou faites connaissance avec un autre classifieur multiclasse probabiliste dans le classifieur bayésien naïf.

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 modèle, projection et chiffre d’exactitude a été produit 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 : LDA & QDA.)
  • Venables, W. N., & Ripley, B. D. (2002). Modern Applied Statistics with S (4e éd.). Springer. (Le package MASSlda() / qda().)
  • Friedman, J. H. (1989). Regularized Discriminant Analysis. Journal of the American Statistical Association, 84(405), 165–175.
  • 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 = {Analyse discriminante en R : LDA \& QDA avec MASS et
    tidymodels},
  date = {2026-06-25},
  url = {https://www.datanovia.com/learn/machine-learning/classification/discriminant-analysis},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Analyse discriminante en R : LDA & QDA avec MASS et tidymodels.” 2026. June 25. https://www.datanovia.com/learn/machine-learning/classification/discriminant-analysis.