Keras 是一个易于使用且功能强大的 Python 深度学习库。
在设计和配置深度学习模型时,需要做出许多决策。其中许多决策必须通过试错和在真实数据上进行评估来经验性地解决。
因此,拥有一个稳健的方法来评估神经网络和深度学习模型的性能至关重要。
在本帖中,您将了解使用 Keras 评估模型性能的几种方法。
通过我新书《Python 深度学习》启动您的项目,其中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。
- 2016 年 5 月:原始帖子
- 2016 年 10 月更新:更新了 Keras 1.1.0 和 scikit-learn v0.18 的示例
- 2017 年 3 月更新:更新了 Keras 2.0.2、TensorFlow 1.0.1 和 Theano 0.9.0 的示例
- 2018 年 3 月更新:添加了下载数据集的备用链接,因为原始链接似乎已被删除
- 2022 年 6 月更新:更新为 TensorFlow 2.x 语法

评估 Keras 中深度学习模型的性能
照片作者:Thomas Leuthard,部分权利保留。
经验性评估网络配置
在设计和配置深度学习模型时,您必须做出无数的决策。
许多这些决策可以通过模仿他人的网络结构和使用启发式方法来解决。最终,最好的技术是进行小型实验,并通过真实数据经验性地评估问题。
这包括关于网络中层数、大小和类型等高级决策。它还包括诸如损失函数、激活函数、优化过程以及训练轮数的选择等低级决策。
深度学习通常用于具有非常大的数据集的问题。即成千上万甚至数十万个实例。
因此,您需要一个强大的测试平台,该平台允许您估计给定配置在未见过的数据上的性能,并可靠地将性能与其他配置进行比较。
Python 深度学习需要帮助吗?
参加我的免费为期两周的电子邮件课程,发现 MLP、CNN 和 LSTM(附代码)。
立即点击注册,还将免费获得本课程的 PDF 电子书版本。
数据分割
大量的数据和模型的复杂性需要很长的训练时间。
因此,通常将数据分为训练集和测试集,或训练集和验证集。
Keras 提供了两种便捷的方法来评估您的深度学习算法。
- 使用自动验证数据集
- 使用手动验证数据集
使用自动验证数据集
Keras 可以将您的训练数据的一部分分离为验证数据集,并在每个 epoch 中在该验证数据集上评估模型的性能。
您可以通过将 fit()
函数上的 validation_split 参数设置为训练数据集大小的百分比来执行此操作。
例如,一个合理的值可能是 0.2 或 0.33,分别表示 20% 或 33% 的训练数据留作验证。
下面的示例演示了在小型二元分类问题上使用自动验证数据集。本帖中的所有示例都使用了Pima 印度人发病糖尿病数据集。您可以从 UCI 机器学习存储库下载,并将数据文件保存在当前工作目录中,文件名为 pima-indians-diabetes.csv(更新:从这里下载)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 具有自动验证集的 MLP from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense import numpy # 设置随机种子以保证结果可复现 numpy.random.seed(7) # 加载皮马印第安人糖尿病数据集 dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") # 分割为输入 (X) 和输出 (Y) 变量 X = dataset[:,0:8] Y = dataset[:,8] # 创建模型 model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 拟合模型 model.fit(X, Y, validation_split=0.33, epochs=150, batch_size=10) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。
运行示例,您可以看到每个 epoch 的详细输出显示了训练集和验证集上的损失和准确率。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... 纪元 145/150 514/514 [==============================] - 0s - loss: 0.5252 - acc: 0.7335 - val_loss: 0.5489 - val_acc: 0.7244 纪元 146/150 514/514 [==============================] - 0s - loss: 0.5198 - acc: 0.7296 - val_loss: 0.5918 - val_acc: 0.7244 第 147 周期/150 514/514 [==============================] - 0s - loss: 0.5175 - acc: 0.7335 - val_loss: 0.5365 - val_acc: 0.7441 第 148 周期/150 514/514 [==============================] - 0s - loss: 0.5219 - acc: 0.7354 - val_loss: 0.5414 - val_acc: 0.7520 第 149 周期/150 514/514 [==============================] - 0s - loss: 0.5089 - acc: 0.7432 - val_loss: 0.5417 - val_acc: 0.7520 第 150 周期/150 514/514 [==============================] - 0s - loss: 0.5148 - acc: 0.7490 - val_loss: 0.5549 - val_acc: 0.7520 |
使用手动验证数据集
Keras 还允许您手动指定用于训练期间验证的数据集。
在此示例中,您可以使用 Python scikit-learn 机器学习库中方便的 train_test_split() 函数将数据分成训练集和测试集。使用 67% 的数据进行训练,其余 33% 用于验证。
验证数据集可以通过 Keras 中的 validation_data
参数传递给 fit()
函数。它接受输入和输出数据集的元组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# 具有手动验证集的 MLP from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from sklearn.model_selection import train_test_split import numpy # 设置随机种子以保证结果可复现 seed = 7 numpy.random.seed(seed) # 加载皮马印第安人糖尿病数据集 dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") # 分割为输入 (X) 和输出 (Y) 变量 X = dataset[:,0:8] Y = dataset[:,8] # 将数据分为 67% 用于训练,33% 用于测试 X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=seed) # 创建模型 model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 拟合模型 model.fit(X_train, y_train, validation_data=(X_test,y_test), epochs=150, batch_size=10) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。
与之前一样,运行示例会提供详细的训练输出,其中包括每个 epoch 的模型在训练集和验证集上的损失和准确率。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... 纪元 145/150 514/514 [==============================] - 0s - loss: 0.4847 - acc: 0.7704 - val_loss: 0.5668 - val_acc: 0.7323 纪元 146/150 514/514 [==============================] - 0s - loss: 0.4853 - acc: 0.7549 - val_loss: 0.5768 - val_acc: 0.7087 第 147 周期/150 514/514 [==============================] - 0s - loss: 0.4864 - acc: 0.7743 - val_loss: 0.5604 - val_acc: 0.7244 第 148 周期/150 514/514 [==============================] - 0s - loss: 0.4831 - acc: 0.7665 - val_loss: 0.5589 - val_acc: 0.7126 第 149 周期/150 514/514 [==============================] - 0s - loss: 0.4961 - acc: 0.7782 - val_loss: 0.5663 - val_acc: 0.7126 第 150 周期/150 514/514 [==============================] - 0s - loss: 0.4967 - acc: 0.7588 - val_loss: 0.5810 - val_acc: 0.6929 |
手动 k 折交叉验证
机器学习模型评估的黄金标准是k 折交叉验证。
它提供了模型在未见过数据上性能的稳健估计。它通过将训练数据集分成 k 个子集,轮流在除一个子集(留出)之外的所有子集上训练模型,并在留出的验证数据集上评估模型性能来实现。该过程重复进行,直到所有子集都有机会成为留出的验证集。然后对创建的所有模型进行平均性能度量。
理解交叉验证意味着估计模型设计(例如,3 层与 4 层神经网络)而不是特定的拟合模型。您不希望使用特定数据集来拟合模型并比较结果,因为这可能由于该特定数据集更好地拟合一个模型设计。相反,您希望使用多个数据集进行拟合,从而产生相同设计的多个拟合模型,并取平均性能度量进行比较。
由于计算成本较高,交叉验证通常不用于评估深度学习模型。例如,k 折交叉验证通常与 5 或 10 折一起使用。因此,必须构建和评估 5 个或 10 个模型,这会显著增加模型评估时间。
尽管如此,当问题足够小时,或者当您有足够的计算资源时,k 折交叉验证可以为您提供对模型性能的偏差更小的估计。
在下面的示例中,您将使用 scikit-learn Python 机器学习库中方便的 StratifiedKFold 类将训练数据集分成 10 折。这些折是分层的,这意味着算法会尝试平衡每个折中每个类的实例数量。
该示例创建并评估了 10 个模型,使用了 10 个数据分割,并收集了所有分数。通过将 fit()
和 evaluate()
函数上的 verbose=0
参数传递给模型,可以关闭每个 epoch 的详细输出。
为每个模型打印性能,并将其存储起来。然后,在运行结束时打印模型性能的平均值和标准差,以提供模型准确率的稳健估计。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# 用于 Pima 印度人数据集的 MLP,带 10 折交叉验证 from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from sklearn.model_selection import StratifiedKFold import numpy as np # 设置随机种子以保证结果可复现 seed = 7 np.random.seed(seed) # 加载皮马印第安人糖尿病数据集 dataset = np.loadtxt("pima-indians-diabetes.csv", delimiter=",") # 分割为输入 (X) 和输出 (Y) 变量 X = dataset[:,0:8] Y = dataset[:,8] # 定义 10 折交叉验证测试平台 kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed) cvscores = [] for train, test in kfold.split(X, Y): # 创建模型 model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 拟合模型 model.fit(X[train], Y[train], epochs=150, batch_size=10, 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))) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请尝试运行示例几次并比较平均结果。
运行示例将花费不到一分钟的时间,并会产生以下输出
1 2 3 4 5 6 7 8 9 10 11 |
acc: 77.92% acc: 68.83% acc: 72.73% acc: 64.94% acc: 77.92% acc: 35.06% acc: 74.03% acc: 68.83% acc: 34.21% acc: 72.37% 64.68% (+/- 15.50%) |
总结
在本帖中,您了解了拥有一个稳健的方法来估计深度学习模型在未见过数据上的性能的重要性。
您了解了使用 Keras 库在 Python 中估计深度学习模型性能的三种方法:
- 使用自动验证数据集
- 使用手动验证数据集
- 使用手动 k 折交叉验证
您对 Keras 深度学习或本帖有任何疑问吗?请在评论中提问,我会尽力回答。
如何打印网络图
您可以使用 keras.utils 中的 plot_model 来绘制 keras 模型。链接:https://keras.org.cn/visualization/
您能否解释一下如何使用不同的评估指标(F1 分数或自定义指标)进行评估?
你好 Hendrik,您可以使用 Keras 模型的一系列目标函数,这里是一个列表
https://keras.org.cn/objectives/
感谢您的回复,但我不是指“optimizer”参数,而是指编译中的“metrics”,目前只能是“accuracy”。我想将其更改为另一个评估指标(例如 F1 分数或 AUC)。
嘿 Hendrik,你是否找到了在 Keras 中使用不同评估指标的解决方案?
你能否提供一些关于如何训练深度模型的说明?如果 X、y 非常大,无法放入内存?
model.fit(X_train, y_train, validation_data=(X_test,y_test), nb_epoch=150, batch_size=10)
好问题 shixudong。
Keras 有一个用于图像数据的 data generator,它不能完全放入内存。
https://keras.org.cn/preprocessing/image/
同样的方法也可以用于表格数据。
https://github.com/fchollet/keras/issues/107
我的数据集结构如下:
-data
–Train
——Dog
——Cat
–Test
——Dog
——Cat
1.如果我使用 flow_from_directory 函数,我如何知道 ImageDataGenerator 的 y_true 值?
2.如何使用 Keras 中的 fit_generator 函数进行 k 折交叉验证?
抱歉,除了用于图像增强之外,我没有其他使用 ImageDataGenerator 的示例。
您好,您现在需要更新它吗?
如何在 Keras 中使用 fit 函数进行机器学习的黄金标准 k 折交叉验证?
另外,如何使用 cross_val_score 模块获取准确率和损失历史以进行绘图?
谢谢,
andrew
好问题。
这是将 Keras 与 scikit-learn 的 k 折交叉验证结合使用的示例。
https://machinelearning.org.cn/use-keras-deep-learning-models-scikit-learn-python/
收集和显示单个训练/测试运行的历史记录要容易得多。这是一个例子。
https://machinelearning.org.cn/display-deep-learning-model-training-history-in-keras/
嘿 Jason,感谢您的精彩教程!
我想进行 CV,但不只读取训练数据的准确率,也读取测试数据的准确率。这个方法对吗?
kfold = StratifiedKFold(n_splits=folds, shuffle=True, random_state=seed)
for train, test in kfold.split(X, Y)
model = Sequential()
model.add(Dense(n, input_dim=dim, init=’uniform’, activation=’sigmoid’))
model.add(Dense(1, init=’uniform’, activation=’sigmoid’))
model.compile(loss=’mse’, optimizer=’adam’, metrics=[‘accuracy’])
asd = model.fit(X[train], Y[train], nb_epoch=epoch, validation_data=(X[test], Y[test]), batch_size=10, verbose=1)
cv_acc_train = asd.history[‘acc’]
cv_acc_test = asd.history[‘val_acc’]
Watterson,在我看来,这看起来不错。
asd = model.fit(X[train], Y[train], nb_epoch=epoch, validation_data=(X[test], Y[test])
请问,validation_data 是不是应该是 validation_data=(Y[test], Y[test])?另外,当我的激活函数是 softmax 时,我可以使用 categorical_crossentropy 吗?非常感谢。
你好 Seun,validation_data 必须包含 X 和 y 的组成部分。
是的,我认为您可以使用 logloss 与 softmax,试试看。
嗨,Jason,
当您使用“自动验证数据集”时,val_loss 低于 loss。
“768/768 [==============================] – 0s – loss: 0.4593 – acc: 0.7839 – val_loss: 0.4177 – val_acc: 0.8386”
这怎么可能?
非常感谢您的帮助和您的工作!
抱歉,我不明白您的问题,也许可以更具体一点?
我从之前的讲座中了解到,当验证误差低且略高于训练误差时,模型拟合得很好。
但是,在您的第一个示例(自动验证数据集)中,验证误差低于训练误差。我无法弄清楚模型如何在验证集上的表现优于训练集。
这是否意味着验证集不是随机定义的?
Jonas,问得好,
这可能是一个统计上的巧合,也是模型不稳定的迹象。
这也可能是数据划分不当的迹象,表明可能需要采用重复划分的策略。
为什么我们取批次大小=10,我的意思是它如何影响模型性能?
您可以在这里了解更多关于批次大小如何影响学习的信息
https://machinelearning.org.cn/how-to-control-the-speed-and-stability-of-training-neural-networks-with-gradient-descent-batch-size/
你好,我不是专家。但看起来你是在用二进制标签进行训练
Y = dataset[:,8] => 标签存在于第8列,对吗?
X = dataset[:,0:8] => 这包括第8列,即标签
我可能错了,我还没看数据集。
不,我相信代码是正确的(至少在Python 2.7中是这样)。
如果你在你的系统上得到不同的结果,我很乐意听取。
你好,Jason,对于一个简单的前馈MLP,在Keras和Sklearn之间进行选择,有什么直观的标准吗?
谢谢!
速度,Keras会更快,因为它使用优化的符号数学库作为CPU或GPU的后端,而sklearn仅限于CPU上的线性代数库。
你好,
非常感谢您的教程,它们非常棒!
这可能有点琐碎,但我想问一下在“model.fit”中使用验证集和不使用验证集之间的区别。而且,例如,如果我们不使用单独的训练/验证/测试集,只使用训练/测试集和验证集划分是否就足够了?
非常感谢!
这取决于你的问题。
如果你能节省数据,最好保留一个验证集用于最终检查。如果你有时间,可以使用k折交叉验证和多次重复来评估你的模型。我们通常没有时间,所以我们使用训练/测试分割。
嗨,Jason,
很好的例子,我喜欢读你的博客。
我有一个问题,如何决定轮数和批次大小?
谢谢
问得好!我推荐尝试和错误。
嗨,Jason,
这是一篇很棒的文章!
我正在努力结合类别交叉熵和分层K折。
根据
http://stackoverflow.com/questions/35022463/stratifiedkfold-indexerror-too-many-indices-for-array
分层K折假定响应是(数字,)形状。但正如你之前解释过的,Keras的类别交叉熵期望响应是一个独热矩阵。我该如何解决这个问题?
谢谢!
你可能需要从交叉验证中移开,并依赖于重复的随机训练/测试集。
或者,你可以尝试手动预先计算折叠,或者使用数据集的修改版本,然后在手动运行交叉验证。
我想你可以这样做
更改
Y=numpy.argmax(Y,axis=1)
然后使用: loss=’sparse_categorical_crossentropy’
它有效,但这是正确的方法吗?
这是一种方法。我建议评估许多方法,看看哪种最适合你的数据。
你好,Jason。
你的博客很棒!
我是keras的新手。在您最近的例子中,您在每个for循环中构建和编译keras模型(我在下面展示了您的代码)。我不知道是否可能,但它似乎更有效率,只需在for循环之外构建和编译一次模型,然后在循环中每次用正确的数据拟合它。在keras中这不可能吗?
for train, test in kfold.split(X, Y)
# 创建模型
model = Sequential()
model.add(Dense(12, input_dim=8, activation=’relu’))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation=’sigmoid’))
# 编译模型
model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
是的,但你可能需要重新初始化权重。
我正在展示循环内模型的完整独立性。
我正在使用lstm进行交叉验证代码,并遇到以下错误
发现维度为3的数组。估计器预期为<= 2。
我的代码如下
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []
for train, test in kfold.split(task_features_padded, task_label_padded)
# 创建模型
model=Sequential()
model.add(LSTM(50,input_shape=(max_seq,number_of_features),return_sequences = 1, activation = 'relu'))
model.add(Dropout(0.2))
model.add(Dense(1,activation='sigmoid'))
打印(model.summary())
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
print('Train…')
model.fit(task_features_padded[train], task_label_padded[train],batch_size=16,nb_epoch=1000,validation_data=(X_test,y_test),verbose=2)
#model.fit(X_train, y_train,batch_size=16,nb_epoch=1000,validation_data=(X_test,y_test),verbose=2)
#model.fit(X_train, y_train,batch_size=1,nb_epoch=1000,validation_data=(X_test,y_test),verbose=2)
score, acc = model.evaluate(task_features_padded[test], task_label_padded[test], batch_size=16,verbose=0)
#score, acc = model.evaluate(X_test, y_test, batch_size=16,verbose=0)
#score, acc = model.evaluate(X_test, y_test, batch_size=1,verbose=0)
print('Test score:', score)
print('Test accuracy:', acc)
scores = model.evaluate(X[test], Y[test], verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], acc*100))
cvscores.append(acc * 100)
task_features_padded 的形状是 (876, 6, 11)
task_label_padded 的形状是 (876, 6, 1)
我只是快速浏览了你的代码,不太确定。
我在FAQ的“你能阅读、审查或调试我的代码吗?”这个问题下有一些调试建议。
https://machinelearning.org.cn/start-here/#faq
希望这能有所帮助。
嗨,Jason,
在这篇文章的最后一部分,你训练了10个不同的模型,而不是在每个折叠上训练一个模型10次。
在其他情况下,我如何从这10个训练好的模型中选择最好的模型?这在机器学习中是一个好习惯吗?
谢谢,
Arno
问得好,请看这篇文章的最后一部分。
https://machinelearning.org.cn/randomness-in-machine-learning/
哇,我不是唯一一个有这些问题的人!
谢谢你的建议!这个网站确实很有帮助。
很高兴它有帮助。
你好,先生,
当我尝试在构建层之后运行代码时,我遇到了这个错误
FileNotFoundError: [WinError 3] 系统找不到指定的路径: ‘C:/deeplearning/openblas-0.2.14-int32/bin’
我通过以下方式更改了theano标志路径
variable = THEANO_FLAGS value = floatX=float32,device=cpu,blas.ldflags=-LC:\openblas -lopenblas
但我仍然遇到同样的问题……
谢谢你!!
抱歉,我没有见过这个错误。
考虑将其作为问题发布到stackoverflow或theano用户组。
嗨,Jason,
如何提供每个测试实例的预测分数(而不是预测标签或预测概率),而不是对整个测试集进行评估结果?
谢谢。
您可以使用以下方法预测概率:
你好Jason,谢谢你的帖子。你的博客对学习Python机器学习非常有帮助,我非常非常感谢你与我们分享这些。谢谢,工作干得好!Muito obrigado, você é muito generoso em compartilhar seu conhecimento。
谢谢José,我很高兴它有帮助。
嘿Jason,感谢你的许多帖子和回复。
我尝试按照本教程来训练和评估一个多输出(3)回归深度网络,使用的是keras的模型类API,这是我的代码
#定义交叉验证方案
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []
for train, test in kfold.split(X_training, [Y_training10,Y_training20,Y_training30])
# 创建模型
inputs=Input(shape=(72,),name=’input_layer’)
x=Dense(200,activation=’relu’,name=’hidden_layer1′)(inputs)
x=Dropout(.2)(x)
y1=Dense(1,name=’GHI10′)(x)
y2=Dense(1,name=’GHI20′)(x)
y3=Dense(1,name=’GHI30′)(x)
model=Model(inputs=inputs,outputs=[y1,y2,y3])
# 编译模型
model.compile(loss=’mean_squared_error’, optimizer=’rmsprop’,metrics=’mean_absolute_error’)
#拟合模型
model.fit(X_training[train],[Y_training10[train],Y_training20[train],Y_training30[train]] ,epochs=100, batch_size=10, verbose=1)
#评估模型
Scores=model.evaluate(X_training[test],[Y_training10[test],Y_training20[test],Y_training30[test]], verbose=1, sample_weight=None)
print(“%s: %.2f%% (MSE)” % (model.metrics_names[1], scores[1]))
print(“%s: %.2f%% (MSE)” % (model.metrics_names[2], scores[2]))
print(“%s: %.2f%% (MSE)” % (model.metrics_names[3], scores[3]))
cvscores.append([scores[1],scores[2],scores[3]])
print(“%.2f MSE of training” % (numpy.mean(cvscores,axis=0)))
但不幸的是,我得到了这个错误
发现输入变量的样本数不一致:[15000,3]。
我有一个[15000样本 x 72预测器]的X_training和[15000样本 x 3输出]的[Y_training10, Y_training20, Y_training30]。
任何帮助都将不胜感激。
你必须确保你的输入和输出数据与你的网络相匹配,并且训练和测试具有相同数量的特征。
你好,谢谢你写了一篇很棒的相关性文章。我有一个关于实现训练\测试\验证80\10\10的问题。这在以下问题中有概述:https://stats.stackexchange.com/questions/19048/what-is-the-difference-between-test-set-and-validation-set --我该如何进一步划分我的测试集?
很高兴能帮到你Ashley。
你为什么要进一步划分你的数据?
这是Udacity的ML课程中的内容。他们使用验证集和测试集。这在以下讲座中有概述:https://classroom.udacity.com/courses/ud730/lessons/6370362152/concepts/63798118330923 课程1 #22。他们解释说,你的测试数据会随着时间的推移渗入你的训练数据,这会使训练偏差,所以要进一步划分你的数据,在训练数据上训练,在验证集上验证,直到最后才在测试数据上测试。
这个链接指向#22 https://classroom.udacity.com/courses/ud730/lessons/6370362152/concepts/63798118300923
正如我所说,我意识到一种方法是训练和验证然后保存模型,然后加载模型并在测试集上进行测试。
当然,你的问题是什么?
最初是:我如何同时处理验证集和测试集,并在最终运行后获得两个不同的测试输出?即:我如何设置我的模型来分割测试/验证集(因此在一个会话中拥有训练、验证、测试)?
现在我只是假设我应该在我的数据上进行训练(拟合),根据我的验证数据优化我的网络(评估)并保存模型。然后重新加载它并再次进行评估,但这次是在它从未见过的新数据上——我希望这能帮助我处理我拥有的少量数据。
你可以做到,听起来不错。
嘿,Jason。很棒的网站!我喜欢你布置文章的方式和你解释概念的方式。我还没有弄清楚k-fold的最终结果。假设我像你在例子中那样执行k-fold。然后,我使用你另一篇精彩文章中的代码来保存模型(到JSON)并保存权重。在k-fold循环中创建的10个模型中,哪个会被保存?最后那一个?
我想要一个可以用于新数据集的已保存模型。通过k-fold创建10个模型如何帮助我获得比使用自动验证集(如本文所述)更好的模型?
谢谢!
与训练/测试分割相比,CV对模型在未见数据上的技能的估计偏差更小,至少在数据集较小(少于数百万个观测值)的情况下是这样。
一旦你调整好了你的模型,就丢弃所有训练好的模型,用所有数据训练一个最终模型,然后开始用它来做预测。
请看这篇文章
https://machinelearning.org.cn/train-final-machine-learning-model/
有些模型训练成本很高,在这种情况下,不要使用CV,而是保留你训练的最好的模型,将它们用于集成作为最终模型。
这有帮助吗?
是的,那篇文章正是我需要的。谢谢!
很高兴听到这个Michael。
你好,Jason
我是你的电子书读者之一:)
让我问一个奇怪的行为,我的案例。
当我使用数据集训练和验证我的模型时,例如
model.fit( train_x, train_y, validation_split=0.1, epochs=15, batch_size=100)
看起来是过拟合的,从acc和val_acc之间可以看出。
67473/67473 [==============================] – 27s – loss: 2.9052 – acc: 0.6370 – val_loss: 6.0345 – val_acc: 0.3758
Epoch 2/15
67473/67473 [==============================] – 26s – loss: 1.7335 – acc: 0.7947 – val_loss: 6.2073 – val_acc: 0.3788
Epoch 3/15
67473/67473 [==============================] – 26s – loss: 1.5050 – acc: 0.8207 – val_loss: 6.1922 – val_acc: 0.3952
Epoch 4/15
67473/67473 [==============================] – 26s – loss: 1.4130 – acc: 0.8380 – val_loss: 6.2896 – val_acc: 0.4092
Epoch 5/15
67473/67473 [==============================] – 26s – loss: 1.3750 – acc: 0.8457 – val_loss: 6.3136 – val_acc: 0.3953
Epoch 6/15
67473/67473 [==============================] – 26s – loss: 1.3350 – acc: 0.8573 – val_loss: 6.4355 – val_acc: 0.4098
Epoch 7/15
67473/67473 [==============================] – 26s – loss: 1.3045 – acc: 0.8644 – val_loss: 6.3992 – val_acc: 0.4018
Epoch 8/15
67473/67473 [==============================] – 26s – loss: 1.2687 – acc: 0.8710 – val_loss: 6.5578 – val_acc: 0.3897
Epoch 9/15
67473/67473 [==============================] – 26s – loss: 1.2552 – acc: 0.8745 – val_loss: 6.4178 – val_acc: 0.4104
Epoch 10/15
67473/67473 [==============================] – 26s – loss: 1.2195 – acc: 0.8796 – val_loss: 6.5593 – val_acc: 0.4044
Epoch 11/15
67473/67473 [==============================] – 26s – loss: 1.1977 – acc: 0.8833 – val_loss: 6.5514 – val_acc: 0.4041
Epoch 12/15
67473/67473 [==============================] – 26s – loss: 1.1828 – acc: 0.8874 – val_loss: 6.5972 – val_acc: 0.3973
Epoch 13/15
67473/67473 [==============================] – 26s – loss: 1.1665 – acc: 0.8890 – val_loss: 6.5879 – val_acc: 0.3882
Epoch 14/15
67473/67473 [==============================] – 26s – loss: 1.1466 – acc: 0.8931 – val_loss: 6.5610 – val_acc: 0.4104
Epoch 15/15
67473/67473 [==============================] – 27s – loss: 1.1394 – acc: 0.8925 – val_loss: 6.5062 – val_acc: 0.4100
但是,当我使用StratifiedKFold(n_splits=10, shuffle=True, random_state=7)将数据分割成训练和测试集时
并用测试数据进行评估,它显示了良好的准确性结果。
score = model.evaluate(test_x, test_y)
[1.3547255955601791, 0.82816451482507525]
所以……我尝试用StratifiedKFold分割的测试数据集进行验证。
model.fit( train_x, train_y, validation_data=(test_x, test_y), epochs=15, batch_size=100)
它显示了良好的val_acc结果。
Epoch 1/14
67458/67458 [==============================] – 27s – loss: 2.9200 – acc: 0.6006 – val_loss: 1.9954 – val_acc: 0.7508
Epoch 2/14
67458/67458 [==============================] – 26s – loss: 1.8138 – acc: 0.7536 – val_loss: 1.6458 – val_acc: 0.7844
Epoch 3/14
67458/67458 [==============================] – 26s – loss: 1.5869 – acc: 0.7852 – val_loss: 1.5848 – val_acc: 0.7876
Epoch 4/14
67458/67458 [==============================] – 25s – loss: 1.4980 – acc: 0.8056 – val_loss: 1.5353 – val_acc: 0.8015
Epoch 5/14
67458/67458 [==============================] – 25s – loss: 1.4375 – acc: 0.8202 – val_loss: 1.4870 – val_acc: 0.8117
Epoch 6/14
67458/67458 [==============================] – 25s – loss: 1.3795 – acc: 0.8324 – val_loss: 1.4738 – val_acc: 0.8139
Epoch 7/14
67458/67458 [==============================] – 26s – loss: 1.3437 – acc: 0.8400 – val_loss: 1.4677 – val_acc: 0.8146
Epoch 8/14
67458/67458 [==============================] – 26s – loss: 1.3059 – acc: 0.8462 – val_loss: 1.4127 – val_acc: 0.8263
Epoch 9/14
67458/67458 [==============================] – 26s – loss: 1.2758 – acc: 0.8533 – val_loss: 1.4087 – val_acc: 0.8219
Epoch 10/14
67458/67458 [==============================] – 25s – loss: 1.2381 – acc: 0.8602 – val_loss: 1.4095 – val_acc: 0.8242
Epoch 11/14
67458/67458 [==============================] – 26s – loss: 1.2188 – acc: 0.8644 – val_loss: 1.3960 – val_acc: 0.8272
Epoch 12/14
67458/67458 [==============================] – 25s – loss: 1.1991 – acc: 0.8677 – val_loss: 1.3898 – val_acc: 0.8226
Epoch 13/14
67458/67458 [==============================] – 25s – loss: 1.1671 – acc: 0.8733 – val_loss: 1.3370 – val_acc: 0.8380
Epoch 14/14
67458/67458 [==============================] – 25s – loss: 1.1506 – acc: 0.8750 – val_loss: 1.3363 – val_acc: 0.8315
您对自动验证集划分和使用测试数据集进行验证的结果有什么想法吗?
提前感谢。
使用交叉验证时不需要验证。模型正在做双倍的工作。
也许数据样本的分类对你的模型很重要?
也许模型在较小的样本上表现更好(例如,如果10折,则为数据量的1/10)?
我在这里遇到同样的问题,当你在Kfold CV时设置shuffle=False,你的准确率也很低。自动validation_split没有打乱验证数据。
你可以试试
StratifiedKFold(n_splits=10, shuffle=True, random_state=7)
model.fit( train_x, train_y, validation_split=0.1, epochs=15, verbose=1 ,batch_size=100)
score = model.evaluate(test_x, test_y)
你会看到val_acc非常低,最终得分很好。
你好,
首先祝贺这些教程,它们非常棒!
我正在尝试在多输入网络(3个输入)上使用分层K折验证进行回归问题,并且在使用时遇到了一些问题。首先,在步骤
“for train,test in kfold.split()”我只引入了其中一个输入和标签结构,如下所示:“for train, test in kfold.split(X1, Y):”,然后在循环内部我定义“X1_train = X1[train], X2_train = X2[train], X3_train=X3[train]”等等。这样,在拟合我的模型时,我使用“model.fit([X1_train, X2_train, X3_train], Y_train….)”。但我得到了错误“n_splits=10不能大于每个类中的成员数”,我不知道如何修复它。
我也尝试了您在本教程中提供的选项:https://machinelearning.org.cn/regression-tutorial-keras-deep-learning-library-python/
但这次我收到的错误是“发现输入变量的样本数不一致”。
我不知道如何实现这一点,我将非常感谢任何帮助。谢谢。
所有行必须具有相同数量的列,这有帮助吗?
X1、X2 和 X3 的形状为 (nb_samples, 2, 8, 10),而 Y 的形状为 (nb_samples, 4)。我不知道它是否无法识别共同的轴是 nb_samples(尽管我在文档中读到它默认取第一个轴)。
我通过创建一个只有一个维度的零结构来解决它:X_split = np.zeros((X1.shape[0])) 和 Y_split = np.zeros((Y.shape[0])),然后我使用这两个数组来创建 for 循环。但我不知道为什么不能用其他方式来做。
你好,我遇到了同样的问题。你能提供代码示例吗?
你为 X2 和 X3 创建了 X_split= = np.zeros((X1.shape[0])),并且之前为 Y 创建了 Y_split。
kfold.split(X1, Y)?
谢谢你
Hi Jason,感谢你的博客,我从你的帖子中学到了很多。
我在使用 Keras 时遇到一个奇怪的问题,我的问题是回归问题,我想在训练时显示和记录损失和验证损失。但是当我只指定“validation_split”时,我只能得到“loss”而没有“validation loss”。在我手动将“validation_data”指定给 model.fit 后,我就可以得到“loss”和“validation loss”。
根据 Keras 的文档,“validation_split”将使用最后 XX% 的数据而不进行打乱作为验证数据,我假设它也应该有“validation loss”,但我找不到和获取它。你有什么想法吗?提前感谢!
如果你设置了 validation data 或 validation split,那么如果 verbose=1,在每个 epoch 都会打印 validation loss,并且在运行结束时可以在 history 对象中找到它。
Hi Jason,在进行 k-fold CV 之后,你如何用你的全部数据集训练 NN?因为通常,我们会训练它直到验证集准确率不断提高。在将 NN 应用到实际之前,我们想在整个数据集上训练它,如果我们数据集的大小很小。我们应该如何训练呢?
好问题,请看这篇帖子
https://machinelearning.org.cn/train-final-machine-learning-model/
Hi Jason。我使用 Keras 训练了一个用于 MRI 图像分割的网络。我的测试数据没有 ground truth。我需要将网络在测试集上的输出保存为图像并提交给评估。我想问你如何在测试部分执行此过程。据我所知,在 Keras 中进行评估,我需要测试样本和相应的 ground truth!
是的,你需要 ground truth 才能评估任何模型。
感谢你宝贵的教程
我有一个关于在 tensorflow+keras 中混淆测试集和验证集的问题。
在你的教程中,验证数据集不影响训练,并且与训练过程完全无关。
验证数据集仅用于监控和提前停止。此外,验证集不用于训练(更新权重、梯度下降等)。
然而,我发现维基百科的说法不同,如下所示:
验证数据集是一组用于调整分类器超参数(即架构)的示例。
链接:https://en.wikipedia.org/wiki/Training,_test,_and_validation_sets
听起来验证数据集是用于调整参数,这意味着它被用于训练过程。
如果这是真的,我们将面临过拟合。
如果你的教程中验证数据集不影响训练,那么 Keras 是否会自动使用训练数据集的一部分来进行验证和调整参数?
是的,验证集用于调整模型,它是训练数据集的一个子集。
也许这篇帖子能让你更清楚
https://machinelearning.org.cn/difference-test-validation-datasets/
感谢 Jason Brownlee 先生的快速回复
让我再次澄清我的问题,我问这个问题不是因为我不知道三个数据集的概念。
是因为我不知道 Keras 的后台是如何使用这些数据集的。
例如。在这篇教程中 https://machinelearning.org.cn/sequence-classification-lstm-recurrent-neural-networks-python-keras/
你只定义了两个数据集,如
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=top_words)
你说如果 K-fold 交叉验证(在这种情况下,验证集是从训练集中选取的),验证数据集可能会消失,但是在教程中我们没有使用 k-fold 交叉验证。那么验证集在哪里?它还在训练集中吗?
在下面的代码中,fit 函数使用了 validation_data 来调整参数,不是吗?而且你还将测试数据分配给了 validation data。在这种情况下,我们需要新的测试数据来进行评估,对吗?
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=64)
在下面的代码中,evaluate 函数的结果是无偏估计,对吗?那么验证数据在哪里?Keras 后台代码会自动分割 X_train 到训练集和验证集吗?
model.fit(X_train, y_train, nb_epoch=3, batch_size=64)
# 模型的最终评估
scores = model.evaluate(X_test, y_test, verbose=0)
我们不必使用验证数据集,在许多教程中,我为了简洁而省略了这部分过程。
意思是 Keras 会自动为验证和调整参数选择训练数据集的一部分吗?
如果我们不使用验证数据集,如何调整参数?
它可以选择一部分,或者我们可以指定它。
你可以在训练数据集上进行调整。
嗨,Jason,
非常感谢你的博客和示例,太棒了!
你看,我合并了你的两个示例:上面的示例和“保存和加载你的 Keras 深度学习模型”(https://machinelearning.org.cn/save-load-keras-deep-learning-models/)。你可以看下面的代码
# 用于 Pima 印度人数据集的 MLP,带 10 折交叉验证
来自 keras.models import Sequential
from keras.layers import Dense
从 sklearn.model_selection 导入 StratifiedKFold
from keras.models import model_from_json
import numpy
# 设置随机种子以保证结果可复现
seed = 7
numpy.random.seed(seed)
# 加载皮马印第安人糖尿病数据集
dataset = numpy.loadtxt(“pima-indians-diabetes.csv”, delimiter=”,”)
# 分割为输入 (X) 和输出 (Y) 变量
X = dataset[:,0:8]
Y = dataset[:,8]
#构建模型
def make_model()
model = Sequential()
model.add(Dense(12, input_dim=8, activation=’relu’))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation=’sigmoid’))
# 编译模型
model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
return(model)
# 定义 10 折交叉验证测试平台
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []
for train, test in kfold.split(X, Y)
# 创建模型
model = make_model()
# 拟合模型
model.fit(X[train], Y[train], epochs=150, batch_size=10, verbose=0)
# 将模型序列化为JSON
model_json = model.to_json()
with open(“model.json”, “w”) as json_file
json_file.write(model_json)
# 将权重序列化为HDF5
model.save_weights(“model.h5”)
print(“Saved model to disk”)
# 评估模型
scores = model.evaluate(X[test], Y[test], verbose=0)
print(“%s: %.2f%%” % (model.metrics_names[1], scores[1]*100))
cvscores.append(scores[1] * 100)
del model_json
del model
print(“%.2f%% (+/- %.2f%%)” % (numpy.mean(cvscores), numpy.std(cvscores)))
# 加载 json 并创建模型
json_file = open(‘model.json’, ‘r’)
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# 将权重加载到新模型中
loaded_model.load_weights(“model.h5”)
print(“Loaded model from disk”)
# 在测试数据上评估加载的模型
loaded_model.compile(loss=’binary_crossentropy’, optimizer=’rmsprop’, metrics=[‘accuracy’])
score = loaded_model.evaluate(X, Y, verbose=0)
print(“%s: %.2f%%” % (loaded_model.metrics_names[1], score[1]*100))
输出如下:
Saved model to disk
acc: 76.62%
Saved model to disk
acc: 74.03%
Saved model to disk
acc: 71.43%
Saved model to disk
acc: 72.73%
Saved model to disk
acc: 70.13%
Saved model to disk
acc: 64.94%
Saved model to disk
acc: 66.23%
Saved model to disk
acc: 64.94%
Saved model to disk
acc: 63.16%
Saved model to disk
acc: 72.37%
69.66% (+/- 4.32%)
Loaded model from disk
acc: 75.91%
我本来天真地期望得到最后一个保存的模型(72.37%)的保存准确率,但我得到了 75.91%。你能解释一下权重是如何在 k-fold 交叉验证中保存的吗?
谢谢,
Estelle
机器学习算法是随机的,请参阅这篇帖子了解更多详情。
https://machinelearning.org.cn/randomness-in-machine-learning/
嗨,Jason,
感谢你的快速回复和引用。
是的,我忘了随机性发生在这么多层面上。
谢谢。
确实如此!
嗨,Jason,
我在我的分类模型中尝试使用你的示例,但遇到了这个错误:
ValueError: 支持的目标类型有:('binary', 'multiclass')。但得到了 'multilabel-indicator'。
很抱歉听到这个。请确保你所有的 Python 库都是最新的,并且你复制了示例中的所有代码。
这可能与 KFold 或 StratifiedKFold 定义“multi-label”的方式有关,请参阅此处:https://stackoverflow.com/questions/48508036/sklearn-stratifiedkfold-valueerror-supported-target-types-are-binary-mul/51795404#51795404
先生,您能建议一下如何为这种情况执行分层 k-fold 交叉验证吗?
https://gist.github.com/dirko/1d596ca757a541da96ac3caa6f291229
抱歉,我没有能力审查您的代码。
抱歉,这不是我的代码——只是在网上找到的,我还在学习——所以我想知道,如果存在前向和后向训练和测试数据,如何将两个参数传递给 kfold.split(X, Y)?
正如链接中所示,它给出了 X_enc_f、X_enc_b 以及 y_enc 作为前向、后向和标签编码器。
也许这个文档会有帮助
https://scikit-learn.cn/stable/modules/generated/sklearn.model_selection.KFold.html
嗨 Jason,
在使用 k-folds 时,如何应用 model.predict?
我想为我的模型创建一个分类报告,可能还有一个 AUC 图、热力图、精确率-召回曲线。
好问题,请参阅这篇关于创建最终模型的帖子。
https://machinelearning.org.cn/train-final-machine-learning-model/
抱歉,我的意思是,在使用 kfold.split 方法时,如何编写 model.predict/predict_proba?
我看到的那些不使用 k-folds 的示例,在应用 model.fit 之后有像 model.predict(x_test) 这样的代码。
我想使用 precision_recall_curve 和 roc_curve 以及 k-folds。
你不用。CV 是用来评估模型的,然后你可以构建一个最终模型。请参阅我链接的帖子。
我们正在对一个光学字符识别数据集进行 10 折交叉验证。我们使用了 kfold 和 kerasclassifier 函数。我们输出的一个快照是:
18000/18000 [==============================] – 1s – loss: 0.5963 – acc: 0.8219
Epoch 144/150
18000/18000 [==============================] – 1s – loss: 0.5951 – acc: 0.8217
纪元 145/150
18000/18000 [==============================] – 1s – loss: 0.5941 – acc: 0.8219
纪元 146/150
18000/18000 [==============================] – 1s – loss: 0.5928 – acc: 0.8225
第 147 周期/150
18000/18000 [==============================] – 1s – loss: 0.5908 – acc: 0.8234
第 148 周期/150
18000/18000 [==============================] – 2s – loss: 0.5903 – acc: 0.8199
第 149 周期/150
18000/18000 [==============================] – 1s – loss: 0.5892 – acc: 0.8217
第 150 周期/150
18000/18000 [==============================] – 1s – loss: 0.5917 – acc: 0.8235
1720/2000 [========================>…..] – ETA: 0s Accuracy: 81.24% (0.94%)
如何解释这个输出?
它显示了进度(当前 epoch 数 n / 总 epoch 数 m)、损失(正在最小化)和准确率(正在最大化)。
问题究竟是什么?
你好 Jason,
我理解得对吗:使用 K-folds 不一定会提高模型的准确率,而是会提供更现实(或“准确”)的准确率?我的模型在使用你的 kfolds 示例时得分或准确率比一个简单地在测试数据上评估的模型略低。
scores = model.evaluate(X_test, Y_test)
是的,其思想是 k-fold 交叉验证提供了对模型在未见过数据上表现的较低偏差的估计。
这是平均值。
困难的问题或不合适的 k 值仍然可能导致较差的技能估计。
嗨,Jason,
我很欣赏你的教程。说实话,我想从头开始编写 k-fold 交叉验证,但我不知道哪个教程对新手学生更好。我想为 lstm、Rnn、cnn 编写 k-fold 交叉验证。
你能推荐我哪个链接最好吗?
1-https://machinelearning.org.cn/use-keras-deep-learning-models-scikit-learn-python/
2-https://machinelearning.org.cn/evaluate-skill-deep-learning-models/
3-https://towardsdatascience.com/train-test-split-and-cross-validation-in-python-80b61beca4b6
4- https://www.kaggle.com/stefanie04736/simple-keras-model-with-k-fold-cross-validation
如果有任何更好的教程链接来教授 Keras 中的深度学习函数进行 k-fold 交叉验证,以及 TensorFlow,请介绍给我们。
任何回答都会受到赞赏。
祝好
Maryam
选择一个适合你风格的教程。
说实话,它们彼此不同,我不知道哪个适合为 RNN、CNN、LSTM 编写 k-fold 交叉验证?
编写 k-fold 交叉验证的代码是不同的。
请告诉我哪个代码对这个问题有效?
谢谢
对于 RNN,您可能需要使用前向验证而不是 k-fold 交叉验证。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
嗨,Jason,
我很感激这个链接。但我有一个情感分析二元分类问题。提供的链接是用于时间序列预测,这并非我的问题。
我不知道哪些代码适合为二元情感分析(文本分类)编写 k-fold 交叉验证,因为代码是不同的,而且我还没有看到用于 cnn 或 lstm 的 k-fold 交叉验证代码。
您能否为我介绍一个类似的示例代码?
任何回复都会受到赞赏。
如果您有资源,我建议使用 scikit-learn 进行深度学习模型的交叉验证。
就像我在提供的链接中那样。
示例中使用的特定数据集无关紧要,您感兴趣的是交叉验证。
我无法为您编写代码。您拥有所需的一切。
嗨,Jason,
我应该感谢这个教程,但当我将你的代码复制并粘贴到我的 spyder 中时,它在这一行命令上给了我一个错误:“model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])”。
错误是:model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
^
IndentationError: unindent does not match any outer indentation level.
但我确信我写的代码和你的一模一样。
为了解决这个问题,我删除了缩进并像下面这样编写代码,但它只给了我最终结果 = acc: 64.47%..
但我想给出每个折叠的结果,就像你的那样。
acc: 77.92%
acc: 68.83%
acc: 72.73%
acc: 64.94%
acc: 77.92%
acc: 35.06%
acc: 74.03%
acc: 68.83%
acc: 34.21%
acc: 72.37%
64.68% (+/- 15.50%)
当我删除缩进空间时,代码只给了我这个结果:acc: 64.47%
64.47% (+/- 0.00%)
我自己的代码,在删除缩进后是这样的:
for train, test in kfold.split(X, Y)
# 创建模型
model = Sequential()
model.add(Dense(12, input_dim=8, activation=’relu’))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation=’sigmoid’))
# 编译模型
model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
model.fit(X[train], Y[train], epochs=15, batch_size=10, 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%%)” % (numpy.mean(cvscores), numpy.std(cvscores)))
我只写了我改变的部分=删除缩进。
我的代码和你代码的不同之处仅仅在于这 5 行命令的缩进,它们是:
model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
model.fit(X[train], Y[train], epochs=150, batch_size=10, 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)
是什么原因导致我输入和你一样的代码时出现这个错误(model.compile(loss=’binary_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
^
IndentationError: unindent does not match any outer indentation level)
我该如何修复这个错误?
我真的很需要你的帮助。
抱歉写得这么长。
此致
Maryam
请确保代码在同一行,例如,这是一个 Python 语法错误。
现在它工作正常了。
谢谢您。
很高兴听到这个消息。
你好,Jason。感谢你的教程。我想在我的代码中使用 KStratifiedFold,但不知道如何操作。这是基于 Keras 博客文章“
使用极少数据构建强大的图像分类模型”。在这里,代码作者使用了“fit_generator”,而不是“X = dataset[:,0:8], Y = dataset[:,8]”。
我该如何实现?我已经为此苦思冥想了好几周,但毫无头绪……
我愿意接受所有建议,任何回答都会受到赞赏。
此致,
SUH
附注:这是完整的代码。
抱歉,我无法为您调试代码。也许可以发布到 Stack Overflow。
你好,
感谢您的辛勤工作。每次我有一个问题,谷歌通常会将我引导到您的网站。
我来这里是因为我搜索了“如何使用 model.fit_generator 计算 AUC”,我发现您的一个读者遇到了类似的问题,但您只使用了“ImageDataGenerator”进行增强。
我试过
——————————————————————————————————————
from sklearn.metrics import roc_curve, auc
y_pred = InceptionV3_model.predict_generator(test_generator,2000 )
但不知道如何获取 y_test
roc_auc_score(y_test, y_pred)
y_test 将是测试数据集的预期输出。
嗨,Jason
请详细说明验证集、训练集分数和测试集分数之间的区别?
这篇文章可能会有帮助
https://machinelearning.org.cn/difference-test-validation-datasets/
你好,
非常感谢这篇精彩的文章……学到了很多……我采用了 5 折交叉验证的方法来处理我的数据集,其中包含 2000 篇帖子,使用了 25 个 epoch。准确率在每一折之后都在不断提高,最终达到了 97% 以上……但是,在您的博客中,准确率在所有折中要么提高,要么降低。您能解释一下为什么我的结果不同吗?
绘制折 1 的准确率、精确率、召回率
准确率::92.18%
绘制折 2 的准确率、精确率、召回率
准确率::95.84%
绘制折 3 的准确率、精确率、召回率
准确率::98.03%
绘制折 4 的准确率、精确率、召回率
准确率::99.26%
绘制折 5 的准确率、精确率、召回率
准确率::100.00%
5 折交叉验证的准确率及标准差
97.21% (+/- 2.57%)
在给定算法的随机性质的情况下,模型在任何给定运行中的技能都是随机的。您可以在这里了解更多信息
https://machinelearning.org.cn/randomness-in-machine-learning/
嗨,Jason
我是 Python 和深度学习的新手
感谢您所有的教程,到目前为止我学到了很多
我有一个问题,您能简单地向我解释一下
模型中的 val_acc、loss 和 val-loss 是什么意思?它们告诉我们什么?
我读了很多评论和文章,但还是没弄明白
epoch 145/150
514/514 [==============================] – 0s – loss: 0.4847 – acc: 0.7704 – val_loss: 0.5668 – val_acc: 0.7323
纪元 146/150
514/514 [==============================] – 0s – loss: 0.4853 – acc: 0.7549 – val_loss: 0.5768 – val_acc: 0.7087
第 147 周期/150
514/514 [==============================] – 0s – loss: 0.4864 – acc: 0.7743 – val_loss: 0.5604 – val_acc: 0.7244
第 148 周期/150
514/514 [==============================] – 0s – loss: 0.4831 – acc: 0.7665 – val_loss: 0.5589 – val_acc: 0.7126
第 149 周期/150
514/514 [==============================] – 0s – loss: 0.4961 – acc: 0.7782 – val_loss: 0.5663 – val_acc: 0.7126
第 150 周期/150
514/514 [==============================] – 0s – loss: 0.4967 – acc: 0.7588 – val_loss: 0.5810 – val_acc: 0.6929
再次感谢
val_loss 是在验证集上计算的损失。
val_acc 是在验证集上计算的准确率。
它们与在训练集上计算的 loss 和 acc 不同。
这有帮助吗?
是的,谢谢 🙂
你好,非常感谢这个教程,我一直在寻找这样的东西,很高兴我终于找到了。但是我想知道如何在示例中可视化这个神经网络的训练,在您的一篇教程中,我可以绘制“val_acc”与“acc”的图,但在这里我无法做到,因为这里没有“val_acc”在 k 折交叉验证中。所以请问如果我用 k 折交叉验证进行评估,我该如何做?谢谢
好问题,这是一个例子
https://machinelearning.org.cn/display-deep-learning-model-training-history-in-keras/
您可以绘制一个训练/测试过程的学习曲线,或者绘制所有过程的学习曲线,例如
https://machinelearning.org.cn/diagnose-overfitting-underfitting-lstm-models/
嗨!
感谢教程,非常有帮助。我使用了 validation_data 方法,它似乎有效并且在每个 epoch 产生不同的准确率(可能在训练和验证之间),但它在模型开始前会显示一个令人困惑的声明
“在 15,000 个样本上训练,在 15,000 个样本上验证。”
这是否意味着我搞砸了,将相同的数据同时用作训练和验证,或者我没问题?在我的例子中,训练集有 15,000 个样本,验证集有 10,000 个样本。
非常感谢!
也许可以确认一下训练集和验证集的大小/形状,以确保您已按照预期设置了它们。
是的,它显然会读取两次训练集。谢谢!
你好,
谢谢。如何将手动 K 折交叉验证改为适用于多类别?例如 Y 是一个 100x4 的零和一数组?
模型是多类别的,而不是交叉验证。
深度学习模型可以通过在隐藏层中为每个类别设置一个神经元并使用 softmax 激活函数来支持多类别分类。
这里有一个例子
https://machinelearning.org.cn/multi-class-classification-tutorial-keras-deep-learning-library/
如果训练阶段的目标是在每个 epoch 中提高我们的模型准确率并降低模型的损失,为什么您要在每次折叠迭代时创建和编译一个新模型?
很好的问题。
我们想知道模型在平均情况下的表现如何,当它在来自该领域的随机样本上进行训练,并在该领域的其他数据上进行预测时。
为了计算这个估计值,我们使用重采样方法,如 k 折交叉验证,这些方法可以有效地利用固定大小的训练数据集。
一旦我们选择了具有最佳估计技能的模型+配置,我们就可以在所有可用数据上对其进行训练,并使用它开始进行预测。
这有帮助吗,Victor?
你好!
是否可以绘制由 StratifiedKFold 类进行的验证产生的准确率和损失图(历史)?
是的,但您将为每个折叠生成一个图。您可能还需要手动迭代折叠以捕获历史并进行绘制。
是的,我能够为每个折叠制作一个图,但我想只制作两个图,一个图是平均准确率,另一个图是 k 折的平均损失。
您可以创建两个图,并在每个图上为每个折叠添加一条线。
我发现如果您的训练数据输入“X”是 Pandas DataFrame,那么您必须使用 X.loc[train] 才能使其正常工作。否则,直接提供 NumPy 数组的 DataFrame 索引(kfold.split 的解包是 NumPy 数组)将引发 KeyError。
在上面的教程中,我们加载数据时使用的是 NumPy 数组。
医生您好。感谢您的示例,它们非常直接。您能用 R 实现 Pima CNN 吗?
不,它没有任何时序或空间结构。
你好,
我在打印混淆矩阵、分类报告和绘制 AUC 曲线时遇到问题。
如果您能提供在 10 折交叉验证的神经网络中使用 Keras 打印混淆矩阵、分类报告和绘制 AUC 曲线的方法,将非常有帮助。
谢谢
这篇帖子将帮助您了解混淆矩阵
https://machinelearning.org.cn/confusion-matrix-machine-learning/
我有关于 ROC 曲线的待发帖子。
Jason 您好..
非常感谢您所有的教程。
如何将 Cross validation 与 flow_from_directory 和 fit_generator 一起使用??
抱歉,我没有这方面的示例。
嗨,Jason,
感谢您关于机器学习的精彩帖子。
在您的交叉验证代码中,您使用了 150 个 epoch,但结果仅显示了 1 个完整的 10 折交叉验证轮次。您只打印了第一个 epoch 的输出?
我真的很难理解交叉验证和 epoch。这是我的理解
这是否意味着每个 epoch 由一次完整的交叉验证组成?那么,在第一个 epoch 中,我们运行 10 折交叉验证并报告平均验证误差,在第二个 epoch 中,我们继续使用第一个 epoch 准备好的模型,并再次运行 k 折交叉验证,依此类推,直到 epoch 150?关于 mini-batches,这是不是意味着我们将每个训练集分成 10 个 mini-batches 来进行前向反向传播,并且在完成对整个 10 个批次的训练后,我们参考验证集来估计验证误差?
您能告诉我我的交叉验证概念是否正确吗?
谢谢,
Samin
不太对。
您可以在这里了解 k 折交叉验证的工作原理
https://machinelearning.org.cn/k-fold-cross-validation/
你好 Jason,
首先,感谢您全面而富有洞察力的教程,当我要查找答案时,您的网站是我首先要去的地方。我为时间序列预测实现了一个深度神经网络。我遇到的问题是,我的拟合和评估部分进展顺利,并且两者的准确率都在 0.8 左右。但是当我尝试预测一个新的样本批次时,我的预测结果全都是零。如果您能建议我从哪里开始调试我的模型,我将非常感激。如果您愿意,我也可以发送我的模型让您看看。
谢谢你。
此致,
Akim
听起来像是您代码的问题,而不是模型的问题。
这篇帖子将向您展示如何进行预测
https://machinelearning.org.cn/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/
在调用 evaluate 函数之前,我们是不是应该将 set_learning_phase 设置为 0?根据 Keras 文档,在进行推理时,应该将其设置为 0。
也许在调用 evaluate() 时会自动设置?
你好。我想了解一些关于验证数据的基础知识。我是否可以手动将总训练数据的 0.2% 放入验证数据文件夹,而不使用 validation_data_split 函数?这在训练模型时有用吗?
这真的取决于你有多少数据可以花费。也许可以看看这篇文章
https://machinelearning.org.cn/difference-test-validation-datasets/
为什么在 kfold 的每次迭代中都创建模型,而不是创建一次模型然后在迭代中调用 model.fit?
每次迭代都需要一组新的权重来拟合新模型。
“你好!如何在多标签问题中使用 K 折交叉验证?”
直接来说,没有变化。你具体遇到了什么问题?
嗨,Jason,
这是一篇很棒的文章!
在你的例子中,你在每个折叠中执行模型编译。这非常慢。我想知道,如果我将模型编译移到 for 循环之外,是否也能获得相同的结果?
我想我真正想问的是,一旦我初始化并编译了模型,每次调用 model.fit() 是否都会使用当前训练和验证数据集的折叠进行独立拟合,而不会受到上一次循环获得的权重的干扰?
如果可以,那么我认为我的代码版本更快,因为结果是一样的。
如果不行,而且我仍然想在 for 循环之前只初始化和编译模型一次,有没有办法在每次 model.fit() 之后重置模型?
非常感谢
Joseph
为了安全起见,我宁愿在每次循环时重新定义和重新编译模型,以确保每次迭代都能获得一套全新的初始权重。
如何修改以下代码以使用 k 折交叉验证绘制图表?
def build_classifier()
classifier = Sequential()
classifier.add(Dense(units = 6, kernel_initializer = ‘uniform’, activation = ‘relu’, input_dim = 13))
classifier.add(Dropout(p = 0.1))
classifier.add(Dense(units = 6, kernel_initializer = ‘VarianceScaling’, activation = ‘relu’))
classifier.add(Dense(units = 6, kernel_initializer = ‘VarianceScaling’, activation = ‘relu’))
classifier.add(Dense(units = 3, kernel_initializer = ‘VarianceScaling’, activation = ‘softmax’))
classifier.compile(optimizer = ‘adam’, loss = ‘categorical_crossentropy’, metrics = [‘accuracy’])
return classifier
classifier = KerasClassifier(build_fn = build_classifier, batch_size = 5, epochs = 200, verbose=1)
accuracies = cross_val_score(estimator = classifier, X = X_train, y = y_train, cv = 10, n_jobs = 1)
mean = accuracies.mean()
variance = accuracies.std()
谢谢并致以问候
Sanghita
对于 k 折交叉验证,我建议绘制分数在各个折叠上的分布,例如使用箱形图和须状图。
将分数收集到一个列表中,然后将其传递给 pyplot.boxplot()
嗨,杰森
使用手动验证数据集的限制/缺点是什么?
与什么相比?
我可以这样写吗?
result = KerasClassifier(build_fn=baseline_model, epochs=200, batch_size=5, verbose=0)
然后
plot_loss_accuracy(result)
这样 result 既可以用于 scikit-learn 的 kfold 验证,也可以用于 Keras 的混淆矩阵显示吗?
或许可以试试?
我只是想知道为什么你对 validation_data 使用 X_test, y_test?
教程中的一个简单快捷方式。理想情况下,我们会使用一个单独的数据集。
在交叉验证期间,是不是应该保存每个拟合,以便以后可以使用最佳拟合?
不,但如果你愿意,也可以。
CV 期间的模型仅用于估计建模过程在未见过的数据上的性能。在获得此估计后,将丢弃模型,并开发一个在所有可用数据上进行拟合的新最终模型,称为最终模型。
https://machinelearning.org.cn/train-final-machine-learning-model/
亲爱的Jason
这里有一些在我看来没什么意义的问题
到目前为止,我使用 Keras 和 Tensorflow 后端(1 批次,序列 1)编写了以下 Python 代码。
# 定义模型
model = Sequential()
model.add(LSTM(128, batch_size=BATCH_SIZE, input_shape=(train_x.shape[1],train_x.shape[2]), return_sequences=True, stateful=False ))#,,return_sequences=Tru# stateful=True
model.add(Dense(2, activation=’softmax’))
opt = tf.keras.optimizers.Adam(lr=0.01, decay=1e-6)
# 编译模型
model.compile(
loss=’sparse_categorical_crossentropy’,
optimizer=opt,
metrics=[‘accuracy’]
)
model.fit(
train_x, train_y,
batch_size=BATCH_SIZE,
epochs=EPOCHS,#,
verbose=1)
#现在我想确保我们可以预测训练集(使用 evaluate),并且它的结果与训练期间相同
score = model.evaluate(train_x, train_y, batch_size=BATCH_SIZE, verbose=0)
print(‘ 训练准确率:’, score[1])
代码的输出是
Epoch 1/10 5872/5872 [==============================] – 0s 81us/sample – loss: 0.6954 – acc: 0.4997
Epoch 2/10 5872/5872 [==============================] – 0s 13us/sample – loss: 0.6924 – acc: 0.5229
Epoch 3/10 5872/5872 [==============================] – 0s 14us/sample – loss: 0.6910 – acc: 0.5256
Epoch 4/10 5872/5872 [==============================] – 0s 13us/sample – loss: 0.6906 – acc: 0.5243
Epoch 5/10 5872/5872 [==============================] – 0s 13us/sample – loss: 0.6908 – acc: 0.5238
训练准确率: 0.52480716
所以问题是,最终的建模准确率(0.5238)应该等于(评估)准确率(0.52480716),但事实并非如此。这没有任何意义,为什么我们不能在训练数据上使用 evaluate 然后获得与训练期间相同的结果?没有 dropout 或其他会导致训练与评估不同的东西。如果我使用验证集,也会发生同样的情况。
我认为训练期间的分数是跨批次估算的,并且在权重更新之前报告。
我认为你可以使用早停来保存特定批次之后的模型权重。也许是自定义的早停/检查点回调?
你好 Jason,
感谢这个有用的教程。
我已经用 ICNET 训练了 Keras 模型用于语义分割。
如何在验证集上用 mIOU(平均交并比)评估我的训练模型?有什么建议或有用的文章吗?
抱歉,我没有关于计算 mIOU 的教程。
你好 Jason,
感谢您提供的详细工作。
两个快速问题
1) 说 CVscores.mean 为 0.78 比 CVscores.mean 为 0.58 具有更好的准确性是否足够?
2) 前者的含义是什么?
谢谢
是的。
你说的“重要性”具体是什么意思?
布朗利先生,
非常感谢您的努力。非常有帮助。
也许我想多了,但我一旦得到了一个结果好的模型,它就会被封装到一个函数中,所以我无法从控制台调用它。我习惯使用“model.predict(x)”。但是,使用这段代码,我得到“‘model’ is not defined”。最终的定型就是将最终的模型定义复制到提示符中,编译它,然后用学习数据拟合它,并预测未知数据吗?
你的代码会产生与在提示符中定义模型然后运行 KFold 循环相同的结果吗?
再次感谢!
你可以训练一个单独的最终模型并将其保存到文件以供以后使用,更多内容请参见此处
https://machinelearning.org.cn/train-final-machine-learning-model/
嗨,Jason,
由于 K 折交叉验证是随机分割数据(3、5、10 等),然后训练模型,因此建议在时间序列数据(多分类,使用 LSTM)上使用 GridSearch / K 折吗?因为一旦时间序列数据被随机化,LSTM 就会失去意义,对吧?
不。正确。
您可以使用前向验证。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
你好,
我看到你通过 scikti 工具以 k 折方式分割数据以获得更准确的估计。
我的问题是,在时域(例如股票价格)中进行 k 折分割的内置函数是否存在?当样本顺序有意义时。
谢谢,
MAK
好问题,是的,这会有帮助
https://machinelearning.org.cn/how-to-use-the-timeseriesgenerator-for-time-series-forecasting-in-keras/
嗨,Jason,
很棒的教程。
我遇到了一个问题,我的损失没有降低。
我使用了分类标签,但 StratifiedKFold 抛出了一个错误,导致我必须将标签转换为数值。
修改后的代码
input_img = Input(shape = (242, 242, 1))
kfold = StratifiedKFold(n_splits=6, shuffle=True, random_state=13)
cvscores = []
for train, test in kfold.split(images, labels)
model = Model(input_img, model(input_img))
# 编译模型
model.compile(loss=’binary_crossentropy’, optimizer = Adam(), metrics=[‘accuracy’])
# 拟合模型
#labels = to_categorical(labels)
model.fit(images[train], labels[train], epochs=epochs, batch_size=batch_size, verbose=1)
# 评估模型
scores = model.evaluate(images[test], labels[test], verbose=1)
print(“%s: %.2f%%” % (model.metrics_names[1], scores[1]*100))
cvscores.append(scores[1] * 100)
print(“%.2f%% (+/- %.2f%%)” % (numpy.mean(cvscores), numpy.std(cvscores)))
结果
时期 1/100
4000/4000 [==============================] – 8s 2ms/step – loss: 7.1741 – acc: 0.5500
时期 2/100
4000/4000 [==============================] – 4s 917us/step – loss: 7.1741 – acc: 0.5500
时期 3/100
4000/4000 [==============================] – 4s 922us/step – loss: 7.1741 – acc: 0.5500
时期 4/100
4000/4000 [==============================] – 4s 955us/step – loss: 7.1741 – acc: 0.5500
Epoch 5/100
4000/4000 [==============================] – 4s 950us/step – loss: 7.1741 – acc: 0.5500
Epoch 6/100
4000/4000 [==============================] – 4s 948us/step – loss: 7.1741 – acc: 0.5500
Epoch 7/100
4000/4000 [==============================] – 4s 918us/step – loss: 7.1741 – acc: 0.5500
Epoch 8/100
4000/4000 [==============================] – 4s 918us/step – loss: 7.1741 – acc: 0.5500
损失似乎没有降低,你能告诉我我哪里出错了。
谢谢
我有一些建议可能会有所帮助
https://machinelearning.org.cn/start-here/#better
先生
据我理解,交叉验证是用于选择模型(或)其超参数的方法。
例如,如果我有
神经网络 1,有 10 层
神经网络 2,有 100 层
它可以指导我选择 1 或 2。
在识别模型后,要获得我的最终模型,我应该使用整个训练集,运行它一定数量的 epoch,并选择在运行过程中提供良好准确率的参数。
我的假设是正确的吗?请澄清这个疑问?!
差不多。CV 仅用于估计模型的性能。
然后你必须解释每个模型/配置的估计性能并进行选择。
你可以直接这样做,也可以使用统计假设检验方法或其他方法。
是的,之后,你对所有数据进行拟合,然后开始使用模型。
嗨,Jason 先生
首先,感谢您提供非常好的教程。
我想知道在使用 k 折交叉验证时,如何计算深度学习模型的整体混淆矩阵?
谢谢。
您不能。
混淆矩阵仅用于单次运行。
交叉验证会估计模型在多次运行中的性能。
我的目的是,如果我能在每个折叠中得到混淆矩阵,那么整体的
混淆矩阵可以通过将所有折叠产生的混淆矩阵相加来获得。事实上,性能度量(即准确率)是所有折叠的平均值。
因此,通过将所有混淆矩阵相加,模型的准确率可以
计算为所得对角线元素之和与所有元素之和的比值。
混淆矩阵
以及所有元素的总和。
再次感谢!
每个折叠的混淆矩阵仅基于模型在测试集上的结果计算。我提出此查询是因为我在该领域的许多工作中发现,作者使用 k 折交叉验证来评估模型,同时他们也绘制了模型的混淆矩阵。
我预计混淆矩阵是基于数据集的标准测试集报告的。
我不推荐这样做,因为矩阵的每个单元格都需要报告均值和方差。这会让人感到困惑。
非常感谢。在这种情况下,您是否知道如何绘制总混淆矩阵?因为在我读过的许多论文中,作者都使用了 k 折交叉验证,并共同设计了混淆矩阵,例如他们写标题“使用 10 折交叉验证获得的混淆矩阵”。
注意:矩阵所有元素的总和等于整个数据集的大小。
谢谢。
你好 Jason,非常感谢,您的教程给了我很多帮助,我是 Python 和机器学习的新手。
我使用了您的 strat k-fold 代码示例,并对其进行了一些修改,用于我的数据,并取得了不错的结果。
我正在保存最佳拟合模型,用于未来的预测。我的问题是如何保存平均模型或以某种方式保存整个模型。
再次感谢!
我的代码:抱歉,我不知道如何将其作为代码放置。
seed = 6
np.random.seed(seed)
# 分割为输入 (X) 和输出 (Y) 变量
X = train_inputs.copy()
Y = train_targ.copy()
# 定义 10 折交叉验证测试平台
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []
adam1=optimizers.Adam(lr=0.0005)
model1 = Sequential()
accc_trn=0
accc_tst=0
for train, test in kfold.split(X, Y)
# 创建模型
model = Sequential()
print(‘model’,type(model))
model.add(Dense(128, input_dim=8, activation=’relu’))
model.add(Dropout(0.))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.))
model.add(Dense(1, activation=’sigmoid’))
# 编译模型
model.compile(loss=’binary_crossentropy’, optimizer=adam1, metrics=[‘accuracy’])
# 拟合模型
history = model.fit(X[train], Y[train], \
validation_data=(X[test], Y[test]), \
epochs=150,batch_size=32, verbose=2)
_, train_acc = model.evaluate(X[train], Y[train], verbose=0)
_, test_acc = model.evaluate(X[test], Y[test], verbose=0)
print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))
if test_acc>accc_tst and train_acc>accc_trn
accc_tst=test_acc
accc_trn=train_acc
model1=deepcopy(model)
# 绘制历史记录
plt.plot(history.history[‘acc’], label=’train’)
plt.plot(history.history[‘val_acc’], label=’test’)
plt.legend()
plt.show()
cvscores.append(test_acc * 100)
print(“%.2f%% (+/- %.2f%%)” % (np.mean(cvscores), np.std(cvscores)))
model1.save(‘my_class.h5’)
new_model = models.load_model(‘my_class.h5’)
_, test_newacc = new_model.evaluate(valid_inputs, valid_targ, verbose=0)
print(‘Test: %.3f’ % (test_newacc))
交叉验证的所有模型都应该被丢弃。
选择模型和配置后,在所有可用数据上拟合一个最终模型,并用它来做出预测。
我在这里解释了更多
https://machinelearning.org.cn/train-final-machine-learning-model/
你好 Jason,非常感谢
我还有另一个关于 strat-k-fold 的问题,我在一些地方读到不平衡的输入会导致模型被拟合以产生不平衡的预测(无论是二元还是多类别),因此建议删除输入以更好地训练模型平衡数据,如果我从您那里正确理解的话,strat-k-fold 的工作方式是考虑到数据的非平衡性质,但我不确定哪种更好:训练一个具有不平衡输入但实际上代表总体的 strat-k-fold 模型,还是在训练之前平衡数据。
谢谢
Ziko
是的,分层确保每个数据分割包含与原始数据集相同比例的每个类别的示例。
https://scikit-learn.cn/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html
你好,感谢你的回答。
我理解分层可以保持所有样本的输入比例,但我不知道模型是否真的以一种会放大错误的方式进行训练,如果它被用来预测相同类型的数据,而这些数据会具有更平衡的特征。
模型会尽力而为,但不能保证。
你还可以使用其他技术,请参阅这篇文章。
https://machinelearning.org.cn/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/
你好,再说一遍,也许我将推广我的问题,如果我训练一个具有特定比例的模型,模型是否真的捕获了数据的比例,因此在预测具有相似比例的数据时会更好?所以,如果我怀疑未来数据具有不同的比例,我应该准备与未来数据比例更接近的训练数据吗?
所以,如果模型确实捕获了训练比例,而我的数据比例随时间或其他任何原因发生变化,我是否应该重新训练它以适应不同的比例?
它会尝试。
是的,给定数据通常应该代表问题。
嗨 Jason。使用“手动验证数据集”有助于防止过拟合吗?还是 K-Fold 好得多?
这真的要看情况。
验证数据集对于超参数调整非常有用。
你好,Jason。
使用 keras 模型,对于输出与输入的完全线性关系,我得到了零准确率,我不确定是我错误地解释了准确率还是在我的代码中做错了什么,任何帮助都将不胜感激。
我尝试添加更多层,更多 epoch 等,但没有任何改变。
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from keras import models
来自 keras.models import Sequential
from keras.layers import Dense, Dropout
from keras import optimizers
from sklearn.model_selection import KFold
from sklearn.preprocessing import MinMaxScaler
tf.reset_default_graph()
from keras.optimizers import SGD
siz=100000
inp=np.random.randint(100, 1000000 , size=[siz,1])
a1=1.5;
uop=np.dot(inp,a1)
normzer_inp = MinMaxScaler()
inp_norm = normzer_inp.fit_transform\
(inp)
normzer_uop = MinMaxScaler()
uop_norm = normzer_uop.fit_transform\
(uop)
X=inp_norm
Y=uop_norm
kfold = KFold(n_splits=2, random_state=None, shuffle=False)
cvscores = []
opti_SGD = SGD(lr=0.01, momentum=0.9)
model1 = Sequential()
for train, test in kfold.split(X, Y)
model = Sequential()
model.add(Dense(16, input_dim=X.shape[1], activation=’relu’))
model.add(Dense(16, activation=’relu’))
model.add(Dense(1, activation=’linear’))
model.compile(loss=’mean_squared_error’, optimizer=opti_SGD,\
metrics=['accuracy'])
history = model.fit(X[train], Y[train], \
validation_data=(X[test], Y[test]), \
epochs=10,batch_size=2048, verbose=2)
_, train_acc = model.evaluate(X[train], Y[train], verbose=0)
_, test_acc = model.evaluate(X[test], Y[test], verbose=0)
print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))
plt.plot(history.history[‘acc’], label=’train’)
plt.plot(history.history[‘val_acc’], label=’test’)
plt.legend()
plt.show()
cvscores.append(test_acc * 100)
print(“%.2f%% (+/- %.2f%%)” % (np.mean(cvscores)\
, np.std(cvscores)))
我很乐意提供帮助,但我没有能力审查和调试您的代码。
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
你好,亲爱的
如何在此代码上执行 k 折交叉验证?
model = Sequential()
model.add(LSTM(150, input_shape=(train_X.shape[1], train_X.shape[2])))#,return_sequences=True
#model.add(LSTM(units=100))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation(‘sigmoid’))
model.compile(loss=’mae’, optimizer=’adam’)#,metrics=[‘accuracy’])#mean_squared_error
# 拟合模型
history = model.fit(train_X, train_y, epochs=150,validation_data=(test_X, test_y),batch_size=24,verbose=2,shuffle=False)
#pyplot.plot(history.history[‘loss’], label=’train’)
看起来你正在使用 LSTM 进行序列预测。
通常,交叉验证不适用于序列预测,你应该使用前向验证。
你可以在这里了解更多
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
再次你好
添加准确率后,训练值的准确率没有变化,测试值的准确率仍然为零?为什么?
# 设计网络
learning_rate = 0.001
model = Sequential()
model.add(LSTM(150, input_shape=(train_X.shape[1], train_X.shape[2])))#,return_sequences=True
#model.add(LSTM(units=100))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation(‘sigmoid’))
model.compile(loss=’mae’, optimizer=’adam’,metrics=[‘accuracy’])#mean_squared_error
# 拟合模型
history = model.fit(train_X, train_y, epochs=50,validation_data=(test_X, test_y),batch_size=24,verbose=2,shuffle=False)
为什么你对分类任务使用 mse 损失?
也许可以试试二元交叉熵?
我没有使用分类
我使用回归进行预测
那样的话,你就无法为回归测量准确率了,更多详情请看这里
https://machinelearning.org.cn/faq/single-faq/how-do-i-calculate-accuracy-for-regression
非常感谢你的信息解答
我有一个最后的请求,我想要一个特定的粒子群优化 (PSO) python 代码来找到最佳权重和偏置以及最佳隐藏层数量和每层隐藏层的节点数。
非常感谢,也很感激你的出版物!
抱歉,我没有关于用于神经网络的 PSO 的教程。
嗨 Jason,我对你的分层 K 折交叉验证部分很感兴趣,我尝试了一下,但出现了一个错误,代码如下:
from keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
# normalize the data
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
X_train = train_data
y_train = train_targets
X_test = test_data
y_test = test_targets
#%%
from keras import models
from keras import layers
从 sklearn.model_selection 导入 StratifiedKFold
def build_model()
# Because we will need to instantiate
# the same model multiple times,
# we use a function to construct it.
model = models.Sequential()
model.add(layers.Dense(64, activation=’relu’,
input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation=’relu’))
model.add(layers.Dense(1))
model.compile(optimizer=’rmsprop’, loss=’mse’, metrics=[‘mae’])
return model
model = build_model()
model.fit(X_train, y_train)
kfold = StratifiedKFold(n_splits=10)
for train, test in kfold.split(X_train, y_train)
model = build_model()
model.fit(train, test)
print(model.evaluate(X_test, y_test, verbose = 0))
错误是 ValueError: Supported target types are: (‘binary’, ‘multiclass’). Got ‘continuous’ instead。
看起来这个方法不适用于浮点训练集,因为我的 X_train 看起来是这样的:
array([[-0.27224633, -0.48361547, -0.43576161, …, 1.14850044,
0.44807713, 0.8252202 ],
[-0.40342651, 2.99178419, -1.33391162, …, -1.71818909,
0.43190599, -1.32920239],
[ 0.1249402 , -0.48361547, 1.0283258 , …, 0.78447637,
0.22061726, -1.30850006],
那么我应该如何在深度学习中使用这种类型的数据进行交叉验证呢?
听到这个消息我很难过。
我相信分层 K 折交叉验证只适用于分类预测建模问题,而不适用于回归问题。
在最后一行,您计算了 numpy.std(cvscores)。您如何使用此信息?
它被打印出来了。
嗨,Jason,
我想使用 kfold.split(x,y),但遇到了这个错误:ValueError: Found array with dim 3. Estimator expected <= 2。因为我的 x.shape=(2000, 1400, 3, 6) and y.shape=(2000, 1400, 3)
我应该将我的输入数据重塑为二维数组吗?
谢谢你
好问题,这会有帮助
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
我该如何使用 k-fold 交叉验证?如果能提供帮助,不胜感激。
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.33, random_state=42)
tokenizer = Tokenizer(num_words=MAX_NUM_WORDS)
tokenizer.fit_on_texts(X_train)
X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)
vocab_size = len(tokenizer.word_index) + 1
X_train = pad_sequences(X_train, maxlen=MAX_SEQUENCE_LENGTH)
X_test = pad_sequences(X_test, maxlen=MAX_SEQUENCE_LENGTH)
def model()
input_shape = (MAX_SEQUENCE_LENGTH,)
model_input = Input(shape = input_shape, name = “input”, dtype = ‘int32′)
embedding = glove_embd(model_input)
lstm = LSTM(100, dropout=0.3, recurrent_dropout=0.3, name=”lstm”)(embedding)
model_output = Dense(2, activation=’softmax’, name=”softmax”)(lstm)
model = Model(inputs=model_input, outputs=model_output)
return model
model = model()
model.compile(loss=’binary_crossentropy’,
optimizer = ‘adam’,
metrics = [‘accuracy’])
history = model.fit(X_train, Y_train, batch_size=1500, epochs=50, verbose=1, validation_data=(X_test, Y_test))
loss, accuracy = model.evaluate(X_train, Y_train, verbose=False)
你必须使用重复前向验证。k 折交叉验证对于序列数据是无效的。
看这里
https://machinelearning.org.cn/how-to-grid-search-deep-learning-models-for-time-series-forecasting/
谢谢。我正在使用情感分析。前向验证是否用于文本分类,如情感分析?我对这个话题是新手。
不是真的需要。如果文档是独立的,你可以使用交叉验证。
嗨 Jason,
谢谢你的信息。帮了我大忙。我有一个问题。在 k 折交叉验证后。例如 5 折。你会在每一折得到 5 个准确率值,对吗?在完成 5 折交叉验证后,如果我想对外部数据进行另一次测试,可以调用模型进行评估,对吗?所以我想知道我调用的是哪个训练好的网络?是最后一折的网络还是所有 5 折的平均模型。哪个是最终的网络?
请给我一些建议。
非常感谢,
Sruthy
你可以计算交叉验证的平均值来估计模型的技能。
要对新数据进行预测,你需要用所有可用数据拟合一个新模型并进行预测。
这个可能会有帮助
https://machinelearning.org.cn/train-final-machine-learning-model/
嗨,Jason,
当使用
scores = model.evaluate(X[test], Y[test], verbose=0),而 compile 中使用的指标是 ‘accuracy’,结果与我计算预测结果的准确率时非常不同。问题是什么?
通过 evaluate 和手动计算得到的同一数据的准确率应该是相同的。
如果不是,请检查你的代码是否有错误。
嘿,杰森!
很喜欢这篇文章,我找了很久的 Tensorflow CV 解决方案,这篇文章解释得很完美。不过我有一个问题。不希望你纠正我的代码,只是想听听你的看法。
我使用与你上面几乎相同的代码来处理我的数据集(下面我会展示代码),但我在一个问题上遇到了困难,即在训练 200 个 epoch 的每次运行后,模型越来越接近 100% 的准确率?我以为我的测试数据集保持不变,模型在每次迭代后都被馈送了一个新的训练数据集折,但我检查过了,测试数据集每次都在变化,所以我感到困惑。我的代码和输出如下:
有什么想法吗?很喜欢这个网站!再次感谢!
是的,你必须为 CV 的每个折叠重新定义模型。否则模型将继续从上一个折叠中学习。
明白了,非常感谢你的时间!并继续做好工作!我们非常感激。
不客气。
嗨,杰森,
我对你的实现有点困惑。你在描述中说分层 K 折将训练数据分成 k 折。但随后你使用
for train, test in kfold.split(X, Y)
那么你为什么还要获取标签 Y?
所以这些折叠是按类别标签分层的。
嗨,杰森,
你是否有用于 LSTM 的 LOO (Leave-One-Out) 交叉验证的 Keras 示例?
你通常不能对 RNN/LSTM 使用交叉验证,而是应该使用前向验证。
请参阅这里的示例。
https://machinelearning.org.cn/start-here/#deep_learning_time_series
感谢你的回答。你这样说是因为这个帖子吗?
https://stats.stackexchange.com/questions/350655/leave-one-out-cross-validation-for-lstm
也许你能为我总结一下要点?
嗨,为了评估哪些准确率和损失我应该关注以获得良好的预测评估,
我建议根据损失来调整模型性能。
我建议根据最能反映你的项目目标的指标的样本外性能来选择模型。
谢谢 Jason,非常有帮助!
不客气,很高兴听到!
放置
model = Sequential()
和重新编译不会重置模型吗?
它重新定义了模型。
我以为我们实际上想要保留具有相同权重等的模型并重新训练它。
不。在交叉验证中,我们在每次迭代中拟合一个新模型,并在迭代结束时将其丢弃。我们只对模型在新数据上进行预测时的性能评估感兴趣。
你可以在这里了解更多
https://machinelearning.org.cn/k-fold-cross-validation/
嗨 Jason,非常有用的教程。有没有什么方法可以计算交叉验证情况下的特异度?
谢谢。
是的,imbalanced-learn 提供了一个你可以直接使用的指标
https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.metrics.specificity_score.html
嗨 Jason
感谢你的教程。
如何使用上述模型计算混淆矩阵、F 分数、召回率和精确率?
这里有一个例子
https://machinelearning.org.cn/how-to-calculate-precision-recall-f1-and-more-for-deep-learning-models/
谢谢 Jason,但我的意思是,在 10 折交叉验证后,我如何计算混淆矩阵等?
我还有两个问题
以下是我的深度模型
1. 每次运行,我都会得到不同的准确率;我该怎么做才能让准确率保持恒定?
2. 训练和验证的准确率和损失之间存在很大差异,我认为发生了过拟合,我甚至使用了 dropout 但没有成功。我的样本数据是 8000,是因为样本数据不足还是有其他原因?有什么方法可以减少过拟合?
.
.
.
# 我的输入数据是 (8000, 100)
MAX_SEQUENCE_LENGTH = 100
MAX_NB_WORDS = 30000
EMBEDDING_DIM = 100
nb_words = max(MAX_NB_WORDS, len(tokenizer.word_index))
model = Sequential()
model.add(Embedding(nb_words,EMBEDDING_DIM,input_length=MAX_SEQUENCE_LENGTH))
model.add(Bidirectional(LSTM(10)))
model.add(Dense(1, activation = ‘sigmoid’))
model.summary()
model.compile(loss=’binary_crossentropy’,optimizer=’adam’,metrics=[‘accuracy’])
# Run LSTM Model
batch = 64
epoch = 500
LSTM_model = model.fit(X_train, Y_train, batch_size=batch, epochs=epoch,verbose = 1,shuffle = True, validation_split=0.1)
test_loss , test_acc = model.evaluate(X_test, Y_test)
pred = model.predict(X_test)
Y_pred = []
for p in pred
if p > 0.5
Y_pred.append(1)
else
Y_pred.append(0)
class_names = [‘Negative’, ‘Positive’]
print(classification_report(Y_test.to_list(), Y_pred, target_names = class_names))
cm = confusion_matrix(Y_test.to_list(),Y_pred)
你不能为交叉验证计算混淆矩阵,只能为训练-测试分割计算。
https://machinelearning.org.cn/how-to-calculate-precision-recall-f1-and-more-for-deep-learning-models/
嗨 Jason。感谢你在 Keras 中进行交叉验证。我想为文本分类(情感分析)进行 LSTM 的分层验证。可以吗?如果可以,你能给我发一个 GitHub 链接或其他什么吗?我在网上找不到好的教程。谢谢。
一般来说,不适合将交叉验证用于时间序列等序列预测问题。相反,你应该使用前向验证。
您可以在博客上找到数百个示例,从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嗨,Jason,
喜欢你的作品,我目前正在研究多标签分类的音频标记问题,为了提高性能,我计划应用K折交叉验证,但是是否可以轻松地将分层K折交叉验证应用于多标签数据?或者即使没有分层,K折交叉验证是否也能帮助我取得好结果?
提前感谢
谢谢!
我不确定分层k折交叉验证是否了解多标签问题。据我所知,它是为多类问题设计的。
也许可以查看文档或进行测试?
验证数据集应该放在交叉验证的哪里?
在交叉验证的每个折叠中,您可以将训练部分划分为训练集和验证集,并使用验证集来调整模型超参数或进行早期停止训练。
嗨!
我正在尝试将神经网络拟合到数据集(回归),我想知道我的步骤是否正确,以获得一个良好且无偏见的模型
1) 基于5折交叉验证进行超参数调优。我正在训练时拟合训练数据并在验证数据上进行验证。训练后,我计算验证数据上的指标。(我没有测试集)
我使用提前停止(Early Stopping)来减少损失(而不是验证损失)以节省时间。
2) 在超参数研究中,使用最优模型训练所有数据。
我想知道这种方法是否可行,因为我没有测试集。另一方面,我已经找到了一个不过拟合且泛化良好的模型。所以额外的数据应该只会改进我的模型。
我有点困惑。
谢谢你的帮助。
没有“客观正确”的概念。选择一个能让你对自己拥有一个适用于数据集的鲁棒模型充满信心的过程。
嗨,Jason,
由于每个epoch都有不同的验证准确率,您建议如何报告最终结果以用于出版?
例如,我使用了70%的数据用于训练,30%用于验证。
100个epoch的验证准确率从62%(epoch 1)开始,达到91%(epoch 100)。
我如何在论文中报告一个单一的模型的准确率数字?
我应该平均100个epoch的准确率吗?
谢谢你。
您可以使用任何您想要的评估程序,只要它清晰、在方法比较中一致且可复现。
你好,
为什么我会收到此错误?
TypeError Traceback (most recent call last)
in
11 print(train, test)
12 # Fit the model
—> 13 model.fit(X[train], Y[train], epochs=20, batch_size=7, verbose=1)
14 # evaluate the model
15 scores = model.evaluate(X[test], Y[test], verbose=1)
TypeError: only integer scalar arrays can be converted to a scalar index
您认为这能解决您的问题吗:https://stackoverflow.com/questions/50997928/typeerror-only-integer-scalar-arrays-can-be-converted-to-a-scalar-index-with-1d
布朗利博士您好!精彩的教程……只有一个问题……
当它运行此命令时
print(“%s: %.2f%%” % (model.metrics_names[1], scores[1]*100))
我收到此错误
TypeError: ‘float’ object is not subscriptable
我该如何修复?
约翰你好……感谢您的反馈!您可能会发现以下内容有所帮助
https://www.arrowhitech.com/typeerror-float-object-is-not-subscriptable/
你好!
从您的文章中,我有一个部分未能完全理解。
如果我有一个使用Tensorflow的CNN的分类交叉熵程序,对于代码
model.compile(loss=’categorical_crossentropy’, metrics=[‘accuracy’])
model.fit(xTrain, yTrain, epochs=100)
loss, accuracy = model.evaluate(xTest, yTest)
print(accuracy)
我能否请教您,evaluate()返回的“accuracy”是如何计算的?
我希望知道它是否是正确预测的平均数。(正确预测的总数/样本总数)。
但是,我找不到Tensorflow的evaluate()的准确率是如何计算的。
如果我的看法是正确的,我能否请您提供哪个Tensorflow网站我可以参考,以便我可以确保?谢谢!
Josh 你好……以下资源应该有助于澄清
https://machinelearning.org.cn/cross-entropy-for-machine-learning/
如何在MLP / CNN / LSTM中找到训练MAPE和测试MAPE以及训练中位数绝对误差和测试中位数绝对误差?
请告诉我。
你好Jason,我有一个问题
我们可以遵循这些步骤吗?
1-将数据分割为训练集和测试集
2-我们将训练数据应用于k折交叉验证(训练数据将作为训练集和验证集)
3-查找k折交叉验证的准确率
4-查找测试数据的准确率
5-最后一步是比较两个准确率以检查过拟合
这个方法是否正确?
非常感谢
Yasir 你好……以下资源可能对您有帮助
https://machinelearning.org.cn/training-validation-test-split-and-cross-validation-done-right/
Jason你好,感谢您的帖子。我有一个问题,Keras的validation_split如何防止信息泄露?
由于我们需要在将训练数据拟合到模型之前对其进行缩放,那么使用validation_split如何防止我们信息泄露?
到目前为止,根据我的学习,我们只能在训练集上拟合缩放器,然后将拟合的缩放器应用于测试集。在这种情况下,我认为我们将验证集视为训练过程中的“测试集”以提高模型性能,因此感到困惑。因为如果我们缩放整个训练集,最终我们将没有未见过的数据用于验证集。
谢谢你。
嘿!你为什么要把准确率乘以100?对归一化数据进行评估有意义吗?我真的很困惑……
Yeon 你好……这些分数旨在从相对的角度比较模型性能。以下资源提供了一些额外的考虑因素
https://machinelearning.org.cn/model-prediction-versus-interpretation-in-machine-learning/
Jason你好,感谢您分享这篇精彩的文章。
我有一个关于分层K折交叉验证的问题。
为什么你选择使用sckit-learn的函数来做这件事?
Keras本身没有内置函数来执行此操作吗?
如果有,你能给我一个使用Keras内置函数来学习它的好资源吗?
谢谢
Michio
Michio你好……以下资源可能对您有帮助
https://machinelearning.org.cn/repeated-k-fold-cross-validation-with-python/