1、TensorFlow模型保存基础:什么是模型保存,为什么需要保存模型,SavedModel与HDF5格式对比
各位同学,咱们今天聊聊模型保存这件事。说实话,我刚入行那会儿,觉得训练完模型就万事大吉了。结果有一次,模型训练了三天三夜,断电了——嗯,你懂的,全没了。从那以后,我养成了一个习惯:每跑完一个epoch就保存一次。
1.1 什么是模型保存?
模型保存,说白了就是把训练好的神经网络参数、网络结构、优化器状态这些东西,打包存到硬盘上。你想想看,训练一个模型可能要花几小时甚至几天,如果不保存,每次用都得重新训练,那得多浪费。
我个人习惯把模型保存理解为「给模型拍张快照」。这张快照里包含了:
- 网络结构:有多少层、每层什么类型、激活函数是什么
- 权重参数:所有可训练的张量数值
- 优化器状态:比如Adam的动量、学习率调度器的当前值
- 训练配置:损失函数、评估指标等
核心要点:保存模型 ≠ 只保存权重。如果你只保存权重,恢复时还得手动重建网络结构,很麻烦。我建议你直接保存完整模型,省心省力。
1.2 为什么需要保存模型?
这个问题我问过不少新手,答案五花八门。其实核心原因就三个:
- 断点续训:训练到一半挂了,或者你想换个GPU继续跑。我遇到过训练了12小时,结果机房断电——幸好有checkpoint,只丢了最后5分钟的数据。
- 模型部署:训练好的模型要放到服务器、手机、嵌入式设备上跑。你不能每次都重新训练吧?
- 版本管理:你可能想对比不同超参数下的模型效果,或者回滚到某个表现更好的版本。
我的经验:在工业级项目中,我通常会同时保存多个checkpoint。比如每5个epoch保存一次,保留最近5个。这样既能回溯,又不会占太多磁盘空间。
1.3 SavedModel vs HDF5:到底选哪个?
好,接下来是今天的重头戏。TensorFlow支持两种主流格式:SavedModel 和 HDF5。我经常被问到「到底该用哪个」,我的回答是——看场景。
| 对比维度 | SavedModel | HDF5 (.h5) |
|---|---|---|
| 格式类型 | 目录结构(包含pb文件、变量、assets) | 单个二进制文件 |
| 跨语言支持 | ✅ Python、C++、Java、Go、JavaScript | ❌ 仅Python(Keras原生) |
| TensorFlow Serving | ✅ 原生支持 | ❌ 需要转换 |
| 自定义层/损失 | ✅ 支持(需注册) | ⚠️ 部分支持(可能报错) |
| 文件大小 | 稍大(包含元数据) | 较小 |
| 加载速度 | 快(支持懒加载) | 中等 |
1.4 实战对比:代码走一波
光说不练假把式。咱们直接上代码,看看两种格式怎么用。
1.4.1 保存为HDF5格式
import tensorflow as tf
# 构建一个简单的模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu', input_shape=(784,)),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 训练...(省略数据加载)
# model.fit(x_train, y_train, epochs=10)
# 保存为HDF5
model.save('my_model.h5') # 单个文件,方便拷贝
# 恢复模型
restored_model = tf.keras.models.load_model('my_model.h5')
注意:HDF5格式有个坑——如果你用了自定义层或自定义损失函数,加载时可能会报错。我曾经在项目中写了一个自定义的Focal Loss,保存成.h5后加载失败,折腾了半天才发现需要传custom_objects参数。
1.4.2 保存为SavedModel格式
# 同样的模型,保存为SavedModel
model.save('saved_model/my_model') # 会生成一个目录
# 恢复模型
restored_model = tf.keras.models.load_model('saved_model/my_model')
# 查看目录结构
import os
print(os.listdir('saved_model/my_model'))
# 输出: ['assets', 'variables', 'saved_model.pb']
你看,SavedModel保存后是一个目录,里面包含:
saved_model.pb:网络结构和计算图variables/:权重参数文件assets/:额外资源(比如词汇表)
1.5 我的选择建议
说了这么多,到底怎么选?我个人总结了一套规则:
- 如果你只是做实验、写论文:用HDF5就够了,简单方便,一个文件搞定。
- 如果你要部署到生产环境:必须用SavedModel。TensorFlow Serving、TensorFlow Lite、TensorFlow.js都只认这个格式。
- 如果你要跨语言调用:SavedModel是唯一选择。C++、Java、Go都能直接加载。
- 如果你有自定义组件:两种格式都行,但SavedModel更稳定。我建议你养成习惯,把自定义层注册到Keras的注册表中。
小技巧:其实你可以同时保存两种格式。我经常在训练结束后,先保存一个.h5方便本地调试,再保存一个SavedModel用于部署。反正磁盘空间又不贵,对吧?
1.6 避坑指南
最后,分享几个我踩过的坑:
- 版本兼容性:用TensorFlow 2.x保存的模型,不一定能在1.x上加载。反过来也一样。我建议你统一版本,或者至少记录下保存时的TF版本。
- 自定义对象:如果你用了自定义层、损失函数或指标,加载时一定要传
custom_objects参数。否则会报ValueError: Unknown layer。 - 文件路径:SavedModel保存时,路径不要带空格和中文。我在Windows上吃过这个亏,路径里有中文,结果加载失败。
- 模型签名:SavedModel支持定义多个签名(serving_default、classify、predict等)。如果你要部署到TensorFlow Serving,建议显式指定签名,避免默认行为不符合预期。
好了,这一章就到这里。下一章咱们聊聊如何用TensorFlow Serving把SavedModel部署成RESTful API服务。到时候你会明白,为什么我这么推崇SavedModel格式。