news 2026/4/15 13:35:28

tensorflow 零基础吃透:SavedModel 与 RaggedTensor 的结合使用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tensorflow 零基础吃透:SavedModel 与 RaggedTensor 的结合使用

零基础吃透:SavedModel与RaggedTensor的结合使用

核心背景(先理清)

SavedModel是 TensorFlow 官方的模型序列化格式,能完整保存模型的「权重+计算图+签名」,支持跨平台部署(如TensorFlow Serving、TFLite)、离线复用;
RaggedTensor 与 SavedModel 兼容的核心规则:

  • TF 2.3+:通过「具体函数(Concrete Function)」原生支持 RaggedTensor,无需额外处理;
  • TF 2.3 前:需将 RaggedTensor 拆解为「values(元素值)+ row_splits(行分割点)」两个张量,再保存/加载。

下面结合你提供的两个核心示例(Keras模型、自定义tf.Module模型),逐行解析代码逻辑、原理和关键注意事项。

前置准备(确保代码可运行)

importtensorflowastfimporttempfile# 用于创建临时目录存储SavedModel

示例1:保存/加载支持RaggedTensor的Keras模型

步骤1:先重建之前的Keras模型(衔接上下文)

# 1. 定义数据(复用之前的句子分类任务)sentences=tf.constant(['What makes you think she is a witch?','She turned me into a newt.','A newt?','Well, I got better.'])is_question=tf.constant([True,False,True,False])# 2. 预处理:字符串→RaggedTensor(单词哈希编码)hash_buckets=1000words=tf.strings.split(sentences,' ')hashed_words=tf.strings.to_hash_bucket_fast(words,hash_buckets)# RaggedTensor# 3. 构建适配RaggedTensor的Keras模型(修正后版本,避免LSTM报错)keras_model=tf.keras.Sequential([tf.keras.layers.Input(shape=[None],dtype=tf.int64,ragged=True),# 声明Ragged输入tf.keras.layers.Embedding(hash_buckets,16),tf.keras.layers.LSTM(32,use_bias=False),tf.keras.layers.Dense(32),tf.keras.layers.Activation(tf.nn.relu),tf.keras.layers.Dense(1)])keras_model.compile(loss='binary_crossentropy',optimizer='rmsprop')keras_model.fit(hashed_words.to_tensor(default_value=0),is_question,epochs=1)# 补0后训练

步骤2:保存Keras模型(支持RaggedTensor输入)

# 创建临时目录(避免手动管理路径)keras_module_path=tempfile.mkdtemp()# 保存模型:自动将Keras模型转换为SavedModel格式,包含RaggedTensor的处理逻辑tf.saved_model.save(keras_model,keras_module_path)print(f"Keras模型已保存到:{keras_module_path}")

步骤3:加载SavedModel并调用(传入RaggedTensor)

# 加载保存的模型imported_model=tf.saved_model.load(keras_module_path)# 直接传入RaggedTensor(hashed_words),模型透明处理result=imported_model(hashed_words)print("\n加载后模型的预测结果:")print(result)

运行结果+关键解读

WARNING:absl:Function `_wrapped_model` contains input name(s) args_0 with unsupported characters which will be renamed to args_0_1 in the SavedModel. INFO:tensorflow:Assets written to: /tmp/xxx/assets <tf.Tensor: shape=(4, 1), dtype=float32, numpy= array([[0.05265009], [0.000567 ], [0.03915224], [0.0021234 ]], dtype=float32)>
  1. 警告含义(非错误)
    SavedModel对输入名称的字符有规范,自动将不兼容的名称(如args_0)重命名为args_0_1,不影响模型功能;
  2. 核心兼容逻辑
    Keras模型的Input层声明了ragged=True,保存为SavedModel时,TF会自动生成适配RaggedTensor的具体函数(Concrete Function),加载后可直接传入RaggedTensor;
  3. 结果一致性
    加载后模型的预测结果与原Keras模型完全一致,说明RaggedTensor的处理逻辑被完整保存。

示例2:保存/加载支持RaggedTensor的自定义tf.Module模型

