songololo
songololo

Reputation: 4954

Tensorflow (Keras API) `model.fit` method returns "Failed to convert object of type <class 'tuple'> to Tensor" error

I am using gaussian noise per the tf.random.normal method (or K.random_normal via the keras API).

It is used from within a custom tensorflow Layer, which, in turn, is used by a custom Model.

For some reason, everything works as intended when calling the layer / model directly, or when using a custom training loop via tf.GradientTape(), but it throws a puzzling error when attempting to use the fit method instead.

It appears to have something to do with inferring the batch dimension, which presents as None when calling the fit method.

I suspect this has something to do with compilation and symbolic tensors vs. eager tensors, but I'm none-the-wiser as to how this would actually be resolved?

I've tried to strip the problem down to a minimal example that reproduces the issue:

import numpy as np
import tensorflow.keras.backend as K
from tensorflow.keras import models
import tensorflow as tf

class Demo(models.Model):

    def __init__(self):
        super().__init__()

    def call(self, inputs, training=None, mask=None):
        # batch gives "2" when called directly or via GradientTape()
        # gives "None" when called via fit
        batch = K.int_shape(inputs)[0]
        dim = K.int_shape(inputs)[1]
        noise = tf.random.normal(shape=(batch, dim), mean=0.0, stddev=1.0)
        # manually specifying the batch dimension does work, e.g.
        # noise = tf.random.normal(shape=(2, dim), mean=0.0, stddev=1.0)
        return inputs * noise

test_data = np.array([[1., 2., 3., 4.], [5., 6., 7., 8.]])

tester = Demo()
tester.compile(optimizer='adam')

# manual calling works
print(test_data - tester(test_data))

# but calling fit does not
tester.fit(x=test_data)
# raises: TypeError: Failed to convert object of type <class 'tuple'> to Tensor.
# Contents: (None, 4). Consider casting elements to a supported type.

Any suggestions for what the problem might be?

Upvotes: 1

Views: 1093

Answers (1)

Bashir Kazimi
Bashir Kazimi

Reputation: 1377

In the call method, instead of using keras.backend to get batch and dim, use tensorflow directly.

batch = tf.shape(inputs)[0]
dim = tf.shape(inputs)[1]

Upvotes: 1

Related Questions