Scikit-Learn: SGDClassifier dazu bringen, eine logistische Regression vorherzusagen

24

Eine Möglichkeit, eine logistische Regression zu trainieren, besteht in der Verwendung einer stochastischen Gradientenabnahme, zu der scikit-learn eine Schnittstelle bietet.

Was ich möchte , ist zu tun , nehmen Sie einen Scikit-Learn des SGDClassifier und haben sie das gleiche wie eine logistische Regression punkten hier . Ich muss jedoch einige Verbesserungen beim maschinellen Lernen verpassen, da meine Punktzahlen nicht gleichwertig sind.

Das ist mein aktueller Code. Was fehle ich am SGDClassifier, der die gleichen Ergebnisse wie eine logistische Regression liefern würde?

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import SGDClassifier
import numpy as np
import pandas as pd
from sklearn.cross_validation import KFold
from sklearn.metrics import accuracy_score

# Note that the iris dataset is available in sklearn by default.
# This data is also conveniently preprocessed.
iris = datasets.load_iris()
X = iris["data"]
Y = iris["target"]

numFolds = 10
kf = KFold(len(X), numFolds, shuffle=True)

# These are "Class objects". For each Class, find the AUC through
# 10 fold cross validation.
Models = [LogisticRegression, SGDClassifier]
params = [{}, {"loss": "log", "penalty": "l2"}]
for param, Model in zip(params, Models):
    total = 0
    for train_indices, test_indices in kf:

        train_X = X[train_indices, :]; train_Y = Y[train_indices]
        test_X = X[test_indices, :]; test_Y = Y[test_indices]

        reg = Model(**param)
        reg.fit(train_X, train_Y)
        predictions = reg.predict(test_X)
        total += accuracy_score(test_Y, predictions)
    accuracy = total / numFolds
    print "Accuracy score of {0}: {1}".format(Model.__name__, accuracy)

Meine Ausgabe:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
quelle
3
Eine Frage und eine Bemerkung: Wie stabil ist Ihre SGD-Genauigkeit bei wiederholten Läufen? Die beiden Algorithmen sind nicht gleichwertig und liefern bei gleichen Daten nicht unbedingt die gleiche Genauigkeit. Praktisch könnten Sie versuchen, die Epochen und / oder die Lernrate für SGD zu ändern. Darüber hinaus können Sie versuchen, die Funktionen für SGD zu normalisieren.
image_doctor
Daher habe ich die SGD nicht bei wiederholten Durchläufen getestet, da die obige 10-fache Kreuzvalidierung verwendet; für mich hat das gereicht.
hlin117
Können Sie mir erklären, warum diese Algorithmen nicht gleichwertig sind? Wenn ich mir den SGDClassifier hier anschaue, erwähnt er "Der 'log'-Verlust ergibt eine logistische Regression, einen wahrscheinlichkeitstheoretischen Klassifikator." Ich glaube, es gibt eine Lücke in meinem maschinellen Lernwissen.
hlin117
Ohne eine detaillierte Untersuchung der Implementierungen kann ich nicht genau sagen, warum sie nicht gleichwertig sind, aber ein guter Hinweis darauf, dass sie nicht gleichwertig sind, ist, dass die Ergebnisse für jede Methode signifikant unterschiedlich sind. Ich vermute, dass dies mit den Konvergenzeigenschaften der jeweils verwendeten Schätzmethoden zu tun hat.
image_doctor
1
Diese Algorithmen unterscheiden sich, da bei der logistischen Regression die Gradientenabnahme verwendet wird, während bei der stochastischen Gradientenabnahme die stochastische Gradientenabnahme verwendet wird. Die Konvergenz der ersteren ist effizienter und führt zu besseren Ergebnissen. Mit zunehmender Größe des Datensatzes sollte sich das SGDC jedoch der Genauigkeit der logistischen Regression annähern. Die Parameter für GD haben andere Bedeutungen als die für SGD. Sie sollten daher versuchen, sie geringfügig anzupassen. Ich würde vorschlagen, ein bisschen mit (abnehmenden) SGD-Lernraten zu spielen, um eine bessere Konvergenz zu erreichen, da es ein bisschen krachen könnte.
AN6U5,

Antworten:

23

