Clustering de voitures
Ce notebook est un exemple de clustering de données. Nous souhaitons diviser des voitures en plusieurs groupes. Commençons par regarder les données.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.io as pio
pio.renderers.default = "notebook"
data = pd.read_excel("voitures_clustering.xlsx")
data.T
L'histogramme de chaque paramètre donne des indications sur sa répartition :
data.hist(bins=10, figsize=(20, 10));
Pour utiliser un algorithme de machine learning, il est toujours conseillé de standardiser les données.
from sklearn import preprocessing
data_scaled = preprocessing.scale(data.iloc[:, 1:]) # standardisation
Pour visualiser les données, nous allons utiliser une analyse par composantes principales (PCA), permettant de réduire le nombre de dimensions (ici, de 9 à 2) :
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
data2d = pd.DataFrame(pca.fit_transform(data_scaled), index=data["Modele"], columns=["x", "y"])
pca.explained_variance_ratio_ # variance expliquée par les deux axes principaux
Le pourcentage de variance expliquée par les deux axes principaux est environ 0.84, ce qui permet donc de conserver beaucoup d'information.
pd.DataFrame(pca.components_, index=["x", "y"], columns=data.columns[1:]) # coordonnées des deux axes principaux
On voit que l'axe x discrimine les grosses voitures : plus cette valeur est petite, plus la voiture correspondante est puissante, rapide, large, polluante... Étonnamment, la hauteur rentre peu en compte sur cet axe et est même inversement proportionnelle aux autre coordonnées.
L'axe y discrimine les voitures selon leur hauteur principalement.
Il y a donc 2 informations particulièrement importantes : la largeur générale de la voiture et sa hauteur.
fig = px.scatter(x=data2d.iloc[:, 0], y=data2d.iloc[:, 1], text=data2d.index)
fig.update_traces(textposition='top center')
fig.show()
Puisque nous ne connaissons pas à l'avance les labels/groupes, nous allons utiliser un algorithme de clustering. L'un des plus connus est K-Means. Comme K-Means dépend largement de la position des centroïdes initiaux, nous l'exécutons plusieurs fois en conservant le meilleur (i.e. avec l'inertie la plus faible) :
def kmeans_multiple(data, k, n):
km_best = KMeans(n_clusters=k).fit(data)
for _ in range(n - 1):
km = KMeans(n_clusters=k).fit(data)
if km.inertia_ < km_best.inertia_:
km_best = km
return km_best
Pour choisir le nombre de clusters $k$, on peut dessiner l'inertie en fonction du nombre de clusters.
from sklearn.cluster import KMeans
X, Y = [], []
for k in range(2, 10):
km = kmeans_multiple(data_scaled, k, 20)
Y.append(km.inertia_)
X.append(k)
plt.plot(X, Y);
On choisit $k$ comme le nombre de clusters à partir duquel l'inertie stagne (elbow method), ici 5 par exemple (on pourrait aussi raisonnablement choisir 4).
Remarque : on pourrait aussi utiliser la méthode par silhouette analysis.
km = kmeans_multiple(data_scaled, 5, 20)
fig = px.scatter(x=data2d.iloc[:, 0], y=data2d.iloc[:, 1], text=data2d.index, color=list(map(str, km.labels_)))
fig.update_traces(marker=dict(size=12), textposition='top center')
fig.update_layout(title_text='Données suivant les deux composantes principales du PCA')
fig.show()
data.groupby(km.labels_) \
.mean() # moyenne des caractéristiques des voitures de chaque cluster
On peut aussi appliquer des classifications one vs all à l'aide de regressions logistiques pour regarder les coefficients de classification, c'est à dire ce qui permet de discriminer chaque classe :
from sklearn.linear_model import LogisticRegression
rows = []
for i in range(km.n_clusters):
t = np.where(km.labels_ == i)[0]
y = np.zeros((len(data.index)))
y[t] = 1
lr = LogisticRegression(max_iter = 4000).fit(data.iloc[:, 1:], y)
rows.append(lr.coef_[0])
pd.DataFrame(rows, columns=data.columns[1:])
Conclusion
Ainsi on distingue :
- Groupe 0 : voitures sportives. Puissante, rapide, polluante, plutôt basse. Exemple : Alfa Romeo 156.
- Groupe 1 : voitures "normales". Exemple : Laguna.
- Groupe 2 : citadines. Peu puissante, petite, légère, faible consommation. Exemple : Twingo.
- Groupe 3 : grosse voiture type SUV. Lourde, polluante, puissante. Exemple : C5.
- Groupe 4 : voiture familiale/petit monospace. Haute, peu rapide. Exemple : Modus.