如何在 Keras 模型中训练和验证样本较小时测量过拟合

Posted

技术标签:

【中文标题】如何在 Keras 模型中训练和验证样本较小时测量过拟合【英文标题】:How to measure overfitting when train and validation sample is small in Keras model 【发布时间】:2018-07-18 10:58:23 【问题描述】:

我有以下情节:

使用以下数量的样本创建模型:

                class1     class2
train             20         20
validate          21         13

据我了解,情节表明没有过度拟合。但我觉得, 由于样本很小,我不确定模型是否通用 足够的。

除了上图还有其他方法可以衡量过拟合吗?

这是我的完整代码:

library(keras)
library(tidyverse)


train_dir <- "data/train/"
validation_dir <- "data/validate/"



# Making model ------------------------------------------------------------


conv_base <- application_vgg16(
  weights = "imagenet",
  include_top = FALSE,
  input_shape = c(150, 150, 3)
)

# VGG16 based model -------------------------------------------------------

# Works better with regularizer
model <- keras_model_sequential() %>%
  conv_base() %>%
  layer_flatten() %>%
  layer_dense(units = 256, activation = "relu", kernel_regularizer = regularizer_l1(l = 0.01)) %>%
  layer_dense(units = 1, activation = "sigmoid")

summary(model)

length(model$trainable_weights)
freeze_weights(conv_base)
length(model$trainable_weights)


# Train model -------------------------------------------------------------
desired_batch_size <- 20 

train_datagen <- image_data_generator(
  rescale = 1 / 255,
  rotation_range = 40,
  width_shift_range = 0.2,
  height_shift_range = 0.2,
  shear_range = 0.2,
  zoom_range = 0.2,
  horizontal_flip = TRUE,
  fill_mode = "nearest"
)

# Note that the validation data shouldn't be augmented!
test_datagen <- image_data_generator(rescale = 1 / 255)


train_generator <- flow_images_from_directory(
  train_dir, # Target directory
  train_datagen, # Data generator
  target_size = c(150, 150), # Resizes all images to 150 × 150
  shuffle = TRUE,
  seed = 1,
  batch_size = desired_batch_size, # was 20
  class_mode = "binary" # binary_crossentropy loss for binary labels
)

validation_generator <- flow_images_from_directory(
  validation_dir,
  test_datagen,
  target_size = c(150, 150),
  shuffle = TRUE,
  seed = 1,
  batch_size = desired_batch_size,
  class_mode = "binary"
)

# Fine tuning -------------------------------------------------------------

unfreeze_weights(conv_base, from = "block3_conv1")

# Compile model -----------------------------------------------------------



model %>% compile(
  loss = "binary_crossentropy",
  optimizer = optimizer_rmsprop(lr = 2e-5),
  metrics = c("accuracy")
)


# Evaluate  by epochs  ---------------------------------------------------------------


#  # This create plots accuracy of various epochs (slow)
history <- model %>% fit_generator(
  train_generator,
  steps_per_epoch = 100,
  epochs = 15, # was 50
  validation_data = validation_generator,
  validation_steps = 50
)

plot(history)

【问题讨论】:

您使用的是 RStudio 教程中的 keras 默认值吗? tensorflow.rstudio.com/blog/…。它看起来像,但只是检查。如果您可以提供示例数据,那就太好了。我的方法是在更大的公共数据集上进行训练,然后在该上下文中分析小型私有数据。您也可以尝试交换训练和验证数据并比较结果。 【参考方案1】:

如果你想测量你当前模型的过度拟合,你可以在你的小测试集上测试模型,每次从validate set中选择34个样本,即通过函数sample和设置replace=TRUE。通过从validate set 中选择您替换的样本,您将能够创建更多“极端”数据集,从而更好地估计预测可能会根据您的可用数据而变化。此方法称为 baggingbootstrap 聚合

【讨论】:

【参考方案2】:

您的验证损失始终低于训练损失。我会很怀疑你的结果。 如果您查看验证准确性,它不应该是那样的。

您拥有的数据越少,您对任何事情的信心就越低。因此,当您不确定过度拟合时,您是对的。唯一可行的方法是收集更多数据,或者通过数据增强,或者与另一个数据集结合。

【讨论】:

【参考方案3】:

这里有两件事:

    根据 w.r.t 对数据进行分层类 - 您的验证数据具有与您的训练集完全不同的类分布(训练集是平衡的,而验证集 - 不是)。这可能会影响您的损失和指标值。最好对结果进行分层,这样两组的班级比例相同。

    由于数据点太少,使用更粗略的验证模式 - 您可能会看到总共只有 74 张图像。在这种情况下 - 将所有图像加载到 numpy.array 不是问题(您仍然可以使用 flow 函数进行数据扩充)并使用当您将数据放在文件夹中时很难获得的验证模式。我建议您使用的模式(来自sklearn)是:

    stratified k-fold cross-validation - 您将数据分成 k 个块 - 对于每个 k - 1 个块的选择 - 您首先在 k - 1 然后计算留待验证的指标。最终结果是在验证块上获得的结果的平均值。当然,您不仅可以检查 mean,还可以检查 losses 分布的其他统计数据(例如 minmax中位数等)。您还可以将它们与在每个折叠的训练集上获得的结果进行比较。 leave-one-out - 这是先前模式的一个特例 - chunks / folds 的数量等于您的示例的数量数据集。这种方法被认为是衡量模型性能的最粗略方法。在深度学习中很少使用它,因为训练过程通常很慢而且数据集很大,以便在合理的时间内完成计算。

【讨论】:

另一种需要考虑的方法,用很少的数据点进行训练,将是 k 折交叉验证的扩展,即“带混洗的迭代 k 折交叉验证”:1) 混洗数据, 2) 执行 k 折交叉验证。执行步骤 1 和 2 共 N 次;然后计算最终分数,取每次运行 k 折交叉验证时获得的分数的平均值。在这种情况下(即数据点数量少),这个分数会比只执行一个 k 倍精确得多。但是,由于需要学习 K×N 个模型,因此计算成本可能更高。【参考方案4】:

我建议将预测视为下一步。

例如,从上图和提供的样本数量来看,您的验证预测在两种准确度之间波动,而这些预测之间的差异恰好是一个猜对了的样本。

因此,与拟合无关,您的模型预测的结果或多或少相同(加减一个观察值)。这是一个不好的迹象。

此外,特征和可训练参数(权重)的数量对于提供的样本数量来说太高了。所有这些权重都没有机会实际训练。

【讨论】:

以上是关于如何在 Keras 模型中训练和验证样本较小时测量过拟合的主要内容,如果未能解决你的问题,请参考以下文章

keras 如何保存训练集与验证集正确率的差最小那次epoch的网络及权重

加载 Keras 模型并使用它进行预测

Keras深度学习实战——基于VGG19模型实现性别分类

在 Keras 中拟合模型时,批量大小和 epoch 数应该有多大?

如何在训练、验证、测试样本中选择几乎均匀分布的类?

如何理解 Keras 模型拟合中的 loss acc val_loss val_acc