0Pricing
R Academy · 课时

训练、验证与防止过拟合

监控 val_loss,应用 Dropout,并使用回调实现提前停止

训练、验证与防止过拟合 是 CoddyKit 上的免费 R Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

训练集、验证集和测试集划分

深度学习需要将数据划分为三部分:训练集(模型学习参数)、验证集(训练期间监控泛化能力并调整超参数)和测试集(进行最终的无偏评估)。fit() 中的 validation_split 参数可以自动创建验证集。

# validation_split = 0.2 reserves last 20% as validation
history <- model |> fit(
  x_train, y_train,
  epochs           = 50,
  batch_size       = 32,
  validation_split = 0.2,
  verbose          = 0
)

# history contains train and val metrics per epoch
names(history$metrics)

训练历史对象

fit() 返回的对象包含一个 $metrics 列表,其中每个训练轮次的每个记录指标各对应一项。调用 plot(history) 可以并排可视化训练曲线和验证曲线。如果两条曲线出现分离(训练效果改善而验证效果趋于停滞),则说明可能发生了过拟合。

# Training loss and accuracy over epochs
head(history$metrics$loss)
head(history$metrics$val_loss)

# Plot training curves
plot(history)

# Or create a custom ggplot
library(ggplot2)
df <- data.frame(
  epoch    = seq_along(history$metrics$loss),
  train    = history$metrics$loss,
  val      = history$metrics$val_loss
)
ggplot(df, aes(epoch)) +
  geom_line(aes(y = train, colour = 'Train')) +
  geom_line(aes(y = val,   colour = 'Validation')) +
  labs(y = 'Loss', title = 'Training Curves')

检测过拟合

当训练损失持续下降,但验证损失开始上升时,就发生了过拟合。模型记住了训练数据,而不是学习可泛化的模式。表现包括:训练准确率和验证准确率之间存在较大差距,验证损失先出现明显的最低点,随后又上升。

# Overfitting is visible in the history
# Example of overfitting signatures:
cat('Epoch 5  — Train loss: 0.12, Val loss: 0.18\n')
cat('Epoch 10 — Train loss: 0.06, Val loss: 0.21\n')
cat('Epoch 20 — Train loss: 0.02, Val loss: 0.31\n')

# The model should have stopped at epoch 5!
# Strategies: early stopping, dropout, regularisation, more data

callback_early_stopping()

callback_early_stopping(monitor, patience, restore_best_weights) 会在所监控的指标不再改善时停止训练。patience 表示在上一次改善后要等待的训练轮次数。将 restore_best_weights = TRUE 设置为 TRUE,即可自动恢复最佳训练轮次的权重。

early_stop <- callback_early_stopping(
  monitor              = 'val_loss',
  patience             = 10,        # wait 10 epochs
  restore_best_weights = TRUE       # rollback to best
)

history <- model |> fit(
  x_train, y_train,
  epochs           = 200,
  batch_size       = 32,
  validation_split = 0.2,
  callbacks        = list(early_stop),
  verbose          = 0
)

cat('Stopped at epoch:', length(history$metrics$loss))

callback_reduce_lr_on_plateau()

当训练陷入停滞时,降低学习率通常可以重新推动模型取得进展。callback_reduce_lr_on_plateau(monitor, factor, patience) 会在所监控的指标经过 patience 个训练轮次仍未改善时,将当前学习率乘以 factor。

reduce_lr <- callback_reduce_lr_on_plateau(
  monitor  = 'val_loss',
  factor   = 0.5,    # halve the learning rate
  patience = 5,      # after 5 stagnant epochs
  min_lr   = 1e-6    # floor for learning rate
)

history <- model |> fit(
  x_train, y_train,
  epochs           = 100,
  batch_size       = 64,
  validation_split = 0.2,
  callbacks        = list(early_stop, reduce_lr),
  verbose          = 1
)

callback_model_checkpoint()

callback_model_checkpoint(filepath, save_best_only) 会在每个训练轮次结束时将模型权重保存到磁盘(或者在性能改善时才保存,此时使用 save_best_only = TRUE)。这样可以防止训练崩溃导致进度丢失,即使训练超过最佳点仍在继续,也能加载最佳模型。

checkpoint <- callback_model_checkpoint(
  filepath       = '/tmp/best_model.h5',
  monitor        = 'val_accuracy',
  save_best_only = TRUE,
  mode           = 'max',      # higher accuracy = better
  verbose        = 1
)

history <- model |> fit(
  x_train, y_train,
  epochs           = 100,
  batch_size       = 32,
  validation_split = 0.2,
  callbacks        = list(early_stop, reduce_lr, checkpoint)
)

# Reload best model
best_model <- load_model_hdf5('/tmp/best_model.h5')

validation_data 与 validation_split

validation_split 会取训练数据中最后的 N%。如果数据有顺序(例如时间序列),这样做会产生偏差。请改用 validation_data = list(x_val, y_val),从随机分层划分中提供一个预先构建好的验证集。

# Manually create a random validation split
set.seed(42)
val_idx  <- sample(nrow(x_train), size = 0.2 * nrow(x_train))
x_val    <- x_train[val_idx, ]
y_val    <- y_train[val_idx, ]
x_tr     <- x_train[-val_idx, ]
y_tr     <- y_train[-val_idx, ]

history <- model |> fit(
  x_tr, y_tr,
  epochs         = 50,
  batch_size     = 32,
  validation_data = list(x_val, y_val),  # explicit val set
  callbacks      = list(early_stop)
)

