如何让Scikit的gp_minimize实现并行运行?
问题原因
你使用的scikit-optimize 0.3是非常老旧的版本,这个版本中gp_minimize的n_jobs参数并非用于并行执行目标函数的评估,它的作用是加速高斯过程模型内部的拟合计算(比如核矩阵的并行运算),所以设置n_jobs>1不会让你的J函数调用并行执行,自然不会减少总耗时。
解决方案
方案1:升级scikit-optimize到新版本(仅适用于Python3环境)
注意:scikit-optimize 0.4及以上版本不再支持Python2.7,如果你必须保留Python2.7环境,请直接看方案2。
这是最简单的方法,新版本(0.9及以上)的gp_minimize中,n_jobs参数已经支持并行执行目标函数的评估。你可以通过conda升级:
conda update scikit-optimize
升级后,你的原有代码应该就能实现并行,总耗时会接近预期的10秒左右。
方案2:在当前0.3版本下手动实现并行
如果无法升级版本,可以用joblib手动并行执行目标函数的调用,以下是简化的实现思路:
from skopt import gp_minimize import time import datetime from joblib import Parallel, delayed def J(paramlist): x = paramlist[0] time.sleep(5) return x**2 # 包装并行评估函数 def parallel_evaluate(params_list): return Parallel(n_jobs=5)(delayed(J)(params) for params in params_list) print("starting at "+str(datetime.datetime.now())) # 先运行随机初始点 initial_x = [[-0.5]] # 对应n_random_starts=1 initial_y = parallel_evaluate(initial_x) # 迭代完成剩余9次函数调用(n_calls=10,已用1次) current_x = initial_x current_y = initial_y for _ in range(9): # 基于已有数据获取下一个候选点 res = gp_minimize(J, [(-1.0, 1.0)], x0=current_x, y0=current_y, n_calls=1, n_random_starts=0, random_state=1234, n_jobs=5) # 并行评估新点 new_x = [res.x] new_y = parallel_evaluate(new_x) current_x.extend(new_x) current_y.extend(new_y) print("ending at "+str(datetime.datetime.now()))
这种方式通过手动迭代实现每一步的并行评估,虽然繁琐,但能在旧版本下实现目标函数的并行执行。
验证
升级版本后,重新运行原有代码,观察总耗时是否接近10秒;如果用手动并行的方式,需确保parallel_evaluate中的n_jobs设置与可用核心数匹配。
内容的提问来源于stack exchange,提问作者Botond
相关产品推荐
相关产品推荐

