Scikit学习:让SGDClassifier进行预测以及Logistic回归


24

训练Logistic回归的一种方法是使用随机梯度下降,scikit-learn提供了接口。

我想做的是使用scikit-learn的SGDClassifier,并使其得分与此处的Logistic回归相同。但是,我必须错过一些机器学习增强功能,因为我的分数并不相同。

这是我当前的代码。我在SGDClassifier上缺少什么,它会产生与Logistic回归相同的结果?

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

3
一个问题和一个观察:您在重复运行中SGD的准确性如何稳定?两种算法并不等效,并且在给定相同数据的情况下不一定会产生相同的精度。实际上,您可以尝试更改SGD的时期或学习率。除此之外,您可以尝试标准化SGD的功能。
image_doctor 2015年

因此,我没有在重复运行中测试SGD,因为上面使用了10倍交叉验证。对我来说这足够了。
hlin117

您能告诉我这些算法为什么不等效吗?如果我在这里查看SGDClassifier,它会提到“'log'损失使逻辑回归成为概率分类器。” 我相信我的机器学习知识存在差距。
hlin117

如果不对实现进行详细研究,我想我无法具体说明它们为何不等效的原因,但是一个很好的线索是它们不等效的原因是每种方法的结果都存在显着差异。我的猜测是,这与每种方法中使用的估计方法的收敛性有关。
image_doctor 2015年

1
这些算法有所不同,因为逻辑回归使用梯度下降,而随机梯度下降使用随机梯度下降。前者的融合将更加有效,并且将产生更好的结果。但是,随着数据集规模的增加,SGDC应该接近逻辑回归的准确性。GD的参数含义不同于SGD的参数含义,因此应尝试对其进行一些调整。我建议稍微学习(降低)SGD的学习率,以尝试获得更好的收敛性,因为它可能会出现一些波动。
AN6U5

Answers:


23

关于迭代编号的注释很明确。默认设置SGDClassifier n_iter5指您5 * num_rows在体重空间中进行锻炼。典型数据的sklearn经验法则约为100万步。对于您的示例,只需将其设置为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

4

顾名思义,SGDClassifier使用随机梯度下降作为优化算法。

如果您查看Sklearn中LogisiticRegression的实现,则提供了五种优化技术(求解器),默认情况下是'LibLinear',它使用坐标下降(CD)进行收敛。

除了迭代次数之外,优化,正则化的类型(惩罚)及其大小(C)也会影响算法的性能。

如果您在Iris数据集调整上运行它,那么所有这些超参数可能不会带来重大变化,但是对于复杂的数据集,它们确实起着有意义的作用。

有关更多信息,您可以参考Sklearn Logistic回归文档


3

您还应该在网格中搜索SGDClassifier的“ alpha”超参数。sklearn文档中明确提到了这一点,根据我的经验,它对准确性有很大的影响。您应该查看的第二个超参数是“ n_iter”-但是我看到的数据影响较小。


1

TL; DR:您可以指定alphan_iter(或max_iter)的网格,并使用parfitSGDClassifier进行超优化

我的同事Vinay Patlolla在关于如何使用parfit使SGD分类器执行以及Logistic回归方面写了一篇很棒的博客文章。

Parfit是一个超参数优化程序包,他使用该程序包找到合适的参数组合,这些参数用于优化SGDClassifier并在更短的时间内对示例数据集执行Logistic回归。

总之,SGDClassifier的两个关键参数是alphan_iter。直接引用Vinay:

sklearn中的n_iter默认情况下为None。我们在这里将其设置为足够大的数量(1000)。最近添加的n_iter的替代参数是max_iter。同样的建议应适用于max_iter。

alpha超参数有双重用途。它既是正则化参数,又是默认计划下的初始学习率。这意味着,除了对逻辑回归系数进行正则化之外,模型的输出还取决于Alpha与拟合例程执行的历元数(n_iter)之间的交互作用。具体来说,随着alpha变得非常小,必须增加n_iter来补偿学习速度慢的问题。这就是为什么在较大范围的alpha上进行搜索时,将n_iter指定为足够大(例如1000)较为安全(但较慢)的原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.