【发布时间】:2020-11-18 00:03:19
【问题描述】:
当通过“fold_column”参数指定折叠时,我试图了解交叉验证如何在 H2o 中工作。图书馆说:
fold_column 选项指定数据集中的列 包含每个观察的交叉验证折叠索引分配。
我假设对于每个交叉验证迭代,具有 fold_column = i 的行用作测试集,其余行用作训练集。但是,如果我改为使用这些拆分分别训练和测试模型,我会得到不同的性能结果。在下面的示例中,我创建了一个值介于 1 和 5 之间的列用作拆分索引,并使用它来运行 H2o 交叉验证(使用 fold_column 参数)。之后,我使用同一列来训练和测试具有相同索引的模型并比较结果。
这是一个可重现的例子:
h2o.init()
from h2o.estimators import H2ORandomForestEstimator
import numpy as np
import pandas as pd
# Import the prostate dataset
prostate = h2o.import_file("http://s3.amazonaws.com/h2o-public-test-data/smalldata/prostate/prostate.csv.zip")
# Set the predictor names and the response column name
response = "CAPSULE"
predictors = prostate.names[3:8]
# Convert the response column to a factor
prostate['CAPSULE'] = prostate['CAPSULE'].asfactor()
# Add column with random value between 1 and 5 to use for cross-validation
np.random.seed(21)
random_folds = np.random.randint(1, 6, len(prostate))
df_folds = pd.DataFrame(random_folds, columns=['folds'])
df_h20 = prostate.cbind(h2o.H2OFrame(df_folds))
##### Train the model using H2o cross-validation #####
# Train model using fold_column argument
drf = H2ORandomForestEstimator(fold_column = 'folds', max_depth=5, ntrees=1, seed=21)
drf.train(x=predictors, y=response, training_frame=df_h20)
# Get folds prediction single models
models = drf.cross_validation_models()
# Prin test and train AUC performance for each CV-fold
print('Fold 1, AUC (test) {} AUC (train) {}'.format(models[0].auc(valid=True), models[0].auc(train=True)))
print('Fold 2, AUC (test) {} AUC (train) {}'.format(models[1].auc(valid=True), models[1].auc(train=True)))
print('Fold 3, AUC (test) {} AUC (train) {}'.format(models[2].auc(valid=True), models[2].auc(train=True)))
print('Fold 4, AUC (test) {} AUC (train) {}'.format(models[3].auc(valid=True), models[3].auc(train=True)))
print('Fold 5, AUC (test) {} AUC (train) {}'.format(models[4].auc(valid=True), models[4].auc(train=True)))
##### Train the model on a single K-fold without using H2o cross-validation #####
# select one the of the 5 folds and create test/train set
test = df_h20[df_h20['folds'] == 1]
train = df_h20[df_h20['folds'] != 1]
# Train the model
drf = H2ORandomForestEstimator(max_depth=5, ntrees=1, seed=21)
drf.train(x=predictors,
y=response,
training_frame=train,
validation_frame=test
)
perf_valid = drf.model_performance(test)
perf_train = drf.model_performance(train)
print('AUC (test) {} AUC (train) {}'.format(perf_valid.auc(), perf_train.auc()))
输出是:
Fold 1, AUC (test) 0.8352221702976504 AUC (train) 0.835269468426379
Fold 2, AUC (test) 0.8215820406943912 AUC (train) 0.8203464750008381
Fold 3, AUC (test) 0.833563260744653 AUC (train) 0.8376839384943596
Fold 4, AUC (test) 0.8295902318635076 AUC (train) 0.8287798683714774
Fold 5, AUC (test) 0.825246953403821 AUC (train) 0.8264781593374212
AUC (test) 0.838142980551675 AUC (train) 0.8382107902781438
在没有使用H2o交叉验证的情况下单折训练和测试的模型的结果与5折交叉验证的5个结果中的任何一个都不对应,这不是我所期望的。我实际上期待看到与 5 个 CV 折叠相对应的最新结果。据我了解,H2o 交叉验证应该在内部训练模型,就像我在代码的最后一部分中所做的那样。
有人知道为什么会这样吗?
编辑:我添加了参数 ntrees=1。我这样做是为了降低模型的复杂性,确保我们处理的是单个决策树。我还在两个模型中添加了参数 seed=21。
【问题讨论】:
-
H2ORandomForestEstimator(与所有 RF 型号一样)包含一个随机元素,这使得您观察到的差异一开始并不令人惊讶。尝试在两个模型实例中显式设置seed(documentation)。 -
我在两个模型中添加了种子并将树的数量限制为 1,但问题仍然存在。
标签: python machine-learning random-forest h2o