Keras 深入解析

FreeGuideOnline 最新 2026-07-16

python from keras.models import Sequential from keras.layers import Dense, Dropout

model = Sequential([ Dense(64, activation='relu', input_shape=(784,)), Dropout(0.2), Dense(10, activation='softmax') ])


也可以使用 `.add()` 方法动态添加层。  
顺序模型的局限:无法表示具有分支、共享层或多输入的架构。复杂拓扑必须使用函数式 API。

## 4. 函数式 API(Functional API)

函数式 API 将层视为可调用对象,接收张量并返回张量,可以构建**任意拓扑结构**的模型,包括多输入、多输出、残差连接等。

### 4.1 基本使用方式

```python
from keras.layers import Input, Dense, concatenate
from keras.models import Model

input_a = Input(shape=(64,))
input_b = Input(shape=(128,))

x_a = Dense(32, activation='relu')(input_a)
x_b = Dense(32, activation='relu')(input_b)
merged = concatenate([x_a, x_b])
output = Dense(1, activation='sigmoid')(merged)

model = Model(inputs=[input_a, input_b], outputs=output)

4.2 层复用的真实案例:孪生网络

利用函数式 API 的层共享特点,同一层可被多次调用:

input_1 = Input(shape=(28,28,1))
input_2 = Input(shape=(28,28,1))

shared_conv = Sequential([
    Conv2D(64, (3,3), activation='relu'),
    GlobalAveragePooling2D()
])

feat_1 = shared_conv(input_1)
feat_2 = shared_conv(input_2)
distance = Lambda(lambda tensors: K.abs(tensors[0] - tensors[1]))([feat_1, feat_2])
output = Dense(1, activation='sigmoid')(distance)
model = Model(inputs=[input_1, input_2], outputs=output)

5. 模型子类化(Model Subclassing)

子类化提供了最大灵活性,适用于研究性、动态结构的模型(如循环网络内部的自定义循环、强化学习中的网络)。

import keras

class CustomModel(keras.Model):
    def __init__(self):
        super().__init__()
        self.dense1 = Dense(64, activation='relu')
        self.dense2 = Dense(10, activation='softmax')

    def call(self, inputs):
        x = self.dense1(inputs)
        return self.dense2(x)

model = CustomModel()

子类化模型的优点:能够编写任意前向逻辑(条件分支、循环)。
缺点:模型结构对框架不可见,无法直接通过 model.summary() 获取结构,也不能使用 save() / load() 保存完整模型结构(仅可保存权重)。

6. 内置层深度解析

Keras 层是构建网络的基本单元,所有层都继承自 keras.layers.Layer。常用层分类如下:

  • 核心层Dense, Activation, Dropout, Flatten, Input
  • 卷积层Conv1D, Conv2D, Conv3D, SeparableConv2D, DepthwiseConv2D 等。
  • 池化层MaxPooling2D, AveragePooling2D, GlobalAveragePooling2D
  • 循环层LSTM, GRU, SimpleRNN, Bidirectional
  • 归一化层BatchNormalization, LayerNormalization, GroupNormalization
  • 融合层Add, Concatenate, Multiply
  • 激活层:虽然激活通常作为层参数设置,但也可以独立成层进行复用。

每个层都管理自己的权重变量计算图build(input_shape) 方法会根据输入形状创建权重,首次调用层时自动触发。

7. 自定义层

当内置层无法满足需求时,通过继承 Layer 并实现 call() 创建自定义层。

class MyDense(keras.layers.Layer):
    def __init__(self, units=32):
        super().__init__()
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(shape=(input_shape[-1], self.units),
                                 initializer='random_normal',
                                 trainable=True)
        self.b = self.add_weight(shape=(self.units,),
                                 initializer='zeros',
                                 trainable=True)

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b
  • add_weight() 创建层参数,可选择是否可训练。
  • build() 在获知输入形状后调用一次。
  • 需要注意:支持 get_config() 以确保模型可序列化。

8. 训练机制的内部原理

model.compile() 配置训练过程,其参数含义:

  • 优化器 (optimizer):如 SGD、Adam、RMSprop,负责更新权重。
  • 损失函数 (loss):衡量预测与真实标签差异,多输出模型可为字典。
  • 评估指标 (metrics):训练和验证时监控的量,不影响训练。
  • 损失缩放混合精度:通过 keras.mixed_precision 设置全局策略。

model.fit() 背后运行的是训练循环
对于每个批次:前向传播计算预测值 → 计算损失 → 反向传播求梯度 → 优化器更新权重。
对于自定义训练需求,Keras 提供 GradientTape(TensorFlow 后端)或等效上下文编写完全自定义的 train_step

8.1 自定义 train_step

在子类化模型中重写 train_step 可以实现独特训练逻辑:

class CustomModel(keras.Model):
    def train_step(self, data):
        x, y = data
        with tf.GradientTape() as tape:
            y_pred = self(x, training=True)
            loss = self.compute_loss(y=y, y_pred=y_pred)
        gradients = tape.gradient(loss, self.trainable_variables)
        self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))
        for metric in self.metrics:
            if metric.name == "loss":
                metric.update_state(loss)
            else:
                metric.update_state(y, y_pred)
        return {m.name: m.result() for m in self.metrics}

9. 回调系统(Callbacks)

回调是在训练关键节点(批次开始、epoch 结束、训练结束等)执行的“钩子”,用于实现模型保存、学习率调整、早停、可视化等非训练功能。常用回调:

  • ModelCheckpoint:按条件保存最优模型。
  • EarlyStopping:监控指标不再改善时提前终止。
  • ReduceLROnPlateau:指标停滞时降低学习率。
  • TensorBoard:记录标量、直方图、图像供可视化。
  • CSVLogger:将训练指标写入 CSV 文件。

自定义回调只需继承 Callback 并实现相应方法:

class MyCallback(keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        if logs['val_accuracy'] > 0.95:
            self.model.stop_training = True

10. 分布式训练与性能优化

10.1 多 GPU 训练

Keras 与 TensorFlow 分布策略无缝衔接:

  • tf.distribute.MirroredStrategy:单机多卡数据并行。
  • tf.distribute.TPUStrategy:使用 TPU 训练。
  • tf.distribute.MultiWorkerMirroredStrategy:多机多卡训练。

使用方式:

strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
    model = create_model()
    model.compile(...)
model.fit(...)

10.2 混合精度训练

启用混合精度可以加速训练并减少内存占用:

keras.mixed_precision.set_global_policy('mixed_float16')

模型输出层通常需强制 float32 以避免数值问题。

10.3 tf.data 管道优化

使用 tf.data.Dataset 可高效加载数据,配合预提取、并行交叠处理:

dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
dataset = dataset.shuffle(buffer_size).batch(batch_size).prefetch(tf.data.AUTOTUNE)

11. 模型保存与序列化

Keras 提供了多种保存格式:

  • SavedModel(默认):包含模型架构、权重、训练配置,可跨平台部署(TensorFlow Serving)。
    保存:model.save('my_model.keras')model.save('my_model')(目录格式)。
    加载:keras.models.load_model('...')
  • H5 格式.h5):单一 HDF5 文件,适用于传统 Keras 2 环境。
  • 仅权重model.save_weights()load_weights()
  • JSON/CSV 配置model.to_json()model_from_json() 配合权重保存。

对于自定义对象,需在 load_model 时通过 custom_objects 传入:

model = keras.models.load_model('model.keras', custom_objects={'MyDense': MyDense})