Chapitre 15. La Régression Logistique - Classifier le monde en "Oui" ou "Non"

Avec la régression linéaire, nous avons appris à prédire une valeur continue, comme un salaire. Mais que se passe-t-il si nous voulons prédire une catégorie ? "Spam" ou "Non Spam" ? "Malade" ou "Sain" ? "Survivant" ou "Non-survivant" ? Une ligne droite qui peut aller de -∞ à +∞ ne peut pas nous donner une réponse "Oui" ou "Non" de manière fiable. Pour cela, nous avons besoin d'un nouvel outil. Au lieu de tracer une ligne, la régression logistique dessine une courbe en forme de "S", appelée la fonction sigmoïde. Cette fonction magique prend n'importe quel score et le transforme élégamment en une probabilité, toujours comprise entre 0 et 1.

De la probabilité à la décision

Étape 1 : Le Score Linéaire (Logit)

Tout commence comme une régression linéaire. Le modèle calcule un score, souvent appelé \(z\) ou "logit", en faisant une somme pondérée des features. Chaque feature \(x_i\) a un poids (ou coefficient) \(m_i\) qui a été appris durant l'entraînement. Le modèle additionne tout cela avec une constante \(b\) (le biais).

$$ z = b + m_1x_1 + m_2x_2 + \dots + m_nx_n $$

Ce score \(z\) peut être n'importe quel nombre réel, de -∞ à +∞. Un score élevé suggère une forte probabilité pour la classe "Oui" (1), tandis qu'un score très bas suggère une forte probabilité pour la classe "Non" (0).

Étape 2 : La transformation en Probabilité avec la Sigmoïde

Pour transformer ce score \(z\) en une probabilité compréhensible (entre 0 et 1), on le passe à travers la fonction sigmoïde, notée \(\sigma(z)\).

$$ P(\text{y}=1) = \sigma(z) = \frac{1}{1 + e^{-z}} $$

Cette fonction est magnifique : si le score \(z\) est très grand (ex: 10), \(e^{-z}\) devient minuscule, et la probabilité se rapproche de 1. Si \(z\) est très négatif (ex: -10), \(e^{-z}\) devient énorme, et la probabilité se rapproche de 0. Si \(z\) est exactement 0, la probabilité est de 0.5. Le résultat est une belle courbe en "S".

Exemple concret :

Imaginons que notre modèle pour le Titanic a appris les coefficients suivants : \(b = -1.5\), \(m_{Pclass} = -0.8\), \(m_{Sex} = 2.5\). Considérons une passagère de 1ère classe (Pclass=1, Sex=1) :

$$ z = -1.5 + (-0.8 \times 1) + (2.5 \times 1) = -1.5 - 0.8 + 2.5 = 0.2 $$ $$ P(\text{survie}) = \frac{1}{1 + e^{-0.2}} \approx \frac{1}{1 + 0.8187} \approx 0.55 $$

Le modèle estime que cette passagère avait environ 55% de chances de survivre.

Étape 3 : Le seuil de décision

Maintenant que nous avons une probabilité, nous avons besoin d'une décision finale. C'est le rôle du seuil de décision. Par défaut, il est fixé à 0.5.

Si \(P(\text{y}=1) > 0.5\), alors la prédiction est 1 ("Oui").

Si \(P(\text{y}=1) \leq 0.5\), alors la prédiction est 0 ("Non").

Dans notre exemple, 55% > 50%, donc notre modèle prédirait que la passagère a survécu (prédiction = 1). Ce seuil est un paramètre crucial que l'on peut ajuster. Pour un test de dépistage médical, on pourrait le baisser à 0.2 pour être sûr de ne manquer aucun malade potentiel (minimiser les faux négatifs), même si cela augmente le nombre de fausses alertes (faux positifs).

La Régression Logistique avec Scikit-Learn

Mettons la théorie en pratique ! Nous allons utiliser la bibliothèque Scikit-Learn pour construire notre propre modèle de prédiction de survie sur le Titanic. Voici les étapes clés.

Étape 1 : Préparation des Données

La première étape, et l'une des plus importantes, est de nettoyer nos données. Un modèle de machine learning est comme un chef cuisinier : il a besoin d'ingrédients de qualité pour préparer un bon plat. Pour nos données, cela signifie gérer les valeurs manquantes et s'assurer que tout est au format numérique.

# Importer les bibliothèques nécessaires
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# Charger les données
df = pd.read_csv('train.csv')

# Remplacer les âges manquants par l'âge médian
age_median = df['Age'].median()
df['Age'].fillna(age_median, inplace=True)

# Supprimer la colonne 'Cabin' car elle a trop de valeurs manquantes
df.drop('Cabin', axis=1, inplace=True)

# Remplacer les ports d'embarquement manquants par le plus fréquent
embarked_mode = df['Embarked'].mode()[0]
df['Embarked'].fillna(embarked_mode, inplace=True)

