1、TensorFlow模型保存基础:什么是模型保存,为什么需要保存模型,SavedModel与HDF5格式对比

各位同学,咱们今天聊聊模型保存这件事。说实话,我刚入行那会儿,觉得训练完模型就万事大吉了。结果有一次,模型训练了三天三夜,断电了——嗯,你懂的,全没了。从那以后,我养成了一个习惯:每跑完一个epoch就保存一次。

1.1 什么是模型保存?

模型保存,说白了就是把训练好的神经网络参数、网络结构、优化器状态这些东西,打包存到硬盘上。你想想看,训练一个模型可能要花几小时甚至几天,如果不保存,每次用都得重新训练,那得多浪费。

我个人习惯把模型保存理解为「给模型拍张快照」。这张快照里包含了:

  • 网络结构:有多少层、每层什么类型、激活函数是什么
  • 权重参数:所有可训练的张量数值
  • 优化器状态:比如Adam的动量、学习率调度器的当前值
  • 训练配置:损失函数、评估指标等

核心要点:保存模型 ≠ 只保存权重。如果你只保存权重,恢复时还得手动重建网络结构,很麻烦。我建议你直接保存完整模型,省心省力。

1.2 为什么需要保存模型?

这个问题我问过不少新手,答案五花八门。其实核心原因就三个:

  1. 断点续训:训练到一半挂了,或者你想换个GPU继续跑。我遇到过训练了12小时,结果机房断电——幸好有checkpoint,只丢了最后5分钟的数据。
  2. 模型部署:训练好的模型要放到服务器、手机、嵌入式设备上跑。你不能每次都重新训练吧?
  3. 版本管理:你可能想对比不同超参数下的模型效果,或者回滚到某个表现更好的版本。

我的经验:在工业级项目中,我通常会同时保存多个checkpoint。比如每5个epoch保存一次,保留最近5个。这样既能回溯,又不会占太多磁盘空间。

1.3 SavedModel vs HDF5:到底选哪个?

好,接下来是今天的重头戏。TensorFlow支持两种主流格式:SavedModelHDF5。我经常被问到「到底该用哪个」,我的回答是——看场景。

对比维度 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格式。