voir aussi slides
classification
La sortie de la régression linéaire est continue
Si nous utilisons la régression linéaire pour classifier des animaux (chat = 0, lapin = 1, chien = 2), nous avons besoin de seuils arbitraires qui ne reflètent pas la réalité
Pourquoi aurions-nous un ordre arbitraire entre les animaux ?
De plus, la plage de sortie de la régression linéaire n'est pas contrainte ou limitée..
On ne peut pas utiliser la régression linéaire pour la classification
L'idée principale derrière la classification binaire avec la régression logistique
Objectif : Classification binaire : 0 / 1
de R -> [0,1]
f(x) = 1/(1 + e^(-x))
Modèle linéaire : y = b₀ + b₁x
Modèle logistique : p = 1/(1 + e^(-(b₀ + b₁x)))

2D : ŷ = a_1 x_1 + a_0
3D : ŷ = a_1 x_1 + a_2 x_2 + a_0

disponible ici
Prédicteurs :
Variable cible :
import statsmodels.formula.api as smf
import pandas as pd
# Charger le dataset
df = pd.read_csv('credit_default_sampled.csv')
# instancier le modèle
model = smf.logit('default ~ income + balance', data = df)
# Ajuster le modèle aux données
results = model.fit()
# Résultats
results.summary()
default ~ income + balance

modele logistic regression
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# Charger le dataset
df = pd.read_csv('credit_default_sampled.csv')
# Préparer les features et la cible
X = df[['income', 'balance']]
y = df['default']
# Optionnel mais recommandé : standardiser les features
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Diviser en ensemble d'entraînement et de test (optionnel)
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42, stratify=y
)
# Instancier le modèle
model = LogisticRegression(max_iter=1000)
# Ajuster le modèle aux données
model.fit(X_train, y_train)
# Obtenir les coefficients et l'intercept
print("Coefficients:", model.coef_)
print("Intercept:", model.intercept_)
# Score du modèle
print("Score d'entraînement:", model.score(X_train, y_train))
print("Score de test:", model.score(X_test, y_test))
# Prédictions
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)
L'histogramme des valeurs estimées fournit une bonne indication du pouvoir de séparation du modèle.
y_proba = results.predict(df[['income', 'balance']])

# sortie des prédictions du modèle sous forme de probabilités, yhat dans [0,1]
y_proba = results.predict(df[['income', 'balance']])
# transformer les probabilités en classe
predicted_class = (y_proba > 0.5).astype(int)
print(predicted_class)
> [1,1,1,1...,0,0,0]
Note que le choix du seuil de classification (0.5) reste arbitraire.
4 cas possibles

2 corrects :
2 faux :
| Prédit 1 | Prédit 0 | |
|---|---|---|
| Réel 1 | Vrais Positifs | Faux Négatifs |
| Réel 0 | Faux Positifs | Vrais Négatifs |
results.pred_table()
| Défaut Prédit | Non-Défaut Prédit | |
|---|---|---|
| Défaut Réel | 286 | 47 |
| Non-Défaut Réel | 40 | 460 |
Sur 333 échantillons de défaut :
Et sur 500 échantillons non-défaut :
Nous pouvons définir plusieurs métriques en utilisant la matrice de confusion
Précision (Accuracy) = (VP + VN) / (P + N)
Taux de Vrais Positifs = (VP) / (VP + FP)
Taux de Faux Positifs = (FP) / (VP + FP)
nombre d'échantillons correctement classifiés : 460 + 286 = 746
nombre total d'échantillons : 833
donc notre précision est 746 / 833 = 89.56%
TPR = 286 / 333 = 85.89%
FPR = 47 / 333 = 14.11%
de la page Wikipedia Confusion Matrix

Construire le modèle : default ~ income + balance + student
Que se passe-t-il si nous utilisons un seuil de classification différent ?
La matrice de confusion et les métriques associées changent également.
t = 0.5
t = 0.75
Tracer la courbe TPR vs FPR en faisant varier le seuil de 0 à 1 donne la courbe ROC.

