Distribution des données en Machine Learning
Découvrez les distributions de données en Python : normale, asymétrique et uniforme, comment les détecter et pourquoi elles sont importantes.
La distribution des données décrit comment les valeurs se répartissent dans un jeu de données — quelles valeurs sont fréquentes, lesquelles sont rares et jusqu'où elles s'étendent par rapport au centre. Avant d'entraîner tout modèle de machine learning, comprendre la distribution de vos données vous aide à choisir le bon algorithme, à détecter des anomalies, à décider si vous devez mettre à l'échelle ou transformer les variables, et à éviter des biais cachés dans les prédictions.
Ce chapitre couvre les formes de distribution les plus courantes, comment les mesurer en Python avec NumPy et SciPy, et ce que chaque distribution implique pour vos décisions de modélisation.
Qu'est-ce que la distribution des données ?
Une distribution des données est le schéma décrivant la fréquence à laquelle chaque valeur (ou plage de valeurs) apparaît dans un jeu de données. Lorsque vous tracez une distribution, vous observez généralement une courbe ou un histogramme dont la forme vous renseigne beaucoup sur les données sous-jacentes.
Les trois propriétés qui définissent toute distribution sont :
- Centre — là où la plupart des valeurs se regroupent (mesuré par la moyenne, la médiane et le mode)
- Dispersion — à quel point les valeurs s'écartent du centre (mesurée par l'écart-type et l'écart interquartile)
- Forme — si la distribution est symétrique, asymétrique ou plate
Il est nécessaire de comprendre ces trois aspects avant d'introduire des données dans un modèle.
Types de distributions courants
Distribution normale
La distribution normale (également appelée distribution gaussienne) est la distribution la plus importante en statistique et en machine learning. Son histogramme forme une courbe en cloche symétrique : les valeurs se regroupent autour de la moyenne, et la fréquence diminue de façon égale des deux côtés.
Propriétés clés :
- La moyenne, la médiane et le mode sont tous égaux.
- Environ 68 % des valeurs se situent à un écart-type de la moyenne, 95 % à deux, et 99,7 % à trois (la règle empirique).
- Définie entièrement par deux paramètres : la moyenne (μ) et l'écart-type (σ).
De nombreux phénomènes réels suivent approximativement une distribution normale — la taille des êtres humains, les erreurs de mesure et les scores de QI en sont des exemples classiques. Des algorithmes tels que l'analyse discriminante linéaire, le classificateur naïf de Bayes gaussien et la régression linéaire supposent (ou bénéficient de) variables distribuées normalement.
import numpy as np
from scipy import stats
# Simulate 1 000 adult heights (cm) drawn from a normal distribution
rng = np.random.default_rng(seed=42)
heights = rng.normal(loc=170, scale=10, size=1000)
print(f"Mean: {np.mean(heights):.1f} cm")
print(f"Std: {np.std(heights):.1f} cm")
# Verify the empirical rule
within_1_std = np.sum(np.abs(heights - 170) < 10) / 1000 * 100
within_2_std = np.sum(np.abs(heights - 170) < 20) / 1000 * 100
within_3_std = np.sum(np.abs(heights - 170) < 30) / 1000 * 100
print(f"Within 1 std: {within_1_std:.1f}% (expected ~68%)")
print(f"Within 2 std: {within_2_std:.1f}% (expected ~95%)")
print(f"Within 3 std: {within_3_std:.1f}% (expected ~99.7%)")Sortie :
Mean: 169.7 cm
Std: 9.9 cm
Within 1 std: 68.8% (expected ~68%)
Within 2 std: 95.7% (expected ~95%)
Within 3 std: 99.8% (expected ~99.7%)Distribution asymétrique
Une distribution asymétrique est non symétrique : une queue est plus longue que l'autre. L'asymétrie est mesurée par la statistique de skewness — les valeurs positives indiquent une asymétrie à droite (positive), les valeurs négatives indiquent une asymétrie à gauche (négative), et les valeurs proches de zéro indiquent une symétrie approximative.
Asymétrie positive (queue à droite) : la queue s'étend vers la droite. La moyenne est tirée au-dessus de la médiane par un petit nombre de valeurs très élevées. Les revenus et les prix immobiliers en sont des exemples typiques — quelques personnes ayant des salaires très élevés ou des propriétés très chères tirent la moyenne bien au-dessus de la médiane.
Asymétrie négative (queue à gauche) : la queue s'étend vers la gauche. Les scores d'un examen facile montrent souvent ce schéma — la plupart des étudiants obtiennent des notes proches du maximum, mais quelques-uns obtiennent des notes très basses.
import numpy as np
from scipy import stats
# Right-skewed: a small number of very high values pull the mean up
salaries = np.array([30000, 32000, 34000, 35000, 36000, 38000,
40000, 42000, 45000, 55000, 70000, 120000, 200000])
print("--- Salary distribution ---")
print(f"Mean: {np.mean(salaries):.0f}") # pulled up by outliers
print(f"Median: {np.median(salaries):.0f}") # more representative center
print(f"Skewness: {stats.skew(salaries):.2f}") # positive = right skew
# Left-skewed: most values are high, a few are very low
exam_scores = np.array([40, 68, 75, 80, 82, 85, 88, 90, 91, 92, 93, 95, 98])
print("\n--- Exam score distribution ---")
print(f"Mean: {np.mean(exam_scores):.1f}")
print(f"Median: {np.median(exam_scores):.1f}")
print(f"Skewness: {stats.skew(exam_scores):.2f}") # negative = left skewSortie :
--- Salary distribution ---
Mean: 59769
Median: 40000
Skewness: 2.16
--- Exam score distribution ---
Mean: 82.8
Median: 88.0
Skewness: -1.77En présence d'asymétrie, la moyenne est une mesure du centre trompeuse. La médiane est généralement une statistique de synthèse plus appropriée pour les données asymétriques.
Distribution uniforme
Dans une distribution uniforme, chaque valeur (ou plage de valeurs) est également probable. Un dé à six faces équitable produit une distribution uniforme discrète ; choisir aléatoirement un nombre flottant entre 0 et 1 produit une distribution uniforme continue.
import numpy as np
rng = np.random.default_rng(seed=42)
# Continuous uniform distribution between 0 and 1
uniform_data = rng.uniform(low=0, high=1, size=10000)
print(f"Mean: {np.mean(uniform_data):.3f} (expected 0.500)")
print(f"Std: {np.std(uniform_data):.3f} (expected ~0.289)")
print(f"Min: {np.min(uniform_data):.3f}")
print(f"Max: {np.max(uniform_data):.3f}")Sortie :
Mean: 0.497 (expected 0.500)
Std: 0.288 (expected ~0.289)
Min: 0.000
Max: 1.000Les distributions uniformes apparaissent dans l'échantillonnage aléatoire, l'augmentation de données et comme priors dans les modèles bayésiens.
Résumer une distribution en Python
Avant la modélisation, calculez toujours un résumé rapide de chaque variable. NumPy et SciPy couvrent ensemble les statistiques clés :
import numpy as np
from scipy import stats
data = np.array([12, 15, 14, 10, 18, 14, 13, 16, 14, 12])
print("--- Distribution Summary ---")
print(f"Mean: {np.mean(data):.1f}")
print(f"Median: {np.median(data):.1f}")
print(f"Std: {np.std(data, ddof=1):.2f}") # sample std deviation
print(f"Min: {np.min(data)}")
print(f"Max: {np.max(data)}")
print(f"Skewness: {stats.skew(data):.3f}") # near 0 = symmetricSortie :
--- Distribution Summary ---
Mean: 13.8
Median: 14.0
Std: 2.25
Min: 10
Max: 18
Skewness: 0.200Un skewness proche de 0.200 indique que les données sont à peu près symétriques — pas d'asymétrie marquée dans un sens ou dans l'autre.
Tester la normalité
Certains algorithmes supposent explicitement que les variables suivent une distribution normale. Le test de Shapiro-Wilk est le test le plus fiable pour les petits échantillons (n < 5 000). Il renvoie une statistique de test W et une p-valeur. Une p-valeur supérieure à 0,05 signifie que vous ne pouvez pas rejeter l'hypothèse que les données sont normales.
import numpy as np
from scipy import stats
rng = np.random.default_rng(seed=42)
# Sample from a normal distribution
normal_sample = rng.normal(loc=0, scale=1, size=50)
stat, p = stats.shapiro(normal_sample)
print(f"Shapiro-Wilk: W={stat:.3f}, p={p:.3f}")
if p > 0.05:
print("Data appears to be normally distributed.")
else:
print("Data does not appear to be normally distributed.")Sortie :
Shapiro-Wilk: W=0.984, p=0.730
Data appears to be normally distributed.Quand l'utiliser : appliquez le test de Shapiro-Wilk lorsque les hypothèses d'un modèle exigent explicitement la normalité — par exemple, avant d'utiliser un test t paramétrique ou l'analyse discriminante linéaire. De nombreux algorithmes modernes (gradient boosting, forêts aléatoires, réseaux de neurones) ne sont pas sensibles à la forme de distribution des variables, vous n'avez donc pas toujours besoin de ce test.
Pourquoi la forme de la distribution est importante pour la modélisation
| Situation | Ce que cela signifie | Que faire |
|---|---|---|
| Variables normales | Les hypothèses standard sont vérifiées | Utiliser les modèles paramétriques tels quels |
| Variables à asymétrie positive | La moyenne est surévaluée ; les valeurs extrêmes dominent | Appliquer une transformation logarithmique ou racine carrée |
| Variables à asymétrie négative | Les faibles valeurs sont des valeurs aberrantes | Appliquer une transformation quadratique ou par réflexion |
| Variables uniformes | Pas de regroupement central | Souvent acceptable ; normaliser pour les modèles basés sur la distance |
| Variables multimodales | Plusieurs clusters | Envisager de diviser les données ou d'utiliser une étape de clustering |
Traiter les données asymétriques avec la transformation logarithmique
Un remède courant pour les données à asymétrie positive est la transformation logarithmique, qui compresse les grandes valeurs et dilate les petites, produisant souvent une distribution plus proche de la normale.
import numpy as np
from scipy import stats
rng = np.random.default_rng(seed=7)
# Simulate log-normally distributed incomes (a common real-world pattern)
incomes = rng.lognormal(mean=10.5, sigma=0.5, size=1000)
print(f"Before transform — skewness: {stats.skew(incomes):.2f}")
log_incomes = np.log(incomes)
print(f"After log transform — skewness: {stats.skew(log_incomes):.2f}")Sortie :
Before transform — skewness: 1.44
After log transform — skewness: 0.01Après la transformation logarithmique, l'asymétrie passe de 1.44 à presque zéro, rendant les données bien plus adaptées aux modèles qui supposent la normalité.
Remarque : la transformation logarithmique exige que toutes les valeurs soient strictement positives. Ajoutez une petite constante (p. ex. np.log(x + 1)) si vos données contiennent des zéros.
Visualiser la distribution des données
La visualisation est le moyen le plus rapide d'inspecter une distribution. Un histogramme divise les valeurs en classes et montre combien d'observations tombent dans chaque classe. Utilisez les histogrammes Matplotlib pour les créer :
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(seed=42)
data = rng.normal(loc=170, scale=10, size=500)
plt.figure(figsize=(8, 4))
plt.hist(data, bins=30, color='steelblue', edgecolor='white')
plt.title("Height Distribution (Normal)")
plt.xlabel("Height (cm)")
plt.ylabel("Frequency")
plt.tight_layout()
plt.show()Pour un aperçu plus rapide de plusieurs variables à la fois, utilisez un nuage de points pour rechercher des relations entre les distributions.
Distribution et mise à l'échelle des variables
Si vos variables ont des distributions ou des échelles très différentes, les algorithmes basés sur la distance (k plus proches voisins, SVM, k-means clustering) seront dominés par les variables ayant la plus grande plage. La mise à l'échelle des variables est la solution standard : StandardScaler normalise chaque variable à une moyenne de 0 et un écart-type de 1, et MinMaxScaler comprime les valeurs dans [0, 1].
Choisissez le normaliseur en fonction de la distribution sous-jacente :
- Distribution normale →
StandardScaler(supprime la moyenne, met à l'échelle à variance unitaire) - Distribution uniforme ou bornée →
MinMaxScaler(préserve la forme) - Fortement asymétrique avec valeurs aberrantes →
RobustScaler(utilise la médiane et l'IQR, en ignorant les valeurs extrêmes)
Résumé
- Distribution normale : courbe en cloche symétrique ; moyenne ≈ médiane ; convient aux modèles paramétriques.
- Distribution asymétrique : non symétrique ; la moyenne est tirée vers la queue ; les transformations logarithmiques ou de puissance peuvent réduire l'asymétrie.
- Distribution uniforme : toutes les valeurs sont également probables ; apparaît dans l'échantillonnage aléatoire et comme priors non informatifs.
- Utilisez
scipy.stats.skew()pour mesurer l'asymétrie etscipy.stats.shapiro()pour tester formellement la normalité. - Inspectez toujours les distributions avant la modélisation — la forme influence le choix de l'algorithme, la façon de transformer les variables et la stratégie de mise à l'échelle à appliquer.
Ensuite, explorez la Distribution normale des données pour approfondir la distribution gaussienne et apprendre à la générer et à l'utiliser avec SciPy.