自定义tf.Module是TF原生的模型封装方式(比Keras更灵活),但需手动构建具体函数(指定RaggedTensor的输入签名),否则SavedModel无法正确处理RaggedTensor。

步骤1:定义自定义tf.Module(含RaggedTensor运算)

classCustomModule(tf.Module):def__init__(self,variable_value):super(CustomModule,self).__init__()# 定义可训练变量(会被SavedModel保存)self.v=tf.Variable(variable_value,dtype=tf.float32)# 用@tf.function装饰:编译为计算图,支持RaggedTensor@tf.functiondefgrow(self,x):# 核心逻辑:RaggedTensor的每个元素 × 变量vreturnx*self.v# 实例化模块(变量v=100.0)module=CustomModule(100.0)

步骤2:预构建具体函数(关键!适配RaggedTensor)

# 必须先构建具体函数:指定输入为RaggedTensorSpec(二维、float32、可变长度)# 作用:让SavedModel记录RaggedTensor的输入签名,避免加载后调用报错concrete_func=module.grow.get_concrete_function(tf.RaggedTensorSpec(shape=[None,None],dtype=tf.float32))print("预构建的具体函数:",concrete_func)

步骤3:保存自定义模块

# 创建临时目录custom_module_path=tempfile.mkdtemp()# 保存模块:包含变量v、grow函数的计算图、RaggedTensor的输入签名tf.saved_model.save(module,custom_module_path)print(f"\n自定义模型已保存到:{custom_module_path}")

步骤4:加载并调用(传入RaggedTensor)

# 加载保存的模块imported_module=tf.saved_model.load(custom_module_path)# 传入RaggedTensor调用grow函数ragged_input=tf.ragged.constant([[1.0,4.0,3.0],[2.0]],dtype=tf.float32)result=imported_module.grow(ragged_input)print("\n自定义模型调用结果:")print(result)

运行结果+关键解读

INFO:tensorflow:Assets written to: /tmp/yyy/assets <tf.RaggedTensor [[100.0, 400.0, 300.0], [200.0]]>
  1. 为什么必须预构建具体函数?
    自定义tf.Module@tf.function函数默认是“动态跟踪”的,未指定输入签名时,SavedModel无法确定输入类型(密集张量/RaggedTensor);
    get_concrete_function+tf.RaggedTensorSpec预构建后,SavedModel会固化RaggedTensor的处理逻辑,加载后可直接调用。
  2. 运算逻辑验证
    RaggedTensor的每个元素 × 变量v(100.0),结果保留RaggedTensor结构:
    • [1.0,4.0,3.0] × 100 → [100.0,400.0,300.0]
    • [2.0] × 100 → [200.0]

关键注意事项(避坑核心)

1. 版本要求(重中之重)

  • TF 2.3+:具体函数原生支持RaggedTensor,无需额外处理;
  • TF 2.3 前:SavedModel的签名不支持RaggedTensor,需手动拆解RaggedTensor为两个张量:
    # 低版本兼容:拆解RaggedTensorrt=tf.ragged.constant([[1.0,2.0],[3.0]])rt_values=rt.values# 所有元素值:[1.0,2.0,3.0]rt_row_splits=rt.row_splits# 行分割点:[0,2,3]# 保存/加载时传递values+row_splits,加载后用tf.RaggedTensor.from_row_splits重构

2. 具体函数(Concrete Function)的必要性

  • Keras模型:TF自动为ragged=True的Input层生成具体函数,无需手动构建;
  • 自定义tf.Module:必须用get_concrete_function(tf.RaggedTensorSpec)预构建,否则加载后调用RaggedTensor会报错。

3. tf.RaggedTensorSpec的作用

  • 定义RaggedTensor的输入签名(形状、 dtype),让SavedModel明确输入约束;
  • 示例中shape=[None, None]表示二维RaggedTensor,两个维度长度均可变;
  • 若需固定某一维(如固定批次大小为32),可写shape=[32, None]

4. SavedModel的核心组成(了解即可)

