En data science, on manipule souvent des jeux de données avec des dizaines, voire des milliers de variables. Visualiser ou analyser directement ces données est alors impossible : c’est ce qu’on appelle le fléau de la dimension (curse of dimensionality). L’analyse en composantes principales, ou ACP, est la méthode la plus classique pour résoudre ce problème : elle projette les données sur un sous-espace de dimension réduite en perdant le moins d’information possible.
L’idée est remarquablement élégante : on cherche les directions de l’espace le long desquelles les données varient le plus, et on ne garde que celles-là. Mathématiquement, cela revient à diagonaliser la matrice de covariance des données, ce qui fait de l’ACP un pont naturel entre l’algèbre linéaire et les statistiques.
Dans cet article, on construit l’ACP de A à Z : intuition géométrique, formalisation mathématique, algorithme, implémentation Python, et applications concrètes en machine learning.
Intuition géométrique
Imaginons un nuage de n points dans \mathbb{R}^2. Si les points forment un nuage allongé (une sorte d’ellipse), ils varient beaucoup le long d’un certain axe et peu le long de l’axe perpendiculaire. L’ACP identifie ces deux axes :
- le premier axe principal est la direction de variance maximale,
- le deuxième axe principal est la direction de variance maximale parmi celles perpendiculaires au premier.

Si la variance le long du deuxième axe est très faible comparée au premier, on peut projeter tous les points sur le premier axe sans perdre beaucoup d’information. On passe de 2 dimensions à 1 dimension : c’est la réduction de dimensionnalité.
En dimension p, le principe est identique : on cherche k < p directions orthogonales qui capturent le maximum de variance. Ces directions sont les composantes principales.
Formalisation mathématique
Centrage des données
On dispose de n observations x_1, x_2, \ldots, x_n \in \mathbb{R}^p, que l’on organise en une matrice X \in \mathbb{R}^{n \times p} (chaque ligne est une observation).
La première étape est de centrer les données : on soustrait la moyenne de chaque variable.
\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i \in \mathbb{R}^pOn note \tilde{X} la matrice centrée, dont la ligne i est x_i - \bar{x}. Dans la suite, on suppose toujours les données centrées et on note simplement X la matrice centrée.
Pourquoi centrer ? Sans centrage, la première composante principale pointerait simplement vers la moyenne des données, ce qui n’apporte aucune information sur leur dispersion. Le centrage garantit que l’ACP capture uniquement la variabilité.
Normalisation (optionnelle) : si les variables ont des unités différentes (par exemple une taille en cm et un poids en kg), on divise en plus chaque variable par son écart-type. L’ACP sur données centrées-réduites est parfois appelée ACP normée ou ACP sur matrice de corrélation.
Matrice de covariance empirique
La matrice de covariance empirique des données centrées est :
\Sigma = \frac{1}{n} X^\top X \in \mathbb{R}^{p \times p}Le coefficient \Sigma_{jk} mesure la covariance entre la variable j et la variable k. En particulier, \Sigma_{jj} est la variance de la variable j.
Propriétés de \Sigma :
- \Sigma est symétrique : \Sigma^\top = \Sigma
- \Sigma est semi-définie positive : pour tout u \in \mathbb{R}^p, u^\top \Sigma u = \frac{1}{n} \lVert Xu \rVert^2 \geq 0
D’après le théorème spectral, toute matrice symétrique réelle est diagonalisable dans une base orthonormée. Autrement dit, il existe une matrice orthogonale P et une matrice diagonale \Lambda telles que :
\Sigma = P \Lambda P^\top
avec \Lambda = \text{diag}(\lambda_1, \lambda_2, \ldots, \lambda_p), où \lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_p \geq 0.
Valeurs propres et composantes principales
Le résultat fondamental de l’ACP est le suivant :
Théorème : la direction u \in \mathbb{R}^p (de norme 1) qui maximise la variance des données projetées \text{Var}(Xu) = u^\top \Sigma u est le vecteur propre de \Sigma associé à la plus grande valeur propre \lambda_1. Plus généralement, la k-ème composante principale est le vecteur propre associé à \lambda_k.
Démonstration : on cherche \max_{\lVert u \rVert = 1} u^\top \Sigma u. C’est un problème d’optimisation sous contrainte : on introduit le multiplicateur de Lagrange \lambda et on écrit le Lagrangien :
\mathcal{L}(u, \lambda) = u^\top \Sigma u - \lambda (u^\top u - 1)La condition \nabla_u \mathcal{L} = 0 donne :
2\Sigma u - 2\lambda u = 0 \quad \Longrightarrow \quad \Sigma u = \lambda u
Donc u est un vecteur propre de \Sigma associé à la valeur propre \lambda. La variance projetée vaut alors u^\top \Sigma u = u^\top \lambda u = \lambda. Pour maximiser cette variance, on choisit le vecteur propre associé à la plus grande valeur propre. \blacksquare
Interprétation : les valeurs propres \lambda_1, \lambda_2, \ldots, \lambda_p de \Sigma sont les variances des données le long de chaque axe principal. Les vecteurs propres correspondants sont les directions de ces axes.
Projection sur les composantes principales
Notons P_k = (v_1 \mid v_2 \mid \cdots \mid v_k) \in \mathbb{R}^{p \times k} la matrice dont les colonnes sont les k premiers vecteurs propres. La projection des données sur les k premières composantes principales est :
Z = X P_k \in \mathbb{R}^{n \times k}Chaque ligne de Z donne les coordonnées d’une observation dans la nouvelle base de dimension k. Les colonnes de Z sont les composantes principales Z_1, Z_2, \ldots, Z_k.
Propriété : les composantes principales sont décorrélées :
\text{Cov}(Z_i, Z_j) = 0 \quad \text{pour } i \neq jC’est une conséquence directe du fait que les vecteurs propres d’une matrice symétrique forment une base orthogonale.
Choix du nombre de composantes
Variance expliquée
La variance totale des données est la trace de \Sigma, c’est-à-dire la somme de toutes les valeurs propres :
\text{Var}_{\text{totale}} = \sum_{j=1}^{p} \lambda_jLa proportion de variance expliquée par les k premières composantes est :
\rho_k = \frac{\sum_{j=1}^{k} \lambda_j}{\sum_{j=1}^{p} \lambda_j}On cherche le plus petit k tel que \rho_k dépasse un seuil fixé (souvent 90 % ou 95 %).
Critère de Kaiser
La règle de Kaiser consiste à ne retenir que les composantes dont la valeur propre est supérieure à la moyenne des valeurs propres :
\lambda_j > \frac{1}{p} \sum_{i=1}^{p} \lambda_iSi les données sont normalisées (ACP sur matrice de corrélation), cela revient à garder les composantes dont \lambda_j > 1.
Scree plot (diagramme des éboulis)
Le scree plot représente les valeurs propres \lambda_j en fonction de j. On cherche un « coude » dans la courbe : le point à partir duquel les valeurs propres décroissent lentement. On retient les composantes situées avant le coude.

