如何使用 DataSet API 在 Tensorflow 中为 tf.train.SequenceExample 数据创建填充批次?
How do I create padded batches in Tensorflow for tf.train.SequenceExample data using the DataSet API?
为了在 Tensorflow 中训练 LSTM 模型,我将数据结构化为 tf.train.SequenceExample 格式并将其存储到 TFRecord 文件 中。我现在想使用新的数据集 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: If shallow structure is a sequence, input must also be a
sequence. Input has type: .
你能帮我弄清楚我应该为 padded_shapes 参数传递什么吗?
(我知道有很多使用线程和队列的示例代码,但我宁愿为这个项目使用新的 DataSet API)
您需要传递一个形状元组。
在你的情况下你应该通过
dataset = dataset.padded_batch(4, padded_shapes=([vectorSize],[None]))
或尝试
dataset = dataset.padded_batch(4, padded_shapes=([None],[None]))
查看此 code 了解更多详情。我不得不调试此方法以弄清楚为什么它对我不起作用。
如果您当前的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
您可能需要从数据集输出形状中获得帮助:
padded_shapes = dataset.output_shapes
注意不要传递一个元组的元组。这给出了一个非常模糊的错误“无法将值 None 转换为类型 None 类型”。
非常正确:
padded_shapes = ([None, None], [None])
不正确:
padded_shapes = ((None, None), (None))
为了在 Tensorflow 中训练 LSTM 模型,我将数据结构化为 tf.train.SequenceExample 格式并将其存储到 TFRecord 文件 中。我现在想使用新的数据集 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: If shallow structure is a sequence, input must also be a sequence. Input has type: .
你能帮我弄清楚我应该为 padded_shapes 参数传递什么吗?
(我知道有很多使用线程和队列的示例代码,但我宁愿为这个项目使用新的 DataSet API)
您需要传递一个形状元组。 在你的情况下你应该通过
dataset = dataset.padded_batch(4, padded_shapes=([vectorSize],[None]))
或尝试
dataset = dataset.padded_batch(4, padded_shapes=([None],[None]))
查看此 code 了解更多详情。我不得不调试此方法以弄清楚为什么它对我不起作用。
如果您当前的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
您可能需要从数据集输出形状中获得帮助:
padded_shapes = dataset.output_shapes
注意不要传递一个元组的元组。这给出了一个非常模糊的错误“无法将值 None 转换为类型 None 类型”。
非常正确:
padded_shapes = ([None, None], [None])
不正确:
padded_shapes = ((None, None), (None))