Scikit-learn: Jak SGDClassifier przewidział, a także regresję logistyczną

24

Metodą trenowania regresji logistycznej jest użycie stochastycznego spadku gradientu, do którego scikit-learn oferuje interfejs.

Co chciałbym zrobić, to wziąć scikit-learn na SGDClassifier i mieć go zdobyć taki sam jak regresja logistyczna tutaj . Jednak muszę brakować niektórych ulepszeń uczenia maszynowego, ponieważ moje wyniki nie są równoważne.

To jest mój obecny kod. Czego mi brakuje w SGDClassifier, który dałby takie same wyniki jak regresja logistyczna?

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)

Moja produkcja:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
źródło
3
Pytanie i spostrzeżenie: jak stabilna jest twoja dokładność SGD przy powtarzanych cyklach? dwa algorytmy nie są równoważne i niekoniecznie będą dawać taką samą dokładność, biorąc pod uwagę te same dane. Praktycznie możesz spróbować zmienić epoki i / lub współczynnik uczenia się dla SGD. Poza tym możesz spróbować znormalizować funkcje SGD.
image_doctor,
Tak więc nie testowałem SGD na powtarzanych cyklach, ponieważ powyższe wykorzystuje 10-krotną walidację krzyżową; dla mnie to wystarczyło.
hlin117
Czy możesz mi wyjaśnić, dlaczego te algorytmy nie są równoważne? Jeśli popatrzę na SGDClassifier tutaj, wspomina „Strata logu daje regresję logistyczną, klasyfikator probabilistyczny”. Wierzę, że istnieje luka w mojej wiedzy dotyczącej uczenia maszynowego.
hlin117
Bez szczegółowego studium wdrożeń nie sądzę, żebym mógł sprecyzować, dlaczego nie są one równoważne, ale dobrą wskazówką, że nie są one równoważne, jest to, że wyniki dla każdej metody są znacząco różne. Domyślam się, że ma to związek z właściwościami konwergencji metod szacowania stosowanych w każdej z nich.
image_doctor,
1
Algorytmy te są różne, ponieważ regresja logistyczna wykorzystuje opadanie gradientu, podczas gdy jako gradient gradientu stochastycznego stosuje się gradient gradientu stochastycznego. Konwergencja tego pierwszego będzie bardziej wydajna i przyniesie lepsze wyniki. Jednak wraz ze wzrostem wielkości zestawu danych SGDC powinno zbliżyć się do dokładności regresji logistycznej. Parametry GD oznaczają inne rzeczy niż parametry SGD, więc powinieneś spróbować je nieco dostosować. Sugerowałbym trochę zabawę z (spadkiem) szybkości uczenia się SGD, aby spróbować uzyskać lepszą zbieżność, ponieważ może to być trochę kłopotliwe.
AN6U5,

Odpowiedzi:

23

Komentarze na temat numeru iteracji są na miejscu. Domyślnie oznacza SGDClassifier n_iterto, 5że wykonujesz 5 * num_rowskroki w przestrzeni wagowej. Reguła sklearn kciuka wynosi ~ 1 milion kroki dla typowych danych. Na przykład ustaw go na 1000, aby najpierw osiągnąć tolerancję. Twoja dokładność jest niższa, SGDClassifierponieważ osiąga limit iteracji przed tolerancją, więc „wcześnie przestajesz”

Szybko i brudnie modyfikując kod otrzymuję:

# 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
źródło
4

SGDClassifier, jak sama nazwa wskazuje, wykorzystuje algorytm gradientu stochastycznego jako algorytm optymalizacji.

Jeśli spojrzysz na implementację LogisiticRegression w Sklearn, dostępnych jest pięć technik optymalizacji (solver), a domyślnie jest to „LibLinear”, który używa zbieżności współrzędnych (CD).

Oprócz liczby iteracji optymalizacja, rodzaj regularyzacji (kara) i jej wielkość (C) również wpływają na wydajność algorytmu.

Jeśli używasz go do strojenia zestawu danych Iris, wszystkie te hiper-parametry mogą nie przynieść znaczących zmian, ale w przypadku złożonego zestawu danych odgrywają znaczącą rolę.

Aby uzyskać więcej informacji, zapoznaj się z dokumentacją regresji logistycznej Sklearn .

Rajat Agarwal
źródło
3

Powinieneś także wyszukać w siatce hiperparametr „alfa” dla SGDClassifier. Jest to wyraźnie wymienione w dokumentacji sklearn i z mojego doświadczenia ma duży wpływ na dokładność. Drugi hiperparametr, na który powinieneś spojrzeć, to „n_iter” - jednak widziałem mniejszy efekt w moich danych.

Diego
źródło
1

TL; DR : Możesz określić siatkę alfa i n_iter (lub max_iter ) i użyć parfit do hiperoptymalizacji na SGDClassifier

Mój kolega, Vinay Patlolla, napisał doskonały post na blogu na temat tego, jak sprawić, by SGD Classifier działał, a także regresji logistycznej za pomocą parfit .

Parfit to pakiet optymalizacji hiperparametrów, który wykorzystał do znalezienia odpowiedniej kombinacji parametrów, które posłużyły do ​​zoptymalizowania SGDClassifier do wykonania, a także regresji logistycznej na jego przykładowym zestawie danych w znacznie krótszym czasie.

Podsumowując, dwa kluczowe parametry SGDClassifier to alfa i n_iter . Cytując bezpośrednio Vinay:

n_iter w sklearn jest domyślnie Brak. Ustawiamy go tutaj na wystarczająco dużą ilość (1000). Alternatywnym parametrem do ostatnio dodanego n_iter jest max_iter. Ta sama rada powinna obowiązywać dla max_iter.

Hiperparametr alfa służy podwójnemu celowi. Jest to zarówno parametr regularyzacji, jak i początkowa szybkość uczenia się w domyślnym harmonogramie. Oznacza to, że oprócz uregulowania współczynników regresji logistycznej, wyniki modelu zależą od interakcji między alfa a liczbą epok (n_iter), które wykonuje procedura dopasowania. W szczególności, ponieważ alfa staje się bardzo małe, wartość n_iter musi zostać zwiększona, aby zrekompensować powolną naukę. Dlatego bezpieczniej (ale wolniej) jest podawać n_iter wystarczająco duży, np. 1000, podczas przeszukiwania szerokiego zakresu alf.

Jason Carpenter
źródło