2017-02-19 4 views
1

Я пытаюсь поставить в очередь данные из файла hdf5. Поскольку Tensorflow не поддерживает hdf5, я создал функцию python, которая читает примеры из файла hdf5 и поднимает tf.errors.OutOfRangeError, когда она достигает конца файла. Затем я завершаю эту функцию python с помощью tf.py_func и использую ее как очередь для очереди.Tensorflow: Пользовательский считыватель данных с использованием py_func

Это мой код:

import h5py 
import tensorflow as tf 
from tensorflow.python.framework import errors 
import numpy as np 

def read_from_hdf5(hdf5_file, batch_size): 
    h5py_handle = h5py.File(hdf5_file) 

    # Check shapes from the hdf5 file so that we can set the tensor shapes 
    feature_shape = h5py_handle['features'].shape[1:] 
    label_shape = h5py_handle['labels'].shape[1:] 

    #generator that produces examples for training. It will be wrapped by tf.pyfunc to simulate a reader 
    def example_generator(h5py_handle): 
     for i in xrange(0, h5py_handle['features'].shape[0]-batch_size+1, batch_size): 
      features = h5py_handle['features'][i:i+batch_size] 
      labels = h5py_handle['labels'][i:i+batch_size] 
      yield [features, labels] 
     raise errors.OutOfRangeError(node_def=None, op=None, message='completed all examples in %s'%hdf5_file) 

    [features_tensor, labels_tensor] = tf.py_func(
     example_generator(h5py_handle).next, 
     [], 
     [tf.float32, tf.float32], 
     stateful=True) 

    # Set the shape so that we can infer sizes etc in later layers. 
    features_tensor.set_shape([batch_size, feature_shape[0], feature_shape[1], feature_shape[2]]) 
    labels_tensor.set_shape([batch_size, label_shape[0]]) 

    return features_tensor, labels_tensor 


def load_data_from_filename_list(hdf5_files, batch_size, shuffle_seed=0): 
    example_list = [read_from_hdf5(hdf5_file, batch_size) for hdf5_file in hdf5_files] 
    min_after_dequeue = 10000 
    capacity = min_after_dequeue + (len(example_list)+1) * batch_size #min_after_dequeue + (num_threads + a small safety margin) * batch_size 
    features, labels = tf.train.shuffle_batch_join(example_list, batch_size, capacity=capacity, min_after_dequeue=min_after_dequeue, seed=shuffle_seed, enqueue_many=True) 
    return features, labels, metadata 

Я ожидал, что tf.errors.OutOfRangeError будет обрабатываться QueueRunner, однако, я получаю следующее сообщение об ошибке и сбой программы. Можно ли делать такой вид чтения из py_func, и если да, то что я делаю неправильно? Если нет, то какой подход следует использовать вместо этого?

Traceback (most recent call last): 
    File "https://stackoverflow.com/users/anaconda2/lib/python2.7/site-packages/tensorflow/python/ops/script_ops.py", line 85, in __call__ 
    ret = func(*args) 
    File "build/bdist.linux-x86_64/egg/tronn/datalayer.py", line 27, in example_generator 
    raise errors.OutOfRangeError(node_def=None, op=None, message='completed all examples in %s'%hdf5_file) 
tensorflow.python.framework.errors_impl.OutOfRangeError: completed all examples 
W tensorflow/core/framework/op_kernel.cc:993] Internal: Failed to run py callback pyfunc_13: see error log. 
+1

Это может помочь, если вы покажете свой код, а также сообщение об ошибке, чтобы люди могли воспроизвести вашу проблему. – merlin2011

+0

Спасибо за подсказку. Я добавил свой код. – navari

ответ

3

Похоже, что обработка исключений в py_func не поддерживается.

Рассмотрим этот код в py_func.cc

// Invokes the trampoline. 
    PyObject* result = PyEval_CallObject(trampoline, args); 
    Py_DECREF(args); 
    if (result == nullptr) { 
    if (PyErr_Occurred()) { 
     // TODO(zhifengc): Consider pretty-print error using LOG(STDERR). 
     PyErr_Print(); 
    } 
    return errors::Internal("Failed to run py callback ", call->token, 
          ": see error log."); 
    } 

PyErr_Occurred устанавливается, когда есть исключение генерируется, так что это приведет исполнение бросить Failed to run py callback.

py_func - нечетное существо, поскольку оно работает в среде клиента Python. Обычно, когда op (например, read op) терпит неудачу, он, который распространяется от TF runtime, возвращает не одобренный статус клиенту Python, который затем преобразует его в исключение Python в raise_exception_on_not_ok_status (в client.py:session.run). Поскольку тело py_func работает в Python-клиенте, TensorFlow необходимо будет изменить для обработки PyErr_Occurred, чтобы вставить плохой статус в среду выполнения TensorFlow.

+0

Большое спасибо за объяснение. Это, по-видимому, указывает на то, что я не могу использовать py_func в качестве читателя. Какой подход я могу взять вместо этого? – navari

+0

Вместо использования читателя у меня будет поток Python, который закроет ваши примеры, а затем закроет вашу очередь. Тогда регулярный dequeue будет поднимать ошибку OutOfRange, когда это делается с примерами. Этот [пример] (https://gist.github.com/jimfleming/d1118cc630f5c883223a4b4645cc2e7b) показывает, как вставить все выходы из пользовательского генератора –