使用 picke/joblib 保存随机森林分类器 (sklearn) 会创建巨大的文件

问题描述 投票:0回答:1

我正在尝试保存一堆经过训练的随机森林分类器,以便以后重用它们。为此,我尝试使用 pickle 或 joblib。我遇到的问题是,保存的文件变得很大。这似乎与我用于训练的数据量相关(每个森林有数千万个样本,导致转储文件高达 20GB!)。

RF分类器本身是否将训练数据保存在其结构中?如果是这样,我怎样才能将结构拆开并只保存必要的参数以供以后预测呢?遗憾的是,我还找不到任何有关尺寸的内容。

感谢您的帮助! 巴拉德斯特

简而言之,这就是我所做的:

我在大型数据集上训练了(相当标准的)RF,然后保存了经过训练的森林,尝试了 pickle 和 joblib(也将压缩选项设置为 3)。

X_train, y_train = ... some data

classifier = RandomForestClassifier(n_estimators=24, max_depth=10)
classifier.fit(X_train, y_train)

pickle.dump(classifier, open(path+'classifier.pickle', 'wb'))

joblib.dump(classifier, path+'classifier.joblib', compress=True)

由于保存的文件变得相当大(5GB 到近 20GB,压缩了大约 1/3 - 而且我需要 > 50 个这样的森林!)并且训练需要一段时间,我尝试了训练数据的不同子集。根据训练集的大小,我发现保存的分类器有不同的大小,这让我相信有关训练的信息也被腌制/工作了。这对我来说似乎不直观,至于预测,我只需要所有经过训练的弱预测器(决策树)的信息,这些预测器应该是稳定的,并且由于树的数量和最大深度不是太高,它们也不应该占用这么大的空间。由于训练集更大,当然不会更多。

总而言之,我怀疑该结构包含的内容超出了我的需要。然而,我找不到关于如何从其中排除这些部分并仅保存我未来预测所需的信息的好答案。

pickle random-forest joblib memory-size
1个回答
1
投票

我遇到了类似的问题,我一开始也认为模型保存了不必要的信息,或者序列化引入了一些冗余。事实上,决策树确实是一种消耗内存的结构,由多个长度由节点总数给出的数组组成。节点通常随着数据大小的增长而增长(像

max_depth
这样的参数不能有效地用来限制增长,因为合理的值仍然有空间生成大量节点)。请参阅详细信息在此答案中,但要点是:

  • 单个决策树可以轻松增长到几 MB(上面的示例有一个用于 100K 数据的 5MB 决策树和一个用于 1M 数据的 50MB 决策树)
  • 随机森林通常包含至少 100 个这样的决策树,对于上面的示例,您将拥有 0.5/5GB 范围内的模型
  • 压缩通常不足以减少到合理的大小(1/2、1/3是通常的范围)

其他注意事项:

  • 使用不同的算法模型可能会保持更易于管理的大小(例如,使用 xgboost 我看到更小的序列化模型)
  • 如果您仅计划将决策树使用的一些数据重新用于预测,则可能可以“修剪”决策树使用的一些数据。特别是,我想
    impurity
    的数组以及可能不需要
    n_samples
    上的数组,但我还没有检查过。
  • 关于随机森林正在保存训练数据的假设:请注意,事实并非如此,数据本身可能比最终模型小一个或多个数量级
  • 另一种策略,如果您有可重复的训练管道,可能是保存数据而不是模型并有目的地重新训练,但这只有在您可以抽出时间重新训练的情况下才有可能(例如,如果在一个用例中,您有一个长期运行的服务,该服务在内存中包含模型,并且您可以序列化模型,以便在模型出现故障时进行备份)

可能还有其他选项来限制随机森林的增长,到目前为止我发现的最好的选项是在这个答案中,其中建议与

min_samples_leaf
一起将其设置为数据的百分比

© www.soinside.com 2019 - 2024. All rights reserved.