python - requisitos - tf.SequenceExample con matrices multidimensionales
tensorflow examples (2)
En Tensorflow, quiero guardar una matriz multidimensional en un TFRecord. Por ejemplo:
[[1, 2, 3], [1, 2], [3, 2, 1]]
Como la tarea que estoy tratando de resolver es secuencial, estoy tratando de usar tf.train.SequenceExample()
de tf.train.SequenceExample()
y cuando escribo los datos escribo correctamente los datos en un archivo TFRecord. Sin embargo, cuando trato de cargar los datos del archivo tf.parse_single_sequence_example
usando tf.parse_single_sequence_example
, tf.parse_single_sequence_example
una gran cantidad de errores crípticos:
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: []
La función que estoy usando para intentar cargar mis datos se encuentra a continuación:
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
La función que estoy usando para guardar los datos está aquí:
# 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
Cualquier ayuda sería bienvenida.
Con el código provisto, no pude reproducir su error, pero hacer algunas conjeturas proporcionó el siguiente código de trabajo.
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''])
Los cambios requeridos fueron:
-
sequence_length = sum([len(word) for word in input_sequence])
asequence_length = len(input_sequence)
De lo contrario, no funciona para sus datos de ejemplo
-
extend
fue cambiado paraappend
Yo tuve el mismo problema. Creo que es completamente solucionable, pero tienes que decidir el formato de salida y luego averiguar cómo lo vas a usar.
Primero cual es tu error?
El mensaje de error le indica que lo que está intentando leer no se ajusta al tamaño de la función que especificó. Entonces, ¿dónde lo especificaste? Aquí:
sequence_features = {
"input_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64),
"output_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64)
}
Esto dice "mi input_characters es una secuencia de valores únicos", pero esto no es cierto; Lo que tienes es una secuencia de secuencias de valores individuales y, por lo tanto, un error.
Segundo, ¿qué puedes hacer?
Si en su lugar usas:
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)
}
No tendrá un error con su código porque ha especificado que cada elemento de la secuencia de nivel superior tiene una longitud de 3 elementos.
Alternativamente, si no tiene secuencias de longitud fija, entonces tendrá que usar un tipo diferente de función.
sequence_features = {
"input_characters": tf.VarLenFeature(tf.int64),
"output_characters": tf.VarLenFeature(tf.int64)
}
El VarLenFeature le dice que la longitud es desconocida antes de leer. Desafortunadamente, esto significa que sus caracteres de entrada ya no pueden leerse como un vector denso en un solo paso. En su lugar, será un SparseTensor por defecto. Puede convertir esto en un tensor denso con tf.sparse_tensor_to_dense por ejemplo:
input_densified = tf.sparse_tensor_to_dense(sequence_parsed[''input_characters''])
Como se mencionó en el artículo que ha estado viendo, si sus datos no siempre tienen la misma longitud, tendrá que tener una palabra "not_really_a_word" en su vocabulario, que usará como índice predeterminado. por ejemplo, digamos que tiene una correlación de índice 0 con la palabra "not_really_a_word", luego use su
a = [[1,2,3], [2,3], [3,2,1]]
lista de python terminará siendo una
array((1,2,3), (2,3,0), (3,2,1))
tensor.
Ser advertido No estoy seguro de que la propagación hacia atrás "simplemente funcione" para los sensores Sparse, como ocurre con los tensores densos. El artículo de wildml habla sobre rellenar 0s por secuencia y enmascarar la pérdida de la palabra "not_actually_a_word" (ver: "NOTA LATERAL: TENGA CUIDADO CON 0''S EN SU VOCABULARIO / CLASES" en su artículo). Esto parece sugerir que el primer método será más fácil de implementar.
Tenga en cuenta que esto es diferente al caso descrito aquí donde cada ejemplo es una secuencia de secuencias. A mi entender, la razón por la que este tipo de método no está bien respaldado es porque es un abuso del caso que está destinado a apoyar; Cargando incrustaciones de tamaño fijo directamente.
Supondré que lo siguiente que quiere hacer es convertir esos números en incrustaciones de palabras. Puede convertir una lista de índices en una lista de incrustaciones con tf.nn.embedding_lookup