Scikit-learn : Entraîne ton premier modèle de Machine Learning en 20 minutes

Scikit-learn : Entraîne ton premier modèle de Machine Learning en 20 minutes

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom":"scikit-learn","version":"1.x"}
  • {"nom":"pandas","version":"2.x"}

Difficulté

Débutant

Tu entends parler de machine learning partout, mais tu n'as jamais osé franchir le pas ? Ce tutoriel est fait pour toi. On va entraîner ton premier vrai modèle de machine learning en une vingtaine de minutes, avec scikit-learn — la bibliothèque de référence du machine learning classique en Python. Pas besoin d'être mathématicien, pas besoin de GPU : juste un ordinateur, Python installé, et l'envie de voir un algorithme apprendre tout seul à partir de données.

Le machine learning, sans le jargon

Le principe du machine learning supervisé est simple : tu montres des exemples à un algorithme, chaque exemple étant accompagné de sa bonne réponse, et l'algorithme apprend la relation qui les relie. Une fois entraîné, il est capable de prédire la réponse pour des exemples qu'il n'a jamais vus.

Un exemple classique : à partir de la longueur et de la largeur des pétales d'une fleur, prédire son espèce. C'est exactement ce que fait le célèbre jeu de données Iris, livré avec scikit-learn, et c'est ce qu'on va utiliser. C'est un problème de classification : la variable à prédire (l'espèce) prend un nombre fini de valeurs.

Le vocabulaire de base à connaître tient en trois termes. Les caractéristiques (ou features) sont les variables d'entrée, ici les mesures des pétales. L'étiquette (ou label, ou cible) est la variable à prédire, ici l'espèce. Et le modèle est l'objet mathématique qui apprend la relation entre les deux. Toute la discipline se résume à bien choisir ces trois ingrédients.

Pourquoi scikit-learn ? Parce que c'est l'outil le plus mature et le plus pédagogique pour ce type de problème. Son API est d'une régularité remarquable : tous les modèles s'utilisent avec les mêmes méthodes fit(), predict() et score(). Une fois que tu maîtrises un modèle, tu sais les utiliser tous.

Prérequis : installer scikit-learn

L'installation se fait en une commande. scikit-learn s'appuie sur NumPy et SciPy, installés automatiquement comme dépendances.

bash
pip install scikit-learn

On vérifie l'installation et on importe de quoi travailler. On aura aussi besoin de pandas pour la lecture des données, et de matplotlib si tu veux tracer des courbes.

python
import sklearn
print(sklearn.__version__)

Charger et explorer le dataset Iris

scikit-learn embarque quelques jeux de données d'exemple, dont Iris. On le charge et on regarde à quoi il ressemble.

python
from sklearn.datasets import load_iris
import pandas as pd

iris = load_iris()
X = iris.data          # les caractéristiques : 4 mesures par fleur
y = iris.target        # les étiquettes : 0, 1 ou 2 (les 3 espèces)

# On transforme en DataFrame pour y voir clair
df = pd.DataFrame(X, columns=iris.feature_names)
df["espece"] = y
print(df.head())
print(df["espece"].value_counts())

Chaque fleur est décrite par quatre mesures : la longueur et la largeur des sépales, et la longueur et la largeur des pétales. L'étiquette est un entier de 0 à 2, chaque valeur correspondant à une espèce. Le jeu de données est équilibré : 50 fleurs par espèce, 150 au total. L'objectif est d'apprendre à prédire l'espèce à partir des quatre mesures.

Ce jeu de données est idéal pour débuter : il est petit, propre, et les trois espèces sont bien séparées. Résultat, un modèle simple suffit à atteindre de très bons scores, ce qui te permet de te concentrer sur la méthode plutôt que sur les difficultés des données.

Séparer les données en train et test

C'est l'étape la plus importante du processus, et la plus souvent bâclée par les débutants. Pour savoir si ton modèle a vraiment appris quelque chose de général — et pas simplement mémorisé ses exemples — tu dois le tester sur des données qu'il n'a jamais vues. On découpe donc le jeu de données en deux : une partie pour l'entraînement, une partie pour l'évaluation.

