克隆和拟合 RandomizedSearchCV 后的随机化行为

问题描述 投票:0回答:1

我有一个基本的嵌套 CV 循环,其中外部循环执行内部模型调整步骤。我的期望是每次折叠都应该抽取不同的超参数值随机样本。然而,在下面的示例中,每次折叠最终都会采样相同的值。

导入并制作数据集:

from sklearn.model_selection import RandomizedSearchCV, KFold, cross_validate
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.base import clone

from scipy.stats import uniform
import numpy as np

X, y = make_classification(n_features=10, random_state=np.random.RandomState(0))

嵌套 CV 循环:

#Used for tuning the random forest:
rf_tuner = RandomizedSearchCV(
    RandomForestClassifier(random_state=np.random.RandomState(0)),
    param_distributions=dict(min_samples_split=uniform(0.1, 0.9)),
    n_iter=5,
    cv=KFold(n_splits=2, shuffle=False),
    random_state=np.random.RandomState(0),
    n_jobs=1,
)

#Nested CV
for trn_idx, tst_idx in KFold(3).split(X, y):
    #'cloned' will now share the same RNG as 'rf_tuner'
    cloned = clone(rf_tuner)
    
    #This should be consuming the RNG of 'rf_tuner'
    cloned.fit(X[trn_idx], y[trn_idx])
    
    #Report hyperparameter values sampled in this fold
    display(cloned.cv_results_['params'])

    #<more code for nested CV, not shown>

输出:

Fold 1/3:
[{'min_samples_split': 0.593},
 {'min_samples_split': 0.743},
 {'min_samples_split': 0.642},
 {'min_samples_split': 0.590},
 {'min_samples_split': 0.481}]

Fold 2/3:
[{'min_samples_split': 0.593},
 {'min_samples_split': 0.743},
 {'min_samples_split': 0.642},
 {'min_samples_split': 0.590},
 {'min_samples_split': 0.481}]

Fold 3/3:
[{'min_samples_split': 0.593},
 {'min_samples_split': 0.743},
 {'min_samples_split': 0.642},
 {'min_samples_split': 0.590},
 {'min_samples_split': 0.481}]

我首先用

RandomizedSearchCV
实例化
RandomForestClassifier
。我将搜索的
random_state=
设置为随机状态实例
np.random.RandomState(0)

对于外循环的每一次传递,我

clone()
fit()
搜索对象 -
cloned
因此应该使用 same RNG 作为原始,在每次传递时对其进行变异。每个循环应该产生不同的超参数值采样。然而,如上所示,每次传递采样的超参数是相同的。这表明每个循环都以相同的未修改的 RNG 开始,而不是突变的 RNG。

文档说估计器的克隆共享相同的随机状态实例:

b = clone(a)
[...] 调用
a.fit
将消耗
b
的 RNG,调用
b.fit
将消耗
a
的 RNG,因为它们是相同的

如何解释折叠之间没有随机化?

scikit-learn cross-validation random-seed
1个回答
0
投票

clone
对每个非估计器参数(
source
)执行 deepcopy,因此在
RandomState
的情况下,克隆都将具有 不同
RandomState
对象,全部从相同状态开始(如在
get_state()
)。所以你的例子是预期的。

我不知道这是否曾经有不同的行为,或者文档在这一点上是否总是错误的。

© www.soinside.com 2019 - 2024. All rights reserved.