卷积层 #

卷积操作原理 #

卷积层通过卷积核在输入上滑动,提取局部特征。

text
┌─────────────────────────────────────────────────────────────┐
│                    卷积操作示意                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入 (5×5)           卷积核 (3×3)       输出 (3×3)         │
│  ┌─┬─┬─┬─┬─┐        ┌─┬─┬─┐           ┌─┬─┬─┐             │
│  │1│1│1│0│0│        │1│0│1│           │4│3│4│             │
│  ├─┼─┼─┼─┼─┤        ├─┼─┼─┤           ├─┼─┼─┤             │
│  │0│1│1│1│0│   *    │0│1│0│    =      │2│4│3│             │
│  ├─┼─┼─┼─┼─┤        ├─┼─┼─┤           ├─┼─┼─┤             │
│  │0│0│1│1│1│        │1│0│1│           │2│3│4│             │
│  ├─┼─┼─┼─┼─┤        └─┴─┴─┘           └─┴─┴─┘             │
│  │0│0│1│1│0│                                              │
│  ├─┼─┼─┼─┼─┤        计算过程:                               │
│  │0│1│1│0│0│        1×1+1×0+1×1+                              │
│  └─┴─┴─┴─┴─┘        0×0+1×1+1×0+                              │
│                      0×1+0×0+1×1 = 4                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Conv2D 层 #

基本用法 #

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
    keras.layers.MaxPooling2D(),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

参数详解 #

python
keras.layers.Conv2D(
    filters=32,
    kernel_size=3,
    strides=(1, 1),
    padding='valid',
    activation='relu',
    use_bias=True,
    kernel_initializer='glorot_uniform',
    bias_initializer='zeros',
    kernel_regularizer=None,
    bias_regularizer=None
)
text
┌─────────────────────────────────────────────────────────────┐
│                    Conv2D 参数说明                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  filters: 卷积核数量(输出通道数)                          │
│  ├── 决定输出特征图的深度                                   │
│  └── 常见值: 32, 64, 128, 256                              │
│                                                             │
│  kernel_size: 卷积核大小                                    │
│  ├── 整数: 正方形卷积核                                    │
│  ├── 元组: (height, width)                                 │
│  └── 常见值: 3, 5, 7                                       │
│                                                             │
│  strides: 步幅                                              │
│  ├── 控制卷积核移动步长                                    │
│  └── 增大步幅会减小输出尺寸                                │
│                                                             │
│  padding: 填充方式                                          │
│  ├── 'valid': 无填充,输出尺寸减小                         │
│  └── 'same': 填充使输出尺寸等于输入                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

输出尺寸计算 #

text
┌─────────────────────────────────────────────────────────────┐
│                    输出尺寸公式                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输出尺寸 = floor((W - K + 2P) / S) + 1                     │
│                                                             │
│  W: 输入尺寸                                                │
│  K: 卷积核大小                                              │
│  P: 填充大小                                                │
│  S: 步幅                                                    │
│                                                             │
│  示例:                                                      │
│  输入: 224×224, 卷积核: 3×3, 填充: 1, 步幅: 1              │
│  输出: (224 - 3 + 2×1) / 1 + 1 = 224                       │
│                                                             │
│  输入: 224×224, 卷积核: 3×3, 填充: 0, 步幅: 2              │
│  输出: (224 - 3 + 0) / 2 + 1 = 112                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

不同配置示例 #

python
import keras

x = keras.Input(shape=(224, 224, 3))

conv1 = keras.layers.Conv2D(64, 3, padding='same')(x)
print(f"Same padding: {conv1.shape}")

conv2 = keras.layers.Conv2D(64, 3, padding='valid')(x)
print(f"Valid padding: {conv2.shape}")

conv3 = keras.layers.Conv2D(64, 3, strides=2, padding='same')(x)
print(f"Stride=2: {conv3.shape}")

conv4 = keras.layers.Conv2D(64, 7, strides=2, padding='same')(x)
print(f"Kernel=7, Stride=2: {conv4.shape}")

池化层 #

池化层用于降低特征图的空间维度。

text
┌─────────────────────────────────────────────────────────────┐
│                    池化类型                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  最大池化 (MaxPooling)                                      │
│  ┌───┬───┬───┬───┐       ┌───┬───┐                        │
│  │ 1 │ 3 │ 2 │ 0 │       │ 3 │ 2 │                        │
│  ├───┼───┼───┼───┤       ├───┼───┤                        │
│  │ 2 │ 0 │ 1 │ 5 │  ───► │ 4 │ 5 │                        │
│  ├───┼───┼───┼───┤       └───┴───┘                        │
│  │ 0 │ 4 │ 3 │ 1 │       取每个区域的最大值                │
│  ├───┼───┼───┼───┤                                        │
│  │ 2 │ 1 │ 0 │ 3 │                                        │
│  └───┴───┴───┴───┘                                        │
│                                                             │
│  平均池化 (AveragePooling)                                  │
│  取每个区域的平均值                                         │
│                                                             │
│  全局池化 (GlobalPooling)                                   │
│  将整个特征图池化为一个值                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

