张量流意外缓存子图结果



我目前正在尝试为 TF 制作一个增强类,如下所示:

    class Augmentations:
        def __init__(self, **kwargs):
            # Some Global Kwargs Define Here
            self.transforms = tf.eye(3)
            self.img_height = kwargs['img_height']
            self.img_width = kwargs['img_width']
        def _generate_random(self, shape, seed, minval, maxval):
            return tf.random_uniform(shape=shape,
                                     minval=minval,
                                     maxval=maxval,
                                     seed=seed,
                                     dtype=tf.float32)
        def rotate(self, seed, max_angle):
            random_rotation_value = self._generate_random([1], seed, 0., max_angle)
            rotation_matrix = tf.contrib.image.angles_to_projective_transforms(
                                random_rotation_value,
                                self.img_height,
                                self.img_width)
            rotation_matrix = tf.reshape(tf.concat([rotation_matrix, [[1.]]], axis=1),
                                         [3, 3])
            self.transforms = tf.matmul(self.transforms, rotation_matrix)
            return self

        def apply(self, img):
            t = tf.reshape(tf.matmul(self.transforms[0],
                                     self.transforms[1]),
                           [1, 9])[0, :8]
            return tf.contrib.image.transform(img, t)

我已经尝试了dataset.maptf.map_fn,两者都返回一致的转换,即:

augment = Augment(**kwargs).rotate(None, 30).shear(None, 30)
dataset = dataset.map(augment.apply, num_parallel_calls=10)

augment = Augment(**kwargs).rotate(None, 30).shear(None, 30)
dataset = tf.map_fn(augment.apply)

这两个调用都返回应用了相同转换的不同图像。

使用随机变换返回图像的唯一方法是调用map()中的变换:

dataset = dataset.map(Augment(**kwargs).rotate(None, 30).shear(None, 30).apply, num_parallel_calls=10)

或将所有随机数移动到apply()中。

random_*()调用的放置在TF中是否重要,我认为放置无关紧要,是否仅对map_fn重要?

这是

预期行为,因为对 apply 方法的所有调用共享相同的tf.random_uniform操作。调用session.run时,此随机操作将计算一次,其结果将用于所有元素。

在 apply 中调用tf.random_uniform会有所不同,因为您将创建多个随机操作,每个操作都会生成不同的随机序列。它基本上是以下两者之间的区别:

sess = tf.InteractiveSession()
x = tf.random_uniform((1,))
y = tf.stack([x * tf.constant(1.0), x * tf.constant(1.0)])
y.eval() 
# Prints
#   array([[ 0.67649043],
#          [ 0.67649043]], dtype=float32)
# because there is only one random operation in the graph and it is evaluated once.

sess = tf.InteractiveSession()
y = tf.stack([tf.random_uniform((1,)) * tf.constant(1.0), tf.random_uniform((1,)) * tf.constant(1.0)])
y.eval()
# Prints
# array([[ 0.08824277],
#        [ 0.4801079 ]], dtype=float32)
# because there are two random operations in the graph and each yields a different value when evaluated

非常基本的是,张量流session.run()每次调用最多评估一次操作(假设它不在while循环或类似循环中(。

最新更新