批大小的影响

批大小是训练中的关键超参数。较小的批次会在梯度估计中引入更多噪声(起到正则化作用),有助于提高泛化能力。较大的批次速度更快,但可能收敛到更尖锐、泛化能力较差的极小值。常用值包括:32、64、128。请先尝试 32。

# Compare training with different batch sizes
for (bs in c(32, 128, 512)) {
  set_weights(model, init_weights)  # reset
  h <- model |> fit(
    x_train, y_train,
    epochs           = 20,
    batch_size       = bs,
    validation_split = 0.2,
    verbose          = 0
  )
  cat('Batch:', bs, '| Val Acc:',
      tail(h$metrics$val_accuracy, 1), '\n')
}

学习率预热

在最初几个训练轮次中从非常小的学习率开始并逐渐增大(即预热),可以稳定训练过程,尤其适用于大型模型或小型数据集。自定义的 LearningRateScheduler 回调可以实现这种模式。

# Custom learning rate schedule with warmup
lr_schedule <- function(epoch, lr) {
  if (epoch < 5) {
    return(lr * (epoch + 1) / 5)  # warmup
  } else if (epoch < 30) {
    return(lr)                     # constant
  } else {
    return(lr * 0.95)              # decay
  }
}

lr_callback <- callback_learning_rate_scheduler(lr_schedule)

history <- model |> fit(
  x_train, y_train,
  epochs     = 50,
  callbacks  = list(lr_callback, early_stop),
  validation_split = 0.2
)

正则化总结

为了实现稳健的深度学习,应结合使用多种正则化技术:

  • Dropout:训练期间随机将神经元置零。
  • 权重衰减(L2):在损失中惩罚较大的权重。
  • 提前停止:在模型过拟合之前停止训练。
  • 数据增强:人为增大训练集规模。
  • 批归一化:稳定激活值并减少协变量偏移。
model <- keras_model_sequential(input_shape = c(784)) |>
  layer_dense(512, use_bias = FALSE,
              kernel_regularizer = regularizer_l2(1e-4)) |>
  layer_batch_normalization() |>
  layer_activation('relu') |>
  layer_dropout(0.4) |>
  layer_dense(256, kernel_regularizer = regularizer_l2(1e-4)) |>
  layer_batch_normalization() |>
  layer_activation('relu') |>
  layer_dropout(0.3) |>
  layer_dense(10, activation = 'softmax')

model |> compile('adam', 'categorical_crossentropy', 'accuracy')

绘制训练曲线

请始终并排可视化训练指标和验证指标。训练良好的模型应当表现为两条曲线逐渐收敛并保持接近。如果两条曲线分离,请增加正则化或降低模型容量。如果两条曲线都在较高损失处趋于平稳,则说明模型欠拟合。

# Detailed training curve plot
df <- data.frame(
  epoch = seq_along(history$metrics$loss),
  train_loss = history$metrics$loss,
  val_loss   = history$metrics$val_loss,
  train_acc  = history$metrics$accuracy,
  val_acc    = history$metrics$val_accuracy
)

par(mfrow = c(1, 2))
plot(df$epoch, df$train_loss, type = 'l', col = 'blue',
     xlab = 'Epoch', ylab = 'Loss', main = 'Loss')
lines(df$epoch, df$val_loss, col = 'red')
legend('topright', c('Train', 'Val'), col = c('blue','red'), lty=1)

plot(df$epoch, df$train_acc, type = 'l', col = 'blue',
     xlab = 'Epoch', ylab = 'Accuracy', main = 'Accuracy')
lines(df$epoch, df$val_acc, col = 'red')

快速检查

在 callback_early_stopping() 中设置 restore_best_weights = TRUE 会执行什么操作?

训练与防止过拟合回顾

训练、验证和防止过拟合的要点:

  • 使用 validation_split 或 validation_data 在训练期间监控泛化能力。
  • plot(history) 可视化训练曲线——曲线分离表示可能发生过拟合。
  • callback_early_stopping(patience, restore_best_weights=TRUE) 会在最佳训练轮次停止训练。
  • callback_reduce_lr_on_plateau() 会在进展停滞时降低学习率。
  • callback_model_checkpoint(save_best_only=TRUE) 会将最佳模型保存到磁盘。
  • 结合使用 dropout、L2 正则化、批归一化和数据增强,以实现稳健训练。
# Best practice training setup
callbacks <- list(
  callback_early_stopping(
    monitor = 'val_loss', patience = 15,
    restore_best_weights = TRUE
  ),
  callback_reduce_lr_on_plateau(
    monitor = 'val_loss', factor = 0.5, patience = 5
  ),
  callback_model_checkpoint(
    '/tmp/best.h5', monitor = 'val_accuracy',
    save_best_only = TRUE
  )
)

model |> fit(
  x_train, y_train,
  epochs = 200, batch_size = 64,
  validation_split = 0.2,
  callbacks = callbacks, verbose = 0
)

常见问题解答

「训练、验证与防止过拟合」课时是免费的吗?

是的 — 「训练、验证与防止过拟合」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「训练、验证与防止过拟合」这节课中我会学到什么?

监控 val_loss,应用 Dropout,并使用回调实现提前停止 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「训练、验证与防止过拟合」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 在 R 中设置 Keras 和 TensorFlow
  2. 构建序列模型
  3. 卷积神经网络基础
  4. 训练、验证与防止过拟合
← 返回 R Academy