MaxPooling2D #

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
    keras.layers.MaxPooling2D(pool_size=2),
    keras.layers.Conv2D(64, 3, activation='relu'),
    keras.layers.MaxPooling2D(pool_size=2),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

AveragePooling2D #

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
    keras.layers.AveragePooling2D(pool_size=2),
    keras.layers.Flatten(),
    keras.layers.Dense(10, activation='softmax')
])

GlobalAveragePooling2D #

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(64, 3, activation='relu', input_shape=(224, 224, 3)),
    keras.layers.Conv2D(128, 3, activation='relu'),
    keras.layers.GlobalAveragePooling2D(),
    keras.layers.Dense(10, activation='softmax')
])

Conv1D 层 #

Conv1D 用于处理序列数据。

python
import keras

model = keras.Sequential([
    keras.layers.Embedding(10000, 128, input_length=100),
    keras.layers.Conv1D(64, 3, activation='relu'),
    keras.layers.GlobalMaxPooling1D(),
    keras.layers.Dense(10, activation='softmax')
])

Conv3D 层 #

Conv3D 用于处理视频或 3D 数据。

python
import keras

model = keras.Sequential([
    keras.layers.Conv3D(32, 3, activation='relu', input_shape=(16, 112, 112, 3)),
    keras.layers.MaxPooling3D(pool_size=2),
    keras.layers.Conv3D(64, 3, activation='relu'),
    keras.layers.GlobalAveragePooling3D(),
    keras.layers.Dense(10, activation='softmax')
])

SeparableConv2D 层 #

深度可分离卷积,参数更少。

python
import keras

model = keras.Sequential([
    keras.layers.SeparableConv2D(32, 3, activation='relu', input_shape=(224, 224, 3)),
    keras.layers.SeparableConv2D(64, 3, activation='relu'),
    keras.layers.GlobalAveragePooling2D(),
    keras.layers.Dense(10, activation='softmax')
])

DepthwiseConv2D 层 #

深度卷积,每个输入通道单独卷积。

python
import keras

model = keras.Sequential([
    keras.layers.DepthwiseConv2D(3, padding='same', input_shape=(224, 224, 3)),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.Conv2D(64, 1),
    keras.layers.GlobalAveragePooling2D(),
    keras.layers.Dense(10, activation='softmax')
])

Conv2DTranspose 层 #

转置卷积(反卷积),用于上采样。

python
import keras

model = keras.Sequential([
    keras.layers.Dense(7 * 7 * 128, input_shape=(100,)),
    keras.layers.Reshape((7, 7, 128)),
    keras.layers.BatchNormalization(),
    keras.layers.Conv2DTranspose(64, 3, strides=2, padding='same', activation='relu'),
    keras.layers.BatchNormalization(),
    keras.layers.Conv2DTranspose(32, 3, strides=2, padding='same', activation='relu'),
    keras.layers.Conv2D(1, 3, padding='same', activation='sigmoid')
])

UpSampling2D 层 #

简单的上采样层。

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(32, 3, padding='same', input_shape=(14, 14, 3)),
    keras.layers.UpSampling2D(size=2),
    keras.layers.Conv2D(64, 3, padding='same'),
    keras.layers.Conv2D(3, 3, padding='same')
])

Cropping2D 层 #

裁剪层,用于去除边缘。

python
import keras

model = keras.Sequential([
    keras.layers.Conv2D(32, 3, padding='same', input_shape=(32, 32, 3)),
    keras.layers.Cropping2D(cropping=4),
])

ZeroPadding2D 层 #

零填充层。

python
import keras

model = keras.Sequential([
    keras.layers.ZeroPadding2D(padding=1, input_shape=(28, 28, 1)),
    keras.layers.Conv2D(32, 3),
])

完整 CNN 示例 #

python
import keras

model = keras.Sequential([
    keras.layers.Input(shape=(32, 32, 3)),
    
    keras.layers.Conv2D(32, 3, padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.Conv2D(32, 3, padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.MaxPooling2D(),
    keras.layers.Dropout(0.25),
    
    keras.layers.Conv2D(64, 3, padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.Conv2D(64, 3, padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.MaxPooling2D(),
    keras.layers.Dropout(0.25),
    
    keras.layers.Flatten(),
    keras.layers.Dense(512),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('relu'),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(10, activation='softmax')
])

model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

model.summary()

下一步 #

现在你已经掌握了卷积层,接下来学习 循环层,处理序列数据!

最后更新:2026-04-04