如何使用 DataSet API 在 Tensorflow 中为 tf.train.SequenceExample 数据创建填充批次?

Posted

技术标签:

【中文标题】如何使用 DataSet API 在 Tensorflow 中为 tf.train.SequenceExample 数据创建填充批次?【英文标题】:How do I create padded batches in Tensorflow for tf.train.SequenceExample data using the DataSet API? 【发布时间】:2018-02-07 20:42:17 【问题描述】:

为了在 Tensorflow 中训练 LSTM 模型,我将数据结构化为 tf.train.SequenceExample 格式并将其存储到TFRecord 文件。我现在想使用新的 DataSet API为训练生成填充批次。在the documentation 中有一个使用 padded_batch 的示例,但对于我的数据,我无法弄清楚 padded_shapes 的值应该是什么。

为了批量读取 TFrecord 文件,我编写了以下 Python 代码:

import math
import tensorflow as tf
import numpy as np
import struct
import sys
import array

if(len(sys.argv) != 2):
  print "Usage: createbatches.py [RFRecord file]"
  sys.exit(0)


vectorSize = 40
inFile = sys.argv[1]

def parse_function_dataset(example_proto):
  sequence_features = 
      'inputs': tf.FixedLenSequenceFeature(shape=[vectorSize],
                                           dtype=tf.float32),
      'labels': tf.FixedLenSequenceFeature(shape=[],
                                           dtype=tf.int64)

  _, sequence = tf.parse_single_sequence_example(example_proto, sequence_features=sequence_features)

  length = tf.shape(sequence['inputs'])[0]
  return sequence['inputs'], sequence['labels']

sess = tf.InteractiveSession()

filenames = tf.placeholder(tf.string, shape=[None])
dataset = tf.contrib.data.TFRecordDataset(filenames)
dataset = dataset.map(parse_function_dataset)
# dataset = dataset.batch(1)
dataset = dataset.padded_batch(4, padded_shapes=[None])
iterator = dataset.make_initializable_iterator()

batch = iterator.get_next()

# Initialize `iterator` with training data.
training_filenames = [inFile]
sess.run(iterator.initializer, feed_dict=filenames: training_filenames)

print(sess.run(batch))

如果我使用dataset = dataset.batch(1)(在这种情况下不需要填充),代码运行良好,但是当我使用padded_batch 变体时,我收到以下错误:

TypeError: 如果浅结构是一个序列,输入也必须是一个 顺序。输入的类型:.

你能帮我弄清楚我应该为 padded_shapes 参数传递什么吗?

(我知道有很多使用线程和队列的示例代码,但我宁愿在这个项目中使用新的 DataSet API)

【问题讨论】:

谢谢玛丽恩!您的问题对我帮助很大! 【参考方案1】:

您需要传递一组形状。 在你的情况下,你应该通过

dataset = dataset.padded_batch(4, padded_shapes=([vectorSize],[None]))

或者试试

dataset = dataset.padded_batch(4, padded_shapes=([None],[None]))

查看code 了解更多详情。我不得不调试这个方法来弄清楚为什么它对我不起作用。

【讨论】:

谢谢!这很有意义。以下适用于我的示例:padded_shapes=([None,vectorSize],[None])。第一个张量是具有维数vectorSize 的向量列表,第二个是具有整数标签的列表。 作为补充,padded_shapes 对嵌套结构的类型很敏感(如果数据集返回元组,则 padded_shapes 也应该是元组而不是列表)【参考方案2】:

如果您当前的Dataset 对象包含一个元组,您还可以指定每个填充元素的形状。

例如,我有一个(same_sized_images, Labels) 数据集,每个标签的长度不同但排名相同。

def process_label(resized_img, label):
    # Perfrom some tensor transformations
    # ......

    return resized_img, label

dataset = dataset.map(process_label)
dataset = dataset.padded_batch(batch_size, 
                               padded_shapes=([None, None, 3], 
                                              [None, None]))  # my label has rank 2

【讨论】:

为什么你使用 3 作为第三个图像维度而不是 None?【参考方案3】:

您可能需要从数据集输出形状中获得帮助:

padded_shapes = dataset.output_shapes

【讨论】:

【参考方案4】:

注意不要传递元组的元组。这给出了一个非常模糊的错误“无法将值 None 转换为类型 Nonetype”。

非常正确: padded_shapes = ([None, None], [None])

不正确: padded_shapes = ((None, None), (None))

【讨论】:

以上是关于如何使用 DataSet API 在 Tensorflow 中为 tf.train.SequenceExample 数据创建填充批次?的主要内容,如果未能解决你的问题,请参考以下文章

机器学习-Tensorflow之Tensor和Dataset学习

tf.data.Dataset .from_tensor_slices() 是不是保留示例的顺序?

tf.data.Dataset.from_tensor_slices,张量和渴望模式

如何从 tf.tensor 中获取字符串值,其中 dtype 是字符串

Tensor Flow量化里representative_dataset参数是什么意思?

Tensor Flow量化里representative_dataset参数是什么意思?