Python 使用来自_生成器()的tf.data.Dataset

Python 使用来自_生成器()的tf.data.Dataset,python,tensorflow,parallel-processing,Python,Tensorflow,Parallel Processing,我有一种计算成本很高的方法来模拟编码为生成器的数据,我想将其输入Tensorflow中的神经网络模型。我希望通过并行化对生成器的调用来快速生成批量数据。我当前的数据输入管道如下所示: def data_iterator(): # data generation procedure to be parallelized pass dataset = tf.data.Dataset.from_generator(data_iterator,

我有一种计算成本很高的方法来模拟编码为生成器的数据,我想将其输入Tensorflow中的神经网络模型。我希望通过并行化对生成器的调用来快速生成批量数据。我当前的数据输入管道如下所示:

def data_iterator():
     # data generation procedure to be parallelized
     pass

dataset = tf.data.Dataset.from_generator(data_iterator, 
                                        (tf.float32,tf.float32), 
                                        (tf.TensorShape([HEIGHT, None, 1]), 
                                         tf.TensorShape([2])))

dataset = dataset.padded_batch(BATCH_SIZE, 
                               padded_shapes=(tf.TensorShape([HEIGHT, None, 1]), 
                                              tf.TensorShape([2])))
iterator = dataset.make_one_shot_iterator()
x_image, y_ = iterator.get_next()
不幸的是,我发现使用
from_generator()
方法创建一批数据很难并行化,因为无法指定用于从生成器提取数据以创建批的线程数。我在这个thread()中尝试了这个解决方案,它并行使用包装函数和映射,发现速度根本没有提高。以前,我使用队列输入数据,似乎效果很好,如下所示:

class CustomRunner(object):
    """
    This class manages the the background threads needed to fill
        a queue full of data.
    """
    def __init__(self):
        self.dataX = tf.placeholder(dtype=tf.float32, shape=[HEIGHT,WIDTH,1])
        self.dataY = tf.placeholder(dtype=tf.float32, shape=[2])
        # The actual queue of data. The queue contains a vector for
        # the features, and a scalar label.
        self.queue = tf.FIFOQueue(shapes=[[HEIGHT,WIDTH,1],[2]],
                                           dtypes=[tf.float32, tf.float32],
                                           capacity=QUEUE_CAPACITY)
        self.enqueue_op = self.queue.enqueue([self.dataX, self.dataY])

    def get_inputs(self,batch_size):
        """
        Return's tensors containing a batch of images and labels
        """
        images_batch, labels_batch = self.queue.dequeue_many(batch_size)
        return images_batch, labels_batch

    def thread_main(self, sess):
        """
        Function run on alternate thread. Basically, keep adding data to the queue.
        """
        for dataX, dataY in data_iterator():
            sess.run(self.enqueue_op, feed_dict={self.dataX:dataX,  self.dataY:dataY})

    def start_threads(self, sess, n_threads=1):
        """ Start background threads to feed queue """
        threads = []
        for n in range(n_threads):
            t = threading.Thread(target=self.thread_main, args=(sess,))
            t.daemon = True # thread will close when parent quits
            t.start()
            threads.append(t)
        return threads

sess = tf.Session(config=tf.ConfigProto(intra_op_parallelism_threads=24, 
                 inter_op_parallelism_threads=24))

我不得不改变这一点,因为我不能用可变宽度输入dict。有人知道有没有解决这个问题的好办法吗?

我不太清楚你的问题是什么。您正在尝试并行执行生成器吗?那是不可能的。生成器本质上是连续的,这就是为什么像上下文管理器这样的东西可以实现为生成器:您可以保证一个接一个地获得结果。如果您的数据生成逻辑不是这样,那么它不应该是生成器。对不起。让我澄清一下。data_迭代器提供单个数据点值。我想通过对生成器的50次调用来并行创建一批数据(例如50个数据点)的过程。看起来tf.data.Dataset.from_generator()并不容易实现这一点。听起来您的数据生成应该只是一个函数。也许有一个非常基本的生成器,可以创建正确数量的插槽,然后将实际的数据生成映射到该插槽上?我确实尝试过,但速度保持不变,因此我不确定我是否只是没有正确地将足够的内核或线程用于该操作。通过
tf.ConfigProto
实现这一点的正确方法是什么。。?