L'aire sous la courbe (AUC) est une métrique plus robuste que la précision.
yhat = results.predict(df)
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(df['default'], yhat)
from sklearn.metrics import roc_auc_score
score = roc_auc_score(df['default'], yhat)
Pour le modèle default ~ income + balance + student :
Comparer avec le modèle default ~ income.
Le dataset original de défaut de crédit contient :
Un modèle (stupide, inutile) qui prédit toujours non-défaut a une précision de 96.67%.
La classe cible est une forte minorité. Le dataset est déséquilibré.
Quatre stratégies pour gérer le déséquilibre de classe :
Stratégies pour résoudre le problème du déséquilibre de la classe minoritaire
On peut aussi
Le but n'est pas de balancer parfaitement les classes 50 / 50
Sur le dataset complet de défaut de crédit :
Puis :
# sur-échantillonner la classe minoritaire
df = pd.read_csv('credit_default.csv')
minority = df[df.default == 0].sample(n = 2000, replace = True)
majority = df[df.default == 1]
data = pd.concat([minority, majority])
# mélanger
data = data.sample(frac = 1)
L'algorithme SMOTE est implémenté en sélectionnant aléatoirement l'un des échantillons de données de classes peu nombreuses, puis en sélectionnant plusieurs de ses données d'échantillons voisins par interpolation linéaire.
L'algorithme SMOTE génère des échantillons artificiels en trois étapes :


"Parce que cela ne fonctionne pas.
Si vous n'êtes pas d'accord, alors bienvenue avec un exemple de SMOTE fonctionnant. N'utilisant pas de données synthétiques, uniquement des données réelles."
Un package Python pour s'attaquer à la malédiction des datasets déséquilibrés dans l'apprentissage automatique http://imbalanced-learn.org
Voir aussi Conseils pour gérer les données déséquilibrées dans l'apprentissage automatique
Encodage one-hot – Encodage dummy
Comment convertir les variables catégorielles en variables numériques ?
Binaire :
Multinomial, non-ordinal :
Exemples
Marque de voiture : Audi, Renault, Ford, Fiat
Si un nombre arbitraire est attribué à chaque marque, une hiérarchie est créée :
De même :
Parfois, attribuer un nombre à chaque catégorie a du sens—catégories ordonnées :
Charger auto-mpg
Origin (3) et name (nombreux) sont des catégories non ordonnées (non-ordinales).
Comment inclure origin comme prédicteur dans un modèle linéaire ?
Avec Pandas, créer une variable par catégorie :
N-1 nouvelles variables sont nécessaires pour N catégories.
origin_variables = pd.get_dummies(df.origin)
df = df.merge(origin_variables, left_index=True, right_index=True)
results = smf.ols('mpg ~ Japanese + European', data = df).fit()
# Essayer
results = smf.ols('mpg ~ Japanese + European + American', data = df).fit()
pd.get_dummies() crée N-1 variables. Puis, définir le modèle : mpg ~ American + European
Statsmodels encode directement les variables catégorielles avec
mpg ~ C(origin)
La moyenne par catégorie
df[['mpg','origin']].groupby(by = 'origin').mean().reset_index()
mpg ~ C(Origin)
Comment inclure la marque de voiture dans auto-mpg ? Il y a 36 catégories. Certaines catégories ont peu d'échantillons.
Encodage binaire !
import category_encoders as ce
# définir l'encodeur
encoder = ce.BinaryEncoder(cols=['brand'])
df = encoder.fit_transform(df)
Au lieu de
Nous utilisons le modèle
https://towardsdatascience.com/all-about-categorical-variable-encoding-305f3361fd02/
Nombre de variables binaires = INT( log2(Nombre de catégories))
https://contrib.scikit-learn.org/category_encoders/index.html
Un ensemble de transformateurs de style scikit-learn pour encoder les variables catégorielles en numérique avec différentes techniques.
One vs One

Pour N catégories on construit N modèles Le modèle final est obtenu par vote ou par moyenne
M1 : lapins vs chiens M2 : chats vs lapins M3 : chiens vs chats
One vs Rest

N-1 modèles sont nécessaires propagation de l'erreur
M1 : lapins vs chats et chiens (non lapins) M2 : chats vs chiens
sur un google colab
Construire un modèle de régression logistique scikit-learn sur le dataset des pingouins
voir aussi la page Kaggle pour le dataset Pingouins sur Kaggle
charger les données dans un dataframe pandas
transformer les valeurs catégorielles en valeurs numériques
utiliser une stratégie un contre tous (one vs rest) ou un contre un (one vs one)
en utilisant le meilleur modèle