Scikit-learn: Obteniendo SGDClassifier para predecir, así como una regresión logística

24

Una forma de entrenar una regresión logística es mediante el uso del descenso de gradiente estocástico, que scikit-learn ofrece una interfaz.

Lo que me gustaría hacer es tomar un clasificador SGDC de scikit-learn y hacer que obtenga el mismo puntaje que una regresión logística aquí . Sin embargo, me faltan algunas mejoras de aprendizaje automático, ya que mis puntajes no son equivalentes.

Este es mi código actual. ¿Qué me falta en el SGDClassifier para que produzca los mismos resultados que una regresión logística?

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)

Mi salida:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
fuente
3
Una pregunta y una observación: ¿qué tan estable es su precisión de SGD en ejecuciones repetidas? los dos algoritmos no son equivalentes y no necesariamente producirán la misma precisión dados los mismos datos. Prácticamente podría intentar cambiar las épocas y / o la tasa de aprendizaje para SGD. Más allá de eso, podría intentar normalizar las funciones para SGD.
image_doctor
Entonces, no probé el SGD en ejecuciones repetidas porque lo anterior usa validación cruzada 10 veces; Para mí esto fue suficiente.
hlin117
¿Me puede explicar por qué estos algoritmos no son equivalentes? Si miro el SGDClassifier aquí, menciona "La pérdida 'log' da regresión logística, un clasificador probabilístico". Creo que hay una brecha en mi conocimiento de aprendizaje automático.
hlin117
Sin un estudio detallado de las implementaciones, no creo que pueda ser específico acerca de por qué no son equivalentes, pero una buena pista de que no son equivalentes es que los resultados para cada método son significativamente diferentes. Supongo que tiene que ver con las propiedades de convergencia de los métodos de estimación utilizados en cada uno.
image_doctor
1
Estos algoritmos son diferentes porque la regresión logística usa el descenso de gradiente, mientras que el descenso de gradiente estocástico usa el descenso de gradiente estocástico. La convergencia de la primera será más eficiente y dará mejores resultados. Sin embargo, a medida que aumenta el tamaño del conjunto de datos, SGDC debe acercarse a la precisión de la regresión logística. Los parámetros para GD significan cosas diferentes a los parámetros para SGD, por lo que debe intentar ajustarlos ligeramente. Sugeriría jugar con (disminuyendo) las tasas de aprendizaje de SGD un poco para tratar de obtener una mejor convergencia, ya que puede estar dando vueltas un poco.
AN6U5

Respuestas:

23

Los comentarios sobre el número de iteración son acertados. El valor por defecto SGDClassifier n_iteres 5lo que significa que 5 * num_rowslos pasos en el espacio de peso. La regla general de sklearn es ~ 1 millón de pasos para datos típicos. Para su ejemplo, simplemente configúrelo en 1000 y podría alcanzar la tolerancia primero. Su precisión es menor SGDClassifierporque está llegando al límite de iteración antes de la tolerancia, por lo que está "deteniéndose antes"

Modificando su código rápido y sucio me sale:

# 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
fuente
4

SGDClassifier, como su nombre lo indica, utiliza el descenso de gradiente estocástico como algoritmo de optimización.

Si observa la implementación de LogisiticRegression en Sklearn, se proporcionan cinco técnicas de optimización (solucionador) y, de forma predeterminada, es 'LibLinear' el que utiliza el Descenso de coordenadas (CD) para converger.

Además del número de iteraciones, la optimización, el tipo de regularización (penalización) y su magnitud (C) también afectan el rendimiento del algoritmo.

Si lo está ejecutando en el ajuste del conjunto de datos Iris, es posible que todos estos hiperparámetros no traigan cambios significativos, pero para un conjunto de datos complejo juegan un papel significativo.

Para obtener más información, puede consultar la documentación de regresión logística de Sklearn .

Rajat Agarwal
fuente
3

También debe hacer una búsqueda en la cuadrícula del hiperparámetro "alfa" para el SGDClassifier. Se menciona explícitamente en la documentación de sklearn y desde mi experiencia tiene un gran impacto en la precisión. El segundo hiperparámetro que debe mirar es "n_iter"; sin embargo, vi un efecto menor con mis datos.

Diego
fuente
1

TL; DR : podría especificar una cuadrícula de alfa y n_iter (o max_iter ) y usar parfit para hiper-optimización en SGDClassifier

Mi colega, Vinay Patlolla, escribió una excelente publicación de blog sobre Cómo hacer que SGD Classifier funcione tan bien como la Regresión logística usando parfit .

Parfit es un paquete de optimización de hiperparámetros que utilizó para encontrar la combinación adecuada de parámetros que sirvió para optimizar SGDClassifier para realizar, así como la regresión logística en su conjunto de datos de ejemplo en mucho menos tiempo.

En resumen, los dos parámetros clave para SGDClassifier son alfa y n_iter . Para citar a Vinay directamente:

n_iter en sklearn es None por defecto. Lo estamos estableciendo aquí en una cantidad suficientemente grande (1000). Un parámetro alternativo a n_iter, que se ha agregado recientemente, es max_iter. El mismo consejo debería aplicarse para max_iter.

El hiperparámetro alfa tiene un doble propósito. Es tanto un parámetro de regularización como la tasa de aprendizaje inicial según el cronograma predeterminado. Esto significa que, además de regularizar los coeficientes de regresión logística, la salida del modelo depende de una interacción entre alfa y el número de épocas (n_iter) que realiza la rutina de ajuste. Específicamente, a medida que alfa se vuelve muy pequeño, n_iter debe aumentarse para compensar la lenta tasa de aprendizaje. Es por eso que es más seguro (pero más lento) especificar n_iter lo suficientemente grande, por ejemplo 1000, cuando se busca en un amplio rango de alfa.

Jason Carpenter
fuente