# Transformer la colonne 'Sex' en valeurs numériques (0 pour homme, 1 for femme)
df['Sex'] = df['Sex'].map({'male': 0, 'female': 1})

Étape 2 : Entraînement du Modèle

Maintenant que nos données sont prêtes, nous pouvons les utiliser pour entraîner notre modèle. Nous allons d'abord sélectionner les "indices" (features) que nous pensons utiles, puis nous diviserons nos données en un ensemble d'entraînement et un ensemble de test.

# 1. Sélectionner les features (X) et la cible (y)
features = ['Pclass', 'Sex', 'Age', 'Fare']
target = 'Survived'
X = df[features]
y = df[target]

# 2. Diviser les données : 70% pour l'entraînement, 30% pour le test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 3. Créer une instance du modèle de Régression Logistique
# max_iter est augmenté pour donner à l'algorithme assez de temps pour converger
model = LogisticRegression(max_iter=200)

# 4. Entraîner le modèle avec les données d'entraînement
model.fit(X_train, y_train)

Étape 3 : Faire et Interpréter les Prédictions

Le modèle est maintenant entraîné ! Utilisons-le sur notre ensemble de test (les données qu'il n'a jamais vues) pour voir ce qu'il a appris.

# Utiliser .predict_proba() pour voir les probabilités brutes
# La première colonne est P(Non-survivant), la seconde est P(Survivant)
probabilities = model.predict_proba(X_test)
print("Probabilités pour les 5 premiers passagers :")
print(probabilities[:5].round(2))

# Utiliser .predict() pour obtenir la décision finale (seuil de 0.5 appliqué)
predictions = model.predict(X_test)
print("\\nPrédictions finales (0=Mort, 1=Survivant) pour les 5 premiers passagers :")
print(predictions[:5])

En observant les sorties, vous pouvez voir comment une probabilité de survie supérieure à 0.5 (comme 0.64 pour le deuxième passager) se traduit par une prédiction finale de 1 (Survivant), tandis qu'une probabilité inférieure (comme 0.13 pour le premier passager) donne une prédiction de 0 (Mort).

Challenge : Évaluer la performance du modèle

Nous avons des prédictions, mais sont-elles bonnes ? Il est temps d'évaluer notre premier modèle de classification.

Votre mission et la solution

Votre mission :

  • Calculez l'exactitude (accuracy) de votre modèle en comparant y_test (les vraies réponses) et predictions (les réponses du modèle).
  • Affichez la matrice de confusion. C'est un tableau qui nous montre en détail où le modèle a eu raison et où il s'est trompé.
  • Interprétez chaque case de cette matrice.

Solution et Interprétation :

# Importer les outils d'évaluation
from sklearn.metrics import accuracy_score, confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt

# 1. Calculer l'exactitude
accuracy = accuracy_score(y_test, predictions)
print(f"\\n--- Évaluation du Modèle ---")
print(f"Exactitude (Accuracy) : {accuracy:.2%}")

# 2. Calculer et afficher la matrice de confusion
conf_matrix = confusion_matrix(y_test, predictions)

# Pour une meilleure visualisation
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
            xticklabels=['Prédit Non-Survivant', 'Prédit Survivant'],
            yticklabels=['Vrai Non-Survivant', 'Vrai Survivant'])
plt.title('Matrice de Confusion', fontsize=16)
plt.ylabel('Vraie Valeur')
plt.xlabel('Valeur Prédite')
plt.show()

Testez vos connaissances !

1. Quelle est la principale différence entre la régression linéaire et la régression logistique ?

2. Quelle est la plage de valeurs de sortie de la fonction sigmoïde ?

3. Si un modèle de régression logistique prédit une probabilité de 0.65 pour la classe "Survivant", quelle sera la prédiction finale avec un seuil de 0.5 ?

4. Dans Scikit-Learn, quelle méthode est utilisée pour obtenir les probabilités prédites par un modèle de classification ?

5. Que représente la "matrice de confusion" en classification ?

Questions pour approfondir

1. Au-delà du binaire : La régression logistique est parfaite pour les problèmes à deux classes (Oui/Non). Comment pourrait-on l'adapter pour prédire plus de deux catégories, par exemple, pour classer des images de fleurs en "Rose", "Tulipe" ou "Pâquerette" ?

2. L'importance des coefficients : Tout comme en régression linéaire, le modèle logistique apprend des coefficients pour chaque feature. Si le coefficient pour la feature "Sex" (où 1 = femme) est fortement positif, qu'est-ce que cela nous dit sur l'impact de ce facteur sur la probabilité de survie ?

3. Le coût d'une erreur : Dans la matrice de confusion, nous avons vu des erreurs. Pour un système de diagnostic médical (prédire "malade" vs "sain"), quelle erreur est la plus grave : prédire "sain" alors que le patient est "malade" (un faux négatif), ou prédire "malade" alors que le patient est "sain" (un faux positif) ? Comment cela pourrait-il influencer notre choix du seuil de décision ?