如何用tf.train.SequenceExample保存含变长列表的时序数据
解决含变长列表的时序样本保存/读取TFRecords问题
这个问题我之前处理多模态时序数据时碰到过,你遇到的TypeError核心是没理清tf.train.SequenceExample的层级结构——它要求序列类特征必须放在feature_lists下的FeatureList中,不能和标量特征混放在普通Feature里。咱们直接上可运行的代码,再拆解逻辑:
一、正确的保存逻辑(写入TFRecords)
首先明确:每个样本是3个时间步的序列,每个时间步包含两个标量和一个变长整数列表。我们需要把这三类特征分别封装成FeatureList,再组合成SequenceExample。
import tensorflow as tf def sample_to_sequence_example(sample): # 提取每个时间步的三类特征,分别整理成列表 s1_list = [step[0] for step in sample] s2_list = [step[1] for step in sample] v_list_list = [step[2] for step in sample] # 构建标量特征的FeatureList:每个标量转成Int64Feature def create_scalar_feature_list(values): feature_list = tf.train.FeatureList( feature=[tf.train.Feature(int64_list=tf.train.Int64List(value=[v])) for v in values] ) return feature_list # 构建变长列表特征的FeatureList:每个变长列表转成Int64Feature def create_varlen_feature_list(values_list): feature_list = tf.train.FeatureList( feature=[tf.train.Feature(int64_list=tf.train.Int64List(value=v_list)) for v_list in values_list] ) return feature_list # 组合所有FeatureList到FeatureLists feature_lists = tf.train.FeatureLists(feature_list={ "s1": create_scalar_feature_list(s1_list), "s2": create_scalar_feature_list(s2_list), "v_list": create_varlen_feature_list(v_list_list) }) # 构建SequenceExample(context可选,这里没有全局特征就留空) sequence_example = tf.train.SequenceExample(feature_lists=feature_lists) return sequence_example # 测试保存你的样本数据 sample_data = [ [[1, 2, [3, 4, 5]], [3, 4, [3, 2]], [1, 2, [4, 5, 6, 7]]], [[1, 0, [3, 4]], [2, 0, [3, 2, 6]], [0, 2, [4, 7]]], [[0, 2, [3, 4, 9, 0]], [2, 3, [3, 2, 9, 1, 0]], [1, 2, [4]]] ] # 写入TFRecord文件 with tf.io.TFRecordWriter("timing_data.tfrecords") as writer: for sample in sample_data: seq_example = sample_to_sequence_example(sample) writer.write(seq_example.SerializeToString())
二、正确的读取逻辑(解析TFRecords)
读取时要对应保存的结构,用tf.io.parse_single_sequence_example解析,同时注意变长列表用tf.io.RaggedFeature处理会更方便:
def parse_sequence_example(serialized_example): # 定义特征解析规则:每个FeatureList对应的数据类型 context_features = {} # 这里没有全局特征,所以为空 sequence_features = { "s1": tf.io.FixedLenSequenceFeature([], tf.int64, allow_missing=True), "s2": tf.io.FixedLenSequenceFeature([], tf.int64, allow_missing=True), "v_list": tf.io.RaggedFeature(tf.int64, ragged_rank=1) # 处理变长列表,ragged_rank=1表示每个元素是一维变长 } # 解析序列样本 context_parsed, sequence_parsed = tf.io.parse_single_sequence_example( serialized_example, context_features=context_features, sequence_features=sequence_features ) # 把解析后的特征整理成和原始样本类似的结构(可选,按需调整) time_steps = tf.stack([ sequence_parsed["s1"], sequence_parsed["s2"] ], axis=1) return time_steps, sequence_parsed["v_list"] # 测试读取 dataset = tf.data.TFRecordDataset("timing_data.tfrecords") dataset = dataset.map(parse_sequence_example) # 打印验证结果 for step_tensor, v_list_tensor in dataset: print("时间步标量特征:") print(step_tensor.numpy()) print("变长列表特征:") print(v_list_tensor.to_list()) print("---")
三、为什么你之前会报错?
你之前的代码应该是误将FeatureList(对应序列特征)赋值给了Feature的位置(比如错误放到context里,或者在feature_lists里用了Feature而非FeatureList)。tf.train.SequenceExample的严格结构要求:
context:存储整个样本的全局非序列特征,每个元素是Featurefeature_lists:存储序列特征,每个元素是FeatureList(每个FeatureList对应一个特征维度的所有时间步数据)
类型不匹配就会触发MergeFrom()的类型错误。
内容的提问来源于stack exchange,提问作者GoingMyWay
相关产品推荐
相关产品推荐

