Tuto Python & Scikit-learn : réduction de dimensionnalité
Table des matières
2.1. PCA avec deux composantes
2.2. PCA avec trois composantes
2.3. LDA avec deux composantes
Introduction
Les algorithmes d’apprentissage automatique reposent sur des facteurs connus sous le nom de variables. Plus le nombre de caractéristiques est élevé, plus il est difficile de visualiser les données d’entrainement et de travailler dessus. Parfois, la plupart des caractéristiques sont corrélées ce qui entraine la redondance. C’est alors là que les algorithmes de réduction de la dimensionnalité se voient utiles pour lutter contre le fléau de la dimensionnalité.
1. Définition
d La réduction de la dimensionnalité peut se faire suivant deux méthodes :
- Suppression de caractéristiques.
- Combinaison de caractéristiques pour obtenir de nouvelles moins redondantes.
Il existe plusieurs méthodes pour la réduction de la dimensionnalité. Dans ce tutoriel, on s’intéressera aux deux méthodes suivantes :
- L’analyse en composantes principales (en anglais, Principal Component Analysis PCA) : est l’algorithme d’apprentissage automatique de type non supervisé le plus pratique qui peut être utilisé pour visualiser des données qui ont plus de trois dimensions;
- L’analyse discriminante linéaire (en anglais, Linear Discriminant Analysis LDA) : est un algorithme d’apprentissage automatique supervisé qui est utilisé pour la réduction de la dimensionnalité, son approche est similaire à celle du PCA. Le LDA trouve les composants qui maximisent à la fois la variance des données et la séparation entre les multiples classes ;
La réduction de la dimensionnalité peut être linéaire ou non linéaire selon la méthode utilisée. La méthode linéaire la plus utilisée est l’analyse en composantes principales (PCA).
La réduction de la dimensionnalité est utile pour les problèmes de vraies données qui peuvent être des données de haute dimension et peuvent aller jusqu’à des millions. Alors cela permet de conserver que les caractéristiques discriminantes pour éviter ainsi le surapprentissage des modèles.
2. Module Scikit-learn
La bibliothèque d’apprentissage automatique Scikit-learn de Python met en place les modules sklearn.decomposition et sklearn.discriminant_analysis pour utiliser la réduction de la dimensionnalité.
Pour illustrer le fonctionnement de l’algorithme de réduction de la dimensionnalité avec Python, nous procéderons par l’appliquer sur la dataset « iris ».
Tout d’abord, nous importons les bibliothèques nécessaires : Pandas et Numpy qui permettent la manipulation des données, Seaborn et Matplotlib pour visualiser ces dernières et finalement sklearn pour l’algorithme en question et pour importer la dataset « iris ».
- Code :
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
- Résultat de l’exécution :
On importe par la suite l’ensemble des données « iris ».
- Code :
# import de l'ensemble de données
iris = datasets.load_iris()
X = iris.data
y = iris.target
cibles = iris.target_names
print(cibles)
- Résultat de l’exécution :
Ensuite, nous examinons l’ensemble des données « iris » qui est assez populaire dans la littérature sur l’apprentissage automatique. Celui-ci contient trois classes, chacune représente un type de la plante iris.
- Code :
df = pd.DataFrame(iris.data, columns = iris.feature_names)
df['Species'] = iris['target']
df['Species'] = df['Species'].apply(lambda x: iris['target_names'][x])
df.head()
- Résultat de l’exécution :
Dans le code suivant, on visualise à l’aide des bibliothèques Seaborn et Matplotlib les classes qui sont séparées en fonction des différentes caractéristiques.
Dans un premier temps, on affiche les classes de l’ensemble des données en fonction de sepal length et sepal width, ensuite en fonction de petal length et petal width.
- Code :
couleur = {'Setosa' : 'blue', 'Versicolor' : 'red', 'Virginica' : 'orange'}
#Voyons comment les classes sont séparées en fonction des différentes caractéristiques
sns.FacetGrid(df, hue = "Species", height = 4,
palette = couleur.values()).map(plt.scatter, "sepal length (cm)",
"sepal width (cm)").add_legend()
sns.FacetGrid(df, hue = "Species", height = 4,
palette = couleur.values()).map(plt.scatter, "petal length (cm)",
"petal width (cm)").add_legend()
plt.show()
- Résultat de l’exécution :
La matrice de corrélation peut aider à mieux comprendre un ensemble de données. Pour notre exemple de dataset « iris », elle va nous indique comment les quatre caractéristiques sont corrélées.
En utilisant la bibliothèque seaborn, on obtient facilement la matrice de corrélation, qui à partir de laquelle on peut remarquer une forte corrélation entre les caractéristiques sepal length et sepal width.
- Code :
#creer une matrice de correlation
df.corr()
sns.heatmap(df.corr(), cmap = 'PiYG', annot = True)
- Résultat de l’exécution :
Dans le code suivant, nous allons normaliser nos caractéristiques avant d’appliquer le PCA à deux composantes afin de représenter les données en deux dimensions.
- Code :
#normalisation des données en utilisant standard scaler
scaler = StandardScaler()
X = scaler.fit_transform(X)
- Résultat de l’exécution :
2.1. PCA avec deux composantes
Après avoir normalisé les données, on transforme les caractéristiques en utilisant le PCA.
Le PCA à deux composantes nous aide à visualiser l’ensemble de données « iris », on peut remarquer que la classe « Setorsa » est très différente des deux autres classes. On calcule également la variance expliquée qui nous indique la part de variance que prennent les deux composantes. On obtient alors un résultat de 95,8% qui signifie que les deux composantes principales absorbent 95.8% de la variance qui veut dire que la représentation en deux dimensions est significative.
Remarque :
Avec un résultat inférieur à 85%, la représentation des données en deux dimensions peut ne pas être valide.
- Code :
#L’analyse en composantes principales PCA
pca = PCA(n_components=2)
X_reduit = pca.fit_transform(X)
for color, i, cibles in zip(couleur.values(), [0, 1, 2], cibles):
plt.scatter(X_reduit[y == i, 0], X_reduit[y == i, 1], color = color, alpha = .8,
label = cibles, s = 130, edgecolors = 'k')
plt.legend(loc = 'best', shadow = False, scatterpoints = 1)
plt.xlabel("1ère composante du PCA")
plt.ylabel("2e composante du PCA")
plt.title('PCA de la dataset iris')
# pourcentage de la variance expliquée pour chaque composantes
print('variance expliquée pour chaque composantes: %s' % str(pca.explained_variance_ratio_))
plt.show()
- Résultat de l’exécution :
2.2. PCA avec trois composantes
Nous allons tracer dans ce qui suit les trois premières composantes du PCA afin de mieux comprendre l’interaction des caractéristiques.
- Code :
from mpl_toolkits.mplot3d import Axes3D
figure = plt.figure(1, figsize = (8, 6))
axe = Axes3D(figure, elev =- 150, azim = 110)
pca3 = PCA(n_components = 3)
X_reduit = pca3.fit_transform(iris.data)
axe.scatter(X_reduit[:, 0], X_reduit[:, 1], X_reduit[:, 2], c = y, cmap = plt.cm.spring, edgecolor = 'k', s = 130)
axe.set_title("trois premieres composantes du PCA")
axe.set_xlabel("1ère composante du PCA")
axe.w_xaxis.set_ticklabels([])
axe.set_ylabel("2e composante du PCA")
axe.w_yaxis.set_ticklabels([])
axe.set_zlabel("3e composante du PCA")
axe.w_zaxis.set_ticklabels([])
# pourcentage de la variance expliquée pour chaque composantes
print('variance expliquée pour chaque composantes: {}'.format(pca3.explained_variance_ratio_))
plt.show()
- Résultat de l’exécution :
2.3. LDA avec deux composantes
Dans la partie du code suivant, on calcule les deux premières composantes du LDA et on les visualise.
Remarquons que la classe « Setosa » est encore une fois séparée des données des deux autres classes. On peut aussi constater que le LDA est plus performant que le PCA pour maintenir le chevauchement à un minimum entre les deux classes « Versicolor » et « Virginica ».
- Code :
couleur = {'Setosa' : 'blue','Versicolor' : 'red','Virginica' : 'orange'}
lda = LinearDiscriminantAnalysis(n_components=2)
lda.fit(X, y)
X_reduit = lda.transform(X)
plt.figure(figsize = (10,8))
for cl, i, cible in zip(couleur.values(), [0, 1, 2], cibles):
plt.scatter(X_reduit[y == i, 0], X_reduit[y == i, 1], alpha = .8, color = cl,
label = cible, s = 130, edgecolors = 'k')
plt.legend(loc = 3, shadow = False, scatterpoints = 1)
plt.xlabel('lda1')
plt.ylabel('lda2')
plt.title("Projection de l'iris sur les 2 premiers discriminants linéaires")
print('variance expliquée pour chaque composantes: {}'.format(lda.explained_variance_ratio_))
plt.show()
- Résultat de l’exécution :
3. Cas d’utilisation
Le PCA fonctionne avec des variables fortement corrélées. Si la relation entre les variables est faible, le PCA ne sera pas efficace. Alors l’utilisation de la matrice de corrélation avant d’appliquer l’algorithme de PCA est fortement recommandée.
Il faut cependant examiner les coefficients de corrélation pour déterminer les variables fortement corrélées.
Le LDA quant à lui est souvent utilisé dans le prétraitement des données destinées aux modèles de classification. Il est utilisé uniquement pour l’apprentissage supervisé c’est-à-dire lorsqu’on connait à l’avance les étiquettes des classes.
Le PCA est utilisé dans les domaines tels que la reconnaissance faciale, la vision par ordinateur et la compression d’images. Cet algorithme de réduction de la dimensionnalité est aussi utilisé dans le domaine de la finance, la data mining et la bio-informatique pour trouver des tendances dans des données de haute dimension.
4. Avantages et limites
4.1. Avantages
Les principaux avantages du PCA sont :
- La suppression des caractéristiques corrélées : dans les cas réels d’apprentissage automatique, les ensembles de données contiennent beaucoup de caractéristiques qui réduisent la performance des algorithmes et rendent difficile la visualisation des données, alors la réduction du nombre de celles-ci se voit incontournable. Le PCA trouve efficacement les variables corrélées et donne des composantes principales indépendantes les unes des autres.
- L’amélioration des performances des algorithmes : le PCA est effectivement un moyen très efficace pour accélérer les algorithmes d’apprentissage automatique en éliminant les variables corrélées qui ne contribuent pas à aucune prise de décision.
- La réduction du sur-apprentissage : ce phénomène est produit principalement lorsqu’il y a trop de variables dans l’ensemble de données. Alors, en réduisant le nombre de caractéristiques on arrive à surmonter ce problème.
- La visualisation des données : le PCA permet de transformer les données en haute dimension en basse dimension afin de les visualiser facilement.
4.2. Limites
Pour les limites du PCA, elles se résument en ce qui suit :
- Les variables indépendantes deviennent moins significatives : après avoir appliqué le PCA sur un ensemble de données, les caractéristiques originales deviennent des composantes principales qui sont la combinaison linéaire des caractéristiques principales. Celles-ci ne sont pas aussi lisibles et interprétables que les caractéristiques originales.
- La normalisation des données est nécessaire avant le PCA : avant de mettre en œuvre le PCA, il faut obligatoirement normaliser les données sinon ce dernier ne sera pas en mesure de trouver des composantes principales optimales.
- La perte d’informations : le PCA essaie de couvrir la variance maximale entre les caractéristiques d’un ensemble de données, alors le choix du nombre de composantes principales doit être fait avec soin pour ne pas manquer certaines informations liées à la liste originales de caractéristiques.
5. Exercices
5.1. Exercice 1 :
Appliquez la méthode du PCA sur l’ensemble de données suivant :
6. Solution des exercices
6.1. Exercice 1
On importe tout d’abord les bibliothèques nécessaires, ensuite l’ensemble de données.
- Code :
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
df = pd.read_csv('C:/Users/LENOVO/Desktop/coursGratuit/mushrooms.csv')
df.head()
- Résultat de l’exécution :
Dans le code suivant, nous avons encodé les données en utilisant le LabelEncoder car nous ne pouvons pas utiliser le PCA avec des variables catégorielles.
La caractéristique de « classe » est la première colonne de l'ensemble de données, c'est pourquoi nous avons divisé les caractéristiques et les étiquettes ainsi.
Ensuite, nous avons standardisé les caractéristiques avec le StandardScaler.
- Code :
encoder = LabelEncoder()
# On transforme les colonnes de la dataset
for colonne in df.columns:
df[colonne] = encoder.fit_transform(df[colonne])
X = df.iloc[:,1:23]
y = df.iloc[:, 0]
#on met à l'echelle les caractéristiques
scaler = StandardScaler()
X = scaler.fit_transform(X)
- Résultat de l’exécution :
Maintenant, nous utilisant le PCA pour obtenir une liste des caractéristiques qu’on va visualiser dans un tracé représentant les caractéristiques qui ont le plus de pouvoir explicatif : c’est les composantes principales. Il semble y avoir 17 soit près de 95% des données.
- Code :
# on visualise
pca = PCA()
pca.fit_transform(X)
pca_variance = pca.explained_variance_
plt.figure(figsize = (8, 6))
plt.bar(range(22), pca_variance, alpha = 0.5, align = 'center',
label = 'variance individuelle')
plt.legend()
plt.ylabel('Rapport de variance')
plt.xlabel('Composantes princiales')
plt.show()
- Résultat de l’exécution :
On convertit les deux premières caractéristiques en composantes principales, puis on trace un diagramme de classification des points en fonction des deux caractéristiques.
- Code :
#PCA avec deux composantes
pca2 = PCA(n_components = 2)
pca2.fit(X)
X_reduit = pca2.transform(X)
plt.figure(figsize=(8,6))
plt.scatter(X_reduit[:,0], X_reduit[:,1], c = df['class'])
plt.show()
- Résultat de l’exécution :
Conclusion
Dans ce tutoriel nous avons vu deux principales méthodes de la réduction de la dimensionnalité qui sont le PCA et le LDA ainsi que leur implémentation en Python. À la fin du tutoriel, nous avons renforcé les connaissances acquises à l’aide de quelques exercices d’application.
Article publié le 03 Décembre 2020 par Imane BENHMIDOU