Scikit-learn: Vorschlag: Unterstützung für unbestrafte logistische Regression hinzufügen

Erstellt am 30. Apr. 2016  ·  34Kommentare  ·  Quelle: scikit-learn/scikit-learn

LinearRegression bietet unbestrafte OLS, und SGDClassifier , das loss="log" unterstützt, unterstützt auch penalty="none" . Aber wenn Sie eine einfache, nicht bestrafte logistische Regression wollen, müssen Sie sie vortäuschen, indem Sie C in LogisticRegression auf eine große Zahl setzen oder Logit von statsmodels stattdessen.

Documentation Easy

Hilfreichster Kommentar

Sie fragen sich, warum ich eine logistische Regression ohne Regularisierung durchführen sollte? Weil (1) manchmal die Stichprobe im Verhältnis zur Anzahl der Features groß genug ist, dass die Regularisierung einem nichts kauft, und (2) manchmal die am besten passenden Koeffizienten von Interesse sind, im Gegensatz zur Maximierung der Vorhersagegenauigkeit.

Alle 34 Kommentare

Sie müssen es fälschen, indem Sie C in LogisticRegression auf eine große Zahl setzen

Was ist das Problem bei diesem Ansatz?

Ich ging davon aus, dass es ungenau und langsamer ist als eine direkte Implementierung einer nicht bestraften logistischen Regression. Liege ich falsch?

Ich stelle fest, dass eine zu hohe Einstellung von C , wie im Folgenden, dazu führt, dass LogisticRegression.fit hängen bleibt. Aber ich weiß nicht, ob dies ein Fehler ist oder nur eine inhärente Eigenschaft des Algorithmus und seiner Implementierung auf einem 64-Bit-Computer.

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_

Ich stelle fest, dass eine zu hohe Einstellung von C, wie im Folgenden, dazu führt, dass LogisticRegression.fit hängen bleibt

Ja, dies ist zu erwarten, da das Problem schlecht gestellt wird, wenn C groß ist. Iterative Solver sind langsam bei schlecht gestellten Problemen.

In Ihrem Beispiel braucht der Algorithmus ewig, um die gewünschte Toleranz zu erreichen. Sie müssen entweder tol erhöhen oder max_iter codieren.

@mblondel gibt es eine Alternative zu "iterativen Solvern"?
Sie werden nicht genau die ungeregelte Option bekommen, oder?

@Kodiologe warum willst du das?

Sie fragen sich, warum ich eine logistische Regression ohne Regularisierung durchführen sollte? Weil (1) manchmal die Stichprobe im Verhältnis zur Anzahl der Features groß genug ist, dass die Regularisierung einem nichts kauft, und (2) manchmal die am besten passenden Koeffizienten von Interesse sind, im Gegensatz zur Maximierung der Vorhersagegenauigkeit.

Ja, das war meine Frage.

(1) stimmt nicht. Es wird Ihnen immer einen schnelleren Solver kaufen.

(2) liegt eher im Bereich der statistischen Analyse, die nicht wirklich im Fokus von scikit-learn steht. Ich denke, wir könnten dies hinzufügen, aber ich weiß nicht, welchen Solver wir verwenden würden. Als Nicht-Statistiker frage ich mich, was Koeffizienten nützen, die sich mit etwas Regularisierung ändern.

Zu (1) kann ich nicht viel sagen, da das Rechnen nicht meine Stärke ist. Für (2) bin ich Datenanalyst mit einem Hintergrund in Statistik. Ich weiß, dass scikit-learn sich auf traditionelles maschinelles Lernen konzentriert, aber meiner Meinung nach ist es derzeit das beste Python-Paket für die Datenanalyse, und ich denke, es wird davon profitieren, sich nicht _zu_ sehr einzuschränken. (Ich denke auch, Larry Wasserman und Andrew Gelman folgend, dass Statistik und maschinelles Lernen gegenseitig von einer stärkeren Vermischung profitieren würden, aber ich denke, das ist ihre eigene Dose.) Alle Koeffizienten werden sich mit der Regularisierung ändern; genau das macht die Regularisierung.

Ich bin nicht dagegen, einen Solver ohne Regularisierung hinzuzufügen. Wir können prüfen, was gut wäre, oder einfach auf Kaution l-bfgs verwenden und vorher prüfen, ob es schlecht konditioniert ist?

Ja, alle Koeffizienten ändern sich mit der Regularisierung. Ich bin nur ehrlich gespannt, was du danach mit ihnen machen willst.

