TensorFlow - tf.data.Dataset leyendo grandes archivos HDF5
Estoy configurando una tubería de TensorFlow para leer grandes archivos HDF5 como entrada para mis modelos de aprendizaje profundo. Cada archivo HDF5 contiene 100 videos de tamaño variable almacenados como una colección de imágenes JPG comprimidas (para que el tamaño en el disco sea manejable). Utilizandotf.data.Dataset
y un mapa paratf.py_func
, leer ejemplos del archivo HDF5 usando la lógica personalizada de Python es bastante fácil. Por ejemplo:
def read_examples_hdf5(filename, label):
with h5py.File(filename, 'r') as hf:
# read frames from HDF5 and decode them from JPG
return frames, label
filenames = glob.glob(os.path.join(hdf5_data_path, "*.h5"))
labels = [0]*len(filenames) # ... can we do this more elegantly?
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.map(
lambda filename, label: tuple(tf.py_func(
read_examples_hdf5, [filename, label], [tf.uint8, tf.int64]))
)
dataset = dataset.shuffle(1000 + 3 * BATCH_SIZE)
dataset = dataset.batch(BATCH_SIZE)
iterator = dataset.make_one_shot_iterator()
next_batch = iterator.get_next()
Este ejemplo funciona, sin embargo, el problema es que parecetf.py_func
solo puede manejar un ejemplo a la vez. Como mi contenedor HDF5 almacena 100 ejemplos, esta limitación causa una sobrecarga significativa ya que los archivos deben abrirse, leerse, cerrarse y reabrirse constantemente. Sería mucho más eficiente leer los 100 ejemplos de video en el objeto del conjunto de datos y luego continuar con el siguiente archivo HDF5 (preferiblemente en varios subprocesos, cada subproceso se ocupa de su propia colección de archivos HDF5).
Entonces, lo que me gustaría es una serie de subprocesos que se ejecutan en segundo plano, que leen cuadros de video de los archivos HDF5, los decodifican desde JPG y luego los introducen en el objeto del conjunto de datos. Antes de la introducción de latf.data.Dataset
pipeline, esto fue bastante fácil usando elRandomShuffleQueue
yenqueue_many
operaciones, pero parece que actualmente no hay una forma elegante de hacerlo (o falta la documentación).
¿Alguien sabe cuál sería la mejor manera de lograr mi objetivo? También he examinado (e implementado) la tubería usandotfrecord
archivos, pero tomando una muestra aleatoria de cuadros de video almacenados en untfrecord
el archivo parece bastante imposible (veraquí) Además, he mirado elfrom_generator()
entradas paratf.data.Dataset
pero eso definitivamente no se ejecutará en múltiples hilos parece. Cualquier sugerencia es más que bienvenida.