Scikit-learn: Suggestion : Ajouter la prise en charge d'une régression logistique non pénalisée

Créé le 30 avr. 2016  ·  34Commentaires  ·  Source: scikit-learn/scikit-learn

LinearRegression fournit un OLS non pénalisé, et SGDClassifier , qui prend en charge loss="log" , prend également en charge penalty="none" . Mais si vous voulez une simple régression logistique non pénalisée, vous devez la simuler en définissant C dans LogisticRegression sur un grand nombre, ou utilisez Logit partir de statsmodels au lieu.

Documentation Easy

Commentaire le plus utile

Vous demandez pourquoi je voudrais faire une régression logistique sans régularisation ? Parce que (1) parfois l'échantillon est suffisamment grand par rapport au nombre de caractéristiques que la régularisation n'achètera rien et (2) parfois les coefficients les mieux adaptés sont intéressants, par opposition à la maximisation de la précision prédictive.

Tous les 34 commentaires

vous devez faire semblant en définissant C dans LogisticRegression sur un grand nombre

Quel est le problème avec cette approche?

J'ai supposé que c'était inexact et plus lent qu'une mise en œuvre directe d'une régression logistique non pénalisée. Ai-je tort?

Je remarque qu'un réglage trop élevé de C , comme dans ce qui suit, entraînera le blocage de LogisticRegression.fit . Mais je ne sais pas s'il s'agit d'un bogue ou simplement d'une propriété inhérente à l'algorithme et à son implémentation sur un ordinateur 64 bits.

import numpy as np
from sklearn.linear_model import LogisticRegression

x = np.matrix([0, 0, 0, 0,  1, 1, 1, 1]).T
y =           [1, 0, 0, 0,  1, 1, 1, 0]

m = LogisticRegression(C = 1e200)
m.fit(x, y)
print m.intercept_, m.coef_

Je remarque qu'un réglage trop élevé de C, comme dans ce qui suit, entraînera le blocage de LogisticRegression.fit

Oui, il faut s'y attendre car le problème devient mal posé lorsque C est grand. Les solveurs itératifs sont lents avec des problèmes mal posés.

Dans votre exemple, l'algorithme met une éternité pour atteindre la tolérance souhaitée. Vous devez soit augmenter tol ou coder en dur max_iter .

@mblondel existe-t-il une alternative aux « solveurs itératifs » ?
Vous n'obtiendrez pas exactement l'option non régularisée, n'est-ce pas ?

@Kodiologist pourquoi tu veux ça ?

Vous demandez pourquoi je voudrais faire une régression logistique sans régularisation ? Parce que (1) parfois l'échantillon est suffisamment grand par rapport au nombre de caractéristiques que la régularisation n'achètera rien et (2) parfois les coefficients les mieux adaptés sont intéressants, par opposition à la maximisation de la précision prédictive.

Oui, c'était ma question.

(1) n'est pas vrai. Cela vous achètera toujours un solveur plus rapide.

(2) est plus dans le domaine de l'analyse statistique, qui n'est pas vraiment l'objet de scikit-learn. Je suppose que nous pourrions ajouter ceci, mais je ne sais pas quel solveur nous utiliserions. En tant que non-statisticien, je me demande à quoi servent les coefficients qui changent avec un peu de régularisation.

Je ne peux pas en dire beaucoup sur (1) car le calcul n'est pas mon fort. Pour (2), je suis analyste de données avec une formation en statistiques. Je sais que scikit-learn se concentre sur l'apprentissage automatique traditionnel, mais c'est à mon avis le meilleur package Python pour l'analyse de données en ce moment, et je pense qu'il gagnera à ne pas trop se limiter. (Je pense également, à la suite de Larry Wasserman et Andrew Gelman, que les statistiques et l'apprentissage automatique gagneraient mutuellement à se mélanger davantage, mais je suppose que c'est sa propre boîte de vers.) Tous les coefficients changeront avec la régularisation ; c'est ce que fait la régularisation.

Je ne suis pas opposé à l'ajout d'un solveur sans régularisation. Nous pouvons vérifier ce qui serait bien, ou simplement cautionner et utiliser l-bfgs et vérifier à l'avance s'il est mal conditionné ?

Oui, tous les coefficients changent avec la régularisation. Je suis juste honnêtement curieux de savoir ce que vous voulez faire avec eux après.

