【问题标题】:MNIST and SGDClassifier classiferMNIST 和 SGDClassifier 分类器
【发布时间】:2013-09-24 14:08:48
【问题描述】:

我正在尝试在线使用(out-of-core) MNIST 问题的学习算法使用SGDClassifier 但似乎准确性并不总是在提高。

在这种情况下我该怎么办?以最准确的方式保存分类器? SGDClassifier 是否收敛到某个最优解?

这是我的代码:

import numpy as np
from sklearn.linear_model.stochastic_gradient import SGDClassifier
from sklearn.datasets import fetch_mldata
from sklearn.utils import shuffle

#use all digits
mnist = fetch_mldata("MNIST original")
X_train, y_train = mnist.data[:70000] / 255., mnist.target[:70000]

X_train, y_train = shuffle(X_train, y_train)
X_test, y_test = X_train[60000:70000], y_train[60000:70000]  

step =1000
batches= np.arange(0,60000,step)
all_classes = np.array([0,1,2,3,4,5,6,7,8,9])
classifier = SGDClassifier()
for curr in batches:
 X_curr, y_curr = X_train[curr:curr+step], y_train[curr:curr+step]
 classifier.partial_fit(X_curr, y_curr, classes=all_classes)
 score= classifier.score(X_test, y_test)
 print score

print "all done"

我在 MNIST 上测试了 linearSVM 与 SGD,使用 10k 样本进行训练和 10k 样本进行测试,得到 0.883 13,95 和 0.85 1,32,因此 SGD 更快但准确度较低。

#test linearSVM vs SGD
t0 = time.time()
clf = LinearSVC()
clf.fit(X_train, y_train)
score= clf.score(X_test, y_test)
print score
print (time.time()-t0)

t1 = time.time()
clf = SGDClassifier()
clf.fit(X_train, y_train)
score= clf.score(X_test, y_test)
print score
print (time.time()-t1)

我也在这里找到了一些信息 https://stats.stackexchange.com/a/14936/16843

更新: 超过 1 次(10 次)通过数据达到 90.8 % 的最佳准确度。因此它可以成为解决方案。 SGD 的另一个特点是数据在传递给分类器之前必须经过洗牌。

【问题讨论】:

  • 能否请您编辑您的问题以添加脚本的输出,以便手边没有安装 sklearn 的人仍然可以关注该问题?您观察到了什么以及您期望会发生什么?
  • Score 的输出在开始时类似于 0.52 0.6 0.75 0.74 0.84 0.80 0.82,但随后会在 0.8+-some_value 上下波动,我希望它会一直增加到某个 max_score 值,然后停止。
  • 您可以在此处找到已解码的 MNIST 数据集版本:mnist-decoded.000webhostapp.com

标签: python machine-learning scikit-learn mnist


【解决方案1】:

第一句话:您正在使用 SGDClassifier 和默认参数:它们可能不是该数据集的最佳值:也可以尝试其他值(特别是对于 alpha,正则化参数)。

现在回答您的问题,线性模型不太可能在像 MNIST 这样的数字图像分类任务这样的数据集上做得很好。您可能想尝试线性模型,例如:

  • SVC(kernel='rbf')(但不可扩展,请尝试训练集的一小部分)而不是增量/核外
  • ExtraTreesClassifier(n_estimator=100) 或更多,但也不是核心。子估计器的数量越多,训练所需的时间就越长。

您还可以尝试SVC(kernel='rbf')Nystroem approximation,方法是使用适合一小部分数据(例如10000 个样本)的Nystroem(n_components=1000, gamma=0.05) 转换数据集,然后将整个转换后的训练集传递给线性模型,例如如SGDClassifier:它需要对数据集进行两次传递。

github 上还有一个 pull request for 1 hidden layer perceptron,它的计算速度应该比 ExtraTreesClassifier 更快,并且在 MNIST 上接近 98% 的测试集准确度(并且还提供了一个用于核外学习的 partial_fit API)。

编辑SGDClassifier 分数的估计值的波动是预期的:SGD 代表随机梯度下降,这意味着一次只考虑一个示例:分类错误的样本可能会导致以对其他样本有害的方式更新模型的权重,您需要对数据进行多次传递以使学习率降低到足以获得对验证准确度的更平滑估计。您可以在 for 循环中使用 itertools.repeat 对数据集执行多次(例如 10 次)。

【讨论】:

  • 感谢您的回答,但我需要在线(核外)算法,我只是在 MNIST 上尝试。 SGDClassifier 是否收敛到某个最优解?
  • 是的,但前提是您有足够的样本并且您的任务是线性可分的。
  • partial_fit 是否仅用于大数据?(当我们无法将所有样本都放入内存时)。当我们有几乎无限的数据时是否会出现这种情况,但是当我们使用 partial_fit 提供数据时,我们得到了一些准确度(例如 80%),但由于分类器的波动我们不知道何时停止(总是更好处理所有可用数据?)那么与其他线性分类器相比有什么优势(它更快或更精确)?(也许对于大数据,我们可以在小批量数据上训练 N 个线性分类器并在此之上进行线性回归?)
  • 我在 MNIST 上测试了 linearSVM 与 SGD,得到了 0.883 13,95 和 0.85 1,32 所以 SGD 更快但不太准确。
  • 您是否对 C(对于 LinearSVM)以及 alpha 和 n_iter(对于 SGDClassifier)进行了网格搜索?还有其他超参数可以针对它们中的每一个进行调整,但它们的影响可能不如上述参数重要。
猜你喜欢
  • 2020-10-02
  • 2016-08-10
  • 2017-03-14
  • 2018-07-28
  • 2018-05-29
  • 1970-01-01
  • 2020-07-05
  • 2020-11-13
  • 1970-01-01
相关资源
最近更新 更多