Subclassing模型需显式构建或首次调用才能初始化权重,call方法必须含training参数并透传,层须在__init__中创建,仅支持SavedModel/Checkpoint保存。

Subclassing模型必须显式调用build()才能访问trainable_variables
直接实例化一个继承tf.keras.Model的子类后,model.trainable_variables常为空——这不是bug,而是TF 2.x的延迟构建机制导致的。模型权重只在第一次前向传播(或显式调用build())时才初始化。
常见错误现象:len(model.trainable_variables)返回0,model.summary()报错或显示无参数。
- 最稳妥的做法:先用匹配形状的输入调用一次
model(input_batch),例如model(tf.random.normal((1, 28, 28, 1))) - 也可手动调用
model.build(input_shape=(None, 28, 28, 1)),但注意input_shape不带batch维,且必须与后续实际输入一致 - 切勿在
__init__里试图访问self.trainable_variables——此时层甚至还没被创建
自定义call()里不能漏掉training参数
call()方法签名必须包含training=False默认参数,否则model(x, training=True)会报TypeError: call() got an unexpected keyword argument 'training',且Dropout、BatchNormalization等层无法正确切换模式。
使用场景:训练/推理逻辑分离、梯度裁剪、中间特征提取等都依赖这个开关。
- 务必写成
def call(self, inputs, training=False):,不能省略training或改名 - 把
training透传给内部层:self.bn(inputs, training=training)、self.dropout(x, training=training) - 若自行实现带随机性的逻辑(如自定义dropout),也要根据
training分支处理
tf.keras.Model子类中,层必须在__init__里创建,不能在call()里新建
在call()中调用tf.keras.layers.Dense(10)会触发“层未追踪”错误,导致权重不参与训练、model.save()失败、get_config()丢失结构。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
根本原因:TF需要在图构建阶段就确定完整计算图和变量归属,动态创建的层脱离了模型的_layers管理链。
- 所有层必须作为实例属性在
__init__中初始化:self.dense = tf.keras.layers.Dense(64) - 禁止在
call()中写tf.keras.layers.Conv2D(32, 3)(x)这类即时调用 - 如果需条件化使用不同层(如多任务分支),应在
__init__中全部创建,再在call()中通过if选择调用
保存Subclassing模型只能用tf.train.Checkpoint或SavedModel格式
model.save('path.h5')会失败并提示NotImplementedError: Saving the model to HDF5 format requires the model to be a Functional model。Subclassing模型没有静态函数式拓扑,不支持HDF5。
性能与兼容性影响:SavedModel是唯一推荐方式,它保存完整的计算图、变量、签名,跨TF版本兼容性好;Checkpoint更轻量,适合断点续训,但需配合代码重建模型结构。
- 存权重+结构(推荐):
tf.saved_model.save(model, 'saved_model_dir') - 仅存权重(需代码重建模型):
ckpt = tf.train.Checkpoint(model=model); ckpt.write('ckpt_path') - 加载SavedModel:
loaded = tf.keras.models.load_model('saved_model_dir')(注意:不是tf.keras.models.load_model对所有Subclassing模型都可靠,有时需用tf.keras.models.load_model(..., custom_objects={...})注册自定义类)
容易被忽略的是:SavedModel加载后,loaded是ConcreteFunction包装的对象,不是原始Python类实例——如果你依赖模型类上的自定义方法(如model.custom_step()),这些方法不会被保存或恢复。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










