J'utilise LogisticRegression du package sklearn et j'ai une question rapide sur la classification. J'ai construit une courbe ROC pour mon classificateur, et il s'avère que le seuil optimal pour mes données d'entraînement est d'environ 0,25. Je suppose que le seuil par défaut lors de la création de prédictions est de 0,5. Comment puis-je modifier ce paramètre par défaut pour connaître la précision de mon modèle lors d'une validation croisée 10 fois? Fondamentalement, je veux que mon modèle prédit un «1» pour toute personne supérieure à 0,25, et non 0,5. J'ai parcouru toute la documentation et je n'arrive pas à trouver quoi que ce soit.

Merci d'avance pour votre aide.

27
Chetan Prabhu 15 juil. 2015 à 00:12

5 réponses

Meilleure réponse

Ce n'est pas une fonction intégrée. Vous pouvez "l'ajouter" en encapsulant la classe LogisticRegression dans votre propre classe et en ajoutant un attribut threshold que vous utilisez dans une méthode predict() personnalisée.

Cependant, quelques mises en garde:

  1. Le seuil par défaut est en fait 0. LogisticRegression.decision_function() renvoie une distance signée à l'hyperplan de séparation sélectionné. Si vous regardez predict_proba(), alors vous regardez logit() de la distance hyperplan avec un seuil de 0,5. Mais c'est plus cher à calculer.
  2. En sélectionnant le seuil «optimal» comme celui-ci, vous utilisez des informations post-apprentissage, qui gâchent votre ensemble de tests (c'est-à-dire que votre ensemble de tests ou de validation ne fournit plus d'estimation impartiale des erreurs hors échantillon). Vous pouvez donc induire un sur-ajustement supplémentaire à moins que vous ne choisissiez le seuil dans une boucle de validation croisée sur votre ensemble d'entraînement uniquement, puis que vous l'utilisiez et le classificateur formé avec votre ensemble de test.
  3. Pensez à utiliser class_weight si vous avez un problème non équilibré plutôt que de définir manuellement le seuil. Cela devrait obliger le classificateur à choisir un hyperplan plus éloigné de la classe d'intérêt sérieux.
7
Andreus 14 juil. 2015 à 21:42
def find_best_threshold(threshould, fpr, tpr):
   t = threshould[np.argmax(tpr*(1-fpr))]
   # (tpr*(1-fpr)) will be maximum if your fpr is very low and tpr is very high
   print("the maximum value of tpr*(1-fpr)", max(tpr*(1-fpr)), "for threshold", np.round(t,3))
   return t

Cette fonction peut être utilisée si vous voulez trouver le meilleur vrai taux positif et le meilleur taux nagatuve

0
Mehraban 1 déc. 2019 à 13:58

Par souci d'exhaustivité, je voudrais mentionner une autre façon de générer avec élégance des prévisions basées sur les calculs de probabilité de scikit en utilisant binarize:

import numpy as np
from sklearn.preprocessing import binarize

THRESHOLD = 0.25

# This probabilities would come from logistic_regression.predict_proba()
y_logistic_prob =  np.random.uniform(size=10)

predictions = binarize(y_logistic_prob.reshape(-1, 1), THRESHOLD).ravel()

De plus, je suis d'accord avec les considérations qu'Andreus fait, spécialement 2 et 3. Assurez-vous de garder un œil sur elles.

0
Arturo 30 juil. 2019 à 08:26

Cas particulier: régression logistique unidimensionnelle

La valeur séparant les régions où un échantillon X est étiqueté comme 1 et où il est étiqueté 0 est calculée en utilisant la formule:

from scipy.special import logit
thresh = 0.1
val = (logit(thresh)-clf.intercept_)/clf.coef_[0]

Ainsi, les prévisions peuvent être calculées plus directement avec

preds = np.where(X>val, 1, 0)
0
Antoine 24 juil. 2019 à 11:56

Je voudrais donner une réponse pratique

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, recall_score, roc_auc_score, precision_score

X, y = make_classification(
    n_classes=2, class_sep=1.5, weights=[0.9, 0.1],
    n_features=20, n_samples=1000, random_state=10
)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

clf = LogisticRegression(class_weight="balanced")
clf.fit(X_train, y_train)
THRESHOLD = 0.25
preds = np.where(clf.predict_proba(X_test)[:,1] > THRESHOLD, 1, 0)

pd.DataFrame(data=[accuracy_score(y_test, preds), recall_score(y_test, preds),
                   precision_score(y_test, preds), roc_auc_score(y_test, preds)], 
             index=["accuracy", "recall", "precision", "roc_auc_score"])

En changeant les THRESHOLD en 0.25, on peut constater que les scores recall et precision diminuent. Cependant, en supprimant l'argument class_weight, le accuracy augmente mais le score recall diminue. Reportez-vous à la réponse @accepted

10
J. Doe 10 sept. 2018 à 08:12