14

In Tensorflow möchte ich ein mehrdimensionales Array zu einem TFRecord speichern. Zum Beispiel:tf.SequenceExample mit mehrdimensionalen Arrays

[[1, 2, 3], [1, 2], [3, 2, 1]] 

Da die Aufgabe, die ich sequentiell zu lösen versuchen, versuche ich Tensorflow die tf.train.SequenceExample() und beim Schreiben der Daten, die ich bin erfolgreich in dem Schreiben die Daten in eine TFRecord-Datei zu verwenden. Allerdings, wenn ich versuche, die Daten aus der TFRecord-Datei zu laden tf.parse_single_sequence_example verwenden, bin ich mit einer großen Anzahl von kryptischen Fehlern begrüßt:

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: [] 

Die Funktion, die ich zu versuchen, bin mit meinen Daten zu laden, sind unten:

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 

die Funktion, die ich die Daten zu speichern, bin mit hier:

# 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 

Jede Hilfe begrüßt werden würde.

+0

Hallo, können Sie mehr Kontext bieten? Am besten stellen Sie ein minimales Beispiel zur Verfügung, das tatsächlich ausgeführt und getestet werden kann, einschließlich des Schritts, wie Sie Ihre Daten in einer Datei speichern. – jlarsch

+0

Ihr Beispiel ist sehr schwer zu befolgen und Sie erhalten mehr Hilfe, wenn Sie Ihr Beispiel so bearbeiten, dass es den relevanten Kontext enthält. Wenn Sie zum Beispiel den Link betrachten, den Sie in den Code eingegeben haben, wird deutlich, dass der Code, der die Sequenz beschreibt, nicht den Code enthält, der die Daten tatsächlich schreibt. –

Antwort

5

Mit dem bereitgestellten Code konnte ich Ihren Fehler nicht reproduzieren, aber einige fundierte Vermutungen ergaben den folgenden funktionierenden Code.

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

Die erforderlichen Änderungen waren:

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

Ansonsten

  1. extend wurde geändert in append
+0

Beim Versuch diese Änderungen zu erhalten, erhalte ich den Fehler: 'TypeError: [37] hat den Typ , erwartet aber einen von: (, )'. – Torkoal

+0

Ich denke, ich sehe das Problem, "[[1, 2, 3], [1, 2], [3, 2, 1]]" soll eine Sequenz sein, nicht viele. – Torkoal

+0

Haben Sie das Snippet in der Antwort versucht? Ich habe keinen Fehler beim Ausführen (Ubuntu, Python3.4, TF ohne GPU). Sehen Ihre Eingabedaten genau so aus? –

3

Ich hatte das gleiche Problem. Ich denke, dass es vollständig lösbar ist, aber Sie müssen sich für das Ausgabeformat entscheiden und dann herausfinden, wie Sie es verwenden werden.

ZuerstWas ist Ihr Fehler?

Die Fehlermeldung besagt, dass das, was Sie zu lesen versuchen, nicht in die von Ihnen angegebene Feature-Größe passt. Also wo hast du es spezifiziert? Genau hier:

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

Dies sagt, dass „mein input_characters ist eine Folge von Einzelwerten“, aber das ist nicht wahr; Was Sie haben, ist eine Folge von Folgen von Einzelwerten und damit ein Fehler.

Zweitewas können Sie tun?

Wenn Sie stattdessen verwenden:

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

Sie einen Fehler nicht mit Ihrem Code haben, weil Sie angegeben haben, dass jedes Element der obersten Ebene Folge 3 Elemente lang ist.

Wenn Sie keine Sequenzen fester Länge haben, müssen Sie alternativ einen anderen Feature-Typ verwenden.

sequence_features = { 
    "input_characters": tf.VarLenFeature(tf.int64), 
    "output_characters": tf.VarLenFeature(tf.int64) 
} 

Die VarLenFeature sagt, dass die Länge vor dem Lesen unbekannt ist. Leider bedeutet dies, dass Ihre input_characters in einem Schritt nicht mehr als dichter Vektor gelesen werden können. Stattdessen wird es standardmäßig ein SparseTensor sein. Sie können dies in einem dichten Tensor drehen mit tf.sparse_tensor_to_dense zB:

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

Wie in the article erwähnt, dass Sie bei der Suche habe, wenn Ihre Daten nicht immer die gleiche Länge haben, werden Sie eine „not_really_a_word“ haben müssen Wort in Ihrem Vokabular, das Sie als Standardindex verwenden. z.B. sagen wir, Sie Index 0 Zuordnung zum "not_really_a_word" Wort haben, dann

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

Python-Liste verwendet, wird

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

Tensor ein am Ende wird.

Achtung! Ich bin mir nicht sicher, ob die Rückpropagation für SparseTensors "genauso funktioniert" wie für dichte Tensoren. Die wildml article spricht über Padding 0s pro Sequenz Maskierung der Verlust für die "not_actually_a_word" Wort (siehe: "SEITENHINWEIS: SORGFÄLTIG MIT 0'S in Ihrem Vokabular/Klassen" in ihrem Artikel). Dies deutet darauf hin, dass die erste Methode einfacher zu implementieren sein wird.

Beachten Sie, dass dies anders ist als in dem hier beschriebenen Fall, wo jedes Beispiel eine Folge von Sequenzen ist. Nach meinem Verständnis ist der Grund, warum diese Art von Methode nicht gut unterstützt wird, der Missbrauch des Falles, den dies unterstützen soll; Fixed-Size-Einbettungen direkt laden.


Ich werde davon ausgehen, dass die nächste Sache, die Sie tun möchten, diese Zahlen in Word-Einbettungen zu machen. Sie können eine Liste von Indizes in eine Liste von Einbettungen mit tf.nn.embedding_lookup

Verwandte Themen