TensorFlow图执行与即时执行形状要求差异及数据集问题排查
TensorFlow图执行模式下创建变长输入输出数据集报错的解决方案
问题背景
输入序列长度为10-100个token,输出序列约1000个token,为提升效率使用独立embedding分支。即时执行模式下代码运行正常,对应的TensorSpec如下:
((TensorSpec(shape=(None, 20), dtype=tf.int32, name=None), TensorSpec(shape=(None, 100), dtype=tf.int32, name=None)), TensorSpec(shape=(None, 100), dtype=tf.int32, name=None))
但切换到图执行模式后,执行tf.data.Dataset.from_tensor_slices((list(problems), list(solutions), list(solutions)))时触发报错:
ValueError: Expected values [array([27, ..., 16], dtype=int32)] to be a dense tensor with shape [20], but got shape [20, 20].
原因分析
- 图执行的严格形状校验:TensorFlow图执行模式对数据形状的一致性要求远高于即时执行。
from_tensor_slices要求输入列表中的所有元素必须是相同形状的张量,如果你的problems/solutions是变长序列(不同样本长度不一),即时执行会隐式处理,但图执行会直接触发形状不匹配的错误。 - 版本差异影响:不同TensorFlow版本对数据校验的严格程度不同,旧版本可能允许
from_tensor_slices处理非统一形状的数据,新版本收紧了规则,导致原本能运行的代码在新环境报错。
解决方案
方案1:统一序列长度(推荐)
对输入和输出序列分别做padding/truncation,固定到最大允许长度,确保所有样本形状一致:
import tensorflow as tf # 定义输入输出的最大长度 max_input_len = 100 max_output_len = 1000 # 对输入序列做padding/truncation padded_problems = tf.keras.preprocessing.sequence.pad_sequences( problems, maxlen=max_input_len, padding='post', truncating='post', dtype='int32' ) # 对输出序列做padding/truncation padded_solutions = tf.keras.preprocessing.sequence.pad_sequences( solutions, maxlen=max_output_len, padding='post', truncating='post', dtype='int32' ) # 创建数据集 dataset = tf.data.Dataset.from_tensor_slices((padded_problems, padded_solutions, padded_solutions))
方案2:使用生成器创建数据集
如果不需要统一长度,用tf.data.Dataset.from_generator动态返回每个样本,图执行模式可兼容变长数据:
def data_gen(problems, solutions): for p, s in zip(problems, solutions): yield p, s, s # 定义输出签名,允许可变长度(shape=(None,)) dataset = tf.data.Dataset.from_generator( lambda: data_gen(problems, solutions), output_signature=( tf.TensorSpec(shape=(None,), dtype=tf.int32), tf.TensorSpec(shape=(None,), dtype=tf.int32), tf.TensorSpec(shape=(None,), dtype=tf.int32) ) )
方案3:对齐TensorFlow版本
如果之前项目运行正常,对比当前环境和旧项目的TensorFlow版本,回退到旧版本可临时解决问题,但长期来看还是建议适配新版本的规则。
内容的提问来源于stack exchange,提问作者Breck Emert
相关产品推荐
相关产品推荐

