Scikit-learn: faire prédire SGDClassifier ainsi qu'une régression logistique

24

Un moyen de former une régression logistique consiste à utiliser la descente de gradient stochastique, avec laquelle scikit-learn offre une interface.

Ce que je voudrais faire est de prendre une scikit-learn de SGDClassifier et l' ont marqué le même comme la régression logistique ici . Cependant, je dois manquer certaines améliorations de l'apprentissage automatique, car mes scores ne sont pas équivalents.

Ceci est mon code actuel. Que manque-t-il sur le SGDClassifier qui lui permettrait de produire les mêmes résultats qu'une régression logistique?

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)

Ma sortie:

Accuracy score of LogisticRegression: 0.946666666667
Accuracy score of SGDClassifier: 0.76
hlin117
la source
3
Une question et une observation: dans quelle mesure votre précision de SGD est-elle stable sur des cycles répétés? les deux algorithmes ne sont pas équivalents et ne produiront pas nécessairement la même précision compte tenu des mêmes données. Pratiquement, vous pouvez essayer de changer les époques et / ou le taux d'apprentissage pour SGD. Au-delà, vous pouvez essayer de normaliser les fonctionnalités de SGD.
image_doctor
Donc, je n'ai pas testé le SGD sur des cycles répétés parce que ce qui précède utilise une validation croisée 10 fois; cela me suffisait.
hlin117
Pouvez-vous m'expliquer pourquoi ces algorithmes ne sont pas équivalents? Si je regarde le SGDClassifier ici, il mentionne "La perte" log "donne une régression logistique, un classificateur probabiliste." Je pense qu'il y a une lacune dans mes connaissances en apprentissage automatique.
hlin117
Sans une étude détaillée des implémentations, je ne pense pas pouvoir expliquer pourquoi elles ne sont pas équivalentes, mais un bon indice qu'elles ne sont pas équivalentes est que les résultats pour chaque méthode sont significativement différents. Je suppose que cela a à voir avec les propriétés de convergence des méthodes d'estimation utilisées dans chacune.
image_doctor
1
Ces algorithmes sont différents car la régression logistique utilise une descente en gradient alors que la descente en gradient stochastique utilise une descente en gradient stochastique. La convergence des premiers sera plus efficace et donnera de meilleurs résultats. Cependant, à mesure que la taille de l'ensemble de données augmente, SGDC devrait approcher la précision de la régression logistique. Les paramètres de GD signifient des choses différentes de celles des paramètres de SGD, vous devriez donc essayer de les ajuster légèrement. Je suggérerais de jouer un peu avec les taux d'apprentissage (décroissants) de SGD pour essayer d'obtenir une meilleure convergence car elle peut être un peu débordante.
AN6U5

Réponses:

23

Les commentaires sur le numéro d'itération sont parfaits. La valeur par défaut SGDClassifier n_iterest qui 5signifie que vous faites 5 * num_rowspas dans l' espace de poids. La règle empirique sklearn est d'environ 1 million de pas pour les données typiques. Pour votre exemple, il suffit de le définir sur 1000 et il pourrait atteindre la tolérance en premier. Votre précision est plus faible SGDClassifiercar elle atteint la limite d'itération avant la tolérance, vous êtes donc en "arrêt anticipé"

Modifier votre code rapidement et sale j'obtiens:

# 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
la source
4

SGDClassifier, comme son nom l'indique, utilise la descente du gradient stochastique comme algorithme d'optimisation.

Si vous regardez l'implémentation de LogisiticRegression dans Sklearn, cinq techniques d'optimisation (solveur) sont fournies et par défaut, c'est «LibLinear» qui utilise la descente de coordonnées (CD) pour converger.

Outre le nombre d'itérations, l'optimisation, le type de régularisation (pénalité) et sa magnitude (C) affectent également les performances de l'algorithme.

Si vous l'exécutez sur le réglage de l'ensemble de données Iris, tous ces hyper-paramètres peuvent ne pas apporter de changement significatif, mais pour un ensemble de données complexe, ils jouent un rôle significatif.

Pour en savoir plus, vous pouvez consulter la documentation de régression logistique Sklearn .

Rajat Agarwal
la source
3

Vous devez également effectuer une recherche dans la grille pour l'hyperparamètre "alpha" du SGDClassifier. Il est explicitement mentionné dans la documentation de sklearn et d'après mon expérience, il a un grand impact sur la précision. Le deuxième hyperparamètre que vous devriez regarder est "n_iter" - mais j'ai vu un effet moindre avec mes données.

Diego
la source
1

TL; DR : Vous pouvez spécifier une grille d' alpha et n_iter (ou max_iter ) et utiliser parfit pour l'hyper-optimisation sur SGDClassifier

Mon collègue, Vinay Patlolla, a écrit un excellent article de blog sur Comment faire fonctionner SGD Classifier ainsi que sur la régression logistique en utilisant parfit .

Parfit est un package d'optimisation d'hyper-paramètre qu'il a utilisé pour trouver la combinaison appropriée de paramètres qui a servi à optimiser SGDClassifier pour effectuer ainsi que la régression logistique sur son exemple de jeu de données en beaucoup moins de temps.

En résumé, les deux paramètres clés de SGDClassifier sont alpha et n_iter . Pour citer directement Vinay:

n_iter dans sklearn est None par défaut. Nous le fixons ici à un montant suffisamment élevé (1000). Un paramètre alternatif à n_iter, qui a été récemment ajouté, est max_iter. Le même conseil devrait s'appliquer pour max_iter.

L'hyper-paramètre alpha a un double objectif. Il s'agit à la fois d'un paramètre de régularisation et du taux d'apprentissage initial dans le cadre du calendrier par défaut. Cela signifie qu'en plus de régulariser les coefficients de régression logistique, la sortie du modèle dépend d'une interaction entre alpha et le nombre d'époques (n_iter) que la routine d'ajustement effectue. Plus précisément, comme alpha devient très petit, n_iter doit être augmenté pour compenser le rythme d'apprentissage lent. C'est pourquoi il est plus sûr (mais plus lent) de spécifier n_iter suffisamment grand, par exemple 1000, lors d'une recherche sur une large gamme d'alphas.

Jason Carpenter
la source