0

我目前正在尝试为 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?

4

1 回答 1

0

这是预期的行为,因为对您的方法的所有调用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

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

于 2017-11-16T23:06:31.720 回答