gpt4 book ai didi

python - 了解 scikit 学习预测的随机森林内存要求

转载 作者:太空狗 更新时间:2023-10-29 20:31:15 26 4
gpt4 key购买 nike

我有一组 2000 棵经过训练的随机回归树(来自 scikit learn 的随机森林回归器,n_estimators=1)。使用 multiprocessing 和共享内存在大型数据集(~100000*700000 = 70GB @ 8 位)上并行训练树(50 个核心),效果非常好。请注意,我没有使用 RF 的内置多核支持,因为我事先进行了功能选择。

问题:并行测试大型矩阵 (~20000*700000) 时,我总是内存不足(我可以访问具有 500 GB RAM 的服务器)。

我的策略是将测试矩阵保存在内存中并在所有进程之间共享。根据statement by one of the developers测试的内存要求是 2*n_jobs*sizeof(X),在我的例子中,另一个因素 *4 是相关的,因为 8 位矩阵条目在 RF 内部向上转换为 float32。

根据数字,我认为测试需要:
14GB 用于在内存中保存测试矩阵 + 50(=n_jobs)*20000(n_samples)*700(=n_features)*4(向上转换为 float )*2 字节 = 14 gb + 5.6 gb = ~21GB 内存。

然而它总是爆炸到几百 GB。我在这里错过了什么?(我使用的是最新版本的 scikit-learn,所以应该解决旧的内存问题)

一个观察:
在一个内核上运行,仅用于测试的内存使用量在 30 到 100 GB 之间波动(根据 free 测量)

我的代码:

#----------------
#helper functions
def initializeRFtest(*args):
global df_test, pt_test #initialize test data and test labels as globals in shared memory
df_test, pt_test = args


def star_testTree(model_featidx):
return predTree(*model_featidx)

#end of helper functions
#-------------------

def RFtest(models, df_test, pt_test, features_idx, no_trees):
#test trees in parallel
ncores = 50
p = Pool(ncores, initializer=initializeRFtest, initargs=(df_test, pt_test))
args = itertools.izip(models, features_idx)
out_list = p.map(star_testTree, args)
p.close()
p.join()
return out_list

def predTree(model, feat_idx):
#get all indices of samples that meet feature subset requirement
nan_rows = np.unique(np.where(df_test.iloc[:,feat_idx] == settings.nan_enc)[0])
all_rows = np.arange(df_test.shape[0])
rows = all_rows[np.invert(np.in1d(all_rows, nan_rows))] #discard rows with missing values in the given features

#predict
pred = model.predict(df_test.iloc[rows,feat_idx])
return predicted

#main program
out = RFtest(models, df_test, pt_test, features_idx, no_trees)

编辑:另一个观察:当对测试数据进行分 block 时,程序运行平稳,内存使用量大大减少。这就是我用来使程序运行的。
更新后的 predTree 函数的代码片段:

def predTree(model, feat_idx):
# get all indices of samples that meet feature subset requirement
nan_rows = np.unique(np.where(test_df.iloc[:,feat_idx] == settings.nan_enc)[0])
all_rows = np.arange(test_df.shape[0])
rows = all_rows[np.invert(np.in1d(all_rows, nan_rows))] #discard rows with missing values in the given features

# predict height per valid sample
chunksize = 500
n_chunks = np.int(math.ceil(np.float(rows.shape[0])/chunksize))


pred = []
for i in range(n_chunks):
if n_chunks == 1:
pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:], feat_idx])
pred.append(pred_chunked)
break
if i == n_chunks-1:
pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:], feat_idx])
else:
pred_chunked = model.predict(test_df.iloc[rows[i*chunksize:(i+1)*chunksize], feat_idx])
print pred_chunked.shape
pred.append(pred_chunked)
pred = np.concatenate(pred)

# populate matrix
predicted = np.empty(test_df.shape[0])
predicted.fill(np.nan)
predicted[rows] = pred
return predicted

最佳答案

我不确定内存问题是否与 args = itertools.izip(models, features_idx)itertools.izip 的使用无关,这可能会触发创建迭代器的副本及其跨所有线程的参数。您试过只使用 zip 吗?

另一种假设可能是低效的垃圾收集——在您需要时未触发。我会检查在 predTree 中的 model.predict 之前运行 gc.collect() 是否没有帮助。

还有第三个潜在原因(可能是最可信的)。让我引用Python FAQ on How does Python manage memory? :

In current releases of CPython, each new assignment to x inside the loop will release the previously allocated resource.

在您的分 block 函数中,您正是这样做的 - 重复分配给 pred_chunked

关于python - 了解 scikit 学习预测的随机森林内存要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38141055/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com