Scikit-learn: Fazendo o SGDClassifier prever e também uma regressão logística

24

Uma maneira de treinar uma regressão logística é usar a descida estocástica do gradiente, para a qual o scikit-learn oferece uma interface.

O que eu gostaria de fazer é pegar o SGDClassifier de um scikit -learn e obter a mesma pontuação que uma regressão logística aqui . No entanto, devo estar perdendo algumas melhorias no aprendizado de máquina, pois minhas pontuações não são equivalentes.

Este é o meu código atual. O que estou faltando no SGDClassifier que produziria os mesmos resultados que uma regressão 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)

Minha saída:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
fonte
3
Uma pergunta e uma observação: quão estável é a sua precisão do SGD em execuções repetidas? os dois algoritmos não são equivalentes e não produzirão necessariamente a mesma precisão, dados os mesmos dados. Praticamente você pode tentar alterar as épocas e / ou a taxa de aprendizado do SGD. Além disso, você pode tentar normalizar os recursos do SGD.
image_doctor
Portanto, não testei o SGD em execuções repetidas porque o acima usa validação cruzada de 10 vezes; para mim isso bastava.
precisa saber é o seguinte
Você pode me explicar como esses algoritmos não são equivalentes? Se eu olhar aqui o SGDClassifier, ele menciona "A perda 'log' fornece regressão logística, um classificador probabilístico". Acredito que haja uma lacuna no meu conhecimento de aprendizado de máquina.
precisa saber é o seguinte
Sem um estudo detalhado das implementações, acho que não posso ser específico sobre por que elas não são equivalentes, mas uma boa pista de que não são equivalentes é que os resultados de cada método são significativamente diferentes. Meu palpite seria que isso tem a ver com as propriedades de convergência dos métodos de estimativa usados ​​em cada um.
Image_doctor 5/08/2015
11
Esses algoritmos são diferentes porque a regressão logística usa descida de gradiente, enquanto a descida de gradiente estocástico usa descida de gradiente estocástico. A convergência do primeiro será mais eficiente e trará melhores resultados. No entanto, à medida que o tamanho do conjunto de dados aumenta, o SGDC deve abordar a precisão da regressão logística. Os parâmetros para GD significam coisas diferentes dos parâmetros para SGD, portanto, tente ajustá-los um pouco. Eu sugeriria brincar um pouco com (diminuindo) as taxas de aprendizado do SGD para tentar obter uma melhor convergência, pois pode estar se debatendo um pouco.
AN6U5 5/05

Respostas:

23

Os comentários sobre o número da iteração estão no local. O padrão SGDClassifier n_iteré 5o que significa que você executa 5 * num_rowsetapas no espaço de peso. A regra prática do sklearn é de ~ 1 milhão de etapas para dados típicos. Para o seu exemplo, basta configurá-lo para 1000 e ele pode alcançar a tolerância primeiro. Sua precisão é menor SGDClassifierporque está atingindo o limite de iteração antes da tolerância, para que você esteja "parando cedo"

Modificando seu código rápido e sujo, recebo:

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

O SGDClassifier, como o nome sugere, usa a descida do gradiente estocástico como seu algoritmo de otimização.

Se você observar a implementação do LogisiticRegression no Sklearn, existem cinco técnicas de otimização (solver) fornecidas e, por padrão, é 'LibLinear' que usa a Descentração das coordenadas (CD) para convergir.

Além do número de iterações, a otimização, o tipo de regularização (penalidade) e sua magnitude (C) também afetam o desempenho do algoritmo.

Se você estiver executando no ajuste do conjunto de dados Iris, todos esses hiperparâmetros podem não trazer mudanças significativas, mas para conjuntos de dados complexos, eles desempenham um papel significativo.

Para obter mais informações, consulte a documentação de regressão logística do Sklearn .

Rajat Agarwal
fonte
3

Você também deve fazer uma pesquisa em grade pelo hiperparâmetro "alfa" para o SGDClassifier. Ele é mencionado explicitamente na documentação do sklearn e, pela minha experiência, tem um grande impacto na precisão. O segundo hiperparâmetro que você deve observar é "n_iter" - no entanto, vi um efeito menor nos meus dados.

Diego
fonte
1

TL; DR : você pode especificar uma grade de alfa e n_iter (ou max_iter ) e usar parfit para hiper otimização no SGDClassifier

Meu colega, Vinay Patlolla, escreveu um excelente post sobre como fazer com que o SGD Classifier funcione bem como a regressão logística usando parfit .

Parfit é um pacote de otimização de hiperparâmetros que ele utilizou para encontrar a combinação apropriada de parâmetros que serviu para otimizar o desempenho do SGDClassifier, bem como a regressão logística em seu conjunto de dados de exemplo em muito menos tempo.

Em resumo, os dois parâmetros principais do SGDClassifier são alfa e n_iter . Para citar Vinay diretamente:

n_iter no sklearn é Nenhum por padrão. Estamos definindo aqui uma quantidade suficientemente grande (1000). Um parâmetro alternativo ao n_iter, que foi adicionado recentemente, é max_iter. O mesmo conselho deve ser aplicado para max_iter.

O hiperparâmetro alfa serve para dois propósitos. É um parâmetro de regularização e a taxa de aprendizado inicial no planejamento padrão. Isso significa que, além de regularizar os coeficientes de regressão logística, a saída do modelo depende de uma interação entre alfa e o número de épocas (n_iter) que a rotina de ajuste executa. Especificamente, como alfa se torna muito pequeno, n_iter deve ser aumentado para compensar a lenta taxa de aprendizado. É por isso que é mais seguro (mas mais lento) especificar n_iter suficientemente grande, por exemplo, 1000, ao pesquisar em uma ampla variedade de alfas.

Jason Carpenter
fonte