Scikit-learn: получение SGDClassifier для прогнозирования, а также логистическая регрессия

24

Способ обучения Логистической регрессии - использование стохастического градиентного спуска, к которому Scikit-Learn предлагает интерфейс.

То , что я хотел бы сделать , это принять scikit-Learn - х SGDClassifier и он забьет такой же , как логистическая регрессия здесь . Тем не менее, мне не хватает некоторых улучшений машинного обучения, так как мои оценки не эквивалентны.

Это мой текущий код. Чего мне не хватает в SGDClassifier, чтобы он давал те же результаты, что и логистическая регрессия?

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)

Мой вывод:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
источник
3
Вопрос и наблюдение: насколько стабильна ваша точность SGD при повторных прогонах? два алгоритма не эквивалентны и не обязательно будут давать одинаковую точность при одинаковых данных. Практически вы можете попытаться изменить эпохи и / или скорость обучения для SGD. Кроме того, вы можете попытаться нормализовать функции SGD.
image_doctor
Итак, я не тестировал SGD на повторных прогонах, потому что в приведенном выше примере используется 10-кратная перекрестная проверка; для меня этого хватило.
hlin117
Можете ли вы объяснить мне, почему эти алгоритмы не эквивалентны? Если я посмотрю на SGDClassifier здесь, он упоминает: «Потеря логарифма дает логистическую регрессию, вероятностный классификатор». Я считаю, что в моих знаниях по машинному обучению есть пробел.
hlin117
Без подробного изучения реализаций, я не думаю, что смогу конкретно сказать, почему они не эквивалентны, но хорошая подсказка, что они не эквивалентны, заключается в том, что результаты для каждого метода значительно отличаются. Я думаю, что это связано со свойствами сходимости методов оценки, используемых в каждом.
image_doctor
1
Эти алгоритмы отличаются тем, что логистическая регрессия использует градиентный спуск, где в качестве стохастического градиентного спуска используется стохастический градиентный спуск. Конвергенция первых будет более эффективной и даст лучшие результаты. Однако по мере увеличения размера набора данных SGDC должен приближаться к точности логистической регрессии. Параметры для GD означают вещи, отличные от параметров для SGD, поэтому вы должны попытаться немного их изменить. Я бы предложил немного поиграть с (уменьшением) скорости обучения SGD, чтобы попытаться улучшить конвергенцию, так как она может немного колебаться.
AN6U5

Ответы:

23

Комментарии о номере итерации находятся на месте. По умолчанию SGDClassifier n_iterэто 5означает , что вы делаете 5 * num_rowsшаги в весовом пространстве. Правило sklearn эмпирического составляет ~ 1 миллиона шагов для типичных данных. Для вашего примера, просто установите его на 1000, и он может сначала достичь допуска. Ваша точность ниже, SGDClassifierпотому что она достигает предела итерации до допуска, поэтому вы «рано останавливаетесь»

Быстро и грязно модифицируя ваш код я получаю:

# 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
источник
4

SGDClassifier, как следует из названия, использует стохастический градиентный спуск в качестве алгоритма оптимизации.

Если вы посмотрите на реализацию LogisiticRegression в Sklearn, есть пять методов оптимизации (решатель), и по умолчанию это LibLinear, который использует Coordinate Descent (CD) для сближения.

Помимо количества итераций, оптимизация, тип регуляризации (штраф) и его величина (C) также влияют на производительность алгоритма.

Если вы используете его при настройке набора данных Iris, все эти гиперпараметры могут не принести существенных изменений, но для сложных наборов данных они играют значимую роль.

Для получения дополнительной информации вы можете обратиться к документации Sklearn Logistic Regression .

Раджат Агарвал
источник
3

Вам также следует выполнить поиск по сетке для «альфа» гиперпараметра для SGDClassifier. Это явно упомянуто в документации по sklearn и, по моему опыту, сильно влияет на точность. Второй гиперпараметр, на который вы должны обратить внимание, это «n_iter» - однако я увидел меньший эффект с моими данными.

Диего
источник
1

TL; DR : вы можете указать сетку альфа и n_iter (или max_iter ) и использовать parfit для гипероптимизации в SGDClassifier

Мой коллега, Винай Патлолла, написал отличную запись в блоге о том, как заставить классификатор SGD работать так же, как и логистическую регрессию с использованием parfit .

Parfit - это пакет оптимизации гиперпараметров, который он использовал, чтобы найти подходящую комбинацию параметров, которая служила для оптимизации SGDClassifier для выполнения, а также для логистической регрессии на его примере набора данных за гораздо меньшее время.

Таким образом, два ключевых параметра для SGDClassifier - это альфа и n_iter . Чтобы процитировать Vinay напрямую:

Значение n_iter в sklearn по умолчанию равно None. Мы устанавливаем здесь достаточно большое количество (1000). Альтернативным параметром для n_iter, который был недавно добавлен, является max_iter. Тот же совет должен применяться для max_iter.

Альфа-гиперпараметр служит двойной цели. Это и параметр регуляризации, и начальная скорость обучения по расписанию по умолчанию. Это означает, что помимо регуляризации коэффициентов логистической регрессии выходные данные модели зависят от взаимодействия между альфа-каналом и числом эпох (n_iter), которое выполняет подпрограмма подбора. В частности, когда альфа становится очень маленькой, n_iter должен быть увеличен, чтобы компенсировать медленную скорость обучения. Вот почему безопаснее (но медленнее) указывать достаточно большое n_iter, например, 1000, при поиске в широком диапазоне альфа.

Джейсон Карпентер
источник