使用手动 KFold 交叉验证与 KerasClassifier-KFold 交叉验证时的不同结果
Different results when using Manual KFold-Cross validation vs. KerasClassifier-KFold Cross Validation
我一直在努力理解为什么两个相似的 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
两个 CV 结果看起来差别不大,它们都在彼此的标准差范围内。
您已修复 StratifiedKFold
class 的种子,很好。但是,您应该控制额外的随机性,它来自 权重初始化 。确保为每个具有不同权重的 CV-运行 初始化模型,但对手动和自动交叉验证使用相同的 10 个初始化。您可以将 initializer 传递给每一层,它们也有一个 seed
参数。一般来说,你应该修复所有可能的种子 (np.random.seed(3)
, tf.set_random_seed(3)
).
如果您 运行 cross_val_score()
或您的手动版本两次会怎样?你得到相同的结果/数字吗?
我一直在努力理解为什么两个相似的 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
两个 CV 结果看起来差别不大,它们都在彼此的标准差范围内。
您已修复 StratifiedKFold
class 的种子,很好。但是,您应该控制额外的随机性,它来自 权重初始化 。确保为每个具有不同权重的 CV-运行 初始化模型,但对手动和自动交叉验证使用相同的 10 个初始化。您可以将 initializer 传递给每一层,它们也有一个 seed
参数。一般来说,你应该修复所有可能的种子 (np.random.seed(3)
, tf.set_random_seed(3)
).
如果您 运行 cross_val_score()
或您的手动版本两次会怎样?你得到相同的结果/数字吗?