Hey,
Quel est l'état d'avancement de ce sujet ? Je serais vraiment intéressé par une régression logistique non pénalisée. De cette façon, les valeurs p signifieront quelque chose d'un point de vue statistique. Sinon, je devrai continuer à utiliser R pour de tels cas d'utilisation...
Merci,
Alexis

Ou des modèles d'État ?

Quels solveurs proposez-vous d'implémenter ? En quoi cela serait-il différent des solveurs que nous avons déjà avec C -> infty ?

Quels solveurs proposez-vous d'implémenter ? En quoi cela serait-il différent des solveurs que nous avons déjà avec C -> infty ?

Vous pouvez essayer de regarder R ou statsmodels pour des idées. Je ne connais pas leurs méthodes, mais elles sont raisonnablement rapides et n'utilisent aucune régularisation.

Oui, statsmodels fait aussi le travail si vous utilisez l'algorithme QR pour l'inversion de matrice. Mon cas d'utilisation concerne l'interprétabilité des modèles. Pour les performances, j'utiliserais certainement la régularisation.

Je ne pense pas que nous ayons besoin d'ajouter un nouveau solveur... La régression logistique ne bénéficie pas d'une solution sous forme fermée, ce qui signifie que statsmodel doit également utiliser un solveur itératif quelconque (je suppose que les moindres carrés repondérés itératives, mais je n'ai pas vérifié). La définition de C=np.inf (ou de manière équivalente alpha=0 ) devrait en principe fonctionner avec nos solveurs actuels. Ma recommandation serait de passer au solveur L-BFGS ou Newton-CG, car liblinear peut en effet être très lent dans ce paramètre. Peut-être pouvons-nous ajouter une option solver="auto" et passer automatiquement à l'une d'entre elles lorsque C=np.inf ou de manière équivalente penalty="none" ?

nous changeons le solveur par défaut en lbfgs dans #10001 fwiw

Pour les gens qui veulent vraiment une régression logistique non régularisée (comme moi). J'ai dû me contenter de l'utilisation de statsmodels et de la création d'une classe wrapper qui imite l'API SKLearn.

Des mises à jour à ce sujet ? C'est un gros obstacle à ma volonté de recommander scikit-learn aux gens. Il n'est pas non plus évident pour les personnes venant d'autres bibliothèques que scikit-learn effectue la régularisation par défaut et qu'il n'y a aucun moyen de la désactiver.

@shermstats suggestions comment améliorer la documentation à ce sujet? Je suis d'accord que ce n'est peut-être pas très évident.
L-bfgs autorise-t-il C=np.inf ?

Vous pouvez spécifier C=np.inf , mais cela vous donnera le même résultat que C=large value . Sur l'exemple que j'ai essayé, cela a donné un meilleur ajustement que statsmodel et statsmodel n'a pas réussi à converger avec la plupart des autres graines aléatoires :

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
import statsmodels.api as sm

X, y = make_classification(random_state=2)
lr = LogisticRegression(C=np.inf, solver='lbfgs').fit(X, y)


logit = sm.Logit(y, X)
res = logit.fit()
Optimization terminated successfully.
         Current function value: 0.167162
         Iterations 10
from sklearn.metrics import log_loss
log_loss(y, lr.predict_proba(X))
log_loss(y, res.predict(X))
0.16197793224715606
0.16716164149746823

Je dirais donc que nous devrions simplement documenter que vous pouvez obtenir un modèle non pénalisé en définissant C large ou sur np.inf.

Je suggérerais d'ajouter à la docstring et au guide de l'utilisateur
"Le modèle LogisticRegregression est pénalisé par défaut. Vous pouvez obtenir un modèle non pénalisé en définissant C=np.inf et solver='lbfgs'."

il a donné un meilleur ajustement que statsmodel et statsmodel n'a pas réussi à converger avec la plupart des autres graines aléatoires

Le glm R est plus mature et peut permettre une meilleure comparaison.

Je suggérerais d'ajouter à la docstring et au guide de l'utilisateur
"Le modèle LogisticRegregression est pénalisé par défaut. Vous pouvez obtenir un modèle non pénalisé en définissant C=np.inf et solver='lbfgs'."

Pourquoi ne pas ajouter allow penalty = "none" a la SGDClassifier ?

@Kodiologist Je ne suis pas opposé à l'ajout de penalty="none" mais je ne sais pas quel est l'avantage d'ajouter une option redondante.
Et je pense que nous serions heureux d'avoir des comparaisons avec glm. Je ne suis pas très familier avec glm donc je ne suis probablement pas une bonne personne pour effectuer la comparaison. Cependant, nous optimisons la perte de log, il ne devrait donc y avoir aucune différence. Peut-être qu'ils implémentent différents solveurs, donc avoir une référence serait bien.

Je ne suis pas opposé à l'ajout de penalty="none" mais je ne sais pas quel est l'avantage d'ajouter une option redondante.

  1. Il devient plus clair comment obtenir un modèle non pénalisé.
  2. Il devient plus clair pour le lecteur ce que le code qui utilise un modèle non pénalisé essaie de faire.
  3. Cela permet à sklearn de modifier son implémentation de modèles non régularisés à l'avenir sans casser le code des gens.

Si vous pensez que cela ajoute à la découvrabilité, nous pouvons l'ajouter, et 3 est un point valide (bien que nous ne puissions pas vraiment changer cela sans probablement des dépréciations, voir le changement actuel du solveur).
Voulez-vous envoyer un PR?

Je n'ai pas les costumes ronds pour ça; Pardon.

@Kodiologist au moins tu m'as appris un idiome que je ne connaissais pas ;)

Alors ouvert aux contributeurs : ajoutez penalty='none' en option. Vérifiez également éventuellement quels solveurs prennent en charge ceci / sont efficaces avec cela (liblinear ne l'est probablement pas) et limitez-vous à ces solveurs.

Je suggérerais d'ajouter à la docstring et au guide de l'utilisateur
"Le modèle LogisticRegregression est pénalisé par défaut. Vous pouvez obtenir un modèle non pénalisé en définissant C=np.inf et solver='lbfgs'."

Cela me semble raisonnable. Je suggérerais également de mettre en gras la première phrase, car c'est légitimement surprenant pour les personnes venant d'autres environnements d'apprentissage automatique ou d'analyse de données.

@shermstats Donc @Kodiologist a suggéré d'ajouter penalty="none" pour le rendre plus explicite, ce qui serait juste un alias pour C=np.inf . Il est logique pour moi de rendre cela plus explicite de cette façon. Avez-vous des idées là-dessus?
Alors ce serait ce qui est dans la documentation. Et je suis d'accord que l'audace pourrait être une bonne idée.
Je pense que pour quelqu'un avec une formation en ML, c'est (peut-être ?) attendu, pour quelqu'un avec une formation en statistiques, cela semble très surprenant.

Exactement! J'ai une formation en statistiques et j'ai travaillé avec de nombreux statisticiens venant de R ou même d'interfaces pointer-cliquer, et ce comportement nous surprend beaucoup. Je pense pour l'instant que penalty=None (pas sûr de "none" vs None ) est une bonne solution. À l'avenir, nous devrions avoir un solveur distinct appelé automatiquement pour une régression logistique non pénalisée afin d'éviter les problèmes décrits par @mblondel .

Pardon, de quel problème parlez-vous ? Nous passons à l-bfgs par défaut, et nous pouvons également basculer en interne le solveur vers l-bfgs automatiquement si quelqu'un spécifie penalty='none' (souvent None est un jeton spécial que nous utilisons pour les paramètres obsolètes, mais nous avons arrêté faire cela. Toujours « aucun » serait plus cohérent avec le reste de la bibliothèque).
Nous avons besoin de solver="auto" toute façon, donc changer le solveur en fonction de la pénalité ne devrait pas être un problème.

Ce problème , qui fait référence à l'algorithme itératif devenant très lent pour les grands C. Je ne suis pas un expert en analyse numérique, mais si l-bfgs l'empêche de ralentir, cela semble être la bonne solution. penalty='none' semble également être la bonne façon de gérer cela.

@shermstats oui, avec l-bfgs, cela ne semble pas être un problème. Cependant, je n'ai pas effectué de tests de performances approfondis et je n'en aurai pas le temps. Si quelqu'un veut exécuter des benchmarks, ce serait d'une grande aide.

Si pénalité='none' doit être inclus, je suggère d'ajouter au guide de l'utilisateur le même avertissement sur colinéaire X que pour OLS (en particulier pour les fonctionnalités encodées à chaud).

Cette page vous a été utile?
0 / 5 - 0 notes