Die Kommentare zur Iterationsnummer sind genau richtig. Der Standard SGDClassifier n_iterwird das 5heißt , Sie tun 5 * num_rowsSchritte in Gewicht Raum. Die Sklearn-Faustregel für typische Daten lautet ~ 1 Million Schritte. Für Ihr Beispiel setzen Sie es einfach auf 1000 und es könnte zuerst die Toleranz erreichen. Ihre Genauigkeit ist geringer, SGDClassifierda sie die Iterationsgrenze vor der Toleranz erreicht, sodass Sie "vorzeitig anhalten".

Wenn ich deinen Code schnell und schmutzig ändere, bekomme ich:

# Added n_iter here
params = [{}, {"loss": "log", "penalty": "l2", 'n_iter':1000}]

for param, Model in zip(params, Models):
    total = 0
    for train_indices, test_indices in kf:
        train_X = X[train_indices, :]; train_Y = Y[train_indices]
        test_X = X[test_indices, :]; test_Y = Y[test_indices]
        reg = Model(**param)
        reg.fit(train_X, train_Y)
        predictions = reg.predict(test_X)
        total += accuracy_score(test_Y, predictions)

    accuracy = total / numFolds
    print "Accuracy score of {0}: {1}".format(Model.__name__, accuracy)

Accuracy score of LogisticRegression: 0.96
Accuracy score of SGDClassifier: 0.96
Cwharland
quelle
4

SGDClassifier verwendet, wie der Name schon sagt, Stochastic Gradient Descent als Optimierungsalgorithmus.

Wenn Sie sich die Implementierung von LogisiticRegression in Sklearn ansehen, stehen fünf Optimierungstechniken (Solver) zur Verfügung. Standardmäßig verwendet 'LibLinear' die Funktion Coordinate Descent (CD) zur Konvergenz.

Neben der Anzahl der Iterationen beeinflussen auch die Optimierung, die Art der Regularisierung (Penalty) und deren Größe (C) die Leistung des Algorithmus.

Wenn Sie es mit der Optimierung von Iris-Datensätzen ausführen, bringen all diese Hyperparameter möglicherweise keine signifikanten Änderungen mit sich, aber für komplexe Datensätze spielen sie eine bedeutende Rolle.

Weitere Informationen finden Sie in der Dokumentation zur logistischen Regression von Sklearn .

Rajat Agarwal
quelle
3

Sie sollten auch eine Rastersuche nach dem Hyperparameter "alpha" für den SGDClassifier durchführen. Es wird ausdrücklich in der sklearn-Dokumentation erwähnt und hat nach meiner Erfahrung einen großen Einfluss auf die Genauigkeit. Der zweite Hyperparameter, den Sie sich ansehen sollten, ist "n_iter" - allerdings habe ich bei meinen Daten einen geringeren Effekt gesehen.

Diego
quelle
1

TL; DR : Sie können ein Raster aus alpha und n_iter (oder max_iter ) angeben und parfit für die Hyperoptimierung in SGDClassifier verwenden

Mein Kollege, Vinay Patlolla, schrieb einen hervorragenden Blogbeitrag über die Leistung von SGD Classifier und die logistische Regression mit Parfit .

Parfit ist ein Hyperparameter-Optimierungspaket, mit dem er die geeignete Kombination von Parametern fand, die dazu diente, SGDClassifier für die Ausführung sowie die logistische Regression seines Beispieldatensatzes in viel kürzerer Zeit zu optimieren.

Zusammenfassend sind die beiden Schlüsselparameter für SGDClassifier alpha und n_iter . Um Vinay direkt zu zitieren:

n_iter in sklearn ist standardmäßig None. Wir setzen es hier auf einen ausreichend großen Betrag (1000). Ein alternativer Parameter zu n_iter, der kürzlich hinzugefügt wurde, ist max_iter. Der gleiche Rat sollte für max_iter gelten.

Der Alpha-Hyperparameter dient einem doppelten Zweck. Dies ist sowohl ein Regularisierungsparameter als auch die anfängliche Lernrate gemäß dem Standardzeitplan. Dies bedeutet, dass neben der Regularisierung der logistischen Regressionskoeffizienten die Ausgabe des Modells von einer Wechselwirkung zwischen Alpha und der Anzahl der von der Anpassungsroutine durchgeführten Epochen (n_iter) abhängt. Insbesondere wenn Alpha sehr klein wird, muss n_iter erhöht werden, um die langsame Lernrate zu kompensieren. Aus diesem Grund ist es sicherer (aber langsamer), n_iter als ausreichend groß anzugeben, z. B. 1000, wenn Sie über einen weiten Bereich von Alphas suchen.

Jason Carpenter
quelle