Tensorflow: 在方法中使用会话/图

5

我的情况是这样的:

我有一个训练tensorflow模型的脚本。在这个脚本中,我实例化了一个类来提供训练数据。这个类的初始化又会实例化另一个名为“image”的类,用于进行各种数据增强等操作。

main script -> instantiates data_feed class -> instantiates image class

我的问题是,我正在尝试使用tensorflow通过传递会话本身或图来在此图像类中执行一些操作。但我没有取得太大的成功。

可行的方法(但速度太慢)

我现在拥有的东西,但工作速度极慢,类似于这样(简化):

class image(object):
    def __init__(self, im):
        self.im = im

    def augment(self):
        aux_im = tf.image.random_saturation(self.im, 0.6)

        sess = tf.Session(graph=aux_im.graph)
        self.im = sess.run(aux_im)

class data_feed(object):
    def __init__(self, data_dir):
        self.images = load_data(data_dir)

    def process_data(self):
        for im in self.images:
            image = image(im)
            image.augment()

if __name__ == "__main__":
    # initialize everything tensorflow related here, including model
    sess = tf.Session()
    # next load the data
    data_feed = data_feed(TRAIN_DATA_DIR)
    train_data = data_feed.process_data()

这种方法能够奏效,但它会为每个图像创建一个新的会话:
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0)
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0)
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0)
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0)
etc ...

不起作用的方法(本应更快)

例如,以下做法并不起作用,我也无法弄清原因:从主脚本传递图或会话:

class image(object):
    def __init__(self, im):
        self.im = im

    def augment(self, tf_sess):
        with tf_sess.as_default():
            aux_im = tf.image.random_saturation(self.im, 0.6)

            self.im = tf_sess.run(aux_im)

class data_feed(object):
    def __init__(self, data_dir, tf_sess):
        self.images = load_data(data_dir)
        self.tf_sess = tf_sess

    def process_data(self):
        for im in self.images:
            image = image(im)
            image.augment(self.tf_sess)

if __name__ == "__main__":
    # initialize everything tensorflow related here, including model
    sess = tf.Session()
    # next load the data
    data_feed = data_feed(TRAIN_DATA_DIR, sess)
    train_data = data_feed.process_data()

这是我收到的错误信息:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 409, in data_generator_task
    generator_output = next(generator)
  File "/home/mathetes/Dropbox/ML/load_gluc_data.py", line 198, in generate
    yield self.next_batch()
  File "/home/mathetes/Dropbox/ML/load_gluc_data.py", line 192, in next_batch
    X, y, l = self.process_image(json_im, X, y, l)
  File "/home/mathetes/Dropbox/ML/load_gluc_data.py", line 131, in process_image
    im.augment_with_tf(self.tf_sess)
  File "/home/mathetes/Dropbox/ML/load_gluc_data.py", line 85, in augment_with_tf
    self.im = sess.run(saturation, {im_placeholder: np.asarray(self.im)})
  File "/home/mathetes/.local/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 766, in run
    run_metadata_ptr)
  File "/home/mathetes/.local/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 921, in _run
    + e.args[0])
TypeError: Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder:0", shape=(96, 96, 3), dtype=float32) is not an element of this graph.

任何帮助都将不胜感激!
1个回答

3

不如创建一个名为ImageAugmenter的类,它在初始化时需要一个会话,并使用Tensorflow处理图像,而不是使用Image类。你可以这样做:

import tensorflow as tf
import numpy as np

class ImageAugmenter(object):
    def __init__(self, sess):
        self.sess = sess
        self.im_placeholder = tf.placeholder(tf.float32, shape=[1,784,3])

    def augment(self, image):
        augment_op = tf.image.random_saturation(self.im_placeholder, 0.6, 0.8)
        return self.sess.run(augment_op, {self.im_placeholder: image})

class DataFeed(object):
    def __init__(self, data_dir, sess):
        self.images = load_data(data_dir)
        self.augmenter = ImageAugmenter(sess)

    def process_data(self):
        processed_images = []
        for im in self.images:
            processed_images.append(self.augmenter.augment(im))
        return processed_images

def load_data(data_dir):
    # True method would read images from disk
    # This is just a mockup
    images = []
    images.append(np.random.random([1,784,3]))
    images.append(np.random.random([1,784,3]))
    return images

if __name__ == "__main__":
    TRAIN_DATA_DIR = '/some/dir/'
    sess = tf.Session()
    data_feed = DataFeed(TRAIN_DATA_DIR, sess)
    train_data = data_feed.process_data()
    print(train_data)

使用这个方法,您不需要为每个图像创建一个新的会话,它应该能给您想要的结果。

请注意如何调用sess.run();我传递给它的feed dict的键是上面定义的placeholder tensor。根据您的错误跟踪,您可能正在尝试从代码的某个部分调用sess.run(),而此时im_placeholder尚未定义,或者已经被定义为非tf.placeholder类型。

另外,您可以通过将下限和上限参数作为输入传递给tf.image.random_saturation()方法来进一步改进代码,或者您可以初始化ImageAugmenter以特定形状而不是硬编码,例如。


谢谢您的回答,但我仍然遇到相同的错误: TypeError: 无法将feed_dict键解释为张量:张量Tensor(“Placeholder:0”,shape =(96,96,3),dtype = float32)不是此图的元素。 - mathetes
我已经更新了我的问题,以反映完整的回溯信息,但上面的代码中可能还有未显示的函数。 - mathetes
我更新了我的答案,附上了可运行的代码片段,并进一步解释了为什么会出现那个错误。 - jabalazs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接