【问题标题】:n_jobs for sklearn multioutput regressor with estimator=random forest regressorn_jobs 用于 sklearn 多输出回归器,估计器 = 随机森林回归器
【发布时间】:2021-10-31 06:37:11
【问题描述】:

当multioutput regressor 的random forest 估计器和多输出回归器本身都有它时,应该如何使用:param n_jobs:?例如,最好不要为估计器指定n_jobs,而是为多输出回归器设置n_jobs?几个例子如下:

# Imports
from sklearn.ensemble import RandomForestRegressor
from sklearn.multioutput import MultiOutputRegressor

# (1) No parallelization
rf_no_jobs = RandomForestRegressor()
multioutput_no_jobs_alpha = MultiOutputRegressor(estimator=rf_no_jobs)

# (2) RF w/ parallelization, multioutput w/o parallelization
rf_with_jobs = RandomForestRegressor(n_jobs=-1)
multioutput_no_jobs_beta = MultiOutputRegressor(estimator=rf_with_jobs)

# (3) RF w/o parallelization, multioutput w parallelization
multioutput_with_jobs_alpha = MultiOutputRegressor(estimator=rf_no_jobs, n_jobs=-1)

# (4) Both parallelized
multioutput_with_jobs_beta = MultiOutputRegressor(estimator=rf_with_jobs, n_jobs=-1)

【问题讨论】:

  • 您有没有为此找到最佳方案? - 谢谢
  • 我没有进一步调查,没有。这是一个研究项目,还有其他我关心优化的事情,所以我没有回到这个。检查它的一种方法可能是使用 timeit 库,不过我不是 100% 确定。

标签: python scikit-learn parallel-processing random-forest


【解决方案1】:

由于RandomForestRegressor 具有“本机”多输出支持(不需要多输出包装器),我转而查看了KNeighborsRegressor 和LightGBM,它们有一个内部n_jobs 参数,关于它我有同样的问题.

在 n_jobs = 8 的 Ryzen 5950X (Linux) 和 Intel 11800H (Windows) 上运行,我发现了一致的结果:

  • 对于低 Y 维度(例如,1 - 10 个目标),n_jobs 去哪里并不重要,无论如何它都会很快完成。初始化多处理需要大约 1 秒的开销,但默认情况下,joblib 会重用现有池,从而加快处理速度。
  • 在高维数(例如 > 20)的情况下,仅将 n_jobs 放置在 MultiOutputRegressor 中,KNN 接收 n_jobs=1 在 160 个维度/目标时快 10 倍。
  • 使用with joblib.parallel_backend("loky", n_jobs=your_n_jobs): 也同样快速且方便地为里面的所有sklearn 设置n_jobs。这是一个简单的选择。
  • RegressorChain 在低维时足够快,但对于 160 维的 KNeighbors 会变得非常慢(500x 慢 vs Multioutput)(我会坚持使用LightGBM 与RegressorChain 一起使用,它的性能更好) .
  • 使用LightGBM,MultiOutputRegressor 仅设置 n_jobs 再次比内部 n_jobs 快,但差异要小得多(5950x Linux 差异为 3x,11800H Windows 仅 1.2x)。

由于完整的代码有点长,这里是一个部分示例:

from timeit import default_timer as timer
import numpy as np
from joblib import parallel_backend
from sklearn.neighbors import KNeighborsRegressor
from sklearn.multioutput import MultiOutputRegressor, RegressorChain
from sklearn.datasets import fetch_california_housing

# adjust n_jobs to the number of physical CPU cores on your machine or pass -1 for auto max
n_jobs = 8
knn_model_param_dict = {}  # kwargs if desired
num_y_dims = 160

X, y_one_dim = fetch_california_housing(return_X_y=True)
y_one_dim = y_one_dim.reshape(-1, 1)
# extra multioutput dims generated randomly
dims = [y_one_dim]
for _ in range(num_y_dims - 1):
    dims.append(np.random.gamma(y_one_dim.std(), size=y_one_dim.shape))
y = np.concatenate(dims, axis=1)


# INIT
regr = MultiOutputRegressor(
    KNeighborsRegressor(**knn_model_param_dict),
    n_jobs=n_jobs,
).fit(X, y)

trial = "KNN with all n_jobs=1"
start = timer()
regr = MultiOutputRegressor(
    KNeighborsRegressor(**knn_model_param_dict, n_jobs=1),
    n_jobs=1,
)
regr.fit(X, y)
regr.predict(X)
end = timer()
print(f"trial: {trial} with runtime: {end - start}")

trial = "KNN inner model with n_jobs"
start = timer()
regr = MultiOutputRegressor(
    KNeighborsRegressor(**knn_model_param_dict, n_jobs=n_jobs),
    n_jobs=1,
)
regr.fit(X, y)
regr.predict(X)
end = timer()
print(f"trial: {trial} with runtime: {end - start}")

trial = "KNN outer multioutput with n_jobs, inner with 1"
start = timer()
regr = MultiOutputRegressor(
    KNeighborsRegressor(**knn_model_param_dict, n_jobs=1),
    n_jobs=n_jobs,
)
regr.fit(X, y)
regr.predict(X)
end = timer()
print(f"trial: {trial} with runtime: {end - start}")

trial = "KNN inner and outer both -1"
start = timer()
regr = MultiOutputRegressor(
    KNeighborsRegressor(**knn_model_param_dict, n_jobs=-1),
    n_jobs=-1,
)
regr.fit(X, y)
regr.predict(X)
end = timer()
print(f"trial: {trial} with runtime: {end - start}")

trial = "joblib backend chooses"
start = timer()
with parallel_backend("loky", n_jobs=n_jobs):
    regr = MultiOutputRegressor(
        KNeighborsRegressor(**knn_model_param_dict),
    )
    regr.fit(X, y)
    regr.predict(X)
end = timer()

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2019-04-20
    • 2020-03-12
    • 2020-10-15
    • 2021-12-25
    • 2013-12-04
    • 2020-08-28
    • 2019-12-06
    相关资源
    最近更新 更多