Sklearn SGDClassifier 部分拟合

Posted

技术标签:

【中文标题】Sklearn SGDClassifier 部分拟合【英文标题】:Sklearn SGDClassifier partial fit 【发布时间】:2014-08-28 08:02:03 【问题描述】:

我正在尝试使用 SGD 对大型数据集进行分类。由于数据太大而无法放入内存,我想使用 partial_fit 方法来训练分类器。我选择了一个适合内存的数据集样本(100,000 行)来测试 fitpartial_fit

from sklearn.linear_model import SGDClassifier

def batches(l, n):
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

clf1 = SGDClassifier(shuffle=True, loss='log')
clf1.fit(X, Y)

clf2 = SGDClassifier(shuffle=True, loss='log')
n_iter = 60
for n in range(n_iter):
    for batch in batches(range(len(X)), 10000):
        clf2.partial_fit(X[batch[0]:batch[-1]+1], Y[batch[0]:batch[-1]+1], classes=numpy.unique(Y))

然后我使用相同的测试集测试两个分类器。在第一种情况下,我得到 100% 的准确率。据我了解,SGD 默认通过训练数据 5 次(n_iter = 5)。

在第二种情况下,我必须将数据传递 60 次才能达到相同的准确度。

为什么会有这种差异(5 对 60)?还是我做错了什么?

【问题讨论】:

给SGD构造函数verbose=1,这可能会给你一个提示。 第一个案例(拟合)以“-- Epoch 5 Norm: 29.25, NNZs: 300, Bias: -1.674706, T: 459595, Avg. loss: 0.076786”结尾。 10 次通过后的第二种情况 (partial_fit) 以“-- Epoch 1 Norm: 22.99, NNZs: 300, Bias: -1.999685, T: 1918, Avg. loss: 0.089302”结束。我应该寻找什么?谢谢 平均损失。检查它是否在批处理情况下下降得更快。 在第一种情况下,它在 15 次传递中从 0.087027 下降到 0.076786(5 个时期;3 次传递/时期)。在第二种情况下,很难说,因为在我看来,平均损失数字与每个批次有关;因此数字变化很大(例如,最后 10 个数字是 0.000748;0.258055;0.001160;0.267540;0.036631;0.291704;0.197599;0.012074;0.109227;0.089302)。 【参考方案1】:

我终于找到了答案。您需要在每次迭代之间打乱训练数据,因为在实例化模型时设置 shuffle=True 不会在使用 partial_fit 时打乱数据(它只适用于fit)。注意:在sklearn.linear_model.SGDClassifier page 上找到此信息会很有帮助。

修改后的代码如下:

from sklearn.linear_model import SGDClassifier
import random
clf2 = SGDClassifier(loss='log') # shuffle=True is useless here
shuffledRange = range(len(X))
n_iter = 5
for n in range(n_iter):
    random.shuffle(shuffledRange)
    shuffledX = [X[i] for i in shuffledRange]
    shuffledY = [Y[i] for i in shuffledRange]
    for batch in batches(range(len(shuffledX)), 10000):
        clf2.partial_fit(shuffledX[batch[0]:batch[-1]+1], shuffledY[batch[0]:batch[-1]+1], classes=numpy.unique(Y))

【讨论】:

洗牌整个数据集是不可能的,因为数据不适合内存(如果可以,我们可以简单地使用 fit)。改组批次内的数据会产生更好的结果吗? 如果您的数据以与索引兼容的方式存储,例如文件名到文件,或索引到数组中的位置,那么您可以将数据索引与数据分开存储,并打乱每个时期之间的索引。 在当前版本的用户指南scikit-learn.org/stable/modules/sgd.htmlshuffle after each iteration中提到了它。我记得 Andrew Ng youtube 讲座中也提到了洗牌。

以上是关于Sklearn SGDClassifier 部分拟合的主要内容,如果未能解决你的问题,请参考以下文章

sklearn中的SGDClassifier

sklearn 使用SGDClassifier 使用 kerasMNIST数据集 进行图片二分类

sklearn SGDClassifier,当没有匹配时产生标签?

sklearn SGDClassifier 模型阈值与模型分数有何关系?

使用自定义转换器子类对 sklearn 管道进行评分时出现 AttributeError,但在拟合时却没有

Scikit-learn——LogisticRegression与SGDClassifier