Sklearn SGDClassifier部分适合

Dav*_* M. 35 python machine-learning gradient-descent scikit-learn

我正在尝试使用SGD对大型数据集进行分类.由于数据太大而无法放入内存,我想使用partial_fit方法来训练分类器.我选择了适合内存的数据集样本(100,000行)来测试拟合partial_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))
Run Code Online (Sandbox Code Playgroud)

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

在第二种情况下,我必须通过60次数据才能达到相同的准确度.

为什么会出现这种差异(5对60)?或者我做错了什么?

Dav*_* M. 55

我终于找到了答案.您需要在每次迭代之间对训练数据进行混洗,因为在实例化模型时设置shuffle = True将不会在使用partial_fit时对数据进行混洗(它仅适用于拟合).注意:在sklearn.linear_model.SGDClassifier页面上找到此信息会很有帮助.

修订后的守则内容如下:

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))
Run Code Online (Sandbox Code Playgroud)

  • 如果您的数据以与索引兼容的方式存储,例如文件的文件名或数组中的位置的索引,那么您可以将数据索引与数据分开存储,并在每个时期之间对索引进行打乱。 (3认同)
  • 由于数据无法容纳在内存中,因此无法对整个数据集进行改组(如果可以的话,我们可以简单地使用fit)。将批次内的数据混排会产生更好的结果吗? (2认同)