Scikit Learn 随机森林内存错误

5 投票
4 回答
10008 浏览
提问于 2025-04-18 03:01

我正在尝试在mnist手写数字数据集上运行scikit learn的随机森林算法。在训练算法的时候,系统出现了内存错误。请告诉我该如何解决这个问题。

CPU统计信息: 英特尔双核处理器,4GB内存

数据集的形状是60000, 784。在linux终端上显示的完整错误信息如下:

> File "./reducer.py", line 53, in <module>
>     main()   File "./reducer.py", line 38, in main
>     clf = clf.fit(data,labels) #training the algorithm   File "/usr/lib/pymodules/python2.7/sklearn/ensemble/forest.py", line 202,
> in fit
>     for i in xrange(n_jobs))   File "/usr/lib/pymodules/python2.7/joblib/parallel.py", line 409, in
> __call__
>     self.dispatch(function, args, kwargs)   File "/usr/lib/pymodules/python2.7/joblib/parallel.py", line 295, in
> dispatch
>     job = ImmediateApply(func, args, kwargs)   File "/usr/lib/pymodules/python2.7/joblib/parallel.py", line 101, in
> __init__
>     self.results = func(*args, **kwargs)   File "/usr/lib/pymodules/python2.7/sklearn/ensemble/forest.py", line 73, in
> _parallel_build_trees
>     sample_mask=sample_mask, X_argsorted=X_argsorted)   File "/usr/lib/pymodules/python2.7/sklearn/tree/tree.py", line 476, in fit
>     X_argsorted=X_argsorted)   File "/usr/lib/pymodules/python2.7/sklearn/tree/tree.py", line 357, in
> _build_tree
>     np.argsort(X.T, axis=1).astype(np.int32).T)   File "/usr/lib/python2.7/dist-packages/numpy/core/fromnumeric.py", line
> 680, in argsort
>     return argsort(axis, kind, order) MemoryError

4 个回答

0

请用一棵树来训练随机森林,并检查这棵树的深度。默认情况下,scikit-learn会生成完整的树。树的深度可能会非常大,所以即使森林里只有几棵树,也会占用很多内存。你可以尝试使用max_depth这个参数来限制树的深度。

我做了一个实验,把树的深度从42(森林中树的平均深度)减少到6。结果内存减少了66倍,而性能稍微提升了大约4%。

1

一个解决办法是使用最新版本的scikit-learn(0.19)。在更新日志中,他们在修复错误的部分提到了一些重要的改进:

 Fixed excessive memory usage in prediction for random forests estimators. #8672 by Mike Benfield.

你可以通过以下方式安装这个版本:

pip3 install scikit-learn==0.19.0
2

Scikit-learn开发团队在内存管理和性能上有了很大改善

尊重其他人的观点,但scikit-learn 0.16.1并没有像早期版本那样存在令人不快的Xy的重复问题。

由于一些其他原因,我花了相当长的时间研究RandomForestRegressor()的超参数,包括它们的内存占用问题。

0.16.1版本中,使用并行处理时,内存需求的增加不到2%,从默认的n_jobs = 1增加到{ 2, 3, ... }

最近的scikit-learn版本的共同创始人@glouppe发布了一份精彩且富有洞察力的演示文稿(2014年8月,版本0.15.0),其中包括与基于R的其他已知随机森林框架的比较。

在我看来,演示文稿的第25页及以后讨论了一些提高速度的技术,包括np.asfortranarray(...),但这些看起来(没有任何实验证明)更像是Scikit-learn开发团队内部共享的方向,而不是给我们这些生活在“外部世界”的普通人的建议。

回归还是分类?

这个问题很重要。如果没有进行全面的特征集向量袋装,可能需要一些额外的特征工程工作和测试。你的学习器似乎是分类器,所以可以深入研究:

  1. 尝试非默认设置的max_features等参数
  2. 如果在调整学习器后需要,可以使用操作系统服务来处理更大的虚拟内存,使用mkswapswapon

附录

经过另一轮测试,出现了一个有趣的观察。

当使用.set_params( n_jobs = -1 ).fit( X, y )配置成功训练RandomForestRegressor()后,后来在尝试使用.predict( X_observed )时却遇到了意外的问题。

在这里,报告了一个类似的内存问题(现在是0.17.0版本)。

不过,使用.set_params( n_jobs = 1 ).predict( X_observed )的单线程工作在.predict()上表现良好。

4

要么把 n_jobs=1 设置成1,要么升级到最新的scikit-learn版本。现在发布的版本使用多个进程来同时训练树模型,这就意味着数据(Xy)需要被复制到这些进程里。下一个版本会改用线程而不是进程,这样树模型的学习者就可以共享内存了。

撰写回答