R Academy · 课时

卷积神经网络基础

添加 Conv2D 和 MaxPooling 层,用于图像分类任务

第 3 / 4 课13 个步骤

卷积神经网络基础 是 CoddyKit 上的免费 R Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

为什么图像适合使用 CNN?

全连接网络会独立处理每个像素,从而丢失空间关系。卷积神经网络(CNN) 会将可学习的滤波器在输入上滑动,无论局部模式位于何处,都能检测边缘、纹理和形状等特征。这种平移不变性以及参数共享机制,使 CNN 成为处理图像数据的标准方法。

library(keras)

# Images are 3D tensors: (height, width, channels)
# MNIST: (28, 28, 1) — grayscale
# CIFAR-10: (32, 32, 3) — RGB

# Reshape flat vectors into image tensors
mnist <- dataset_mnist()
x_train <- array_reshape(mnist$train$x / 255, c(-1, 28, 28, 1))
y_train <- to_categorical(mnist$train$y, 10)

cat('Input shape:', dim(x_train))

layer_conv_2d()——核心层

layer_conv_2d(filters, kernel_size, activation) 会对输入应用 filters 个大小为 kernel_size 的可学习二维卷积核。每个滤波器都会学习检测一种空间模式。输出的形状为 (height, width, filters)。

library(keras)

# First conv layer: 32 filters of 3x3
model <- keras_model_sequential(input_shape = c(28, 28, 1)) |>
  layer_conv_2d(
    filters     = 32,
    kernel_size = c(3, 3),
    activation  = 'relu',
    padding     = 'same'  # keep spatial dimensions
  )

summary(model)  # output: (None, 28, 28, 32)

layer_max_pooling_2d()

layer_max_pooling_2d(pool_size) 会在每个池化窗口中取最大值,从而缩小空间维度。这样做有两个作用:减少后续层中的参数数量,并引入一定程度的平移不变性(即使发生小幅位移,输出也不会发生明显变化)。

model <- keras_model_sequential(input_shape = c(28, 28, 1)) |>
  layer_conv_2d(32, kernel_size = c(3, 3), activation = 'relu') |>
  layer_max_pooling_2d(pool_size = c(2, 2))

summary(model)
# After pooling: (None, 13, 13, 32)
# Spatial dims halved, channel count preserved

堆叠卷积层

更深的 CNN 会堆叠多个“卷积层+池化层”模块。较早的层检测低级特征(边缘、梯度);较深的层将这些特征组合成高级特征(形状、物体)。随着空间维度缩小,每个卷积层都会增加滤波器数量,以此进行补偿。

model <- keras_model_sequential(input_shape = c(32, 32, 3)) |>
  layer_conv_2d(32, c(3, 3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2, 2)) |>   # 16x16
  layer_conv_2d(64, c(3, 3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2, 2)) |>   # 8x8
  layer_conv_2d(128, c(3, 3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2, 2))      # 4x4

summary(model)

layer_flatten()

layer_flatten() 会将最后一个卷积模块的三维输出 (height, width, filters) 转换为一维向量。它连接了特征提取主干(卷积层)和分类头(全连接层)。

model <- keras_model_sequential(input_shape = c(28, 28, 1)) |>
  layer_conv_2d(32, c(3, 3), activation = 'relu') |>
  layer_max_pooling_2d(c(2, 2)) |>
  layer_conv_2d(64, c(3, 3), activation = 'relu') |>
  layer_max_pooling_2d(c(2, 2)) |>
  layer_flatten() |>     # 3D -> 1D vector
  layer_dense(128, activation = 'relu') |>
  layer_dense(10, activation = 'softmax')

summary(model)

CNN 中的 layer_dropout()

在 CNN 中,dropout 通常应用于展平层和全连接层之后,而不是卷积模块内部(卷积模块中更适合使用空间 dropout layer_spatial_dropout_2d())。在第一个全连接层之后使用 0.25 到 0.5 的比率很常见。

model <- keras_model_sequential(input_shape = c(28, 28, 1)) |>
  layer_conv_2d(32, c(3, 3), activation = 'relu') |>
  layer_max_pooling_2d(c(2, 2)) |>
  layer_conv_2d(64, c(3, 3), activation = 'relu') |>
  layer_max_pooling_2d(c(2, 2)) |>
  layer_flatten() |>
  layer_dense(128, activation = 'relu') |>
  layer_dropout(rate = 0.5) |>    # regularise the classifier head
  layer_dense(10, activation = 'softmax')

summary(model)

编译和训练 CNN

编译和训练 CNN 的方式与全连接网络相同。对于使用独热标签的多分类问题,请使用 'categorical_crossentropy';对于整数标签,请使用 'sparse_categorical_crossentropy'。与全连接网络相比,CNN 通常适合使用稍低的学习率。

model |> compile(
  optimizer = optimizer_adam(learning_rate = 0.0005),
  loss      = 'categorical_crossentropy',
  metrics   = c('accuracy')
)

history <- model |> fit(
  x = x_train,
  y = y_train,
  epochs     = 10,
  batch_size = 64,
  validation_split = 0.1,
  verbose = 1
)

plot(history)

数据增强

