我使用的学习数据集是一张灰度图像,通过flatten
处理,使每个像素代表一个独立的样本。训练完多层感知机
(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
增加隐藏层的neurons数量,但没有看到任何改善。即使我将隐藏层的激活函数从默认的relu
更改为logistic
(使用activation
参数),也没有改善。
以下是我正在处理的图像(全部是512x512
的图像),并提供了一个链接到Google Fusion
表格,其中它们被从numpy
数组导出为CSV
格式(以保持图像为浮点数而不是整数):
训练数据:
白色区域被遮盖: Google Fusion Table (training_data)
Class0:
Class1:
训练目标:
Google Fusion Table (training_target)
测试数据:
Google Fusion Table (test_data)
预测(使用partial_fit):
Google Fusion Table (predictions)
回答:
长话短说:对数据进行多次循环,使用小的学习率和不同的观察顺序,你的partial_fit
性能会像fit
一样好。
使用partial_fit
处理多个数据块的问题在于,当模型完成最后一个数据块时,它可能会忘记第一个数据块。这意味着,由于早期批次引起的模型权重变化可能会被后期批次完全覆盖。
然而,这个问题可以通过以下组合轻松解决:
- 低学习率。如果模型学习速度慢,那么它遗忘的速度也会慢,早期批次不会被后期批次覆盖。
MLPClassifier
的默认学习率是0.001,但你可以将其乘以3或10倍,看看会发生什么。 - 多次循环。如果学习率慢,那么对所有训练样本进行一次循环可能不足以使模型收敛。因此,你可以对训练数据进行多次循环,结果可能会显著改善。直观的策略是将循环次数增加与学习率减少的相同倍数。
- 打乱观察顺序。如果你的数据中狗的图像在猫的图像之前,那么最终模型会更多地记住猫而不是狗。然而,如果你在批处理生成器中以某种方式打乱观察顺序,就不会有这个问题。最安全的策略是在每个循环前重新打乱数据。