tf.keras.preprocessing.image_dataset_from_directory 中的 validation_split 是否会导致数据泄漏?

数据挖掘 机器学习 神经网络 喀拉斯 张量流 美国有线电视新闻网
2022-02-17 22:16:08

对于二值图像分类问题(使用 tf.keras 的 CNN)。我的图像数据被分成文件夹(训练、验证、测试),每个文件夹都有两个平衡类的子文件夹。借用本教程中的代码,我最初以这种方式加载我的训练和验证集:

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    train_path,
    validation_split=0.2,
    subset="training",
    seed=42,
    image_size=image_size,
    batch_size=batch_size,
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    train_path,
    validation_split=0.2,
    subset="validation",
    seed=42,
    image_size=image_size,
    batch_size=batch_size,
)

请注意,我从同一个文件夹加载训练和验证,然后使用validation_split(因为我想在使用真正的验证集之前先玩一下)。我的模型表现非常好,验证准确度约为 0.95。

然后我决定更新我的代码以加载真正的验证集:

train_ds = image_dataset_from_directory(
    train_path,
    seed=42,
    image_size=image_size,
    batch_size=batch_size,
)

val_ds = image_dataset_from_directory(
    val_path,
    seed=42,
    image_size=image_size,
    batch_size=batch_size,
)

现在我的模型表现得更差了(~0.75 准确度)。我试图理解为什么。我怀疑我的初始代码导致了一些数据泄漏。现在我看了一下,我不知道第二次调用 image_dataset_from_directory(对于 val_ds)如何知道不加载已经为第一次调用(对于 train_ds)加载的图像(除非具有相同的随机种子可以防止这种情况)。我可以肯定这是问题所在,除了我直接从 keras.io 教程中提取了这段代码——他们肯定不会犯这样的基本错误吗?

主要问题:鉴于validation_splitsubset交互的方式,image_dataset_from_directory()我的代码的第一个版本是否会导致数据泄漏?

如果它应该导致训练集和验证集之间的数据泄漏,那么我将需要考虑其他可能性,例如:

  • 训练集和验证集文件夹中的图像之间存在实际差异。我可以合并并重新洗牌。
  • 训练文件夹中图像的顺序是这样的,即给定我的随机种子“更容易”的图像被提取用于验证集。
1个回答

一个可能的问题是 Kerasvalidation_split使用“最后一个x百分比”的数据作为验证数据,而不是打乱数据。所以如果你的数据有一定的分层,这个分层会影响验证集。

我从文档中进一步了解到,在分配验证数据之前,shuffle参数 in.fit()不会对数据进行洗牌。它在每个 epoch 之前对训练数据进行洗牌。

据我记得,我遇到了类似的问题,需要在将数据提供给 NN 之前“手动”打乱我的数据,以避免在验证集中(由 定义validation_split)出现问题的类分组。

从文档:

validation_split
介于 0 和 1 之间的浮点数。要用作验证数据的训练数据的一部分。该模型将分离这部分训练数据,不会对其进行训练,并将在每个 epoch 结束时评估该数据的损失和任何模型指标。在改组之前,从提供的 x 和 y 数据中的最后一个样本中选择验证数据。

shuffle
逻辑(是否在每个 epoch 之前对训练数据进行洗牌)或字符串(对于“batch”)。“批处理”是处理 HDF5 数据限制的特殊选项;它以批量大小的块进行洗牌。当 steps_per_epoch 不为 NULL 时无效。