Concepts de machine learning avec scikit-learn
Introduction au Machine Learning et à scikit-learn
Bienvenue dans cette leçon consacrée aux concepts fondamentaux du Machine Learning (ML) et à leur implémentation pratique avec la bibliothèque Python scikit-learn. Dans le cadre de votre parcours en développement avancé avec Python, maîtriser le ML est devenu une compétence indispensable, ouvrant les portes à des applications complexes allant de la prédiction de données à la reconnaissance de formes.
Qu'est-ce que le Machine Learning ?
Le Machine Learning est un sous-domaine de l'intelligence artificielle qui permet aux systèmes d'apprendre à partir de données, d'identifier des motifs et de prendre des décisions avec une intervention humaine minimale. Plutôt que d'être explicitement programmés pour chaque tâche, les modèles ML apprennent en analysant de grandes quantités de données et en ajustant leurs paramètres internes pour améliorer leurs performances.
Il existe principalement trois paradigmes d'apprentissage :
- Apprentissage supervisé (Supervised Learning) : Le modèle apprend à partir d'un ensemble de données étiquetées, c'est-à-dire des données pour lesquelles la sortie souhaitée est connue. L'objectif est de prédire une étiquette ou une valeur pour de nouvelles données non vues.
- Apprentissage non supervisé (Unsupervised Learning) : Le modèle explore des données non étiquetées pour trouver des structures cachées ou des motifs intrinsèques. Il n'y a pas de "bonne réponse" prédéfinie.
- Apprentissage par renforcement (Reinforcement Learning) : Le modèle apprend à prendre des décisions séquentielles en interagissant avec un environnement, recevant des récompenses ou des pénalités pour ses actions.
Pourquoi scikit-learn ?
scikit-learn est LA bibliothèque de facto en Python pour le Machine Learning. Elle offre des implémentations efficaces de la plupart des algorithmes classiques de ML, ainsi que des outils robustes pour le prétraitement des données, la sélection de modèles et l'évaluation des performances.
Ses principaux atouts sont :
- Simplicité et cohérence de l'API : Tous les estimateurs scikit-learn partagent une interface commune (
.fit(),.predict(),.transform()). - Efficacité : Les algorithmes sont optimisés et souvent écrits en Cython ou en C pour de meilleures performances.
- Richesse fonctionnelle : Une large gamme d'algorithmes de classification, régression, clustering, réduction de dimensionnalité, etc.
- Documentation exhaustive : Très bien documentée et accompagnée de nombreux exemples.
- Intégration : S'intègre parfaitement avec d'autres bibliothèques Python comme NumPy, SciPy et Matplotlib.
Cette leçon vous guidera à travers les concepts clés du ML et vous montrera comment les appliquer concrètement avec scikit-learn.
Concepts Fondamentaux du Machine Learning
Avant de plonger dans le code, il est crucial de comprendre la terminologie et les principes de base.
Données : Caractéristiques et Cibles
Dans le contexte du Machine Learning, les données sont généralement structurées sous forme de tableaux ou de matrices.
- Caractéristiques (Features) / Variables explicatives (X) : Ce sont les colonnes du jeu de données qui contiennent les informations utilisées pour faire une prédiction. Par exemple, pour prédire le prix d'une maison, les caractéristiques pourraient être la surface, le nombre de chambres, l'emplacement, etc.
- Cible (Target) / Variable dépendante (y) : C'est la colonne que nous essayons de prédire. Dans l'exemple de la maison, ce serait le prix.
Types de Problèmes de Machine Learning
Apprentissage Supervisé
L'apprentissage supervisé est utilisé lorsque vous avez des données historiques avec des résultats connus.
-
Classification :
- Objectif : Prédire une catégorie discrète (ou classe).
- Exemples : Détecter si un e-mail est du spam (oui/non), classer une image en chien ou chat, diagnostiquer une maladie (présente/absente).
- Algorithmes courants : Régression Logistique, K-Nearest Neighbors (KNN), Machines à Vecteurs de Support (SVM), Arbres de Décision, Forêts Aléatoires.
-
Régression :
- Objectif : Prédire une valeur continue.
- Exemples : Prédire le prix d'une maison, estimer les ventes futures d'un produit, prévoir la température de demain.
- Algorithmes courants : Régression Linéaire, Arbres de Décision de Régression, Forêts Aléatoires de Régression, SVR (Support Vector Regression).
Apprentissage Non Supervisé
L'apprentissage non supervisé est utilisé lorsque vous n'avez pas de cibles connues et que vous cherchez à découvrir des structures dans les données.
-
Clustering (Regroupement) :
- Objectif : Regrouper des points de données similaires en clusters, sans savoir au préalable combien de groupes il y a ou à quoi ils ressemblent.
- Exemples : Segmentation de clientèle, regroupement de documents similaires, détection d'anomalies.
- Algorithmes courants : K-Means, DBSCAN, Agglomerative Clustering.
-
Réduction de Dimensionnalité :
- Objectif : Réduire le nombre de caractéristiques tout en conservant autant d'informations que possible. Utile pour la visualisation ou pour accélérer les algorithmes d'apprentissage.
- Exemples : Compression d'images, simplification de données génétiques.
- Algorithmes courants : Analyse en Composantes Principales (PCA), t-SNE.
Séparation des Données : Entraînement et Test
Pour évaluer la capacité de généralisation d'un modèle (c'est-à-dire sa capacité à bien performer sur de nouvelles données), il est crucial de diviser le jeu de données en deux parties :
- Jeu d'entraînement (Training Set) : Utilisé pour entraîner le modèle. Le modèle "apprend" les motifs et relations à partir de ces données.
- Jeu de test (Test Set) : Utilisé pour évaluer la performance du modèle après son entraînement. Ces données n'ont jamais été vues par le modèle pendant l'entraînement, ce qui donne une estimation réaliste de sa performance en production.
Un ratio courant est de 70-80% pour l'entraînement et 20-30% pour le test.
Le Workflow Standard avec scikit-learn
L'API de scikit-learn est conçue pour être simple et intuitive. La plupart des modèles suivent le même schéma :
- Importation du modèle :
from sklearn.modèle import MonModele - Instanciation du modèle :
model = MonModele(parametre=valeur) - Entraînement du modèle :
model.fit(X_train, y_train) - Prédiction :
predictions = model.predict(X_test) - Évaluation : Comparer
predictionsavecy_testen utilisant des métriques appropriées.
Exemples Pratiques avec scikit-learn
Nous allons maintenant illustrer ces concepts avec des exemples de code. Assurez-vous d'avoir scikit-learn (et ses dépendances comme NumPy et SciPy) installé : pip install scikit-learn pandas matplotlib.
Exemple 1 : Classification (Apprentissage Supervisé) avec l'Iris Dataset
Nous utiliserons le célèbre jeu de données Iris, qui contient des mesures de différentes espèces de fleurs Iris. L'objectif est de prédire l'espèce d'une fleur basée sur ses mesures.
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
# 1. Charger le jeu de données Iris
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names) # Caractéristiques
y = iris.target # Cible (espèces d'Iris: 0, 1, 2)
print("Premières lignes des caractéristiques (X):")
print(X.head())
print("\nPremières valeurs de la cible (y):")
print(y[:5])
print("\nNom des espèces d'Iris (mapping des cibles):", iris.target_names)
# 2. Séparer les données en ensembles d'entraînement et de test
# test_size=0.3 signifie 30% des données pour le test, 70% pour l'entraînement
# random_state assure la reproductibilité du découpage
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print(f"\nDimensions de l'ensemble d'entraînement X_train: {X_train.shape}")
print(f"Dimensions de l'ensemble de test X_test: {X_test.shape}")
# 3. Choisir et instancier un modèle (Régression Logistique pour la classification)
# max_iter augmenté pour éviter un avertissement de convergence sur certains datasets
model = LogisticRegression(max_iter=200, random_state=42)
# 4. Entraîner le modèle sur les données d'entraînement
print("\nEntraînement du modèle...")
model.fit(X_train, y_train)
print("Modèle entraîné.")
# 5. Faire des prédictions sur les données de test
y_pred = model.predict(X_test)
print("\nPremières 10 prédictions sur l'ensemble de test:")
print(y_pred[:10])
print("Premières 10 vraies valeurs sur l'ensemble de test:")
print(y_test[:10])
# 6. Évaluer la performance du modèle
accuracy = accuracy_score(y_test, y_pred)
print(f"\nPrécision (Accuracy) du modèle: {accuracy:.4f}")
# Rapport de classification détaillé
print("\nRapport de Classification:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
Explication du code :
- Nous commençons par importer les modules nécessaires :
pandaspour la manipulation de données (bien que l'Iris dataset puisse être utilisé directement de scikit-learn),load_irispour le dataset,train_test_splitpour diviser les données,LogisticRegressioncomme modèle de classification, etaccuracy_scoreetclassification_reportpour l'évaluation. - Le dataset Iris est chargé et ses caractéristiques (
X) et cibles (y) sont séparées. train_test_splitest la fonction clé pour créer des ensembles d'entraînement et de test.random_stateest utilisé pour s'assurer que la division est la même à chaque exécution, garantissant la reproductibilité.- Nous instancions un objet
LogisticRegression. La Régression Logistique est un algorithme de classification, même si son nom contient "Régression". - La méthode
.fit(X_train, y_train)est appelée pour entraîner le modèle. C'est ici que l'algorithme "apprend" des relations entre les caractéristiques et les cibles. - La méthode
.predict(X_test)est utilisée pour obtenir les prédictions du modèle sur les données qu'il n'a jamais vues. - Enfin,
accuracy_scoreetclassification_reportnous donnent des mesures de performance. La précision (accuracy) est le ratio de prédictions correctes. Le rapport de classification fournit des métriques plus détaillées comme la précision (precision), le rappel (recall) et le score F1 pour chaque classe.
Exemple 2 : Régression (Apprentissage Supervisé) avec le Diabetes Dataset
Nous utiliserons le jeu de données Diabetes pour prédire la progression de la maladie un an après le diagnostic, basée sur diverses mesures.
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
# 1. Charger le jeu de données Diabetes
diabetes = load_diabetes()
X = pd.DataFrame(diabetes.data, columns=diabetes.feature_names) # Caractéristiques
y = diabetes.target # Cible (progression de la maladie)
print("Premières lignes des caractéristiques (X):")
print(X.head())
print("\nPremières valeurs de la cible (y):")
print(y[:5])
# 2. Séparer les données en ensembles d'entraînement et de test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"\nDimensions de l'ensemble d'entraînement X_train: {X_train.shape}")
print(f"Dimensions de l'ensemble de test X_test: {X_test.shape}")
# 3. Choisir et instancier un modèle (Régression Linéaire)
model = LinearRegression()
# 4. Entraîner le modèle sur les données d'entraînement
print("\nEntraînement du modèle...")
model.fit(X_train, y_train)
print("Modèle entraîné.")
# 5. Faire des prédictions sur les données de test
y_pred = model.predict(X_test)
print("\nPremières 10 prédictions sur l'ensemble de test:")
print(y_pred[:10].round(2)) # Arrondir pour une meilleure lisibilité
print("Premières 10 vraies valeurs sur l'ensemble de test:")
print(y_test[:10])
# 6. Évaluer la performance du modèle
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"\nErreur Quadratique Moyenne (MSE): {mse:.2f}")
print(f"Coefficient de Détermination (R²): {r2:.2f}")
# 7. Visualisation des prédictions vs vraies valeurs (facultatif mais utile)
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, alpha=0.7)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2) # Ligne y=x
plt.xlabel("Valeurs réelles")
plt.ylabel("Prédictions")
plt.title("Prédictions du Modèle de Régression Linéaire")
plt.grid(True)
plt.show()
Explication du code :
- Le processus est très similaire à la classification. Nous importons
load_diabetes,LinearRegressionet les métriquesmean_squared_error(Erreur Quadratique Moyenne) etr2_score(Coefficient de Détermination) pour l'évaluation. load_diabetesfournit un dataset pour la régression.- Nous divisons à nouveau les données en ensembles d'entraînement et de test.
- Nous instancions un modèle
LinearRegression, qui est un algorithme fondamental pour la régression. - La méthode
.fit()est utilisée pour entraîner le modèle. - La méthode
.predict()génère les valeurs continues prédites. - Pour l'évaluation,
mean_squared_errormesure l'erreur moyenne des prédictions (une valeur plus basse est meilleure).r2_scoreindique la proportion de la variance des variables dépendantes qui peut être prédite à partir des variables indépendantes (plus proche de 1 est meilleur). - La visualisation aide à comprendre la performance du modèle en comparant les prédictions aux vraies valeurs. Les points devraient se regrouper autour de la ligne rouge
y=xpour un modèle parfait.
Considérations Avancées en Machine Learning
Pour des applications réelles, il est rare que les données soient parfaites ou que le premier modèle entraîné soit le meilleur.
Prétraitement des Données (Data Preprocessing)
Les données brutes sont rarement prêtes à être utilisées directement par les algorithmes de ML. Le prétraitement est une étape cruciale :
- Gestion des valeurs manquantes : Imputation (remplacer par la moyenne, médiane, mode) ou suppression des lignes/colonnes.
- Encodage des caractéristiques catégorielles : Les algorithmes de ML travaillent avec des nombres. Les catégories textuelles (ex: "ville") doivent être converties en valeurs numériques. scikit-learn propose
OneHotEncoderouLabelEncoder. - Mise à l'échelle des caractéristiques (Feature Scaling) : Beaucoup d'algorithmes sont sensibles à l'échelle des caractéristiques.
- Standardisation (
StandardScaler) : Met les données à une moyenne de 0 et un écart-type de 1. - Normalisation (
MinMaxScaler) : Met les données dans une plage spécifique, souvent entre 0 et 1.
- Standardisation (
- Gestion des valeurs aberrantes (Outliers) : Détection et traitement des données extrêmes qui peuvent biaiser le modèle.
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer # Un autre dataset pour l'exemple
# Charger un dataset (Breast Cancer pour cet exemple, contient des données numériques)
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
# Simuler une colonne catégorielle et des valeurs manquantes pour l'exemple
X['city'] = ['A'] * 50 + ['B'] * 50 + ['C'] * (len(X) - 100)
X.loc[10, 'mean radius'] = None # Ajouter une valeur manquante
X.loc[20, 'mean texture'] = None
# Définir les colonnes numériques et catégorielles
numerical_cols = X.select_dtypes(include=['number']).columns
categorical_cols = X.select_dtypes(include=['object']).columns
# Créer des pipelines pour le prétraitement
numerical_transformer = Pipeline(steps=[
('imputer', pd.DataFrame.median), # Pour l'exemple, utiliser une fonction simple comme median
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
# Combiner les transformateurs avec ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numerical_cols), # Remplacer par numerical_transformer si imputation
('cat', OneHotEncoder(handle_unknown='ignore'), categorical_cols)
])
# Créer un pipeline complet incluant le prétraitement et le modèle
model_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
('classifier', LogisticRegression(max_iter=1000))])
# Séparer les données
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Entraîner le pipeline (le prétraitement est automatiquement appliqué avant l'entraînement)
print("\nEntraînement du pipeline (prétraitement + modèle)...")
model_pipeline.fit(X_train, y_train)
print("Pipeline entraîné.")
# Faire des prédictions
y_pred_pipeline = model_pipeline.predict(X_test)
# Évaluer
accuracy_pipeline = accuracy_score(y_test, y_pred_pipeline)
print(f"\nPrécision (Accuracy) du modèle avec pipeline de prétraitement: {accuracy_pipeline:.4f}")
Explication du code :
- Cet exemple introduit
PipelineetColumnTransformer, des outils essentiels pour structurer le prétraitement. ColumnTransformerpermet d'appliquer différents transformateurs (commeStandardScalerouOneHotEncoder) à différentes colonnes de votre dataset.Pipelinepermet de chaîner plusieurs étapes de traitement (prétraitement, réduction de dimensionnalité, entraînement du modèle) en un seul objet. L'utilisation de pipelines est une bonne pratique car elle garantit que les mêmes transformations sont appliquées de manière cohérente aux données d'entraînement et de test, évitant ainsi les fuites de données (data leakage).
Surapprentissage (Overfitting) et Sous-apprentissage (Underfitting)
Deux problèmes courants en ML :
- Surapprentissage (Overfitting) : Le modèle apprend trop bien les données d'entraînement, y compris le bruit, et ne généralise pas bien aux nouvelles données. Il a une faible erreur sur l'ensemble d'entraînement mais une erreur élevée sur l'ensemble de test.
- Sous-apprentissage (Underfitting) : Le modèle est trop simple pour capturer la complexité des données. Il a une erreur élevée sur les ensembles d'entraînement et de test.
Ajustement des Hyperparamètres (Hyperparameter Tuning)
Les hyperparamètres sont des paramètres des modèles de ML qui ne sont pas appris à partir des données mais qui sont définis avant l'entraînement (ex: C dans LogisticRegression, n_estimators dans RandomForestClassifier). Trouver les meilleurs hyperparamètres est crucial pour la performance du modèle.
GridSearchCV: Recherche exhaustive de la meilleure combinaison d'hyperparamètres parmi une grille définie.RandomizedSearchCV: Échantillonne aléatoirement des combinaisons d'hyperparamètres, plus efficace pour de grands espaces de recherche.
Ces méthodes intègrent également la validation croisée (Cross-validation), une technique robuste pour évaluer un modèle en le divisant en plusieurs plis (folds) et en entraînant/testant sur différentes combinaisons de ces plis, réduisant ainsi la variance de l'estimation de la performance.
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
# Charger un dataset (Wine pour cet exemple)
data = load_wine()
X = data.data
y = data.target
# Séparer les données
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Définir le modèle
rf_model = RandomForestClassifier(random_state=42)
# Définir la grille d'hyperparamètres à tester
param_grid = {
'n_estimators': [50, 100, 200], # Nombre d'arbres dans la forêt
'max_depth': [None, 10, 20], # Profondeur maximale de chaque arbre
'min_samples_split': [2, 5, 10] # Nombre minimum d'échantillons requis pour diviser un nœud
}
# Configurer GridSearchCV
# cv=5 signifie validation croisée sur 5 plis
grid_search = GridSearchCV(estimator=rf_model, param_grid=param_grid, cv=5, scoring='accuracy', n_jobs=-1, verbose=1)
# Exécuter la recherche
print("\nRecherche des meilleurs hyperparamètres avec GridSearchCV...")
grid_search.fit(X_train, y_train)
print("Recherche terminée.")
# Afficher les meilleurs paramètres et le meilleur score
print(f"\nMeilleurs hyperparamètres trouvés: {grid_search.best_params_}")
print(f"Meilleur score de validation croisée: {grid_search.best_score_:.4f}")
# Utiliser le meilleur estimateur pour faire des prédictions sur l'ensemble de test
best_model = grid_search.best_estimator_
y_pred_tuned = best_model.predict(X_test)
# Évaluer le modèle final
accuracy_tuned = accuracy_score(y_test, y_pred_tuned)
print(f"Précision (Accuracy) du modèle optimisé sur l'ensemble de test: {accuracy_tuned:.4f}")
Explication du code :
GridSearchCVest importé et un modèleRandomForestClassifierest choisi.param_gridest un dictionnaire où les clés sont les noms des hyperparamètres du modèle et les valeurs sont des listes de valeurs à tester pour chaque hyperparamètre.GridSearchCVest instancié avec le modèle, la grille de paramètres, le nombre de plis pour la validation croisée (cv), la métrique de score (scoring), le nombre de cœurs CPU à utiliser (n_jobs=-1pour tous les cœurs), et le niveau de verbosité.- La méthode
.fit()exécute la recherche exhaustive. grid_search.best_params_etgrid_search.best_score_donnent les résultats de la recherche.grid_search.best_estimator_retourne le modèle avec les meilleurs hyperparamètres entraîné sur l'ensemble d'entraînement complet (par défaut).
Conclusion
Cette leçon vous a introduit aux concepts fondamentaux du Machine Learning et à leur mise en œuvre pratique avec la puissante bibliothèque scikit-learn. Vous avez appris les distinctions entre la classification et la régression, l'importance de la séparation des données en ensembles d'entraînement et de test, et les étapes clés pour entraîner et évaluer des modèles. Nous avons également exploré des sujets avancés comme le prétraitement des données à l'aide de pipelines et l'optimisation des hyperparamètres avec GridSearchCV.
scikit-learn est un pilier pour tout développeur Python travaillant avec le Machine Learning. Sa cohérence API et sa vaste gamme d'outils en font un choix incontournable pour prototyper et déployer des solutions ML.
Pour aller plus loin, nous vous encourageons à :
- Explorer d'autres algorithmes de scikit-learn (SVM, K-Means, PCA).
- Approfondir les différentes métriques d'évaluation selon le type de problème.
- Expérimenter avec des datasets plus complexes et réels.
- Étudier les techniques avancées de gestion des données (imputation plus sophistiquée, détection d'anomalies).
- Comprendre les biais et l'équité des modèles de ML.
La maîtrise du Machine Learning est un voyage continu. scikit-learn vous fournit les outils pour démarrer et progresser efficacement dans ce domaine passionnant.