Scikit-learn:让 SGDClassifier 进行预测以及 Logistic 回归

数据挖掘 Python 逻辑回归 scikit-学习 梯度下降
2021-09-20 22:21:48

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

我想做的是采用 scikit-learn 的SGDClassifier并让它的得分与这里的 Logistic Regression 相同。但是,我一定错过了一些机器学习增强功能,因为我的分数不相等。

这是我当前的代码。我在 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
4个回答

关于迭代次数的评论是正确的。默认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

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

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

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

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

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

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

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

我的同事 Vinay Patlolla 写了一篇关于如何使用 parfit 使 SGD 分类器表现和 Logistic 回归一样出色的博客文章。

Parfit是一个超参数优化包,他用它来找到合适的参数组合,这些参数组合可以在更短的时间内优化 SGDClassifier 以在他的示例数据集上执行以及 Logistic 回归。

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

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

alpha 超参数有双重用途。它既是一个正则化参数,也是默认调度下的初始学习率。这意味着,除了正则化 Logistic 回归系数之外,模型的输出还取决于 alpha 和拟合例程执行的时期数 (n_iter) 之间的交互作用。具体来说,随着 alpha 变得非常小,必须增加 n_iter 以补偿缓慢的学习率。这就是为什么在搜索大范围的 alpha 时指定足够大的 n_iter(例如 1000)更安全(但更慢)的原因。