使用手动 KFold-Cross 验证与 KerasClassifier-KFold 交叉验证时的不同结果

Posted

技术标签:

【中文标题】使用手动 KFold-Cross 验证与 KerasClassifier-KFold 交叉验证时的不同结果【英文标题】:Different results when using Manual KFold-Cross validation vs. KerasClassifier-KFold Cross Validation 【发布时间】:2020-08-31 13:11:00 【问题描述】:

我一直在努力理解为什么两个相似的 Kfold-cross 验证会导致两个不同的平均值。

当我使用手动 KFold 方法(使用 Tensorflow 和 Keras)时

cvscores = []
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=3)
for train, test in kfold.split(X, y):
  model = create_baseline()
  model.fit(X[train], y[train], epochs=50, batch_size=32, verbose=0)
  scores = model.evaluate(X[test], y[test], verbose=0)
  #print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
  cvscores.append(scores[1] * 100)

print("%.2f%% (+/- %.2f%%)" % (np.mean(cvscores), np.std(cvscores)))

我明白了

65.89% (+/- 3.77%)

当我使用 scikit 中的 KerasClassifier 包装器时

estimator = KerasClassifier(build_fn=create_baseline, epochs=50, batch_size=32, verbose=0)
kfold = StratifiedKFold(n_splits=10,shuffle=True, random_state=3)
results = cross_val_score(estimator, X, y, cv=kfold, scoring='accuracy')
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

我明白了

63.82% (5.37%)

此外,使用 KerasClassifier 时会出现以下警告

WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/wrappers/scikit_learn.py:241: Sequential.predict_classes (from tensorflow.python.keras.engine.sequential) is deprecated and will be removed after 2021-01-01.
Instructions for updating:
Please use instead:* `np.argmax(model.predict(x), axis=-1)`,   if your model does multi-class classification   (e.g. if it uses a `softmax` last-layer activation).* `(model.predict(x) > 0.5).astype("int32")`,   if your model does binary classification   (e.g. if it uses a `sigmoid` last-layer activation).

结果是否不同是因为 KerasClassifier 使用 predict_classes() 而手动 Tensorflow/Keras 方法仅使用 predict()?如果是这样,哪种方法更合理?

我的模型是这样的

def create_baseline():
model = tf.keras.models.Sequential()
model.add(Dense(8, activation='relu', input_shape=(12,)))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model

【问题讨论】:

【参考方案1】:

两个 CV 结果看起来并没有太大的不同,它们都在彼此的标准差之内。

您修复了 StratifiedKFold 类的种子,这很好。但是,您应该控制额外的随机性,它来自 权重初始化。确保为每个 CV 运行使用不同的权重初始化模型,但对手动和自动的交叉验证使用相同的 10 次初始化。您可以将initializer 传递给每一层,它们也有一个seed 参数。一般来说,您应该修复所有可能的种子(np.random.seed(3)tf.set_random_seed(3))。

如果您运行cross_val_score() 或您的手动版本两次会发生什么?你得到相同的结果/数字吗?

【讨论】:

你说得对,我只是认为它们会完全一样而不是不同。我想我已经按照你的建议做了:当我导入所有包时,我也会调用from numpy.random import seed seed(3) from tensorflow.random import set_seed tf.random.set_seed(3) 不管怎样,我也将种子与初始化程序一起使用并运行了两次:结果仍然不同。由于 predict_classes 将在年底折旧,您是否更喜欢手册?只要您回答我最后一个,我就会将其标记为已接受:) 如果您打算不再更新您的库或只运行一次程序,请选择您喜欢的任何内容。否则我强烈建议使用手册;) 如果您真的很偏执并且好奇问题是什么,请打印每个中间步骤。查看拆分,查看从初始化程序返回的权重,查看每一集的输出,在 fit() 方法中设置 shuffle=Flase。基本上解决所有你可以调查的问题。

以上是关于使用手动 KFold-Cross 验证与 KerasClassifier-KFold 交叉验证时的不同结果的主要内容,如果未能解决你的问题,请参考以下文章

Sklearn 交叉验证产生与手动执行不同的结果

kera 学习-线性回归

sklearn 交叉验证 R^2 分数与使用训练模型对训练和验证数据进行的手动检查不匹配

python中kera LSTM网络的模型拟合和尺寸大小误差

机器学习:我选kera

python-灰色预测平均房价趋势kera深度学习库的介绍