4、仅保存架构:使用model.to_json()与model.from_json(),保存模型结构不保存参数
好,咱们继续聊模型保存的话题。
前面我们讲了保存全部参数,也讲了只保存权重。那有没有一种场景,我只想要模型的结构,参数一个都不要?
有,而且很常见。
什么时候只需要架构?
我举个例子你就明白了。假设你在公司训练了一个超大的BERT模型,参数文件好几个G。你想把这个模型分享给同事做二次开发,或者部署到不同环境。但同事那边可能只需要你的网络结构,他自己有另外一套预训练权重。
这时候你把整个模型文件发过去,太笨重了。你想想看,几个G的文件传来传去,多麻烦。
另一个场景:你在做模型架构的对比实验。比如你想比较ResNet50和ResNet101在同样数据上的表现。你只需要把网络结构保存下来,然后分别加载不同的权重去跑。这样代码更干净,逻辑也更清晰。
model.to_json() 怎么用?
Keras 提供了一个非常方便的方法——model.to_json()。它会把模型的结构序列化成 JSON 字符串。说白了,就是把你的网络层、连接方式、激活函数这些信息,用文本的形式记录下来。
# 假设你已经有了一个训练好的模型
from tensorflow import keras
# 保存模型架构为 JSON 字符串
json_string = model.to_json()
print(json_string) # 你会看到一长串 JSON 文本
# 也可以直接保存到文件
with open('model_architecture.json', 'w') as f:
f.write(json_string)
嗯,这里要注意一点:to_json() 保存的是模型的拓扑结构。包括每一层的类型、参数设置、输入输出连接关系。但它不保存任何训练好的权重值。
核心区别:
model.to_json()→ 只保存结构,不保存参数model.save_weights()→ 只保存参数,不保存结构model.save()→ 结构和参数一起保存
model.from_json() 怎么恢复?
有保存就得有恢复。从 JSON 重建模型用的是 keras.models.model_from_json()。
from tensorflow import keras
# 从 JSON 文件读取架构
with open('model_architecture.json', 'r') as f:
json_string = f.read()
# 重建模型(此时只有结构,没有权重)
new_model = keras.models.model_from_json(json_string)
# 查看模型结构
new_model.summary()
这时候你得到的 new_model 是一个未编译、未训练的模型。它的权重是随机初始化的。你需要重新编译它,然后要么加载之前保存的权重,要么重新训练。
我的习惯:
我个人习惯把模型架构和权重分开保存。这样版本管理更方便。比如我改了一个小结构,只需要更新 JSON 文件,权重文件不用动。如果一起保存,每次改结构都得重新保存整个模型,太慢了。
实战中的坑
我曾经在项目里踩过一个坑,分享给你。
有一次我用 model.to_json() 保存了一个自定义层的模型。结果加载的时候报错了,说找不到这个自定义层。为什么呢?因为 from_json() 默认只认识 Keras 内置的层。如果你用了自定义层,比如自己写的 MyDenseLayer,就得在加载时告诉它。
# 自定义层
class MyDenseLayer(keras.layers.Layer):
def __init__(self, units=32, **kwargs):
super(MyDenseLayer, self).__init__(**kwargs)
self.units = units
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
# 加载时需要传入 custom_objects
new_model = keras.models.model_from_json(
json_string,
custom_objects={'MyDenseLayer': MyDenseLayer}
)
警告:
如果你用了自定义层、自定义损失函数或自定义指标,加载模型时一定要通过 custom_objects 参数传入对应的类或函数。否则会报 ValueError: Unknown layer 错误。
什么时候用这个方案?
我总结了几种典型场景:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 分享模型结构给同事 | to_json() | 文件小,方便传输 |
| 做架构对比实验 | to_json() + save_weights() | 结构独立,权重复用 |
| 部署到不同框架 | to_json() | JSON 是通用格式,容易转换 |
| 版本控制 | to_json() | 文本文件,方便 diff 对比 |
小结一下
model.to_json() 和 model.from_json() 是一对好搭档。它们让你可以轻量级地保存和恢复模型结构。说白了,就是只保留骨架,不要血肉。
我个人建议,在项目初期或者做实验时,多用这个方案。等模型稳定了,再考虑用 model.save() 做完整保存。这样既灵活又高效。
嗯,下一节我们聊聊更高级的保存方式——SavedModel 格式。那是 TensorFlow 官方推荐的生产级方案,也是 TensorFlow Serving 部署的基础。