在Tensorflow中,我想将多维数组保存到TFRecord。例如:
[[1, 2, 3], [1, 2], [3, 2, 1]]
由于我要解决的任务是顺序的,因此我尝试使用Tensorflow的
tf.train.SequenceExample()
,并且在写入数据时成功将数据写入TFRecord文件。但是,当我尝试使用tf.parse_single_sequence_example
从TFRecord文件中加载数据时,我遇到了很多神秘的错误:W tensorflow/core/framework/op_kernel.cc:936] Invalid argument: Name: , Key: input_characters, Index: 1. Number of int64 values != expected. values size: 6 but output shape: []
E tensorflow/core/client/tensor_c_api.cc:485] Name: , Key: input_characters, Index: 1. Number of int64 values != expected. values size: 6 but output shape: []
我用来尝试加载数据的功能如下:
def read_and_decode_single_example(filename):
filename_queue = tf.train.string_input_producer([filename],
num_epochs=None)
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
context_features = {
"length": tf.FixedLenFeature([], dtype=tf.int64)
}
sequence_features = {
"input_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64),
"output_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64)
}
context_parsed, sequence_parsed = tf.parse_single_sequence_example(
serialized=serialized_example,
context_features=context_features,
sequence_features=sequence_features
)
context = tf.contrib.learn.run_n(context_parsed, n=1, feed_dict=None)
print context
我用来保存数据的功能在这里:
# http://www.wildml.com/2016/08/rnns-in-tensorflow-a-practical-guide-and-undocumented-features/
def make_example(input_sequence, output_sequence):
"""
Makes a single example from Python lists that follows the
format of tf.train.SequenceExample.
"""
example_sequence = tf.train.SequenceExample()
# 3D length
sequence_length = sum([len(word) for word in input_sequence])
example_sequence.context.feature["length"].int64_list.value.append(sequence_length)
input_characters = example_sequence.feature_lists.feature_list["input_characters"]
output_characters = example_sequence.feature_lists.feature_list["output_characters"]
for input_character, output_character in izip_longest(input_sequence,
output_sequence):
# Extend seems to work, therefore it replaces append.
if input_sequence is not None:
input_characters.feature.add().int64_list.value.extend(input_character)
if output_characters is not None:
output_characters.feature.add().int64_list.value.extend(output_character)
return example_sequence
任何帮助都将受到欢迎。
最佳答案
我有同样的问题。我认为这完全可以解决,但是您必须确定输出格式,然后弄清楚如何使用它。
首先您遇到什么错误?
错误消息告诉您您尝试读取的内容不符合您指定的功能大小。那么您在哪里指定呢?就在这儿:
sequence_features = {
"input_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64),
"output_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64)
}
这说“我的input_characters是一个单值序列”,但这不是真的。您所拥有的是一个序列的单值序列,因此是一个错误。
第二您可以做什么?
如果您改为使用:
a = [[1,2,3], [2,3,1], [3,2,1]]
sequence_features = {
"input_characters": tf.FixedLenSequenceFeature([3], dtype=tf.int64),
"output_characters": tf.FixedLenSequenceFeature([3], dtype=tf.int64)
}
因为您已指定顶层序列的每个元素长3个元素,所以您的代码不会出错。
另外,如果您没有固定长度的序列,那么您将不得不使用其他类型的功能。
sequence_features = {
"input_characters": tf.VarLenFeature(tf.int64),
"output_characters": tf.VarLenFeature(tf.int64)
}
VarLenFeature告诉它读取前的长度是未知的。不幸的是,这意味着您的input_characters不能再一步就被读取为密集向量。而是默认为SparseTensor。您可以使用tf.sparse_tensor_to_dense将其变成密集的张量,例如:
input_densified = tf.sparse_tensor_to_dense(sequence_parsed['input_characters'])
正如您一直在the article中提到的那样,如果您的数据长度不总是相同,则您的词汇表中必须有一个“not_really_a_word”字样,您将其用作默认索引。例如假设您有索引0映射到“not_really_a_word”字词,然后使用
a = [[1,2,3], [2,3], [3,2,1]]
python列表将最终成为
array((1,2,3), (2,3,0), (3,2,1))
张量。
被警告;我不确定像SparseTensors那样,反向传播是否“奏效”,就像密集的张量那样。 wildml article讨论每个序列的填充0,以掩盖“not_actually_a_word”一词的损失(请参见:“注意:请谨慎对待您的词汇/类(class)中的0”)。这似乎表明第一种方法将更易于实现。
注意,这与此处描述的情况不同,在此情况下,每个示例都是一个序列序列。据我了解,这种方法没有得到很好支持的原因是因为它滥用了本应支持的情况;直接加载固定大小的嵌入。
我将假设您接下来要做的就是将这些数字转换为单词嵌入。您可以使用
tf.nn.embedding_lookup
将索引列表转换为嵌入列表