在小型数据集上训练 CNN 往往会导致过拟合。数据增强 会在训练时应用随机变换(翻转、旋转、缩放),以人为扩充训练集。在 keras3 中,请将 layer_random_flip()、layer_random_rotation() 作为模型内部的预处理层使用。

model <- keras_model_sequential(input_shape = c(32, 32, 3)) |>
  # Data augmentation layers (only active during training)
  layer_random_flip('horizontal') |>
  layer_random_rotation(factor = 0.1) |>
  layer_random_zoom(height_factor = 0.1) |>
  # CNN backbone
  layer_conv_2d(32, c(3, 3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2, 2)) |>
  layer_flatten() |>
  layer_dense(10, activation = 'softmax')

summary(model)

评估 CNN

evaluate(model, x_test, y_test) 返回测试损失和准确率。若要进行更深入的分析,请使用 predict() 获取各类别的概率,然后构建混淆矩阵或计算各类别的 F1 分数,以了解模型在哪些方面表现不佳。

# Evaluate on test set
test_scores <- model |> evaluate(x_test, y_test, verbose = 0)
cat('Test accuracy:', test_scores['accuracy'])

# Get predicted classes
prob_matrix <- model |> predict(x_test)
pred_classes <- max.col(prob_matrix) - 1  # 0-indexed
true_classes <- mnist$test$y

# Confusion matrix
table(Predicted = pred_classes, True = true_classes)

迁移学习概念

从头开始训练 CNN 需要大型数据集。迁移学习 会复用在 ImageNet 上预训练的特征提取层(例如 VGG、ResNet、MobileNet),只训练自定义分类头。在 keras 中,使用 application_mobilenet_v2() 加载预训练主干,并冻结其中的层。

# Load MobileNetV2 pretrained on ImageNet
base_model <- application_mobilenet_v2(
  weights      = 'imagenet',
  include_top  = FALSE,          # remove original classifier head
  input_shape  = c(224, 224, 3)
)

# Freeze pretrained weights
base_model$trainable <- FALSE

# Add custom classifier head
model <- keras_model(
  inputs  = base_model$input,
  outputs = base_model$output |>
    layer_global_average_pooling_2d() |>
    layer_dense(128, activation = 'relu') |>
    layer_dense(5, activation = 'softmax')
)

Conv2D 填充和步幅

layer_conv_2d 有两个重要参数:padding = 'same' 会在输入周围补零,使输出的空间大小与输入相同;padding = 'valid'(默认值)会使维度减少 kernel_size - 1。strides = c(2,2) 让滤波器以 2 为步长滑动,从而替代最大池化。

# 'same' padding: output = input size
conv_same <- layer_conv_2d(filters = 32, kernel_size = c(3, 3),
                           padding = 'same')

# Strided convolution instead of pooling
conv_strided <- layer_conv_2d(filters = 64, kernel_size = c(3, 3),
                              strides = c(2, 2),  # halves spatial dims
                              padding = 'same')

# Model using strides instead of max pooling
model2 <- keras_model_sequential(input_shape = c(28, 28, 1)) |>
  layer_conv_2d(32, c(3,3), strides = c(2,2), activation = 'relu',
                padding = 'same') |>
  layer_conv_2d(64, c(3,3), strides = c(2,2), activation = 'relu',
                padding = 'same') |>
  layer_flatten() |>
  layer_dense(10, activation = 'softmax')
summary(model2)

快速检查

在 CNN 中,layer_max_pooling_2d(pool_size = c(2, 2)) 的主要作用是什么?

CNN 回顾

卷积神经网络基础的要点:

  • CNN 使用局部感受野和参数共享机制,高效处理图像。
  • layer_conv_2d(filters, kernel_size, activation) 提取空间特征。
  • layer_max_pooling_2d(pool_size) 进行下采样,并提供平移不变性。
  • layer_flatten() 将卷积主干连接到全连接分类头。
  • layer_dropout(rate) 对分类头进行正则化。
  • 数据增强层(layer_random_flip() 等)可以减少过拟合。
  • 对于小型数据集,使用预训练主干进行迁移学习是实用的方法。
# Standard CNN architecture for image classification
model <- keras_model_sequential(input_shape = c(32, 32, 3)) |>
  layer_conv_2d(32,  c(3,3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2,2)) |>
  layer_conv_2d(64,  c(3,3), activation = 'relu', padding = 'same') |>
  layer_max_pooling_2d(c(2,2)) |>
  layer_conv_2d(128, c(3,3), activation = 'relu', padding = 'same') |>
  layer_flatten() |>
  layer_dense(256, activation = 'relu') |>
  layer_dropout(0.5) |>
  layer_dense(num_classes, activation = 'softmax')

model |> compile('adam', 'categorical_crossentropy', 'accuracy')
summary(model)
免费开始

用 AI 导师学习 R — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
43
课程
159

常见问题解答

「卷积神经网络基础」课时是免费的吗?

是的 — 「卷积神经网络基础」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「卷积神经网络基础」这节课中我会学到什么?

添加 Conv2D 和 MaxPooling 层,用于图像分类任务 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

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

「卷积神经网络基础」课时需要多长时间?

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

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

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

此课程中的所有课时

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