在监督分类中,使用 partial_fit() 的 MLP 比使用 fit() 表现更差

Posted

技术标签:

【中文标题】在监督分类中,使用 partial_fit() 的 MLP 比使用 fit() 表现更差【英文标题】:MLP with partial_fit() performing worse than with fit() in a supervised classification 【发布时间】:2018-05-19 19:27:15 【问题描述】:

我使用的学习数据集是一个灰度图像,flatten 让每个像素代表一个单独的样本。第二张图像将在前一张上训练Multilayer perceptron (MLP) 分类器后逐像素分类。

我遇到的问题是,MLP 在一次接收所有训练数据集 (fit()) 时比通过块训练时 (partial_fit()) 表现更好。在这两种情况下,我都保留Scikit-learn 提供的默认参数。

我问这个问题是因为当训练数据集大约有数百万个样本时,我将不得不使用partial_fit() 来分块训练MLP

def batcherator(data, target, chunksize):
    for i in range(0, len(data), chunksize):
        yield data[i:i+chunksize], target[i:i+chunksize]

def classify():
    classifier = MLPClassifier(verbose=True)

    # classifier.fit(training_data, training_target)

    gen = batcherator(training.data, training.target, 1000)
    for chunk_data, chunk_target in gen:
        classifier.partial_fit(chunk_data, chunk_target,
                               classes=np.array([0, 1]))

    predictions = classifier.predict(test_data)

我的问题是我应该在 MLP 分类器中调整哪些参数,以使其在通过数据块训练时更容易接受?

我尝试使用hidden_layer_sizes 增加隐藏层中的神经元数量,但没有看到任何改进。如果我使用activation 参数将隐藏层的激活函数从默认的relu 更改为logistic,也没有任何改进。

下面是我正在处理的图像(它们都是512x512 图像),带有指向Google Fusion 表的链接,它们从numpy 数组导出为CSV(离开图像作为浮点数而不是整数):

训练数据:

白色区域被屏蔽:Google Fusion Table (training_data)

类0:

第一类:

培训目标:

Google Fusion Table (training_target)

测试数据:

Google Fusion Table (test_data)

预测(使用 partial_fit):

Google Fusion Table (predictions)

【问题讨论】:

您正在比较一个线性分类器(受参数调整影响较小)和一个非线性分类器(受影响较大)与某些未知数据集上的默认设置,而不显示预处理和 co,询问为什么一个占主导地位另一个没有显示有关这种统治的一些指标。此外:由于一个是线性的,另一个是非线性的,您试图通过使其更加非线性来改善非线性,结果更糟。其中大部分没有多大意义,并且由于它不可重现,因此很难提供帮助。除了可能会说:移除隐藏层/增加正则化。 另外:SGD 允许执行 5 个 epoch。 MLP 做 1(有相当大的小批量)。 @sascha 我刚刚更新了问题,因为我的问题发生了一些变化。如果问题的任何方面需要更多详细信息,请告诉我。 【参考方案1】:

TL,DR:以较小的学习率和不同的观察顺序对您的数据进行多次循环,您的partial_fit 的性能将与fit 一样好。

partial_fit 有很多块的问题是,当你的模型完成最后一个块时,它可能会忘记第一个块。这意味着,由于早期批次而导致的模型权重变化将被后期批次完全覆盖。

然而,这个问题可以通过以下组合很容易地解决:

    学习率低。如果模型学习慢,那么它也会慢慢忘记,早期批次不会被后期批次覆盖。 MLPClassifier 中的默认学习率是 0.001,但您可以将其更改为 3 或 10 的倍数,看看会发生什么。 多个时期。如果学习率很慢,那么对所有训练样本进行一次循环可能不足以使模型收敛。因此,您可以对训练数据进行多次循环,结果很可能会有所改善。直观的策略是通过降低学习率的相同因素来增加循环数。 洗牌观察。如果在你的数据中狗的图像先于猫的图像,那么最终模型会记住更多关于猫的信息而不是关于狗的信息。但是,如果您在批处理生成器中以某种方式打乱您的观察,这将不是问题。最安全的策略是在每个 epoch 之前重新洗牌。

【讨论】:

您对shuffling 的必要性是正确的。当我添加它时,partial_fit() 得到的结果与fit() 得到的结果相似。另一个稍微提高分类准确性的因素是数据集的balancing(因为我有一个训练类,与另一个相比非常大)。不过,我还没有尝试调整学习率和时期。 @Hakim 我注意到partial_fit 默认运行 1 个 epoch。那么,您运行它的时间是否比这更多?如果是,如何? for循环中多次运行【参考方案2】:

您可以使用sklearn提供的adaptive学习率功能,而不是手动提供速率。

model = SGDClassifier(loss="hinge", penalty="l2", alpha=0.0001, max_iter=3000, tol=None, shuffle=True, verbose=0, learning_rate='adaptive', eta0=0.01, early_stopping=False)

这在 [scikit docs] 中被描述为:

‘adaptive’:eta = eta0,只要训练不断减少。如果 early_stopping 为 True,则每次 n_iter_no_change 连续 epoch 未能将训练损失减少 tol 或未能将验证分数增加 tol 时,当前学习率除以 5。

【讨论】:

以上是关于在监督分类中,使用 partial_fit() 的 MLP 比使用 fit() 表现更差的主要内容,如果未能解决你的问题,请参考以下文章

GridSearchCV/RandomizedSearchCV 与 sklearn 中的 partial_fit

在 RandomForestRegressor 中使用 Partial_fit() 方法

Sklearn SGDClassifier 部分拟合

sklearn SGDClassifier fit() 与 partial_fit()

在监督学习中提取分类函数

监督学习分类