Hey,
Wie ist der Stand zu diesem Thema? Ich wäre wirklich an einer straflosen logistischen Regression interessiert. Auf diese Weise werden p-Werte statistisch gesehen etwas bedeuten. Ansonsten muss ich für solche Anwendungsfälle weiterhin R 😢 verwenden...
Vielen Dank,
Alex

Oder Staatsmodelle?

Welche Solver schlagen Sie zur Implementierung vor? Wie würde sich das von den Solvern unterscheiden, die wir bereits mit C -> infty haben?

Welche Solver schlagen Sie zur Implementierung vor? Wie würde sich das von den Solvern unterscheiden, die wir bereits mit C -> infty haben?

Sie könnten versuchen, sich R oder Statsmodels anzusehen, um Ideen zu finden. Ich kenne ihre Methoden nicht, aber sie sind relativ schnell und verwenden überhaupt keine Regularisierung.

Ja, statsmodels erledigt die Arbeit auch, wenn Sie den QR-Algorithmus für die Matrixinversion verwenden. Mein Anwendungsfall dreht sich um die Interpretierbarkeit von Modellen. Für die Leistung würde ich auf jeden Fall die Regularisierung verwenden.

Ich glaube nicht, dass wir einen neuen Löser hinzufügen müssen ... Die logistische Regression genießt keine geschlossene Lösung, was bedeutet, dass statsmodel auch einen iterativen Löser verwenden muss (meine Vermutung wäre iterativ neu gewichtete kleinste Quadrate, aber habe ich nicht überprüft). Das Setzen von C=np.inf (oder äquivalent alpha=0 ) sollte im Prinzip mit unseren aktuellen Solvern funktionieren. Meine Empfehlung wäre, auf den L-BFGS- oder Newton-CG-Solver umzusteigen, da liblinear in dieser Einstellung tatsächlich sehr langsam sein kann. Vielleicht können wir eine Option solver="auto" hinzufügen und automatisch zu einer dieser Optionen wechseln, wenn C=np.inf oder entsprechend penalty="none" ?

Wir ändern den Standard-Solver in #10001 fwiw in lbfgs

Für die Leute, die wirklich unregulierte logistische Regression wollen (wie ich). Ich musste mich damit begnügen, Statsmodels zu verwenden und eine Wrapper-Klasse zu erstellen, die die SKLearn-API nachahmt.

Irgendwelche Updates dazu? Dies ist ein großer Blocker für meine Bereitschaft, scikit-learn Leuten zu empfehlen. Es ist auch für Leute, die aus anderen Bibliotheken kommen, überhaupt nicht offensichtlich , dass scikit-learn die Regularisierung standardmäßig durchführt und dass es keine Möglichkeit gibt, sie zu deaktivieren.

@shermstats Vorschläge, wie man die Dokumentation dazu verbessern kann? Ich stimme zu, dass es möglicherweise nicht sehr offensichtlich ist.
Erlaubt l-bfgs C=np.inf ?

Sie können C=np.inf angeben, erhalten jedoch dasselbe Ergebnis wie C=large value . In dem Beispiel, das ich ausprobiert habe, passte es besser als statsmodel und statsmodel konnte nicht mit den meisten anderen zufälligen Seeds konvergieren:

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

Ich würde also argumentieren, dass wir einfach dokumentieren sollten, dass Sie ein nicht bestraftes Modell erhalten können, indem Sie C large oder auf np.inf setzen.

Ich würde vorschlagen, den Docstring und das Benutzerhandbuch hinzuzufügen
"Das LogisticRegregression-Modell wird standardmäßig bestraft. Sie können ein nicht bestraftes Modell erhalten, indem Sie C=np.inf und Solver='lbfgs' setzen."

es passte besser als statsmodel und statsmodel konnte nicht mit den meisten anderen zufälligen Seeds konvergieren

Rs glm ist ausgereifter und kann einen besseren Vergleich ermöglichen.

Ich würde vorschlagen, den Docstring und das Benutzerhandbuch hinzuzufügen
"Das LogisticRegregression-Modell wird standardmäßig bestraft. Sie können ein nicht bestraftes Modell erhalten, indem Sie C=np.inf und Solver='lbfgs' setzen."

Warum nicht penalty = "none" à la SGDClassifier zulassen hinzufügen?

@Kodiologe Ich bin nicht dagegen, penalty="none" hinzuzufügen, aber ich bin mir nicht sicher, welchen Vorteil es hat, eine redundante Option hinzuzufügen.
Und ich denke, wir würden Vergleiche mit glm begrüßen. Ich bin mit glm nicht sehr vertraut, daher bin ich wahrscheinlich keine gute Person, um den Vergleich durchzuführen. Wir optimieren jedoch den Log-Loss, sodass es wirklich keinen Unterschied geben sollte. Vielleicht implementieren sie verschiedene Solver, daher wäre es schön, einen Benchmark zu haben.