python
from sklearn.model_selection import train_test_split

# 80 % pour l'entraînement, 20 % pour le test
# random_state fige le hasard pour que le découpage soit reproductible
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"Entraînement : {len(X_train)} exemples")
print(f"Test : {len(X_test)} exemples")

Le paramètre random_state fixe la graine du générateur aléatoire : sans lui, le découpage changerait à chaque exécution et tes résultats ne seraient pas reproductibles. C'est une bonne habitude à prendre dès maintenant. Quant à la répartition 80/20, c'est un point de départ raisonnable : assez d'exemples pour bien entraîner, assez pour évaluer honnêtement.

Entraîner ton premier modèle

On choisit un modèle simple et interprétable pour commencer : un arbre de décision. Il apprend une série de règles du type « si la longueur du pétale est supérieure à 2,45 cm, alors... ». L'entraînement tient en une ligne :

python
from sklearn.tree import DecisionTreeClassifier

# On crée le modèle puis on l'entraîne sur les données d'entraînement
modele = DecisionTreeClassifier(random_state=42, max_depth=3)
modele.fit(X_train, y_train)

print("Modèle entraîné !")

max_depth limite la profondeur de l'arbre. Pourquoi se limiter ? Parce qu'un arbre trop profond mémorise les exemples au lieu d'apprendre la tendance générale : c'est le sur-apprentissage, sur lequel on revient plus bas. Une profondeur de 3 donne un modèle simple, robuste et facile à expliquer.

L'intérêt de l'arbre de décision pour débuter, c'est qu'on peut littéralement le lire. Chaque noeud est une question, chaque branche une réponse. Tu peux tracer l'arbre et voir exactement pourquoi le modèle a pris telle décision — un luxe que n'offrent pas les modèles plus complexes comme les réseaux de neurones.

Évaluer le modèle : prédire et mesurer

Le moment de vérité : on demande au modèle de prédire les espèces des données de test, puis on compare ses prédictions à la réalité.

python
from sklearn.metrics import accuracy_score, classification_report

predictions = modele.predict(X_test)

# La précision : proportion de bonnes réponses
print(f"Précision : {accuracy_score(y_test, predictions):.2f}")

# Le rapport détaillé, classe par classe
print(classification_report(y_test, predictions, target_names=iris.target_names))

La précision (accuracy) te donne le score global : la proportion de prédictions correctes. Mais ce n'est pas toujours suffisant. Le classification_report te montre, pour chaque espèce, la précision, le rappel et le F1-score — trois métriques complémentaires qui révèlent comment le modèle se comporte classe par classe. Sur Iris, un arbre de profondeur 3 atteint typiquement plus de 95 % de bonnes réponses, ce qui est excellent pour un premier modèle.

Lire une matrice de confusion

Une autre façon de voir les erreurs du modèle est la matrice de confusion : un tableau qui croise les espèces réelles et les espèces prédites. Chaque case indique combien de fleurs d'une espèce donnée ont été classées dans telle catégorie.

python
from sklearn.metrics import confusion_matrix

matrice = confusion_matrix(y_test, predictions)
print(matrice)

Sur la diagonale, tu trouves les bonnes prédictions ; partout ailleurs, les confusions. C'est l'outil le plus parlant pour repérer les paires de classes que le modèle a du mal à distinguer — par exemple deux espèces de fleurs aux pétales très proches.

Comprendre le sur-apprentissage

C'est LE concept qui sépare les bons modèles des modèles trompeurs. Un modèle en sur-apprentissage est excellent sur ses données d'entraînement mais médiocre sur des données nouvelles : il a appris par cœur au lieu de généraliser. On le détecte en comparant le score d'entraînement et le score de test :

python
print(f"Score entraînement : {modele.score(X_train, y_train):.2f}")
print(f"Score test : {modele.score(X_test, y_test):.2f}")

