【问题标题】:tf.SequenceExample with multidimensional arraystf.SequenceExample 与多维数组
【发布时间】:2017-01-24 06:14:15
【问题描述】:

在 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

欢迎任何帮助。

【问题讨论】:

  • 嗨,您能提供更多上下文吗?最好提供一个可以实际运行和测试的最小示例,包括如何将数据保存到文件的步骤。
  • 您的示例很难理解,如果您编辑示例以包含相关上下文,您将获得更多帮助。例如 - 查看您在代码中添加注释的链接,很明显您生成序列示例的 sn-p 不包含实际写入数据的代码。

标签: python multidimensional-array tensorflow protocol-buffers


【解决方案1】:

我遇到了同样的问题。我认为它是完全可以解决的,但你必须决定输出格式,然后弄清楚你将如何使用它。

首先 你的错误是什么?

错误消息告诉您,您尝试读取的内容不适合您指定的特征大小。那么你在哪里指定呢?就在这里:

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))

张量。

被警告;我不确定反向传播对稀疏张量“是否有效”,就像对密集张量一样。 wildml article 讨论了在每个序列中填充 0 以掩盖“not_actually_a_word”单词的损失(请参阅:“旁注:在他们的文章中使用 0'S 在您的词汇/类别中小心”)。这似乎表明第一种方法更容易实现。

请注意,这与此处描述的情况不同,其中每个示例都是一系列序列。据我了解,这种方法之所以没有得到很好的支持,是因为它是滥用本应支持的情况;直接加载固定大小的嵌入。


我假设您接下来要做的就是将这些数字转换为词嵌入。您可以使用 tf.nn.embedding_lookup 将索引列表转换为嵌入列表

【讨论】:

    【解决方案2】:

    使用提供的代码,我无法重现您的错误,但做出一些有根据的猜测给出了以下工作代码。

    import tensorflow as tf
    import numpy as np
    import tempfile
    
    tmp_filename = 'tf.tmp'
    
    sequences = [[1, 2, 3], [1, 2], [3, 2, 1]]
    label_sequences = [[0, 1, 0], [1, 0], [1, 1, 1]]
    
    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 = len(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 zip(input_sequence,
                                                              output_sequence):
    
            if input_sequence is not None:
                input_characters.feature.add().int64_list.value.append(input_character)
    
            if output_characters is not None:
                output_characters.feature.add().int64_list.value.append(output_character)
    
        return example_sequence
    
    # Write all examples into a TFRecords file
    def save_tf(filename):
        with open(filename, 'w') as fp:
            writer = tf.python_io.TFRecordWriter(fp.name)
            for sequence, label_sequence in zip(sequences, label_sequences):
                ex = make_example(sequence, label_sequence)
                writer.write(ex.SerializeToString())
            writer.close()
    
    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)
        }
    
    
        return serialized_example, context_features, sequence_features
    
    save_tf(tmp_filename)
    ex,context_features,sequence_features = read_and_decode_single_example(tmp_filename)
    context_parsed, sequence_parsed = tf.parse_single_sequence_example(
        serialized=ex,
        context_features=context_features,
        sequence_features=sequence_features
    )
    
    sequence = tf.contrib.learn.run_n(sequence_parsed, n=1, feed_dict=None)
    #check if the saved data matches the input data
    print(sequences[0] in sequence[0]['input_characters'])
    

    所需的更改是:

    1. sequence_length = sum([len(word) for word in input_sequence])sequence_length = len(input_sequence)

    否则它不适用于您的示例数据

    1. extend 更改为 append

    【讨论】:

    • 尝试这些更改时,我收到错误:TypeError: [37] has type <type 'list'>, but expected one of: (<type 'int'>, <type 'long'>)
    • 我想我明白了问题所在,[[1, 2, 3], [1, 2], [3, 2, 1]] 是一个序列而不是多个序列。
    • 您是否尝试过答案中的 sn-p?运行它时我没有收到任何错误(Ubuntu,python3.4,没有 GPU 的 TF)。您的输入数据看起来与问题完全一样吗?
    • 我的输入完全相同,但是您将[[1, 2, 3], [1, 2], [3, 2, 1]] 视为三个不同的示例。这是一个例子。
    • 来自文档:minimal reproducible example 包含一个键值存储(功能);其中 // 每个键(字符串)映射到 Feature 消息(它是打包的 BytesList、// FloatList 或 Int64List 之一)。对于您的数据结构,除了单独存储列表并在阅读后加入它们之外,我没有看到任何其他解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-01-03
    • 2011-01-31
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 2016-12-09
    • 1970-01-01
    • 2021-08-27
    相关资源
    最近更新 更多