gpt4 book ai didi

python - 如何在多核上将 RandomState 与 Sklearn RandomizedSearchCV 结合使用

转载 作者:行者123 更新时间:2023-12-01 01:22:02 24 4
gpt4 key购买 nike

我对在多核上运行时将 np.random.RandomStatesklearn.model_selection.RandomizedSearchCV 一起使用的正确方法感到困惑。

我使用RandomState来生成伪随机数,以便我的结果是可重现的。我为 RandomizedSearchCV 提供一个 RandomState 实例,并设置 n_jobs=-1 以便它使用所有六个核心。

在多个核心上运行引入了异步元素。我预计这将导致在不同的运行中以不同的顺序从各个核心发出对伪随机数的请求。因此,不同的运行应该给出不同的结果,而不是显示重现性。

但实际上结果是可以重现的。对于给定的 n_iter 值(即从参数空间中抽取的次数),每次运行中找到的最佳超参数值都是相同的。如果 n_jobs 是小于核心数量的正数,我也会得到相同的值。

具体来说,代码如下:

import numpy as np
import scipy.stats as stats
from sklearn.datasets import load_iris
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import RandomizedSearchCV, StratifiedKFold, train_test_split

# Use RandomState for reproducibility.
random_state = np.random.RandomState(42)

# Get data. Split it into training and test sets.
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.4, random_state=random_state, stratify=y)

# Prepare for hyper-parameter optimization.
n_iter = 1_000

base_clf = GradientBoostingClassifier(
random_state=random_state, max_features='sqrt')

param_space = {'learning_rate': stats.uniform(0.05, 0.2),
'n_estimators': [50, 100, 200],
'subsample': stats.uniform(0.8, 0.2)}

# Generate data folds for cross validation.
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=random_state)

# Create the search classifier.
search_clf = RandomizedSearchCV(
base_clf, param_space, n_iter=n_iter, scoring='f1_weighted', n_jobs=-1,
cv=skf, random_state=random_state, return_train_score=False)

# Optimize the hyper-parameters and print the best ones found.
search_clf.fit(X_train, y_train)
print('Best params={}'.format(search_clf.best_params_))

我有几个问题。

  1. 尽管存在异步方面,为什么我仍能获得可重现的结果?

  2. RandomizedSearchCV 的文档关于 random_state 参数的说明:“伪随机数生成器状态用于从可能值列表而不是 scipy.stats 分布中进行随机均匀采样。”这是否意味着它不会影响参数空间中的分布?上面的代码是否足以确保可重复性,或者我是否需要设置np.random.seed(),或者可能编写如下内容:

    distn_learning_rate = stats.uniform(0.05, 0.2)  
    distn_learning_rate.random_state = random_state
    distn_subsample = stats.uniform(0.8, 0.2)
    distn_subsample.random_state = random_state
    param_space = {'learning_rate': distn_learning_rate,
    'n_estimators': [50, 100, 200],
    'subsample': distn_subsample}
  3. 总的来说,这是设置 RandomizedSearchCV 以获得再现性的正确方法吗?

  4. 是否可以使用 RandomState 的单个实例,或者我应该为 train_test_splitGradientBoostingClassifier 使用单独的实例StratifiedKFoldRandomizedSearchCV?另外,np.random.seed 的文档表示在初始化 RandomState 时设置种子。它如何与 RandomizedSearchCV 设置种子交互?

  5. n_jobs设置为使用少于所有核心时,我仍然看到所有核心上的事件,尽管每个核心的使用级别会增加,并且耗时会随着核心数量的增加而减少。核心增加。这只是 sklearn 和/或 macOS 优化机器使用吗?

我使用的是 macOS 10.14.2、Python 3.6.7、Numpy 1.15.4、Scipy 1.1.0 和 Sklearn 0.20.1。

最佳答案

候选参数是在使用 ParameterSampler object 传递到多线程功能之前生成的。 。所以只有一个random_state足以保证 RandomizedSearchCV 的重现性。

请注意,我说的是"reproducibility of RandomizedSearchCV" 。对于其中使用的估计器(此处为base_clf),每个估计器应携带自己的random_state。正如你所做的那样。

现在谈论a single instance of RandomState ,对于顺序代码来说这是完全正确的。唯一需要担心的情​​况是多处理启动时。因此,让我们分析一下程序执行期间发生的步骤。

  1. 您设置了 RandomState带有种子的对象。现在它有一个状态了。
  2. 内部train_test_split ,一个StratifiedShuffleSplit使用(因为您已使用 stratify 参数),它将使用传递的 RandomState对象在训练和测试数据中分割和生成排列。所以RandomState的内部状态现在改变了。但它是连续的,无需担心。
  3. 现在你设置这个random_state skf 中的对象。但直到 fit() 才会发生 split 。在RandomizedSearchCV叫做。所以状态没有改变。
  4. 之后,当 search_clf.fit称为 the following happens :

    1. _run_search() 被执行,它将使用 random_state一次生成所有参数组合(根据给定 n_iters )。所以多线程仍然没有发生,一切都很好。
    2. evaluate_candidates() 叫做。有趣的部分是:

      out = parallel(delayed(_fit_and_score)(clone(base_estimator),
      X, y,
      train=train, test=test,
      parameters=parameters,
      **fit_and_score_kwargs)
      for parameters, (train, test)
      in product(candidate_params,
      cv.split(X, y, groups)))
    3. parallel(delayed(_fit_and_score)之后的部分仍然是顺序的,由父线程处理。

      • cv.split()将使用random_state (改变其状态)生成训练测试分割
      • clone(estimator)将克隆估计器的所有参数(还有random_state)。所以RandomState的状态改变了来自cv.split对象成为 estimator 中的基本状态
      • 上述两个步骤从父线程发生多次(分片数 x 参数组合次数)(无异步性)。而且每次都是原创RandomState被克隆以服务于估计器。因此结果是可重复的。
      • 所以当实际的多线程部分启动时,原来的RandomState未使用,但每个估计器(线程)都会有自己的 RandomState 副本

希望这是有道理的,并能回答您的问题。 Scikit-learn explicitly requests the user像这样设置:

import numpy as np
np.random.seed(42)

使整个执行过程可重现,但你正在做的事情也可以。

我不完全确定您的最后一个问题,因为我无法在我的系统上重现该问题。我有 4 个核心,当我设置 n_jobs=2 时或3我只看到那些核心处于 100% 状态,并且保持在 20-30% 左右。我的系统规范:

System:
python: 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 17:14:51) [GCC 7.2.0]
machine: Linux-4.15.0-20-generic-x86_64-with-debian-buster-sid

Python deps:
pip: 18.1
setuptools: 40.2.0
sklearn: 0.20.1
numpy: 1.15.4
scipy: 1.1.0
Cython: 0.29
pandas: 0.23.4

关于python - 如何在多核上将 RandomState 与 Sklearn RandomizedSearchCV 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53726915/

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