Si le score d'entraînement est proche de 1 mais que le score de test s'effondre, c'est le signe d'un sur-apprentissage. Les remèdes classiques : limiter la complexité du modèle (comme on l'a fait avec max_depth), fournir plus de données, ou régulariser. À l'inverse, si les deux scores sont faibles, le modèle est trop simple : c'est le sous-apprentissage, et il faut un modèle plus expressif.

Retiens la métaphore : un modèle en sur-apprentissage est un élève qui a appris ses annales par cœur et panique le jour de l'examen ; un modèle en sous-apprentissage est un élève qui n'a pas assez travaillé. Le bon modèle est celui qui a compris le principe général et sait l'appliquer à des cas nouveaux.

Un pipeline complet et propre

Dans un vrai projet, tu ne te contentes pas d'un modèle nu. Tu enchaînes plusieurs étapes : normaliser les caractéristiques, puis entraîner le modèle. scikit-learn propose l'objet Pipeline pour chaîner ces étapes de façon propre et éviter les fuites de données. On en profite pour changer de modèle et passer à un classifieur plus puissant, la forêt aléatoire :

python
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier

# Le pipeline : normalisation des données, puis forêt aléatoire
pipeline = make_pipeline(
    StandardScaler(),
    RandomForestClassifier(n_estimators=100, random_state=42),
)

pipeline.fit(X_train, y_train)
print(f"Précision : {pipeline.score(X_test, y_test):.2f}")

StandardScaler centre et réduit chaque caractéristique pour qu'elle ait une moyenne nulle et un écart-type unitaire. C'est important pour certains modèles, et ça ne coûte rien de le faire systématiquement. La forêt aléatoire, elle, agrège des centaines d'arbres de décision pour produire une prédiction plus stable et plus précise qu'un arbre unique.

L'intérêt du pipeline dépasse la simple commodité : il garantit que les mêmes transformations sont appliquées à l'entraînement et à la prédiction. C'est la parade contre les fuites de données — le biais sournois qui survient quand tu calcules tes statistiques de normalisation sur l'ensemble des données, y compris celles que tu aurais dû garder pour le test.

La validation croisée pour un score fiable

Un seul découpage train/test peut être trompeur si le hasard tombe mal. La validation croisée est plus robuste : elle découpe les données en plusieurs sous-ensembles, entraîne et évalue le modèle plusieurs fois, et moyenne les scores.

python
from sklearn.model_selection import cross_val_score

scores = cross_val_score(pipeline, X, y, cv=5)
print(f"Scores : {scores}")
print(f"Moyenne : {scores.mean():.2f} (+/- {scores.std():.2f})")

cv=5 signifie que les données sont découpées en 5 parties : le modèle est entraîné 5 fois, chaque fois sur 4 parties et évalué sur la cinquième. La moyenne des scores est une estimation bien plus fiable de la performance réelle du modèle.

Sauvegarder et réutiliser le modèle

Un modèle entraîné n'a de valeur que si tu peux le réutiliser plus tard, sans refaire l'entraînement. joblib sérialise le modèle sur disque :

python
import joblib

# Sauvegarder le pipeline complet (normalisation + modèle)
joblib.dump(pipeline, "modele_iris.joblib")

# Le recharger plus tard, dans un autre script ou en production
modele_charge = joblib.load("modele_iris.joblib")

# Prédire l'espèce d'une nouvelle fleur (4 mesures)
nouvelle_fleur = [[5.1, 3.5, 1.4, 0.2]]
prediction = modele_charge.predict(nouvelle_fleur)
print(f"Espèce prédite : {iris.target_names[prediction[0]]}")

Remarque qu'on sauvegarde le pipeline entier, pas seulement le modèle : ainsi, la normalisation est rechargée avec le modèle, et tu ne risques pas d'oublier une étape de prétraitement au moment de prédire. C'est un détail qui t'évitera bien des bugs en production.

Visualiser l'arbre de décision

L'un des grands avantages de l'arbre de décision, c'est qu'on peut le représenter graphiquement et le lire comme un organigramme. Chaque noeud pose une question, chaque branche est une réponse, et les feuilles donnent la prédiction finale. C'est précieux pour comprendre et expliquer tes décisions.

python
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 8))
plot_tree(modele, feature_names=iris.feature_names,
          class_names=iris.target_names, filled=True)
