Sklearn SGDClassifier 部分拟合
我正在尝试使用随机梯度下降(SGD)来对一个很大的数据集进行分类。因为数据量太大,无法一次性放进内存,所以我想用partial_fit这个方法来训练分类器。我选取了一个适合放进内存的样本(10万行)来测试fit和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))
然后,我用相同的测试集来测试这两个分类器。在第一种情况下,我得到了100%的准确率。根据我的理解,SGD默认会对训练数据进行5次遍历(n_iter = 5)。
而在第二种情况下,我需要对数据进行60次遍历才能达到相同的准确率。
为什么会有这样的差别(5次和60次)?或者我是不是做错了什么?
1 个回答
78
我终于找到了答案。你需要在每次迭代之间打乱训练数据,因为在创建模型时设置shuffle=True并不会在使用partial_fit时打乱数据(这个设置只对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))