# ACP avec Python - Un peu de théorie et exemples
Dans le monde du Data Science, nous sommes de plus en plus confrontés à des jeux de données de très grande dimension, c'est-à-dire comportant un nombre élevé de variables (ou *features*). Travailler avec de telles données peut poser de nombreux défis :
* **Malédiction de la dimensionnalité** : Les algorithmes de Machine Learning deviennent moins performants, le surapprentissage est plus fréquent, et la distance entre les points devient moins significative.
* **Coût computationnel** : Le temps de calcul et la mémoire requise augmentent considérablement.
* **Visualisation** : Il est impossible de visualiser des données au-delà de trois dimensions.
* **Interprétabilité** : Comprendre les relations entre un grand nombre de variables est complexe.
Pour adresser ces problèmes, les techniques de **réduction de dimensionnalité** sont devenues indispensables. Elles visent à transformer un jeu de données de haute dimension en un jeu de données de plus faible dimension, tout en préservant au maximum l'information pertinente. Cette approche est une pierre angulaire du *Data Mining*, que vous avez déjà eu l'occasion d'explorer.
Dans ce chapitre, nous allons nous concentrer sur l'une des méthodes de réduction de dimensionnalité les plus populaires et les plus utilisées : l'**Analyse en Composantes Principales (ACP)**, ou *Principal Component Analysis (PCA)* en anglais. Nous allons en explorer les fondements théoriques, puis nous verrons comment l'appliquer concrètement avec Python, en utilisant la bibliothèque `scikit-learn`.
**Objectifs du chapitre :**
* Comprendre les principes mathématiques sous-jacents à l'ACP.
* Savoir quand et pourquoi utiliser l'ACP.
* Maîtriser l'implémentation de l'ACP avec Python.
* Interpréter les résultats d'une ACP.
# Fondements Théoriques de l'ACP
L'ACP est une technique statistique qui permet de transformer un ensemble de variables corrélées en un ensemble de variables non corrélées, appelées **composantes principales**. Ces nouvelles variables sont ordonnées de manière à ce que la première composante principale explique la plus grande part de la variance totale des données, la deuxième la deuxième plus grande part, et ainsi de suite.
> [!definition] Définition : Analyse en Composantes Principales (ACP)
> L'Analyse en Composantes Principales (ACP) est une méthode statistique linéaire de réduction de dimensionnalité. Elle projette les données originales sur un nouvel ensemble d'axes (les composantes principales) qui maximisent la variance des données projetées, tout en assurant que ces axes sont orthogonaux entre eux.
Les objectifs principaux de l'ACP sont :
* **Réduction de dimensionnalité** : Diminuer le nombre de variables tout en conservant le maximum d'information.
* **Décorrélation des variables** : Transformer des variables originales potentiellement corrélées en variables indépendantes.
* **Visualisation** : Faciliter la représentation des données en 2 ou 3 dimensions.
* **Réduction du bruit** : Les composantes principales de faible variance sont souvent associées au bruit.
## Concepts Clés
Pour bien comprendre l'ACP, il est essentiel de maîtriser quelques concepts statistiques et d'algèbre linéaire.
### Variance et Covariance
Ces deux mesures sont fondamentales pour comprendre la dispersion et la relation entre les variables.
> [!definition] Définition : Variance
> La **variance** mesure la dispersion d'un ensemble de données autour de sa moyenne. Une variance élevée indique que les points de données sont très éloignés de la moyenne et les uns des autres, tandis qu'une faible variance indique qu'ils sont regroupés.
> Pour une variable $X$ avec $N$ observations $x_i$, la variance est donnée par :
> $ \text{Var}(X) = \frac{1}{N-1} \sum_{i=1}^{N} (x_i - \bar{x})^2 $
> où $\bar{x}$ est la moyenne de $X$.
> [!definition] Définition : Covariance
> La **covariance** mesure la direction dans laquelle deux variables varient ensemble. Une covariance positive indique que les deux variables ont tendance à augmenter ou diminuer ensemble. Une covariance négative indique que lorsque l'une augmente, l'autre diminue. Une covariance proche de zéro signifie qu'il n'y a pas de relation linéaire forte.
> Pour deux variables $X$ et $Y$ avec $N$ observations $(x_i, y_i)$, la covariance est donnée par :
> $ \text{Cov}(X, Y) = \frac{1}{N-1} \sum_{i=1}^{N} (x_i - \bar{x})(y_i - \bar{y}) $
> [!note] Remarque : Matrice de Covariance
> Pour un jeu de données avec $p$ variables, la **matrice de covariance** est une matrice carrée $p \times p$ où l'élément à la position $(i, j)$ est la covariance entre la variable $i$ et la variable $j$. Les éléments diagonaux de cette matrice sont les variances des variables respectives.
> Pour un jeu de données $X$ de dimension $N \times p$ (où $N$ est le nombre d'observations et $p$ le nombre de variables), la matrice de covariance $\Sigma$ est définie comme :
> $ \Sigma = \frac{1}{N-1} (X - \bar{X})^T (X - \bar{X}) $
> où $\bar{X}$ est la matrice où chaque ligne est la moyenne des variables. Cette matrice est symétrique.
### Valeurs Propres et Vecteurs Propres
Au cœur de l'ACP se trouve la décomposition en valeurs et vecteurs propres de la matrice de covariance.
> [!definition] Définition : Vecteur Propre et Valeur Propre
> Pour une matrice carrée $A$, un **vecteur propre** $\mathbf{v}$ est un vecteur non nul qui, lorsqu'il est multiplié par $A$, ne change que d'échelle. Le facteur d'échelle est appelé la **valeur propre** $\lambda$.
> Cette relation est exprimée par l'équation :
> $ A\mathbf{v} = \lambda\mathbf{v} $
> où $A$ est une matrice carrée, $\mathbf{v}$ est le vecteur propre, et $\lambda$ est la valeur propre associée.
> [!note] Importance en ACP
> Dans le contexte de l'ACP, les **vecteurs propres** de la matrice de covariance représentent les directions des composantes principales. Le vecteur propre associé à la plus grande valeur propre indique la direction le long de laquelle les données varient le plus.
> Les **valeurs propres** correspondantes indiquent l'ampleur de la variance des données le long de ces directions. Plus une valeur propre est grande, plus la variance expliquée par la composante principale associée est importante.
### Composantes Principales
Les composantes principales sont les nouvelles variables créées par l'ACP.
> [!definition] Définition : Composante Principale
> Une **composante principale** est une combinaison linéaire des variables originales. Chaque composante principale est un axe dans l'espace des données, choisi de manière à maximiser la variance des données projetées sur cet axe, tout en étant orthogonale aux composantes principales précédentes.
Les propriétés clés des composantes principales sont :
* Elles sont **orthogonales** (ou non corrélées) entre elles.
* Elles sont **ordonnées** par la quantité de variance qu'elles expliquent. La première composante principale (CP1) capture le plus de variance, la CP2 le deuxième plus, et ainsi de suite.
* Le nombre total de composantes principales est au maximum égal au nombre de variables originales (ou au nombre d'observations moins un, si celui-ci est plus petit).
## Algorithme Général de l'ACP (étapes conceptuelles)
Voici les étapes conceptuelles pour réaliser une ACP :
1. **Centrage des données** : Soustraire la moyenne de chaque variable à toutes les observations de cette variable. Cela garantit que la moyenne de chaque variable est zéro.
* $X_{centré} = X - \bar{X}$
2. **Calcul de la matrice de covariance** : Calculer la matrice de covariance des données centrées. Cette matrice décrit comment chaque variable varie par rapport aux autres.
* $\Sigma = \frac{1}{N-1} X_{centré}^T X_{centré}$
3. **Décomposition en valeurs et vecteurs propres** : Calculer les valeurs propres et les vecteurs propres de la matrice de covariance.
* $\Sigma\mathbf{v} = \lambda\mathbf{v}$
4. **Tri des vecteurs propres** : Ordonner les vecteurs propres par ordre décroissant de leurs valeurs propres correspondantes. Les vecteurs propres ainsi triés sont les directions des composantes principales.
5. **Sélection des composantes principales** : Choisir un sous-ensemble des vecteurs propres (les $k$ premiers, correspondant aux $k$ plus grandes valeurs propres) pour former la matrice de projection $W$. Ce $k$ sera la nouvelle dimension de vos données.
6. **Projection des données** : Projeter les données originales (centrées) sur les nouvelles axes définis par les vecteurs propres sélectionnés. C'est le produit matriciel entre les données centrées et la matrice de projection $W$.
* $X_{projeté} = X_{centré} W$
> [!tip] Astuce : Standardisation
> Avant d'appliquer l'ACP, il est crucial de **standardiser** les données (centrage et réduction à une variance unitaire). Si les variables n'ont pas la même échelle (par exemple, une variable est en euros et une autre en kilogrammes), celles avec une plus grande variance auront une influence disproportionnée sur les premières composantes principales. La standardisation assure que chaque variable contribue équitablement à l'analyse.
# Implémentation de l'ACP avec Python
Nous allons maintenant mettre en pratique l'ACP à l'aide de Python et de la bibliothèque `scikit-learn`, qui est la référence pour le Machine Learning.
## ,Préparation de l'environnement
Commençons par importer les bibliothèques nécessaires :
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris # Pour un jeu de données d'exemple
```
## Jeu de Données d'Exemple
Nous utiliserons le célèbre jeu de données **Iris** de `scikit-learn`. Ce jeu de données contient 150 observations de fleurs d'iris, avec 4 caractéristiques (longueur et largeur des sépales, longueur et largeur des pétales) et 3 espèces distinctes. C'est un excellent exemple pour visualiser la réduction de dimensionnalité de 4D à 2D.
> [!example] Exemple : Chargement du jeu de données Iris
```python
# Charger le jeu de données Iris
iris = load_iris()
X = iris.data # Les caractéristiques (features)
y = iris.target # Les étiquettes (labels) des espèces
# Créer un DataFrame pour une meilleure manipulation et visualisation
df = pd.DataFrame(data=X, columns=iris.feature_names)
df['species'] = iris.target_names[y]
print("Aperçu des 5 premières lignes du jeu de données Iris :")
print(df.head())
print("\nDimensions du jeu de données :", df.shape)
print("\nNoms des caractéristiques :", iris.feature_names)
print("Noms des espèces :", iris.target_names)
```
**Sortie attendue (partielle) :**
```
Aperçu des 5 premières lignes du jeu de données Iris :
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
Dimensions du jeu de données : (150, 5)
Noms des caractéristiques : ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
Noms des espèces : ['setosa' 'versicolor' 'virginica']
```
## Prétraitement des Données : Standardisation
Comme mentionné précédemment, la standardisation est une étape cruciale avant d'appliquer l'ACP, surtout lorsque les variables ont des échelles différentes. `StandardScaler` de `scikit-learn` est l'outil parfait pour cela.
```python
# Initialiser le StandardScaler
scaler = StandardScaler()
# Appliquer la standardisation aux caractéristiques
X_scaled = scaler.fit_transform(X)
print("\nAperçu des 5 premières lignes des données standardisées :")
print(pd.DataFrame(X_scaled, columns=iris.feature_names).head())
```
**Sortie attendue (partielle) :**
```
Aperçu des 5 premières lignes des données standardisées :
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 -0.900681 1.019004 -1.340227 -1.315444
1 -1.143017 -0.131979 -1.340227 -1.315444
2 -1.385353 0.328414 -1.392723 -1.315444
3 -1.506521 0.098217 -1.287732 -1.315444
4 -1.021849 1.249201 -1.340227 -1.315444
```
> [!warning] Attention : Éviter la fuite de données
> Dans un vrai projet de Machine Learning, si vous avez un ensemble d'entraînement et un ensemble de test, il est impératif d'appliquer `fit_transform` uniquement sur l'ensemble d'entraînement et ensuite `transform` sur l'ensemble de test. Cela évite la "fuite de données" du test vers l'entraînement. Pour cet exemple de visualisation et de compréhension de l'ACP, nous standardisons l'ensemble complet.
## Application de l'ACP avec `scikit-learn`
Maintenant que nos données sont standardisées, nous pouvons appliquer l'ACP. Nous allons spécifier `n_components=2` pour réduire les 4 dimensions originales à 2 dimensions, ce qui nous permettra de visualiser les résultats.
> [!example] Exemple : Application de PCA
```python
# Initialiser l'objet PCA avec 2 composantes principales
pca = PCA(n_components=2)
# Appliquer l'ACP aux données standardisées
X_pca = pca.fit_transform(X_scaled)
print("\nAperçu des 5 premières lignes des données transformées par l'ACP :")
print(pd.DataFrame(X_pca, columns=['PC1', 'PC2']).head())
print("\nDimensions des données après ACP :", X_pca.shape)
```
**Sortie attendue (partielle) :**
```
Aperçu des 5 premières lignes des données transformées par l'ACP :
PC1 PC2
0 -2.264703 0.480027
1 -2.080961 -0.674134
2 -2.364229 -0.341908
3 -2.299384 -0.597395
4 -2.389842 0.646835
Dimensions des données après ACP : (150, 2)
```
## Interprétation des Résultats
Après avoir appliqué l'ACP, il est crucial d'interpréter les résultats pour comprendre ce que les nouvelles composantes principales représentent et quelle quantité d'information elles conservent.
### Variance Expliquée
L'attribut `explained_variance_ratio_` de l'objet `PCA` nous donne la proportion de la variance totale expliquée par chaque composante principale.
```python
# Variance expliquée par chaque composante principale
explained_variance_ratio = pca.explained_variance_ratio_
print("\nVariance expliquée par chaque composante principale :", explained_variance_ratio)
print("Variance cumulée expliquée par les 2 premières composantes :", explained_variance_ratio.sum())
```
**Sortie attendue (partielle) :**
```
Variance expliquée par chaque composante principale : [0.72962445 0.22850761]
Variance cumulée expliquée par les 2 premières composantes : 0.9581320573934579
```
Cela signifie que la première composante principale (PC1) explique environ 72.96% de la variance totale des données, et la deuxième (PC2) explique environ 22.85%. Ensemble, elles expliquent environ 95.81% de la variance totale, ce qui est excellent pour une réduction de 4D à 2D !
> [!note] Remarque : Ratio de variance cumulée
> Le ratio de variance cumulée est un indicateur clé pour décider du nombre optimal de composantes principales à conserver. On vise généralement à conserver un pourcentage élevé (par exemple, 80-95%) de la variance totale.
#### Visualisation : Scree Plot
Un **Scree Plot** (ou graphique des éboulis) est un graphique qui affiche la variance expliquée par chaque composante principale. Il aide à déterminer le nombre optimal de composantes à retenir en cherchant un "coude" où la pente du graphique diminue fortement.
> [!example] Exemple : Visualisation du Scree Plot
```python
# Pour un Scree Plot complet, nous avons besoin de toutes les composantes
pca_full = PCA(n_components=None) # None signifie toutes les composantes (min(n_features, n_samples))
pca_full.fit(X_scaled)
# Calcul de la variance expliquée cumulée
cumulative_variance = np.cumsum(pca_full.explained_variance_ratio_)
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(pca_full.explained_variance_ratio_) + 1), pca_full.explained_variance_ratio_, marker='o', linestyle='--', label='Variance individuelle')
plt.plot(range(1, len(pca_full.explained_variance_ratio_) + 1), cumulative_variance, marker='o', linestyle='-', label='Variance cumulée')
plt.title('Scree Plot (Variance expliquée par les Composantes Principales)')
plt.xlabel('Numéro de la Composante Principale')
plt.ylabel('Proportion de Variance Expliquée')
plt.xticks(range(1, len(pca_full.explained_variance_ratio_) + 1))
plt.grid(True)
plt.legend()
plt.show()
```
**Interprétation du Scree Plot :**
On observe un "coude" après la deuxième composante. Les composantes suivantes expliquent une part beaucoup plus faible de la variance. Cela confirme que retenir 2 composantes principales est un choix judicieux pour ce jeu de données, car elles capturent la quasi-totalité de l'information (95.8%).
### Composantes Principales (Vecteurs Propres)
L'attribut `pca.components_` contient les vecteurs propres (ou *loadings*) qui définissent les nouvelles directions. Chaque ligne représente une composante principale, et chaque colonne représente une variable originale.
```python
# Les vecteurs propres (loadings)
components_df = pd.DataFrame(pca.components_, columns=iris.feature_names, index=['PC1', 'PC2'])
print("\nVecteurs propres (loadings) des Composantes Principales :")
print(components_df)
```
**Sortie attendue (partielle) :**
```
Vecteurs propres (loadings) des Composantes Principales :
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
PC1 0.521066 -0.269347 0.580413 0.564857
PC2 0.377418 0.923296 0.024492 0.066942
```
**Interprétation :**
* **PC1** : On voit que `petal length (cm)` (0.58) et `petal width (cm)` (0.56) ont les coefficients les plus élevés et positifs pour PC1, suivis de `sepal length (cm)` (0.52). `sepal width (cm)` a un coefficient négatif (-0.26). Cela suggère que PC1 est principalement liée à la taille générale de la fleur (longueur et largeur des pétales et sépales), avec une relation inverse pour la largeur des sépales.
* **PC2** : `sepal width (cm)` (0.92) a de loin le coefficient le plus élevé. Les autres caractéristiques ont des coefficients très faibles. PC2 semble donc principalement liée à la largeur des sépales.
Ces coefficients nous aident à comprendre la signification biologique ou physique de chaque composante principale.
### Données Transformées
Enfin, les données transformées (`X_pca`) sont les coordonnées de nos observations dans le nouvel espace des composantes principales. Nous pouvons maintenant visualiser ces données en 2D.
> [!example] Exemple : Visualisation des données projetées
```python
# Créer un DataFrame pour les données projetées avec les espèces
pca_df = pd.DataFrame(data=X_pca, columns=['PC1', 'PC2'])
pca_df['species'] = iris.target_names[y]
plt.figure(figsize=(10, 8))
sns.scatterplot(x='PC1', y='PC2', hue='species', data=pca_df, s=70, alpha=0.8)
plt.title('Données Iris projetées sur les 2 premières Composantes Principales')
plt.xlabel('Composante Principale 1 (PC1)')
plt.ylabel('Composante Principale 2 (PC2)')
plt.grid(True)
plt.show()
```
**Interprétation de la visualisation :**
Le graphique montre clairement que les trois espèces d'Iris sont bien séparées dans l'espace des deux premières composantes principales.
* L'espèce 'setosa' est très distincte et se regroupe bien.
* Les espèces 'versicolor' et 'virginica' sont un peu plus proches mais restent globalement séparées.
Cette visualisation en 2D, qui était impossible avec les 4 dimensions originales, nous donne une excellente compréhension de la structure des données et de la séparabilité des classes.
# Quand et Comment Utiliser l'ACP ?
## Avantages et Limitations
L'ACP est un outil puissant, mais il est important de connaître ses forces et ses faiblesses.
**Avantages :**
* **Réduction de la dimensionnalité** : Simplifie les jeux de données complexes.
* **Décorrélation** : Les nouvelles variables (composantes principales) sont non corrélées, ce qui peut améliorer les performances de certains algorithmes de Machine Learning (par exemple, la régression linéaire ou logistique qui supposent l'indépendance des features).
* **Visualisation** : Permet de visualiser des données de haute dimension en 2 ou 3D.
* **Réduction du bruit** : Les composantes de faible variance peuvent souvent être considérées comme du bruit et être supprimées.
* **Amélioration des performances des modèles** : En éliminant les caractéristiques redondantes et le bruit, l'ACP peut aider à prévenir le surapprentissage et à accélérer l'entraînement des modèles.
**Limitations :**
* **Linéarité** : L'ACP est une méthode linéaire. Elle ne peut pas capturer les relations non linéaires entre les variables. Si la structure intrinsèque des données est non linéaire, l'ACP peut échouer à la révéler.
* **Perte d'information** : Toute réduction de dimensionnalité implique une perte d'information. Il faut trouver un compromis entre la réduction de dimension et la quantité d'information conservée.
* **Interprétabilité** : Les composantes principales sont des combinaisons linéaires des variables originales, ce qui les rend parfois difficiles à interpréter dans le contexte du domaine d'application.
* **Sensibilité à l'échelle des données** : Comme nous l'avons vu, l'ACP est sensible à l'échelle des variables, d'où la nécessité de la standardisation.
* **Ne prend pas en compte les étiquettes de classe** : L'ACP est une méthode non supervisée. Elle cherche à maximiser la variance globale sans tenir compte des étiquettes de classe, ce qui peut parfois entraîner une moins bonne séparation des classes par rapport à des méthodes supervisées de réduction de dimensionnalité.
## Choix du Nombre de Composantes
Le choix du nombre de composantes principales à retenir est une étape cruciale. Plusieurs approches peuvent être utilisées :
1. **Règle du coude (Scree Plot)** : Examiner le Scree Plot et identifier le point où la courbe de variance expliquée commence à s'aplatir. Ce "coude" suggère un nombre optimal de composantes.
2. **Variance cumulée expliquée** : Choisir le nombre de composantes qui explique un certain pourcentage de la variance totale (par exemple, 80%, 90% ou 95%). C'est une méthode très courante.
3. **Connaissance du domaine** : Parfois, des connaissances spécifiques au domaine peuvent guider le choix (par exemple, si l'on sait que seulement quelques facteurs sous-jacents sont importants).
4. **Optimisation des performances du modèle** : Utiliser l'ACP comme étape de prétraitement et choisir le nombre de composantes qui maximise les performances d'un modèle de Machine Learning en aval (via validation croisée).
## Cas d'Usage Typiques
L'ACP est utilisée dans une grande variété de domaines :
* **Visualisation de données** : Pour explorer la structure des données et identifier des clusters ou des séparations (comme dans notre exemple Iris).
* **Prétraitement pour le Machine Learning** : Réduire la dimensionnalité avant d'appliquer des algorithmes de classification, de régression ou de clustering, ce qui peut améliorer la vitesse et la précision des modèles.
* **Compression de données** : Réduire l'espace de stockage nécessaire pour les données.
* **Réduction du bruit** : En ne conservant que les composantes de plus grande variance, on peut filtrer le bruit présent dans les données originales.
* **Analyse exploratoire des données (EDA)** : Pour identifier les variables les plus importantes et les relations sous-jacentes.
# Conclusion
L'Analyse en Composantes Principales (ACP) est une technique fondamentale et puissante en Data Science pour la **réduction de dimensionnalité**. Elle permet de transformer des données de haute dimension en un ensemble plus petit de variables non corrélées, appelées composantes principales, tout en maximisant la variance expliquée.
Nous avons exploré les concepts clés tels que la variance, la covariance, les valeurs et vecteurs propres, qui sont au cœur de son fonctionnement. L'implémentation avec Python, grâce à la bibliothèque `scikit-learn`, s'est avérée simple et efficace, nous permettant de standardiser les données, d'appliquer l'ACP et d'interpréter les résultats via la variance expliquée, les vecteurs propres et les visualisations.
L'ACP est un outil précieux pour la **visualisation**, la **réduction du bruit** et l'**amélioration des performances des modèles** en Machine Learning, agissant comme une étape de prétraitement efficace. Cependant, il est essentiel de se souvenir de ses limitations, notamment sa nature linéaire et la perte d'information inhérente à toute réduction de dimension.
Maîtriser l'ACP est une compétence essentielle pour tout ingénieur en Data Science. Elle ouvre la porte à une meilleure compréhension des structures complexes de données et à l'optimisation des flux de travail de *Data Mining*. Pour aller plus loin, vous pourrez explorer d'autres techniques de réduction de dimensionnalité, linéaires ou non linéaires (comme l'ICA, t-SNE, UMAP), qui peuvent être plus adaptées à certains types de données ou de problèmes.
# ➡️ C'est la fin !
- Cours précèdent: `cours-de-départ`
- Prochain cours: [[Exercices - Python et Data]]
- Page d'accueil de la compétence: [[Exercices - Python et Data]]
# 🗓️ Historique
- Dernière MAJ: `13-Octobre-2025`
- Rédigé par: [[Hamilton DE ARAUJO]]