Ich bin nicht dagegen, penalty="none" hinzuzufügen, aber ich bin mir nicht sicher, welchen Vorteil es hat, eine redundante Option hinzuzufügen.

  1. Es wird klarer, wie man ein bestrafungsfreies Modell erhält.
  2. Es wird dem Leser klarer, was Code zu tun versucht, der ein nicht bestraftes Modell verwendet.
  3. Es ermöglicht sklearn, die Implementierung von nicht regulierten Modellen in Zukunft zu ändern, ohne den Code der Leute zu brechen.

Wenn Sie der Meinung sind, dass dies die Auffindbarkeit erhöht, können wir es hinzufügen, und 3 ist ein gültiger Punkt (obwohl wir das wahrscheinlich ohne Abstriche nicht wirklich ändern können, siehe aktuelle Änderung des Solvers).
Möchten Sie eine PR senden?

Ich habe nicht die Rundkurse dafür; Verzeihung.

@Kodiologe, zumindest hast du mir ein Idiom beigebracht, das ich nicht kannte ;)

Also offen für Mitwirkende: Fügen Sie penalty='none' als Option hinzu. Überprüfen Sie möglicherweise auch, welche Solver dies unterstützen / damit effizient sind (liblinear ist es wahrscheinlich nicht) und beschränken Sie sich auf diese Solver.

Ich würde vorschlagen, den Docstring und das Benutzerhandbuch hinzuzufügen
"Das LogisticRegregression-Modell wird standardmäßig bestraft. Sie können ein nicht bestraftes Modell erhalten, indem Sie C=np.inf und Solver='lbfgs' setzen."

Das klingt für mich vernünftig. Ich würde auch vorschlagen, den ersten Satz fett zu schreiben, weil er für Leute, die aus anderen Umgebungen für maschinelles Lernen oder Datenanalyse kommen, zu Recht überraschend ist.

@shermstats Also schlug @Kodiologist vor, penalty="none" hinzuzufügen, um es expliziter zu machen, was nur ein Alias ​​für C=np.inf . Es macht für mich Sinn, dies auf diese Weise deutlicher zu machen. Hast du Gedanken dazu?
Das steht dann in der Dokumentation. Und ich stimme zu, dass fett eine gute Idee sein könnte.
Ich denke, für jemanden mit ML-Hintergrund ist dies (vielleicht?) zu erwarten, für jemanden mit Statistik-Hintergrund erscheint dies sehr überraschend.

Genau! Ich habe einen Statistikhintergrund und habe mit vielen Statistikern aus R oder sogar Point-and-Click-Schnittstellen gearbeitet, und dieses Verhalten ist für uns sehr überraschend. Ich denke im Moment, dass penalty=None (nicht sicher über "none" vs. None ) eine gute Lösung ist. In Zukunft sollten wir einen separaten Solver haben, der automatisch für eine nicht bestrafte logistische Regression aufgerufen wird, um die von @mblondel beschriebenen Probleme zu

Entschuldigung, welches Problem meinst du? Wir wechseln standardmäßig zu l-bfgs und können den Solver auch intern automatisch auf l-bfgs umstellen, wenn jemand penalty='none' angibt (oft ist None ein spezielles Token, das wir für veraltete Parameter verwenden, aber wir haben aufgehört das zu tun. Dennoch würde 'keine' mit dem Rest der Bibliothek konsistenter sein).
Wir brauchen sowieso solver="auto" also sollte es kein Problem sein, den Solver basierend auf der Strafe zu ändern.

Dieses Problem bezieht sich darauf, dass der iterative Algorithmus für große C sehr langsam wird. Ich bin kein Experte für numerische Analyse, aber wenn l-bfgs verhindert, dass er langsamer wird, dann klingt das nach der richtigen Lösung. penalty='none' klingt auch nach dem richtigen Weg, damit umzugehen.

@shermstats ja, mit l-bfgs scheint dies kein Problem zu sein. Ich habe jedoch keine umfangreichen Benchmarks durchgeführt und werde keine Zeit dazu haben. Wenn jemand Benchmarks ausführen möchte, wäre das eine große Hilfe.

Wenn Penalty='none' eingefügt werden soll, schlage ich vor, dem Benutzerhandbuch die gleiche Warnung zu kolinearem X wie bei OLS hinzuzufügen (insbesondere für One-Hot-codierte Funktionen).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen