中国全尺寸年度N2O数据集(1980-2020)
2026/6/16 8:57:57
tf.function:TensorFlow的核心装饰器,能把Python函数编译成TensorFlow计算图(而非逐行执行的Eager模式),大幅提升代码执行效率(尤其是重复调用/部署场景);tf.function——无需修改函数逻辑,同时支持密集张量(普通tf.Tensor)和RaggedTensor输入,TF会自动适配计算图。先准备基础运行环境:
importtensorflowastfprint(f"TensorFlow版本:{tf.__version__}")# 建议2.3+,具体函数需此版本支持被@tf.function装饰的函数,对密集张量和RaggedTensor的处理逻辑完全一致——TF会自动识别输入类型,调用适配RaggedTensor的算子(如tf.concat有专门的Ragged处理逻辑),无需额外修改代码。
# 1. 定义编译成计算图的函数(生成回文序列)@tf.function# 核心装饰器:转计算图defmake_palindrome(x,axis):# 逻辑:拼接原张量 + 反转后的张量(生成回文)reversed_x=tf.reverse(x,[axis])# 反转张量(支持Ragged)returntf.concat([x,reversed_x],axis)# 拼接(支持Ragged)# 2. 测试1:传入密集张量(普通tf.Tensor)dense_x=tf.constant([[1,2],[3,4],[5,6]])dense_result=make_palindrome(dense_x,axis=1)print("=== 密集张量执行结果 ===")print(dense_result)# 3. 测试2:传入RaggedTensor(无需改函数)ragged_x=tf.ragged.constant([[1,2],[3],[4,5,6]])ragged_result=make_palindrome(ragged_x,axis=1)print("\n=== RaggedTensor执行结果 ===")print(ragged_result)=== 密集张量执行结果 === tf.Tensor( [[1 2 2 1] [3 4 4 3] [5 6 6 5]], shape=(3, 4), dtype=int32) === RaggedTensor执行结果 === 2022-12-14 22:26:12.602591: W tensorflow/core/grappler/optimizers/loop_optimizer.cc:907] Skipping loop optimization for Merge node with control input: RaggedConcat/assert_equal_1/Assert/AssertGuard/branch_executed/_9 <tf.RaggedTensor [[1, 2, 2, 1], [3, 3], [4, 5, 6, 6, 5, 4]]>函数逻辑通用:
[1,2]反转后[2,1],拼接成[1,2,2,1];[3]反转后[3],拼接成[3,3];[4,5,6]反转后[6,5,4],拼接成[4,5,6,6,5,4]——完全符合回文逻辑,无需改代码。警告说明(非错误!):
Skipping loop optimization for Merge node...;tf.function对RaggedTensor的“透明支持”:
tf.concat内部会判断输入类型,选择密集/Ragged拼接逻辑);input_signature是tf.function的参数,作用是限定输入的类型/形状:
tf.function为不同输入类型/形状重复生成计算图;tf.RaggedTensorSpec替代普通的tf.TensorSpec。# 装饰器:指定input_signature为RaggedTensorSpec(限定输入规范)@tf.function(# 输入签名:二维RaggedTensor,shape=[None, None](两个维度都可变),dtype=int32input_signature=[tf.RaggedTensorSpec(shape=[None,None],dtype=tf.int32)])defmax_and_min(rt):# 计算最后一维的最大值/最小值(原生支持Ragged)max_vals=tf.math.reduce_max(rt,axis=-1)min_vals=tf.math.reduce_min(rt,axis=-1)return(max_vals,min_vals)# 测试:传入符合签名的RaggedTensorragged_x=tf.ragged.constant([[1,2],[3],[4,5,6]])max_vals,min_vals=max_and_min(ragged_x)print("\n=== 指定input_signature后的执行结果 ===")print("每行最大值:",max_vals)print("每行最小值:",min_vals)=== 指定input_signature后的执行结果 === 每行最大值: tf.Tensor([2 3 6], shape=(3,), dtype=int32) 每行最小值: tf.Tensor([1 3 4], shape=(3,), dtype=int32)[1,2]→ 最大2、最小1;[3]→ 最大3、最小3;[4,5,6]→ 最大6、最小4。tf.RaggedTensorSpec是描述RaggedTensor的“输入签名类”,核心参数如下:
| 参数 | 含义 |
|---|---|
shape | RaggedTensor的形状,None表示可变维度(如[None, None]=二维,两个维度都可变);均匀维度可指定具体值(如 [3, None]=固定3行,每行元素数可变) |
dtype | RaggedTensor的元素类型(如tf.int32/tf.string) |
ragged_rank | 可选,不规则维度的数量(如ragged_rank=1表示只有最后1个维度是不规则的) |
# 三维RaggedTensor:固定2个样本,后两维可变,且后两维都是不规则的spec=tf.RaggedTensorSpec(shape=[2,None,None],dtype=tf.int32,ragged_rank=2)print("自定义RaggedTensorSpec:",spec)tf.function编译后生成的具体计算图实例(绑定了特定输入类型/形状),比普通tf.function更快(无需动态跟踪),是部署的首选;# 1. 定义编译成计算图的函数(元素+1)@tf.functiondefincrement(x):returnx+1# 对RaggedTensor的每个元素+1,保留原始结构# 2. 构建RaggedTensorrt=tf.ragged.constant([[1,2],[3],[4,5,6]])# 3. 获取具体函数(绑定RaggedTensor的输入类型/形状)cf=increment.get_concrete_function(rt)# 4. 执行具体函数(性能更高)cf_result=cf(rt)print("\n=== 具体函数执行结果 ===")print(cf_result)=== 具体函数执行结果 === <tf.RaggedTensor [[2, 3], [4], [5, 6, 7]]>[1,2]→[2,3]、[3]→[4]、[4,5,6]→[5,6,7];tf.function更高。若需兼容低版本TF,可加异常捕获:
try:cf=increment.get_concrete_function(rt)print(cf(rt))exceptExceptionase:print(f"TF版本过低不支持:{type(e).__name__}:{e}")| 场景 | 核心用法 | 关键API/参数 |
|---|---|---|
| 透明支持 | 直接传入RaggedTensor,无需改函数逻辑 | @tf.function+ 普通TF算子(concat/reduce_max等) |
| 指定输入签名 | 用RaggedTensorSpec限定RaggedTensor的形状/类型 | tf.RaggedTensorSpec(shape, dtype) |
| 具体函数 | TF2.3+直接调用get_concrete_function(rt) | tf.function.get_concrete_function |
reduce_max/concat/range等)都原生支持RaggedTensor,可直接在tf.function中使用;input_signature的shape:RaggedTensor的不规则维度必须用None表示,均匀维度可指定具体值(如[5, None]=固定5行)。input_signature,避免重复编译计算图;tf.function内动态创建RaggedTensor(如tf.ragged.constant),尽量把数据预处理放在函数外。