Sequential 序列模型 #
什么是 Sequential 模型? #
Sequential 模型是 Keras 中最简单的模型类型,它将多个网络层线性堆叠在一起。
text
┌─────────────────────────────────────────────────────────────┐
│ Sequential 模型结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 输入 ──► [层1] ──► [层2] ──► [层3] ──► 输出 │
│ │
│ 特点: │
│ ✅ 简单直观,易于理解 │
│ ✅ 适合初学者入门 │
│ ✅ 适合简单的前馈网络 │
│ │
│ 局限: │
│ ❌ 不支持多输入/多输出 │
│ ❌ 不支持层共享 │
│ ❌ 不支持复杂拓扑结构 │
│ │
└─────────────────────────────────────────────────────────────┘
创建 Sequential 模型 #
方式一:列表方式 #
python
import keras
model = keras.Sequential([
keras.layers.Dense(64, activation='relu', input_shape=(784,)),
keras.layers.Dropout(0.2),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
方式二:逐层添加 #
python
import keras
model = keras.Sequential()
model.add(keras.layers.Dense(64, activation='relu', input_shape=(784,)))
model.add(keras.layers.Dropout(0.2))
model.add(keras.layers.Dense(32, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
方式三:指定输入层 #
python
import keras
model = keras.Sequential([
keras.layers.Input(shape=(784,)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
指定输入形状 #
text
┌─────────────────────────────────────────────────────────────┐
│ 输入形状指定 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 方式 1: 在第一个层指定 input_shape │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Dense(64, input_shape=(784,)) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 方式 2: 使用 Input 层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Input(shape=(784,)) │ │
│ │ Dense(64) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 方式 3: 使用 build 方法 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ model.build(input_shape=(None, 784)) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 注意: batch 维度不需要指定 │
│ input_shape=(784,) 表示 (batch_size, 784) │
│ │
└─────────────────────────────────────────────────────────────┘
不同数据类型的输入形状 #
python
import keras
image_model = keras.Sequential([
keras.layers.Conv2D(32, 3, input_shape=(28, 28, 3)),
keras.layers.MaxPooling2D(),
keras.layers.Flatten(),
keras.layers.Dense(10)
])
sequence_model = keras.Sequential([
keras.layers.Embedding(10000, 128, input_length=100),
keras.layers.LSTM(64),
keras.layers.Dense(10)
])
video_model = keras.Sequential([
keras.layers.Conv3D(32, 3, input_shape=(16, 112, 112, 3)),
keras.layers.GlobalAveragePooling3D(),
keras.layers.Dense(10)
])
模型摘要 #
python
model.summary()
text
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ dense (Dense) │ (None, 64) │ 50,240 │
├──────────────────────────────────────┼─────────────────────┼──────────────┤
│ dropout (Dropout) │ (None, 64) │ 0 │
├──────────────────────────────────────┼─────────────────────┼──────────────┤
│ dense_1 (Dense) │ (None, 32) │ 2,080 │
├──────────────────────────────────────┼─────────────────────┼──────────────┤
│ dense_2 (Dense) │ (None, 10) │ 330 │
└──────────────────────────────────────┴─────────────────────┴──────────────┘
Total params: 52,650 (205.66 KB)
Trainable params: 52,650 (205.66 KB)
Non-trainable params: 0 (0.00 B)
编译模型 #
python
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=0.001),
loss=keras.losses.CategoricalCrossentropy(),
metrics=[
'accuracy',
keras.metrics.Precision(),
keras.metrics.Recall()
]
)
训练模型 #
基础训练 #
python
history = model.fit(
x_train, y_train,
epochs=10,
batch_size=32
)
完整训练配置 #
python
history = model.fit(
x_train, y_train,
epochs=50,
batch_size=32,
validation_data=(x_val, y_val),
validation_split=0.1,
shuffle=True,
verbose=1,
callbacks=[
keras.callbacks.EarlyStopping(patience=5),
keras.callbacks.ModelCheckpoint('best_model.keras')
]
)
text
┌─────────────────────────────────────────────────────────────┐
│ 训练参数说明 │
├─────────────────────────────────────────────────────────────┤
│ │
│ x_train, y_train: 训练数据和标签 │
│ │
│ epochs: 训练轮数,完整遍历数据集的次数 │
│ │
│ batch_size: 每次梯度更新使用的样本数 │
│ ├── 较小 (16-32): 更新频繁,训练慢,泛化好 │
│ └── 较大 (64-256): 更新少,训练快,可能陷入局部最优 │
│ │
│ validation_data: 验证数据 │
│ │
│ validation_split: 从训练数据中划分验证集比例 │
│ │
│ shuffle: 每个 epoch 前是否打乱数据 │
│ │
│ verbose: 输出详细程度 (0=静默, 1=进度条, 2=每轮一行) │
│ │
│ callbacks: 回调函数列表 │
│ │
└─────────────────────────────────────────────────────────────┘
评估与预测 #
评估模型 #
python
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
print(f'测试损失: {test_loss:.4f}')
print(f'测试准确率: {test_acc:.4f}')
预测 #
python
predictions = model.predict(x_test)
predicted_classes = predictions.argmax(axis=1)
probabilities = model.predict(x_test[:1])
print(f'预测概率: {probabilities}')
完整示例:MNIST 分类 #
python
import keras
import numpy as np
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, 784).astype('float32') / 255.0
x_test = x_test.reshape(-1, 784).astype('float32') / 255.0
model = keras.Sequential([
keras.layers.Input(shape=(784,)),
keras.layers.Dense(512, activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.3),
keras.layers.Dense(256, activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.3),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
x_train, y_train,
epochs=20,
batch_size=128,
validation_split=0.1,
callbacks=[
keras.callbacks.EarlyStopping(
monitor='val_loss',
patience=3,
restore_best_weights=True
)
]
)
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
print(f'\n测试集准确率: {test_acc:.4f}')
完整示例:图像分类 CNN #
python
import keras
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
model = keras.Sequential([
keras.layers.Input(shape=(32, 32, 3)),
keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.MaxPooling2D(),
keras.layers.Dropout(0.25),
keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.MaxPooling2D(),
keras.layers.Dropout(0.25),
keras.layers.Flatten(),
keras.layers.Dense(512, activation='relu'),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
x_train, y_train,
epochs=50,
batch_size=64,
validation_split=0.1,
callbacks=[
keras.callbacks.EarlyStopping(patience=10, restore_best_weights=True)
]
)
模型操作 #
获取层信息 #
python
for layer in model.layers:
print(f'{layer.name}: {layer.output_shape}')
first_layer = model.layers[0]
print(f'权重形状: {first_layer.kernel.shape}')
提取中间层输出 #
python
intermediate_model = keras.Model(
inputs=model.inputs,
outputs=model.layers[2].output
)
intermediate_output = intermediate_model.predict(x_test)
冻结层 #
python
for layer in model.layers[:-3]:
layer.trainable = False
model.compile(optimizer='adam', loss='categorical_crossentropy')
下一步 #
现在你已经掌握了 Sequential 模型,接下来学习 Functional API,构建更复杂的网络结构!
最后更新:2026-04-04