web-dev-qa-db-ja.com

多次元配列を持つtf.SequenceExample

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
_

どんな助けでも歓迎します。

20
Torkoal

私も同じ問題を抱えていました。私はそれは完全に解決できると思いますが、あなたは出力フォーマットを決定し、それからそれをどのように使用するのかを理解する必要があります。

最初あなたのエラーは何ですか?

エラーメッセージは、読み取ろうとしているものが指定したフィーチャサイズに適合しないことを示しています。それで、どこでそれを指定しましたか?ここで:

sequence_features = {
    "input_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64),
    "output_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64)
}

これは「私のinput_charactersは単一の値のシーケンスです」と言っていますが、これは真実ではありません。あなたが持っているのは、単一の値のシーケンスのシーケンスであり、したがってエラーです。

2番目何ができますか?

代わりに使用する場合:

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を1つのステップで密なベクトルとして読み取ることができないことを意味します。代わりに、デフォルトでは SparseTensor になります。 tf.sparse_tensor_to_dense でこれを密なテンソルに変えることができます。例:

input_densified = tf.sparse_tensor_to_dense(sequence_parsed['input_characters'])

記事 で説明したように、データが常に同じ長さではない場合、ボキャブラリに「not_really_a_Word」という単語が必要であり、これをデフォルトとして使用します。インデックス。例えばたとえば、「not_really_a_Word」という単語にマッピングするインデックス0があるとします。

a = [[1,2,3],  [2,3],  [3,2,1]]

pythonリストは最終的には

array((1,2,3),  (2,3,0),  (3,2,1))

テンソル。

注意してください。密なテンソルの場合のように、逆伝播がSparseTensorsに対して「機能する」かどうかはわかりません。 wildml記事 は、「not_actually_a_Word」という単語の損失をマスクするシーケンスごとの0のパディングについて説明しています(記事の「サイドノート:語彙/クラスの0に注意してください」を参照)。これは、最初の方法の方が実装しやすいことを示唆しているようです。

これは、各例がシーケンスのシーケンスである、ここで説明するケースとは異なることに注意してください。私の理解では、この種の方法が十分にサポートされていない理由は、これがサポートすることを意図されているケースの乱用であるためです。固定サイズの埋め込みを直接読み込みます。


次に行うことは、これらの数値をWordの埋め込みに変換することだと思います。 tf.nn.embedding_lookupを使用すると、インデックスのリストを埋め込みのリストに変換できます

7
Multihunter

提供されたコードではエラーを再現できませんでしたが、知識に基づいた推測を行うと、次のコードが機能しました。

_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. extendappendに変更されました
5