Keras 深入解析
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})