【问题标题】:Is it possible to fit() a scikit-learn model in a loop or with an iterator是否可以在循环或迭代器中拟合()一个 scikit-learn 模型
【发布时间】:2022-01-11 09:52:42
【问题描述】:

通常人们使用scikit-learn这样训练模型:

from sklearn.ensemble import GradientBoostingClassifier as gbc
clf = gbc()
clf.fit(X_train, y_train)
predicted = clf.predict(X_test)

只要用户的内存足够大以容纳整个数据集,它就可以正常工作。我的困境正是这个——数据集对我的记忆来说太大了。我目前的解决方案是扩大我机器的虚拟内存,而我已经因为拥有太多虚拟内存而使系统变得非常慢 - 所以我开始考虑是否可以在fit() 方法中输入样本像这样的批次(答案是否定的,请继续阅读并停止提醒我答案是否定的):

clf = gbc()
for i in range(X_train.shape[0]):
    clf.fit(X_train[i], y_train[i])

这样我可以仅在需要时从硬盘读取训练集。我读了sklearn's manual,在我看来它不支持这个:

Calling fit() more than once will overwrite what was learned by any previous fit()

那么,这可能吗?

【问题讨论】:

  • 我认为您需要为循环的每次迭代创建一个单独的 LinearRegression 类实例。
  • @njp emmm?我的理解是,假设我创建了多个 LinearRegression 实例,我将只使用一个样本来训练几个单独的模型......这不是我想要的......
  • 您的建议不起作用。它只是在每次迭代时拟合一个新模型(具有不同的系数)
  • 您是否在将完整数据集加载到内存时遇到问题,或者在拟合期间卡住了?
  • @StupidWolf 你是对的——正如官方手册和我的报价所示,我提出的代码行不通。所以问题是我是否有可能让它发挥作用。

标签: python scikit-learn


【解决方案1】:

这在 scikit-learn 中不起作用,如评论部分和文档中所述。但是,您可以使用river(这是一个用于在线/流式机器学习的 python 包)。这个包应该很适合你有问题的。

以下是使用河流训练线性回归的示例。

from river import datasets
from river import linear_model
from river import metrics
from river import preprocessing

dataset = datasets.TrumpApproval()

model = (
    preprocessing.StandardScaler() |
    linear_model.LinearRegression(intercept_lr=.1)
)
metric = metrics.MAE()

for x, y, in dataset:
    y_pred = model.predict_one(x)

    # Update the running metric with the prediction and ground truth value
    metric.update(y, y_pred)

    # Train the model with the new sample
    model.learn_one(x, y)

【讨论】:

  • 感谢您的提议,但我想保留scikit-learn,因为这也是其他同事使用的库...在此阶段切换到新框架有点过于激烈我……
【解决方案2】:

您的问题不清楚机器学习中的哪些步骤对您来说很慢。正如riverml 的手册和sklearn 中的post 的手册中所指出的那样,可以选择进行部分拟合。您将在可用于此incremental learning 的模型方面受到限制。

因此,使用您的示例假设我们使用stochastic gradient descent classifier

from sklearn.linear_model import SGDClassifier
from sklearn.datasets import make_classification

X,y = make_classification(100000)
clf = SGDClassifier(loss='log')
all_classes  = list(set(y))

for ix in np.split(np.arange(0,X.shape[0]),100):
    clf.partial_fit(X[ix,:],y[ix],classes = all_classes)
 

【讨论】:

  • 感谢@StupidWolf,我认为增量学习链接是我正在寻找的东西-尽管它明确表示只有有限的模型子集具有此功能...关于“慢”部分...嗯,这超出了这个问题的范围,所以也许我应该修改我原来的陈述以避免使用“慢”这个词,但我会说“程序已经在使用大量的虚拟内存,通常是物理的,所以我也会探索其他可能性,让我拥有更大的数据集”
【解决方案3】:

在阅读了@StupidWolf 在这篇文章中提到的官方手册的6. Strategies to scale computationally: bigger data 部分后,我意识到这个问题不仅仅是表面上的问题。

真正的难点在于很多模型的设计。

以随机森林为例,与更简单的决策树相比,用于提高其性能的最重要技术之一是bagging的应用,这意味着该算法必须从整个数据集中挑选一些随机样本构建几个弱学习器作为随机森林的基础。这意味着在这个设计中,一个接一个地给模型提供样本将不适用。

尽管scikit-learn 仍然可以为最终用户定义一个接口来实现,以便scikit-learn 可以通过调用此接口来选择一个随机样本,最终用户将决定他们如何实现该接口通过扫描硬盘驱动器上的数据集来返回所需的数据,它变得比我最初想象的要复杂得多,并且鉴于 IO 繁重的“全表扫描”(数据库术语)经常出现,性能提升可能不是很显着需要。

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 2021-06-09
    • 2019-08-09
    • 1970-01-01
    • 2013-12-19
    • 2020-03-04
    • 1970-01-01
    • 2015-12-01
    • 2014-01-07
    相关资源
    最近更新 更多