保存后的SavedModel目录包含:

  • assets/:静态资源(如词汇表);
  • variables/:模型权重(如CustomModule的变量v);
  • saved_model.pb:计算图+签名(包含RaggedTensor的处理逻辑)。

核心总结(SavedModel + RaggedTensor)

模型类型保存关键步骤加载后调用方式
Keras模型Input层设置ragged=True,直接tf.saved_model.save直接传入RaggedTensor
自定义tf.Moduleget_concrete_function(tf.RaggedTensorSpec)预构建具体函数,再保存传入符合RaggedTensorSpec的RaggedTensor

核心原则

  1. SavedModel对RaggedTensor的支持依赖「具体函数(Concrete Function)」,需确保保存前生成适配RaggedTensor的具体函数;
  2. TF 2.3+是兼容的最低版本,低版本需拆解RaggedTensor为分量张量;
  3. Keras模型的兼容性更“傻瓜化”(自动处理),自定义tf.Module需手动指定输入签名。

这套方案是生产环境中部署“处理可变长度数据(文本、序列)”模型的标准流程,既保留RaggedTensor无冗余的优势,又能利用SavedModel实现模型的序列化和部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 23:25:06

7、网络与传输层攻击及防御全解析

网络与传输层攻击及防御全解析 1. 网络层攻击类型 在网络安全领域,网络层攻击是常见且具有威胁性的安全问题。以下为你详细介绍几种典型的网络层攻击方式。 - 可疑TTL值攻击 :在本地子网中,数据包的TTL(Time To Live)值为零是一种可疑现象。这种情况的出现,要么是因…

作者头像 李华
网站建设 2026/4/15 10:26:49

如何快速掌握PIKE-RAG:从零开始的完整指南

如何快速掌握PIKE-RAG&#xff1a;从零开始的完整指南 【免费下载链接】PIKE-RAG PIKE-RAG: sPecIalized KnowledgE and Rationale Augmented Generation 项目地址: https://gitcode.com/gh_mirrors/pi/PIKE-RAG 您是否正在寻找一个能够处理复杂领域知识问答的智能系统&…

作者头像 李华
网站建设 2026/4/15 11:46:28

29、深入探索fwknop:强化网络安全的利器

深入探索fwknop:强化网络安全的利器 1. fwknop与iptables规则 fwknop在操作规则时,不会与iptables策略中的现有规则产生冲突。在30秒计时器到期前,可在fwknop服务器上执行以下命令查看授予对SSHD访问权限的iptables规则: [root@spaserver ~]# fwknopd --fw-list [+] Lis…

作者头像 李华
网站建设 2026/4/7 12:46:53

告别客服加班:用Dify.AI零代码打造智能工单处理系统

告别客服加班&#xff1a;用Dify.AI零代码打造智能工单处理系统 【免费下载链接】dify 一个开源助手API和GPT的替代品。Dify.AI 是一个大型语言模型&#xff08;LLM&#xff09;应用开发平台。它整合了后端即服务&#xff08;Backend as a Service&#xff09;和LLMOps的概念&a…

作者头像 李华
网站建设 2026/4/15 10:54:41

18、构建前端面板与帧缓冲接口的技术解析

构建前端面板与帧缓冲接口的技术解析 1. Laddie前端面板UI软件架构 Laddie前端面板UI软件采用事件驱动的状态机。事件包括按钮按下、定时器到期以及指示报警系统状态可能变化的日志消息到达。程序输出包括发送给Laddie守护进程的SQL命令、LED闪烁(或不闪烁)标志以及LCD上显…

作者头像 李华
网站建设 2026/4/10 21:00:41

22、红外遥控系统搭建与LIRC软件配置指南

红外遥控系统搭建与LIRC软件配置指南 1. 红外波形解码方案 在红外遥控领域,有多种解码波形的方法。理论上,若设备能完整获取输入波形的信息,就可以对任何协议的波形进行解码。以下是几种不同的实现方案: - UIRT2协议 :LIRC网站提供了通用红外远程收发器第二版(UIRT2…

作者头像 李华