流式推理需复用计算图状态、避免重复编译:用tf.function固定输入形状,显式管理rnn状态,直调concretefunction而非predict()。

流式推理不是调用 model.predict() 那么简单
直接对每条新数据调用 model.predict() 看似可行,但实际会触发完整前向传播 + 内存分配 + 张量拷贝,延迟高、内存抖动大,尤其在边缘设备或低延迟场景下不可接受。TensorFlow 2.x 的流式推理核心是「复用计算图状态」和「避免重复编译」,而不是反复喂单样本。
必须用 tf.function + 静态输入形状封装推理逻辑
未经装饰的 Python 函数每次调用都会重新追踪(tracing),生成新图;而 tf.function 能缓存图并复用。但关键陷阱在于:若输入 shape 含 None(如 [None, 128]),TF 会为每个不同 batch size 生成新图——这反而加剧开销。
- 正确做法:固定 batch 维度为 1,例如用
@tf.function(input_signature=[tf.TensorSpec([1, 128], tf.float32)]) - 若需真正动态 batch(如 1~8 条混入),改用
tf.function+tf.vectorized_map批处理内部逻辑,而非放任自动追踪 - 务必关闭 eager execution?不必要——TF 2.x 默认 eager,
tf.function在 eager 下仍生效,且更易调试
状态类模型(RNN/LSTM)必须显式管理隐藏态
普通 Dense 模型无状态,但 tf.keras.layers.LSTM 在 return_state=True 模式下,每次调用会输出新 hidden state 和 cell state。流式场景下,这些 state 就是「上下文」,必须手动传入下次调用。
- 不能写
model(x),要写outputs, h, c = model(x, initial_state=[h_prev, c_prev]) -
h_prev和c_prev需初始化为tf.zeros,且 dtype、shape 必须与 layer 定义完全一致(查layer.state_size) - 若用
tf.keras.models.Sequential,记得用model.layers[0].state_size获取,别硬编码
部署时绕过 Keras API,直连 ConcreteFunction
Keras 的 predict() 有额外封装层(batch 处理、验证、回调),流式推理应跳过它,直接调用底层 ConcreteFunction 实例。这是降低延迟最有效的一步。
- 先用
concrete_func = model.signatures['serving_default']或model.__call__.get_concrete_function(...)获取 - 输入必须是
tf.Tensor,不能是 numpy array;类型、shape、name(若签名指定)全需匹配 - 错误信息如
ValueError: Input 0 of node ... was passed float32 from ... incompatible with expected int32,往往因 dtype 不一致,用.astype(tf.float32)显式转换
真正的流式难点不在“怎么跑通”,而在“如何让 state 持久、图不重编、tensor 不拷贝”。这三个点没对齐,哪怕模型结构再简单,也只会变成慢速批处理。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