Lien avec la SVD
L’ACP est intimement liée à la décomposition en valeurs singulières (SVD). Si X = U S V^\top est la SVD de la matrice de données centrée X \in \mathbb{R}^{n \times p}, alors :
\Sigma = \frac{1}{n} X^\top X = \frac{1}{n} V S^2 V^\topLes colonnes de V sont donc les vecteurs propres de \Sigma, et les valeurs propres de \Sigma sont \lambda_j = s_j^2 / n où s_j est la j-ème valeur singulière.
Les composantes principales sont :
Z = XV = US
En pratique, quand n \gg p, on calcule l’ACP par diagonalisation de \Sigma. Quand p \gg n (données en grande dimension comme des images), la SVD de X est plus efficace car on évite de former la matrice p \times p.
Application ML : dans la reconnaissance faciale (eigenfaces), chaque image 64×64 pixels est un vecteur de p = 4096 dimensions. Si on a n = 400 images, la matrice \Sigma serait de taille 4096×4096. L’astuce de la SVD (ou de la matrice duale XX^\top de taille 400×400) rend le calcul faisable.
Reconstruction et erreur
Après projection sur k composantes, on peut reconstruire une approximation des données d’origine :
\hat{X} = Z P_k^\top = X P_k P_k^\topL’erreur moyenne de reconstruction par observation (au sens de la norme de Frobenius) est :
\frac{1}{n}\lVert X - \hat{X} \rVert_F^2 = \sum_{j=k+1}^{p} \lambda_jC’est la somme des variances perdues, c’est-à-dire les valeurs propres qu’on n’a pas retenues. L’ACP minimise cette erreur parmi toutes les projections linéaires de rang k : c’est le théorème d’Eckart-Young.
Algorithme pas-à-pas
Voici l’algorithme complet de l’ACP :
- Centrer les données : soustraire la moyenne de chaque variable.
- (Optionnel) Normaliser : diviser chaque variable par son écart-type.
- Calculer la matrice de covariance \Sigma = \frac{1}{n} X^\top X.
- Diagonaliser \Sigma : obtenir les valeurs propres \lambda_1 \geq \cdots \geq \lambda_p et les vecteurs propres v_1, \ldots, v_p.
- Choisir k composantes (variance expliquée, Kaiser ou scree plot).
- Projeter : Z = X P_k où P_k = (v_1 \mid \cdots \mid v_k).
Implémentation Python
ACP from scratch avec NumPy
import numpy as npdef acp(X, k): """ ACP sur la matrice X (n x p). Retourne les composantes principales Z (n x k), les vecteurs propres V_k (p x k) et les valeurs propres. """ # 1. Centrage moyenne = X.mean(axis=0) X_centre = X - moyenne # 2. Matrice de covariance n = X_centre.shape[0] Sigma = (X_centre.T @ X_centre) / n # 3. Diagonalisation valeurs_propres, vecteurs_propres = np.linalg.eigh(Sigma) # eigh renvoie les valeurs propres en ordre croissant, on inverse idx = np.argsort(valeurs_propres)[::-1] valeurs_propres = valeurs_propres[idx] vecteurs_propres = vecteurs_propres[:, idx] # 4. Projection sur les k premières composantes V_k = vecteurs_propres[:, :k] Z = X_centre @ V_k return Z, V_k, valeurs_propres
Quelques remarques sur cette implémentation :
- On utilise
np.linalg.eigh(et noneig) car \Sigma est symétrique :eighest plus rapide et numériquement plus stable. eighrenvoie les valeurs propres en ordre croissant, d’où le tri inverse.- En grande dimension, on préférerait
np.linalg.svddirectement sur X centrée.
Avec scikit-learn
from sklearn.decomposition import PCAfrom sklearn.datasets import load_irisimport matplotlib.pyplot as plt# Charger le jeu de données Iris (4 variables, 150 observations)iris = load_iris()X = iris.data# ACP en 2 composantespca = PCA(n_components=2)Z = pca.fit_transform(X)# Variance expliquéeprint(f"Variance expliquée : {pca.explained_variance_ratio_}")# [0.9246, 0.0531] => 97.8 % avec 2 composantes sur 4# Visualisationplt.figure(figsize=(8, 6))for i, nom in enumerate(iris.target_names): mask = iris.target == i plt.scatter(Z[mask, 0], Z[mask, 1], label=nom, alpha=0.7)plt.xlabel("Composante principale 1")plt.ylabel("Composante principale 2")plt.legend()plt.title("ACP du jeu de données Iris")plt.show()
Avec seulement 2 composantes sur 4, l’ACP capture 97,8 % de la variance totale. La visualisation montre que les trois espèces (setosa, versicolor, virginica) se séparent bien dans le plan des deux premières composantes.
Application ML : en pratique, l’ACP est souvent utilisée comme étape de prétraitement avant un algorithme de classification (k-NN, SVM, réseau de neurones). Réduire la dimension permet d’accélérer l’entraînement, de limiter le surapprentissage, et parfois même d’améliorer les performances en éliminant le bruit.
ACP vs t-SNE vs UMAP
L’ACP n’est pas la seule méthode de réduction de dimensionnalité. En machine learning, on rencontre souvent t-SNE et UMAP pour la visualisation. Voici les différences principales :
- ACP : projection linéaire, rapide, interprétable (les composantes sont des combinaisons linéaires des variables d’origine), mais ne capture que les structures linéaires.
- t-SNE : projection non linéaire, excellente pour la visualisation en 2D, mais lente sur de grands jeux de données et non interprétable (les axes n’ont pas de signification).
- UMAP : similaire à t-SNE mais plus rapide et mieux adapté aux grandes dimensions, préserve davantage la structure globale.
En résumé : on utilise l’ACP quand on veut réduire la dimension pour du prétraitement (classification, régression) ou quand on veut interpréter les composantes. On utilise t-SNE ou UMAP quand on veut uniquement visualiser des données en haute dimension.
Exercices corrigés
Exercice 1 : ACP à la main en dimension 2
On considère les 5 points suivants dans \mathbb{R}^2 :
x_1 = (1, 2), \quad x_2 = (3, 4), \quad x_3 = (5, 6), \quad x_4 = (2, 3), \quad x_5 = (4, 5)
- Centrer les données.
- Calculer la matrice de covariance \Sigma.
- Trouver les valeurs propres et vecteurs propres de \Sigma.
- Quelle proportion de variance explique la première composante ?
- Projeter les données sur la première composante principale.
Correction :
1. La moyenne est :
\bar{x} = \frac{1}{5}(1+3+5+2+4, ;2+4+6+3+5) = (3, 4)Les données centrées sont :
\tilde{x}_1 = (-2, -2), \quad \tilde{x}_2 = (0, 0), \quad \tilde{x}_3 = (2, 2), \quad \tilde{x}_4 = (-1, -1), \quad \tilde{x}_5 = (1, 1)2. La matrice de covariance est \Sigma = \frac{1}{5} \tilde{X}^\top \tilde{X} :
\tilde{X}^\top \tilde{X} = \left(\begin{array}{cc} (-2)^2+0^2+2^2+(-1)^2+1^2 & (-2)(-2)+0+4+1+1 \\ (-2)(-2)+0+4+1+1 & (-2)^2+0^2+2^2+(-1)^2+1^2 \end{array}\right) = \left(\begin{array}{cc} 10 & 10 \\ 10 & 10 \end{array}\right)Donc :
\Sigma = \frac{1}{5}\left(\begin{array}{cc} 10 & 10 \\ 10 & 10 \end{array}\right) = \left(\begin{array}{cc} 2 & 2 \\ 2 & 2 \end{array}\right)3. Le polynôme caractéristique est :
\det(\Sigma - \lambda I) = (2-\lambda)^2 - 4 = \lambda^2 - 4\lambda = \lambda(\lambda - 4) = 0
Les valeurs propres sont \lambda_1 = 4 et \lambda_2 = 0.
Pour \lambda_1 = 4 : (\Sigma - 4I)v = 0 donne -2v_1 + 2v_2 = 0, soit v_1 = \frac{1}{\sqrt{2}}(1, 1).
Pour \lambda_2 = 0 : v_2 = \frac{1}{\sqrt{2}}(1, -1).
4. La proportion de variance expliquée par la première composante est :
\rho_1 = \frac{\lambda_1}{\lambda_1 + \lambda_2} = \frac{4}{4 + 0} = 100%La première composante capture toute la variance. C’est normal : les données centrées sont toutes alignées sur la droite y = x, il n’y a aucune dispersion perpendiculairement à cette droite.
5. La projection sur la première composante est z_i = \tilde{x}_i \cdot v_1 :
z_1 = \frac{-2-2}{\sqrt{2}} = -2\sqrt{2}, \quad z_2 = 0, \quad z_3 = 2\sqrt{2}, \quad z_4 = -\sqrt{2}, \quad z_5 = \sqrt{2}Exercice 2 : implémentation Python et comparaison
Écrire une fonction Python qui effectue l’ACP from scratch (centrage, covariance, diagonalisation, projection), puis comparer les résultats avec sklearn.decomposition.PCA sur le jeu de données Iris.
Correction :
import numpy as npfrom sklearn.decomposition import PCAfrom sklearn.datasets import load_iris# Charger les donnéesiris = load_iris()X = iris.data # 150 x 4# --- ACP from scratch ---X_centre = X - X.mean(axis=0)n = X_centre.shape[0]Sigma = (X_centre.T @ X_centre) / nvaleurs_propres, vecteurs_propres = np.linalg.eigh(Sigma)idx = np.argsort(valeurs_propres)[::-1]valeurs_propres = valeurs_propres[idx]vecteurs_propres = vecteurs_propres[:, idx]k = 2V_k = vecteurs_propres[:, :k]Z_scratch = X_centre @ V_k# --- ACP avec sklearn ---pca = PCA(n_components=2)Z_sklearn = pca.fit_transform(X)# Comparaison (les signes des vecteurs propres peuvent différer)print("Variance expliquée (scratch) :", valeurs_propres[:2] / valeurs_propres.sum())print("Variance expliquée (sklearn) :", pca.explained_variance_ratio_) np.min([np.abs(Z_scratch - Z_sklearn).max(), np.abs(Z_scratch + Z_sklearn).max()]))
Les résultats sont identiques (à un signe près sur les vecteurs propres, ce qui est normal : si v est vecteur propre, -v aussi). La variance expliquée par les deux premières composantes est d’environ 92,5 % et 5,3 %, soit 97,8 % au total.
Remarque : sklearn utilise la SVD plutôt que la diagonalisation de \Sigma pour des raisons de stabilité numérique. La convention sklearn divise par n-1 (variance non biaisée) et non par n, ce qui peut créer de légères différences sur les valeurs propres.
Exercice 3 : interprétation des composantes sur Iris
On reprend l’ACP du jeu Iris en k = 2 composantes. Déterminer quelles variables d’origine contribuent le plus à chaque composante principale (loadings), et interpréter.
Correction :
Les quatre variables du jeu Iris sont : longueur du sépale, largeur du sépale, longueur du pétale, largeur du pétale.
Les loadings sont les coefficients des vecteurs propres. Avec Python :
noms = ['Long. sépale', 'Larg. sépale', 'Long. pétale', 'Larg. pétale']for j in range(2): print(f"\nComposante {j+1} :") for i, nom in enumerate(noms): print(f" {nom} : {vecteurs_propres[i, j]:.3f}")
Résultat typique :
- Composante 1 : dominée par la longueur du pétale (≈ 0.86) et la longueur du sépale (≈ 0.36). Cette composante capture essentiellement la taille du pétale.
- Composante 2 : dominée par la largeur du sépale (≈ 0.73) et la longueur du sépale (≈ 0.66). Cette composante capture la forme du sépale.
L’ACP permet ainsi de résumer 4 mesures par 2 variables interprétables : « taille de la fleur » et « forme du sépale ». La première composante seule suffit à séparer l’espèce setosa des deux autres.
Exercices d’entraînement
- Soit la matrice de covariance \Sigma = \left(\begin{array}{cc} 5 & 3 \\ 3 & 2 \end{array}\right). Calculer les valeurs propres, les vecteurs propres, et la proportion de variance expliquée par la première composante.
- On dispose de n = 1000 observations en dimension p = 50. Le scree plot montre que les 5 premières valeurs propres valent 45, 30, 15, 8, 2 et que la somme de toutes les valeurs propres vaut 120. Combien de composantes retenir avec le critère des 90 % de variance expliquée ?
- Expliquer pourquoi l’ACP ne peut pas séparer deux classes disposées en cercles concentriques (une classe au centre, l’autre autour). Quelle méthode utiliser à la place ?
FAQ
L’analyse en composantes principales (ACP) est une méthode statistique qui consiste à projeter des données sur les directions de variance maximale. Mathématiquement, cela revient à diagonaliser la matrice de covariance des données : les vecteurs propres donnent les directions principales et les valeurs propres mesurent la variance le long de chaque direction.
L’ACP sert principalement à réduire la dimension des données tout en conservant le maximum d’information. En machine learning, on l’utilise pour visualiser des données en haute dimension, accélérer les algorithmes d’apprentissage, éliminer le bruit et les variables redondantes, et lutter contre le fléau de la dimension.
La SVD (décomposition en valeurs singulières) est un outil d’algèbre linéaire qui décompose toute matrice en A = USV^T. L’ACP utilise la SVD en coulisse : les composantes principales sont les colonnes de US et les directions principales sont les colonnes de V. La SVD est la méthode de calcul, l’ACP est la méthode statistique.
Trois critères sont couramment utilisés. Le critère de la variance expliquée : on retient assez de composantes pour capturer 90 à 95 % de la variance totale. Le critère de Kaiser : on ne garde que les composantes dont la valeur propre dépasse la moyenne. Le scree plot : on cherche un coude dans le graphique des valeurs propres et on retient les composantes avant le coude.