Home > front end >  Tensorflow rotate with random uniform take 1 positional argument but 2 were given
Tensorflow rotate with random uniform take 1 positional argument but 2 were given

Time:04-02

I have the following code that uses tensorflow to calculate a custom average loss when the image is consistently rotated:

import tensorflow as tf
import cv2

#initialize x_hat    
img = cv2.imread("4.jpg")
x_hat = tf.Variable(img,name = 'x_hat') #img we want to attack 

@tf.function 
def cost2():
    image=x_hat
    #Now it will generate 100 samples rotated
    num_samples = 100
    average_loss = 0

    for j in range(num_samples):

        #ADD ROTATION (there may be a problem here)
        rotated = tf.keras.preprocessing.image.random_rotation(image, 
        tf.random.uniform(shape=(),minval=40, maxval=90),channel_axis=2)

        #get logits
        rotated_logits, _ = resnet(rotated)
        #get average CUSTOM loss
        average_loss =-1 * tf.nn.softmax_cross_entropy_with_logits(logits=rotated_logits, labels=labels)/ num_samples
return average_loss

and here is how I call it

learning_rate = 1e-1
optim = tf.optimizers.SGD (learning_rate=learning_rate)

epsilon = 2.0/255.0 # a really small perturbation
below = x - epsilon
above = x   epsilon

demo_steps = 200


# projected gradient descent
for i in range(demo_steps):

    loss = optim.minimize(cost2, var_list=[x_hat])

    if (i 1) % 10 == 0:
        print('step %d, loss=%g' % (i 1, loss.numpy()))

    projected = tf.clip_by_value(tf.clip_by_value(x_hat, below, above), 0, 1)

    with tf.control_dependencies([projected]):
        x_hat.assign(projected)

adv_robust = x_hat.numpy() 

However, the following error returns to me once I run the code:

TypeError: in user code:

<ipython-input-183-abde02909da7>:14 cost2  *
    rotated = tf.keras.preprocessing.image.random_rotation(image, 
tf.random.uniform(shape=(),minval=40, maxval=90),channel_axis=2)
/home/me/.local/lib/python3.8/site- 
packages/keras_preprocessing/image/affine_transformations.py:55 random_rotation  *
theta = np.random.uniform(-rg, rg)
mtrand.pyx:1111 numpy.random.mtrand.RandomState.uniform  **
    

TypeError: __array__() takes 1 positional argument but 2 were given

I am on Tensorflow 2.4.0 and the random_rotation and random.uniform functions are correct according to the TF 2.4.0 documentation HERE and HERE. So, what am I missing here?

CodePudding user response:

The error might be coming from using TF tensors. As stated in the docs you linked regarding random_rotation:

Performs a random rotation of a Numpy image tensor.

Meaning you cannot use TF tensors with this operation. If you are in eager execution mode you can use tensor.numpy():

import tensorflow as tf

image = tf.random.normal((180, 180, 3))
rotated = tf.keras.preprocessing.image.random_rotation(image.numpy(), 
        tf.random.uniform(shape=(),minval=40, maxval=90).numpy(),channel_axis=2)

Otherwise, it is recommended to use the preprocessing layer: tf.keras.layers.RandomRotation, since using numpy in graph mode (for example in a function decorated with @tf.function) is not recommended.

Here is an example using the tf.keras.layers.RandomRotation:

import tensorflow as tf
import os
import matplotlib.pyplot as plt

_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')

train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')

BATCH_SIZE = 1
IMG_SIZE = (160, 160)

train_ds = tf.keras.utils.image_dataset_from_directory(train_dir,
                                                            shuffle=True,
                                                            batch_size=BATCH_SIZE,
                                                            image_size=IMG_SIZE)

data_augmentation = tf.keras.Sequential([
  tf.keras.layers.RandomRotation(tf.random.uniform(shape=(),minval=40, maxval=90)),
])
for image, _ in train_ds.take(1):
  plt.figure(figsize=(10, 10))
  first_image = image[0]
  for i in range(9):
    ax = plt.subplot(3, 3, i   1)
    augmented_image = data_augmentation(tf.expand_dims(first_image, 0), training=True)
    plt.imshow(augmented_image[0] / 255)
    plt.axis('off')
  • Related