plt.show()

Sur le tracé, tu verras que la toute première question porte sur la largeur du pétale — c'est la caractéristique la plus discriminante, celle qui sépare le mieux les espèces. Cette lisibilité est une raison majeure de choisir un arbre de décision quand tu dois justifier tes prédictions auprès d'un client ou d'une équipe non technique.

Choisir le bon modèle

Il n'existe pas de modèle universellement meilleur : tout dépend de tes données et de ton problème. Voici un aperçu des classifieurs les plus courants de scikit-learn et de leurs cas d'usage :

  • DecisionTreeClassifier : simple et interprétable, mais sujet au sur-apprentissage s'il n'est pas limité.
  • RandomForestClassifier : très robuste, précis, peu sensible au bruit ; un excellent choix par défaut.
  • LogisticRegression : rapide et efficace quand la relation entre les variables est à peu près linéaire.
  • SVC (machines à vecteurs de support) : puissant sur les petits jeux de données bien séparés.
  • KNeighborsClassifier : intuitif (il regarde les exemples les plus proches), mais lent sur de gros volumes.

La bonne nouvelle, c'est que grâce à l'API uniforme de scikit-learn, changer de modèle revient à changer deux lignes : l'import et l'instanciation. Le reste du code — fit, predict, score — ne bouge pas. N'hésite donc pas à en essayer plusieurs et à comparer leurs scores sur tes données de test.

python
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC

# Le même entraînement, trois modèles différents
modeles = {
    "Forêt aléatoire": RandomForestClassifier(n_estimators=100, random_state=42),
    "Régression logistique": LogisticRegression(max_iter=200),
    "SVM": SVC(),
}

for nom, m in modeles.items():
    m.fit(X_train, y_train)
    print(f"{nom:24} -> {m.score(X_test, y_test):.2f}")

Et la régression, alors ?

On a traité la classification, où la sortie est une catégorie. Mais le machine learning sait aussi prédire des valeurs continues : le prix d'une maison, la température de demain, le nombre de visiteurs d'un site. On parle alors de régression. La bonne nouvelle, c'est que la recette est exactement la même — seuls le modèle et la métrique changent.

python
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split

# Un mini-jeu de données : la taille d'une maison et son prix
X = [[35], [50], [65], [80], [110], [130]]   # surface en m²
y = [120000, 150000, 180000, 220000, 280000, 330000]  # prix en euros

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0
)

modele = LinearRegression()
modele.fit(X_train, y_train)

# L'erreur moyenne en euros sur le jeu de test
pred = modele.predict(X_test)
print(f"Erreur moyenne : {mean_absolute_error(y_test, pred):.0f} euros")

Remarque la symétrie : on retrouve train_test_split, fit et predict, identiques à la classification. Seule la métrique change — ici l'erreur absolue moyenne, qui s'exprime dans la même unité que la cible. C'est toute la force de scikit-learn : une fois la logique comprise, passer de la classification à la régression est un simple changement de modèle.

Conclusion

Tu viens de franchir la ligne : tu as chargé des données, séparé l'entraînement du test, entraîné un premier modèle, mesuré sa performance de plusieurs façons, compris le sur-apprentissage, construit un pipeline complet et sauvegardé le tout. C'est le squelette de n'importe quel projet de machine learning supervisé, de la classification de fleurs à la détection de fraude.

La suite logique : applique exactement la même recette à un problème qui te parle — prédire un prix, classer des emails, détecter une anomalie. Change le dataset, garde la méthode. C'est en répétant ce cycle que tu développeras l'intuition qui distingue un bon praticien d'un simple exécutant.

Sources et ressources