【发布时间】:2015-02-15 00:18:32
【问题描述】:
我做了一些奇怪的观察,我的 GridSearch 在几个小时后一直失败,我一开始不知道为什么。随着时间的推移,我监控了内存使用情况,发现它从几 GB(~6 Gb)开始并不断增加,直到达到最大值时节点崩溃。硬件可以占用 128 Gb。 我正在尝试使用随机森林对大量文本文档进行分类。为简单起见——为了弄清楚发生了什么——我回到了朴素贝叶斯。
我使用的版本是
- Python 3.4.2
- scikit-learn 0.15.2
我在 GitHub 上的 scikit-issue 列表上找到了一些关于这个主题的相关讨论:https://github.com/scikit-learn/scikit-learn/issues/565 和 https://github.com/scikit-learn/scikit-learn/pull/770
听起来它已经成功解决了!
所以,我使用的相关代码是
grid_search = GridSearchCV(pipeline,
parameters,
n_jobs=1, #
cv=5,
scoring='roc_auc',
verbose=2,
pre_dispatch='2*n_jobs',
refit=False) # tried both True and False
grid_search.fit(X_train, y_train)
print('Best score: {0}'.format(grid_search.best_score_))
print('Best parameters set:')
出于好奇,我后来决定通过嵌套的 for 循环以快速而肮脏的方式进行网格搜索
for p1 in parameterset1:
for p2 in parameterset2:
...
pipeline = Pipeline([
('vec', CountVectorizer(
binary=True,
tokenizer=params_dict[i][0][0],
max_df=params_dict[i][0][1],
max_features=params_dict[i][0][2],
stop_words=params_dict[i][0][3],
ngram_range=params_dict[i][0][4],)),
('tfidf', TfidfTransformer(
norm=params_dict[i][0][5],
use_idf=params_dict[i][0][6],
sublinear_tf=params_dict[i][0][7],)),
('clf', MultinomialNB())])
scores = cross_validation.cross_val_score(
estimator=pipeline,
X=X_train,
y=y_train,
cv=5,
scoring='roc_auc',
n_jobs=1)
params_dict[i][1] = '%s,%0.4f,%0.4f' % (params_dict[i][1], scores.mean(), scores.std())
sys.stdout.write(params_dict[i][1] + '\n')
到目前为止一切顺利。网格搜索运行并将结果写入标准输出。但是,一段时间后,它再次超过了 128 Gb 的内存上限。与 scikit 中的 GridSearch 相同的问题。经过一番实验,我终于发现
gc.collect()
len(gc.get_objects()) # particularly this part!
在 for 循环中解决了问题,内存使用量在约 10 小时的运行时间内始终保持在 6.5 Gb。
最终,我得到了解决上述问题的方法,但是,我很想听听您对可能导致此问题的原因的想法以及您的提示和建议!
【问题讨论】:
-
这太奇怪了。您能否在 github 上提交一个新问题,包括使用随机生成的数据(甚至是恒定数据,例如
np.ones(shape=(n_samples, n_features), dtype=np.float))重现问题的脚本? -
当然,没问题。我将一些导致此问题的代码上传到 github.com/rasbt/bugreport/tree/master/scikit-learn/… 并在此处打开了一个问题:github.com/scikit-learn/scikit-learn/issues/3973。谢谢!
-
过去我也发现sklearn中的一些东西(通常是随机森林)消耗太多内存。根据问题,我不得不解决它。一种评论是,对于 tfidf/文档问题,GradientBoostingClassifier 可能比 RandomForest 提供更好的结果。另外,我很确定 tfidf 转换器将返回一个稀疏矩阵(待办事项:确保为您的版本确定这一点)......所以您需要更新您的 sklearn,因为 0.15.2 中的 RandomForest 不支持稀疏输入。跨度>
-
您是如何在
GridSearchCV()方法中使用gc.collect()和len(gc.get_objects())来解决它的?这种方法不会有正确的循环,因此没有地方放置您提到的 2 行?
标签: python memory scikit-learn