Tengo un CSV con aproximadamente 40 millones de filas. Cada fila es una instancia de entrenamiento. Segúnla documentación sobre el consumo de TFRecords , estoy tratando de codificar y guardar los datos en un archivo TFRecord.
Todos los ejemplos que he encontrado ( incluso los del repositorio de TensorFlow ) muestran que el proceso de creación de un TFRecord depende de la clase TFRecordWriter. Esta clase tiene un método de write que toma como entrada una representación de cadena serializada de los datos y la escribe en el disco. Sin embargo, esto parece hacerse una instancia de entrenamiento a la vez.
¿Cómo escribo un lote de los datos serializados?
Digamos que tengo una función:
def write_row(sentiment, text, encoded): feature = {"one_hot": _float_feature(encoded), "label": _int64_feature([sentiment]), "text": _bytes_feature([text.encode()])} example = tf.train.Example(features=tf.train.Features(feature=feature)) writer.write(example.SerializeToString()) Escribir en el disco 40 millones de veces (una vez para cada ejemplo) será increíblemente lento. Sería mucho más eficiente agrupar estos datos por lotes y escribir 50k o 100k ejemplos a la vez (en la medida en que lo permitan los recursos de la máquina). Sin embargo, no parece haber ningún método para hacer esto dentro TFRecordWriter .
Algo del estilo de:
class MyRecordWriter: def __init__(self, writer): self.records = [] self.counter = 0 self.writer = writer def write_row_batched(self, sentiment, text, encoded): feature = {"one_hot": _float_feature(encoded), "label": _int64_feature([sentiment]), "text": _bytes_feature([text.encode()])} example = tf.train.Example(features=tf.train.Features(feature=feature)) self.records.append(example.SerializeToString()) self.counter += 1 if self.counter >= 10000: self.writer.write(os.linesep.join(self.records)) self.counter = 0 self.records = []Pero al leer el archivo creado por este método me sale el siguiente error:
tensorflow/core/framework/op_kernel.cc:1192] Invalid argument: Could not parse example input, value: ' �� label �� one_hot���� �� Nota: podría cambiar el proceso de codificación para que cada prototipo de example contenga varios miles de ejemplos en lugar de solo uno, pero no quiero pre-hacer un lote de datos al escribir en el archivo TFrecord de esta manera, ya que introducirá una sobrecarga adicional en mi tubería de entrenamiento cuando quiero usar el archivo para entrenar con diferentes tamaños de lote.
TFRecords es un formato binario. Con la siguiente línea, lo está tratando como un archivo de texto: self.writer.write(os.linesep.join(self.records))
Esto se debe a que está utilizando el sistema operativo según linesep (ya sea \n o \r\n ).
Solución: Simplemente escriba los registros. Usted está pidiendo que los escriba por lotes. Puede utilizar un escritor almacenado en búfer. Para 40 millones de filas, también puede considerar dividir los datos en archivos separados para permitir una mejor paralelización.
Al usar TFRecordWriter : el archivo ya está almacenado en el búfer.
La evidencia de eso se encuentra en la fuente:
pywrap_tensorflow.PyRecordWriter_NewEnv::Default()->NewWritableFileNewWritableFile en el FileSystem coincidentefopen