Sklearn Train Test Split : Guide Complet pour Diviser les Données en Python
Updated on
Entraîner un modèle de machine learning sur l'ensemble de votre jeu de données puis l'évaluer sur les mêmes données conduit à un problème critique : votre modèle semblera bien fonctionner, mais il aura simplement mémorisé les données au lieu d'apprendre des motifs. Ce surapprentissage signifie que votre modèle échouera lamentablement lorsqu'il rencontrera de nouvelles données non vues. Les data scientists ont besoin d'un moyen fiable d'évaluer les performances du modèle sur des données que le modèle n'a jamais vues pendant l'entraînement.
La solution est la division train-test. En réservant une partie de vos données pour l'évaluation, vous obtenez une évaluation honnête de la façon dont votre modèle fonctionnera dans le monde réel. La fonction train_test_split de sklearn rend ce processus simple, mais l'utiliser incorrectement peut toujours conduire à des fuites de données, une mauvaise généralisation et des métriques de performance trompeuses.
Ce guide couvre tout ce que vous devez savoir sur train_test_split de sklearn, de l'utilisation de base aux techniques avancées pour les données de séries temporelles, les classes déséquilibrées et les problèmes multi-sorties.
Qu'est-ce que Train Test Split ?
Train test split est la technique fondamentale pour évaluer les modèles de machine learning. Vous divisez votre jeu de données en deux parties : un ensemble d'entraînement utilisé pour ajuster le modèle, et un ensemble de test utilisé pour évaluer les performances du modèle sur des données non vues.
La fonction train_test_split de scikit-learn (sklearn) automatise ce processus, gérant le mélange aléatoire et la division avec une seule ligne de code.
from sklearn.model_selection import train_test_split
# Utilisation de base
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)Dans cet exemple, X contient vos features (variables d'entrée) et y contient votre variable cible (ce que vous voulez prédire). La fonction renvoie quatre tableaux : features d'entraînement, features de test, étiquettes d'entraînement et étiquettes de test.
Syntaxe de Base de train_test_split
L'utilisation la plus simple de train_test_split nécessite seulement deux arguments : vos features et votre variable cible.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
# Charger des données d'exemple
iris = load_iris()
X = iris.data
y = iris.target
# Diviser les données (80% entraînement, 20% test)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
print(f"Training samples: {len(X_train)}")
print(f"Test samples: {len(X_test)}")Cela divise vos données de manière aléatoire, avec 80% allant à l'entraînement et 20% au test. Cependant, cette utilisation de base a un défaut critique : la division est différente à chaque fois que vous exécutez le code, rendant les résultats non reproductibles.
Paramètres Essentiels
test_size et train_size
Le paramètre test_size contrôle la quantité de données qui vont dans l'ensemble de test. Vous pouvez le spécifier comme :
- Un float entre 0.0 et 1.0 (proportion du jeu de données)
- Un entier (nombre absolu d'échantillons de test)
# Ensemble de test de 30%
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# 50 échantillons dans l'ensemble de test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=50)
# Alternativement, spécifier train_size
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)Si vous spécifiez à la fois test_size et train_size, ils doivent s'additionner à 1.0 (ou à la taille totale du jeu de données si vous utilisez des entiers). Dans la plupart des cas, spécifier seulement test_size est suffisant.
random_state pour la Reproductibilité
Le paramètre random_state est crucial pour des résultats reproductibles. Sans lui, vous obtenez une division différente à chaque fois que vous exécutez votre code, rendant impossible le débogage ou la comparaison d'expériences.
# Sans random_state - division différente à chaque fois
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2)
print(f"Same split? {(X_train1 == X_train2).all()}") # False
# Avec random_state - même division à chaque fois
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2, random_state=42)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Same split? {(X_train1 == X_train2).all()}") # TrueUtilisez n'importe quel entier pour random_state. Le nombre spécifique n'a pas d'importance ; ce qui compte, c'est d'utiliser le même nombre de manière cohérente dans votre projet.
Paramètre shuffle
Par défaut, train_test_split mélange les données avant de les diviser. Pour la plupart des tâches de machine learning, c'est exactement ce que vous voulez. Cependant, pour les données de séries temporelles ou lorsque l'ordre compte, vous devriez désactiver le mélange.
# Mélange activé (par défaut)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
# Mélange désactivé (pour les séries temporelles)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)Lorsque shuffle=False, la fonction prend simplement la première portion pour l'entraînement et la dernière portion pour le test, en conservant l'ordre original.
Tableau de Référence des Paramètres
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
test_size | float ou int | None | Proportion (0.0-1.0) ou nombre d'échantillons pour l'ensemble de test |
train_size | float ou int | None | Proportion (0.0-1.0) ou nombre d'échantillons pour l'ensemble d'entraînement |
random_state | int | None | Graine aléatoire pour la reproductibilité |
shuffle | bool | True | Si les données doivent être mélangées avant division |
stratify | array-like | None | Données à utiliser pour division stratifiée |
Division Stratifiée pour Données Déséquilibrées
Lorsque votre jeu de données a des classes déséquilibrées (certaines classes ont beaucoup moins d'échantillons que d'autres), une division aléatoire peut créer des ensembles d'entraînement ou de test qui représentent mal la distribution globale. Cela est particulièrement problématique pour les tâches de classification.
Le paramètre stratify garantit que la distribution des classes dans les ensembles d'entraînement et de test correspond au jeu de données original.
import numpy as np
from sklearn.model_selection import train_test_split
# Créer un jeu de données déséquilibré (90% classe 0, 10% classe 1)
X = np.random.randn(1000, 5)
y = np.array([0] * 900 + [1] * 100)
# Sans stratification
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")
# Avec stratification
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"\nStratified train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Stratified test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")Avec la stratification, les ensembles d'entraînement et de test conservent la distribution de classes 90/10. Sans elle, vous pourriez avoir de la chance et obtenir une division représentative, ou vous pourriez vous retrouver avec un ensemble de test qui n'a que 5% de la classe 1, conduisant à des métriques d'évaluation peu fiables.
Diviser Plusieurs Tableaux
Vous pouvez diviser plusieurs tableaux en même temps, et sklearn s'assurera qu'ils sont divisés de la même manière (mêmes indices pour tous les tableaux).
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
sample_weights = np.random.rand(100)
# Diviser les trois tableaux
X_train, X_test, y_train, y_test, weights_train, weights_test = train_test_split(
X, y, sample_weights, test_size=0.2, random_state=42
)
print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")
print(f"weights_train shape: {weights_train.shape}")Ceci est particulièrement utile lorsque vous avez des poids d'échantillons, plusieurs variables cibles ou des métadonnées supplémentaires qui doivent être divisées de manière cohérente.
Train/Test Split vs Validation Croisée vs Holdout
Différentes stratégies de validation servent différents objectifs. Voici une comparaison :
| Méthode | Utilisation des Données | Coût Calculatoire | Meilleur Pour | Limitations |
|---|---|---|---|---|
| Train/Test Split | 70-80% entraînement, 20-30% test | Faible | Évaluation rapide du modèle, grands jeux de données | Évaluation unique, pourrait avoir de la chance/malchance avec la division |
| Validation Croisée | 100% utilisé pour entraînement/test (k-fold) | Élevé (k fois plus lent) | Petits jeux de données, estimation fiable des performances | Coûteux en calcul, pas pour les séries temporelles |
| Train/Val/Test (Holdout) | 60% entraînement, 20% validation, 20% test | Moyen | Réglage d'hyperparamètres, évaluation finale | Plus de données nécessaires, flux de travail plus complexe |
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
model = RandomForestClassifier(random_state=42)
# Méthode 1 : Division simple train/test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model.fit(X_train, y_train)
print(f"Train/Test Split Score: {model.score(X_test, y_test):.3f}")
# Méthode 2 : Validation croisée à 5 plis
scores = cross_val_score(model, X, y, cv=5)
print(f"Cross-Validation Score: {scores.mean():.3f} (+/- {scores.std():.3f})")
# Méthode 3 : Division Train/Val/Test
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
model.fit(X_train, y_train)
print(f"Validation Score: {model.score(X_val, y_val):.3f}")
print(f"Test Score: {model.score(X_test, y_test):.3f}")Pour la plupart des projets, commencez par une simple division train/test. Utilisez la validation croisée lorsque vous avez des données limitées ou besoin d'une estimation de performance plus robuste. Utilisez train/val/test lorsque vous devez ajuster des hyperparamètres.
Techniques Avancées de Division
Division de Séries Temporelles
Pour les données de séries temporelles, le mélange aléatoire détruit l'ordre temporel, ce qui peut conduire à des fuites de données (utiliser des informations futures pour prédire le passé). Utilisez plutôt TimeSeriesSplit :
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randn(100)
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
print(f"Train size: {len(train_index)}, Test size: {len(test_index)}")TimeSeriesSplit crée plusieurs divisions train/test où chaque ensemble d'entraînement inclut toutes les données passées jusqu'à un certain point, et l'ensemble de test inclut la période immédiatement suivante. Cela simule les prévisions du monde réel où vous n'avez que des données passées pour prédire l'avenir.
GroupShuffleSplit pour Données Groupées
Lorsque vos données ont des groupes (par exemple, plusieurs mesures du même patient, plusieurs transactions du même client), vous devez vous assurer que des groupes entiers restent ensemble dans l'ensemble d'entraînement ou de test pour éviter les fuites de données.
from sklearn.model_selection import GroupShuffleSplit
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
groups = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25) # 4 groupes
gss = GroupShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_idx, test_idx in gss.split(X, y, groups):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
print(f"Train groups: {np.unique(groups[train_idx])}")
print(f"Test groups: {np.unique(groups[test_idx])}")Cela garantit que tous les échantillons d'un groupe donné sont dans l'ensemble d'entraînement ou dans l'ensemble de test, jamais dans les deux.
Division Stratifiée Multi-Sorties
Pour les problèmes de classification multi-sorties, vous ne pouvez pas utiliser directement stratify avec un tableau 2D. Créez plutôt une seule étiquette qui représente la combinaison de toutes les sorties :
import numpy as np
from sklearn.model_selection import train_test_split
X = np.random.randn(1000, 10)
y = np.random.randint(0, 2, (1000, 3)) # 3 sorties binaires
# Créer des étiquettes combinées pour la stratification
y_combined = y[:, 0] * 4 + y[:, 1] * 2 + y[:, 2]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y_combined
)
print(f"Original distribution: {np.unique(y_combined, return_counts=True)[1]}")
print(f"Train distribution: {np.unique(y_combined[:(len(X) - len(X_test))], return_counts=True)[1]}")Meilleures Pratiques pour Train Test Split
Choisir le Bon Ratio de Division
Les ratios de division les plus courants sont :
- 80/20 : Choix standard pour les jeux de données moyens à grands (10 000+ échantillons)
- 70/30 : Meilleur pour les petits jeux de données (1 000-10 000 échantillons) pour avoir une évaluation de test plus robuste
- 90/10 : Pour les très grands jeux de données (100 000+ échantillons) où même 10% fournit suffisamment d'échantillons de test
- 60/20/20 : Pour train/validation/test lors de l'ajustement d'hyperparamètres
import numpy as np
def recommend_split_ratio(n_samples):
if n_samples < 1000:
return "Consider cross-validation instead of simple split"
elif n_samples < 10000:
return "70/30 split recommended"
elif n_samples < 100000:
return "80/20 split recommended"
else:
return "90/10 or 80/20 split recommended"
sample_sizes = [500, 5000, 50000, 500000]
for size in sample_sizes:
print(f"{size} samples: {recommend_split_ratio(size)}")Éviter les Fuites de Données
Les fuites de données se produisent lorsque des informations de l'ensemble de test influencent le processus d'entraînement. Sources courantes :
- Prétraitement avant division : Divisez toujours d'abord, puis prétraitez
- Mise à l'échelle des features sur données combinées : Ajustez le scaler uniquement sur les données d'entraînement
- Sélection de features sur données combinées : Sélectionnez les features en utilisant uniquement les données d'entraînement
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import numpy as np
X = np.random.randn(1000, 10)
y = np.random.randint(0, 2, 1000)
# INCORRECT : Mettre à l'échelle avant division (fuite de données !)
scaler_wrong = StandardScaler()
X_scaled_wrong = scaler_wrong.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled_wrong, y, test_size=0.2)
# CORRECT : Diviser d'abord, puis mettre à l'échelle
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # Ajuster sur données d'entraînement
X_test_scaled = scaler.transform(X_test) # Transformer les données de test avec les statistiques d'entraînementL'approche incorrecte utilise des informations de l'ensemble du jeu de données (y compris les échantillons de test) pour calculer les paramètres de mise à l'échelle, ce qui fuit des informations sur l'ensemble de test dans le processus d'entraînement.
Stratifier Autant que Possible
Pour les problèmes de classification, utilisez toujours une division stratifiée sauf si vous avez une raison spécifique de ne pas le faire. Cela est particulièrement critique pour :
- Les jeux de données déséquilibrés
- Les petits jeux de données
- Les problèmes multi-classes avec des classes rares
from sklearn.model_selection import train_test_split
import numpy as np
# Jeu de données de maladie rare : 1% de cas positifs
X = np.random.randn(1000, 20)
y = np.array([0] * 990 + [1] * 10)
# Sans stratification - pourrait ne pas avoir de cas positifs dans l'ensemble de test !
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=123)
print(f"Non-stratified test positives: {sum(y_test)}")
# Avec stratification - garantit une représentation proportionnelle
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.1, random_state=123, stratify=y
)
print(f"Stratified test positives: {sum(y_test)}")Erreurs Courantes à Éviter
1. Oublier random_state
Sans random_state, vos résultats changent à chaque fois que vous exécutez le code. Cela rend le débogage impossible et les expériences non reproductibles.
# MAUVAIS : Pas de random_state
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# BON : Définir random_state
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)2. Ne Pas Stratifier les Classes Déséquilibrées
Pour les jeux de données déséquilibrés, la division aléatoire peut créer des ensembles de test très non représentatifs, conduisant à des métriques de performance peu fiables.
# MAUVAIS : Pas de stratification pour données déséquilibrées
X_train, X_test, y_train, y_test = train_test_split(X, y_imbalanced, test_size=0.2)
# BON : Utiliser la stratification
X_train, X_test, y_train, y_test = train_test_split(
X, y_imbalanced, test_size=0.2, stratify=y_imbalanced, random_state=42
)3. Diviser les Données de Séries Temporelles avec Shuffle
Les modèles de séries temporelles dépendent de l'ordre temporel. Le mélange détruit cette structure et peut conduire à de graves fuites de données.
# MAUVAIS : Mélanger les données de séries temporelles
X_train, X_test, y_train, y_test = train_test_split(
X_timeseries, y_timeseries, test_size=0.2, shuffle=True
)
# BON : Désactiver le mélange ou utiliser TimeSeriesSplit
X_train, X_test, y_train, y_test = train_test_split(
X_timeseries, y_timeseries, test_size=0.2, shuffle=False
)4. Prétraiter Avant de Diviser
Ajuster des préprocesseurs (scalers, imputers, encodeurs) sur l'ensemble du jeu de données avant de diviser cause des fuites de données.
# MAUVAIS : Prétraiter avant division
X_scaled = StandardScaler().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2)
# BON : Diviser d'abord, puis prétraiter
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)5. Utiliser l'Ensemble de Test pour le Réglage d'Hyperparamètres
L'ensemble de test ne devrait être utilisé que pour l'évaluation finale. Si vous l'utilisez pour choisir des hyperparamètres, vous entraînez essentiellement sur vos données de test.
# MAUVAIS : Réglage sur ensemble de test
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
model = RandomForestClassifier(n_estimators=n_estimators)
model.fit(X_train, y_train)
score = model.score(X_test, y_test) # Utiliser l'ensemble de test !
if score > best_score:
best_score = score
best_params = n_estimators
# BON : Utiliser ensemble de validation ou validation croisée
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
model = RandomForestClassifier(n_estimators=n_estimators)
model.fit(X_train, y_train)
score = model.score(X_val, y_val) # Utiliser ensemble de validation
if score > best_score:
best_score = score
best_params = n_estimatorsExemple Pratique : Flux de Travail Complet
Voici un flux de travail complet de machine learning utilisant train_test_split correctement :
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# Charger les données
np.random.seed(42)
X = np.random.randn(1000, 10)
y = (X[:, 0] + X[:, 1] > 0).astype(int) # Classification binaire
# Étape 1 : Diviser les données (stratifié pour ensemble de test équilibré)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Étape 2 : Prétraiter (ajuster uniquement sur données d'entraînement)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Étape 3 : Entraîner le modèle
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train_scaled, y_train)
# Étape 4 : Évaluer
y_pred = model.predict(X_test_scaled)
print("Classification Report:")
print(classification_report(y_test, y_pred))
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))
# Étape 5 : Vérifier le surapprentissage
train_score = model.score(X_train_scaled, y_train)
test_score = model.score(X_test_scaled, y_test)
print(f"\nTrain accuracy: {train_score:.3f}")
print(f"Test accuracy: {test_score:.3f}")
print(f"Overfitting gap: {train_score - test_score:.3f}")Utiliser RunCell pour la Division Interactive de Données
Lors du travail dans les notebooks Jupyter, expérimenter avec différents ratios de division et paramètres peut être fastidieux. RunCell (opens in a new tab) fournit un agent IA spécialement conçu pour les flux de travail de data science dans Jupyter. Il peut vous aider à :
- Tester automatiquement plusieurs ratios de division et comparer les résultats
- Détecter les fuites de données dans votre pipeline de prétraitement
- Suggérer des stratégies de stratification optimales pour votre jeu de données spécifique
- Générer des courbes de validation pour choisir le bon ratio train/test
RunCell s'intègre directement dans votre environnement Jupyter, facilitant l'itération sur votre stratégie de division de données sans écrire de code répétitif.
Visualiser vos Données avec PyGWalker
Après avoir divisé vos données, il est crucial de vérifier que vos ensembles d'entraînement et de test ont des distributions similaires. PyGWalker (opens in a new tab) transforme vos DataFrames pandas en visualisations interactives de style Tableau, facilitant :
- La comparaison des distributions de features entre les ensembles d'entraînement et de test
- L'identification des biais d'échantillonnage potentiels dans vos divisions
- La visualisation des déséquilibres de classes et la vérification que la stratification a fonctionné correctement
- L'exploration des relations entre les features dans vos données d'entraînement
import pygwalker as pyg
import pandas as pd
# Convertir en DataFrames pour visualisation
train_df = pd.DataFrame(X_train, columns=[f'feature_{i}' for i in range(X_train.shape[1])])
train_df['dataset'] = 'train'
test_df = pd.DataFrame(X_test, columns=[f'feature_{i}' for i in range(X_test.shape[1])])
test_df['dataset'] = 'test'
combined = pd.concat([train_df, test_df])
# Créer une visualisation interactive
pyg.walk(combined)Cela vous permet d'explorer de manière interactive si vos distributions d'entraînement et de test correspondent, ce qui est crucial pour une évaluation fiable du modèle.
FAQ
Comment choisir entre une division 80/20 et 70/30 ?
Utilisez 80/20 pour les jeux de données de plus de 10 000 échantillons, et 70/30 pour les petits jeux de données (1 000-10 000 échantillons). La clé est de s'assurer que votre ensemble de test a suffisamment d'échantillons pour une évaluation fiable, généralement au moins 200-500 échantillons pour les problèmes de classification. Pour les très grands jeux de données (100 000+ échantillons), vous pouvez utiliser 90/10 ou même 95/5 car même 5% fournit des milliers d'échantillons de test.
Qu'est-ce que random_state et pourquoi est-ce important ?
random_state est la graine pour le générateur de nombres aléatoires qui mélange vos données avant la division. Utiliser la même valeur de random_state garantit que vous obtenez la division identique à chaque fois que vous exécutez votre code, ce qui est essentiel pour la reproductibilité et le débogage. Sans lui, vous obtiendrez différentes divisions train/test à chaque fois, rendant impossible de déterminer si les changements de performance sont dus à des améliorations du modèle ou simplement à des divisions de données chanceuses/malchanceuses.
Quand dois-je utiliser le paramètre stratify ?
Utilisez stratify=y pour tous les problèmes de classification, en particulier lorsque vous avez des classes déséquilibrées ou de petits jeux de données. La stratification garantit que la distribution des classes dans vos ensembles d'entraînement et de test correspond à la distribution globale. Par exemple, si 10% de vos données sont des cas positifs, la stratification garantit que les ensembles d'entraînement et de test ont environ 10% de cas positifs, évitant les biais d'évaluation dus à des divisions non représentatives.
Puis-je utiliser train_test_split pour des données de séries temporelles ?
Non, vous ne devriez pas utiliser train_test_split avec shuffle=True pour des données de séries temporelles, car cela détruit l'ordre temporel et cause des fuites de données (utiliser des données futures pour prédire le passé). Utilisez plutôt train_test_split avec shuffle=False pour une division chronologique simple, ou utilisez TimeSeriesSplit pour une validation croisée qui respecte l'ordre temporel. Pour les séries temporelles, assurez-vous toujours que les données d'entraînement viennent chronologiquement avant les données de test.
En quoi train_test_split diffère-t-il de la validation croisée ?
train_test_split crée une seule partition train/test (généralement 80/20), vous donnant une estimation de performance. La validation croisée (comme k-fold) crée plusieurs divisions train/test et moyenne les résultats, fournissant une estimation de performance plus robuste. Utilisez train_test_split pour une évaluation rapide et de grands jeux de données. Utilisez la validation croisée pour de petits jeux de données (moins de 1 000 échantillons) ou lorsque vous avez besoin d'estimations de performance plus fiables. La validation croisée est k fois plus lente (par exemple, 5-fold est 5× plus lent) mais réduit la variance dans vos métriques de performance.
Conclusion
Le train_test_split de sklearn est l'outil fondamental pour évaluer les modèles de machine learning. En divisant correctement vos données, vous obtenez des estimations de performance honnêtes qui prédisent le comportement réel du modèle. Rappelez-vous les principes clés : définissez toujours random_state pour la reproductibilité, utilisez stratify pour les problèmes de classification, évitez le prétraitement avant la division et choisissez votre ratio de division en fonction de la taille du jeu de données.
Maîtrisez ces fondamentaux et vous éviterez les pièges les plus courants qui conduisent à des modèles surappris et à des métriques de performance trompeuses. Que vous construisiez un classificateur simple ou un système complexe de deep learning, la division train-test appropriée est la première étape vers un machine learning fiable.