7

I am trying to convert a tensor to numpy in the tesnorflow2.0 version. Since tf2.0 have eager execution enabled then it should work by default and working too in normal runtime. While I execute code in tf.data.Dataset API then it gives an error

"AttributeError: 'Tensor' object has no attribute 'numpy'"

I have tried ".numpy()" after tensorflow variable and for ".eval()" I am unable to get default session.

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
# tf.executing_eagerly()
import os
import time
import matplotlib.pyplot as plt
from IPython.display import clear_output
from model.utils import  get_noise
import cv2


def random_noise(input_image):
  img_out = get_noise(input_image)
  return img_out


def load_denoising(image_file):
  image = tf.io.read_file(image_file)
  image = tf.image.decode_png(image)
  real_image = image
  input_image = random_noise(image.numpy())
  input_image = tf.cast(input_image, tf.float32)
  real_image = tf.cast(real_image, tf.float32)
  return input_image, real_image


def load_image_train(image_file):
  input_image, real_image = load_denoising(image_file)
  return input_image, real_image

This works fine

inp, re = load_denoising('/data/images/train/18.png')
# Check for correct run
plt.figure()
plt.imshow(inp)
print(re.shape,"  ", inp.shape)

And this produces mentioned error

train_dataset = tf.data.Dataset.list_files('/data/images/train/*.png')
train_dataset = train_dataset.map(load_image_train,num_parallel_calls=tf.data.experimental.AUTOTUNE)

Note: random_noise have cv2 and sklearn functions

vikram meena
  • 303
  • 1
  • 2
  • 8
  • I have trouble reading your code. Do you always remove all whitespace, even between function definitions? And almost none of your code has anything to do with your problem. Please try to formulate a [MCVE](https://stackoverflow.com/help/mcve). – Nils Werner May 10 '19 at 10:43
  • Hi Nils, I have formatted code. code is fully working with tensorflow2.0 and produces the same output and error. please help me with this error. – vikram meena May 10 '19 at 12:12
  • provide complete error message – Sociopath May 10 '19 at 12:13
  • 1
    @AkshayNevrekar When I use tensorname.numpy() it produces `"AttributeError: 'Tensor' object has no attribute 'numpy'` – vikram meena May 13 '19 at 08:59

2 Answers2

9

You can't use the .numpy method on a tensor, if this tensor is going to be used in a tf.data.Dataset.map call.

The tf.data.Dataset object under the hood works by creating a static graph: this means that you can't use .numpy() because the tf.Tensor object when in a static-graph context do not have this attribute.

Therefore, the line input_image = random_noise(image.numpy()) should be input_image = random_noise(image).

But the code is likely to fail again since random_noise calls get_noise from the model.utils package. If the get_noise function is written using Tensorflow, then everything will work. Otherwise, it won't work.

The solution? Write the code using only the Tensorflow primitives.

For instance, if your function get_noise just creates random noise with the shee of your input image, you can define it like:

def get_noise(image):
    return tf.random.normal(shape=tf.shape(image))

using only the Tensorflow primitives, and it will work.

Hope this overview helps!

P.S: you could be interested in having a look at the articles "Analyzing tf.function to discover AutoGraph strengths and subtleties" - they cover this aspect (perhaps part 3 is the one related to your scenario): part 1 part 2 part 3

nessuno
  • 26,493
  • 5
  • 83
  • 74
  • 'def get_noise(image)' function is not written in tensorflow. This function's implementation has OpenCV, sklearn and other libraries. Can you suggest me any method by which I can call get_noise function in the tensorflow execution? – vikram meena May 13 '19 at 08:54
  • If you want to add random noise to an image, the function I wrote previously (the get_noise` can be used in the pipeline as: `image = image + get_noise(image)` – nessuno May 13 '19 at 10:31
  • So this actually means that if I want to use a custom library for image augmentation, like albumentations, I will not be able to use it, right, due to the tensorflow constraints. – Timbus Calin Jan 18 '20 at 18:26
  • 1
    Yes, or better, you can wrap your augmentation step into a `py_func` call and use it inside your data processing pipeline. All the content of the `py_func` won't be converted to graph code (because tensorflow has no idea about how to convert to nodes these kinds of operations), but your pipeline will be fine. I suggest to do your data augmentation step into a py_func, then invoke the .cache() method of tf.data.Dataset so the cache into actual tensors the result of the augmentation and thus remove any python bottleneck – nessuno Jan 19 '20 at 11:22
  • 1
    Very comprehensive response, thank you very much. Appreciate it. – Timbus Calin Jan 19 '20 at 16:32
  • Not helpful, the question was how to transfer a tensor to numpy in tf 2.0 which doesn't have a session (which is an important issue). – mcExchange Oct 01 '20 at 17:52
  • 1
    You're wrong @mcExchange. tf.data.Dataset object works in graph mode, not in eager mode. That's why this issue is present. You can't call the .numpy() method on a tensor inside a method that's going to be graph-converted. The same happens if you invoke the .numpy() method on a tensor that's used inside a function decorated with tf.function. – nessuno Oct 01 '20 at 18:08
0

In TF2.x version, use tf.config.run_functions_eagerly(True).

Patrick J. Holt
  • 516
  • 4
  • 7