为什么GridSearchCV在scikit-learn中产生了如此多的线程

时间:2017-09-21 18:46:26

标签: python multithreading scikit-learn grid-search

以下是我当前运行的GridSearch的{​​{1}}输出,我很想知道正在进行哪些进程,还有一些我无法解释的内容。

pstree

我删除了无关的东西。粗略的括号意味着线程。

  • perl的出现是因为我使用 ├─bash─┬─perl───20*[bash───python─┬─5*[python───31*[{python}]]] │ │ └─11*[{python}]] │ └─tee └─bash───pstree 来启动我的python作业。如您所见,parallel -j 20确实显示有20个进程。
  • 每个python进程之前的20*进程是由于使用bash激活Anaconda虚拟环境。
  • 在每个python进程中,还有另外5个python进程(source activate venv)生成。这是因为我将5*指定为n_jobs=5

我的理解在此结束。

问题:任何人都可以解释为什么还有另外11个python线程(GridSearchCV)以及网格搜索,并且每个内部产生31个python线程(11*[{python}]) 5个网格搜索工作?

更新:添加了调用31*[{python}]

的代码
GridSearchCV

更新(2017-09-27)

如果感兴趣的话,我会为你提供一个test code,以便你轻松复制。

我在Mac Pro和多台Linux机器上测试了相同的代码,并重现了@igrinis的结果,但仅限于Mac Pro。在linux机器上,我得到的数字与以前不同,但始终如一。因此,生成的线程数可能取决于GridSearchCV的特定数据馈送。

Cs = 10 ** np.arange(-2, 2, 0.1)
skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=0)
clf = LogisticRegression()
gs = GridSearchCV(
    clf,
    param_grid={'C': Cs, 'penalty': ['l1'],
                'tol': [1e-10], 'solver': ['liblinear']},
    cv=skf,
    scoring='neg_log_loss',
    n_jobs=5,
    verbose=1,
    refit=True)
gs.fit(Xs, ys)

请注意,在Mac Pro和Linux机器上由homebrew / linuxbrew安装的pstree是不同的。在这里,我发布我使用的确切版本:

Mac:

python─┬─5*[python───31*[{python}]]
       └─3*[{python}]

Linux的:

pstree $Revision: 2.39 $ by Fred Hucht (C) 1993-2015
EMail: fred AT thp.uni-due.de

Mac版似乎没有显示线程的选项,我认为这可能是他们在结果中看不到的原因。我还没有找到一种在Mac Pro上轻松检查线程的方法。如果你碰巧知道某种方式,请发表评论。

更新(2017-10-12)

在另一组实验中,我确认设置环境变量pstree (PSmisc) 22.20 Copyright (C) 1993-2009 Werner Almesberger and Craig Small 会产生影响。

OMP_NUM_THREADS之前,有很多(在这种情况下是63个)线程,如上所述产生了不明确的使用:

export OMP_NUM_THREADS=1

此处不使用linux bash───python─┬─23*[python───63*[{python}]] └─3*[{python}] parallel

n_jobs=23之后,没有线程产生,但是3个Python进程仍然存在,我仍然没有意识到它的使用。

export OMP_NUM_THREADS=1

我最初遇到bash───python─┬─23*[python] └─3*[{python}] ,因为它导致我的一些GridSearchCV作业出错,错误消息是这样的

OMP_NUM_THREADS

1 个答案:

答案 0 :(得分:2)

来自sklearn.GridSearchCV doc:

  

n_jobs:int,默认= 1   并行运行的作业数量。

     

pre_dispatch:int或string,optional   控制在并行执行期间调度的作业数。减少此数量可有助于避免在分配的作业多于CPU可处理的内容时消耗内存消耗。这个参数可以是:   无,在这种情况下,所有作业都会立即创建并生成。将此用于轻量级和快速运行的作业,以避免因按需生成作业而导致的延迟   一个int,给出生成的总工作的确切数量   一个字符串,表达式为n_jobs的函数,如'2 * n_jobs'

如果我正确理解文档,GridSearchCV会产生一堆线程作为网格点数,并且只能同时运行n_jobs。 31号我相信是你的40个可能值的上限。尝试使用pre_dispatch参数的值。

我认为另外11个线程与GridSearchCV本身无关,因为它显示在同一级别上。我认为这是剩下的其他命令。

顺便说一句,我没有在Mac上观察到这种行为(只看到GridSearchCV产生的5个进程,正如人们所期望的那样),所以它可能来自不兼容的库。尝试手动更新sklearnnumpy

这是我的pstree输出(隐私删除路径的一部分):

 └─┬= 00396 *** -fish
   └─┬= 21743 *** python /Users/***/scratch_5.py
     ├─── 21775 *** python /Users/***/scratch_5.py
     ├─── 21776 *** python /Users/***/scratch_5.py
     ├─── 21777 *** python /Users/***/scratch_5.py
     ├─── 21778 *** python /Users/***/scratch_5.py
     └─── 21779 *** python /Users/***/scratch_5.py

回答第二条评论:

这实际上是你的代码。刚生成可分离的1d两类问题:

N = 50000
Xs = np.concatenate( (np.random.random(N) , 3+np.random.random(N)) ).reshape(-1, 1)
ys = np.concatenate( (np.zeros(N), np.ones(N)) )

100k样本足以让CPU忙碌大约一分钟。