pythontensorflowkerasreinforcement-learningkeras-layer

Exception encountered when calling layer and 'KerasTensor' object is not callable


I'm newbie to reinforcement learning. I'd like to see and understand the code that predicts Keras actor critic value, and then run it with some changes.

Example code: https://github.com/keras-team/keras-io/blob/master/examples/rl/actor_critic_cartpole.py

However, I ran into a problem when running it.

Below is the total error.

예외가 발생했습니다. TypeError
Exception encountered when calling layer "custom_model" "f"(type CustomModel).
'KerasTensor' object is not callable
Call arguments received by layer "custom_model""f"(type CustomModel):
  • inputs=tf.Tensor(shape=(1, 10, 10), dtype=float32)
  File "C:\Users\cglab\Desktop\Match3\Model.py", line 19, in call
    common = self.common(inputs)
TypeError: 'KerasTensor' object is not callable

Here is the code

import tensorflow as tf

from keras import layers

class CustomModel(tf.keras.Model):
    def __init__(self, num_hidden, max_x, max_y, n_tile_type):
        super(CustomModel, self).__init__()
        self.inputs = layers.Input(shape=(max_y, max_x))
        self.common = layers.Dense(num_hidden, activation="relu")(self.inputs)
        tf.debugging.assert_shapes([(self.inputs, (tf.TensorShape([None, 10, 10])))]) #not assert
        self.x_probs = layers.Dense(max_x, activation="softmax")(self.common)
        self.y_probs = layers.Dense(max_y, activation="softmax")(self.common)
        self.tile_prob = layers.Dense(n_tile_type, activation="softmax")(self.common)
        self.critic = layers.Dense(1)(self.common)

    def call(self, inputs):
        tf.debugging.assert_shapes([(inputs, (tf.TensorShape([None, 10, 10])))]) #not assert

        common = self.common(inputs) ##Error
        x_probs = self.x_probs(common)
        y_probs = self.y_probs(common)
        tile_prob = self.tile_prob(common)
        critic = self.critic(common)

    return [x_probs, y_probs, tile_prob, critic]

#Initialize and call

model = CustomModel(256, max_x, max_y, max_tile_type)

state = np.full((self.max_y, self.max_x), -1)
state = tf.convert_to_tensor(state, dtype=tf.float32)
state = tf.expand_dims(state, 0)

x_probs, y_probs, tile_probs, critic_value = model(state)

I need help. thank you


Solution

  • I tried to recreate your code with demo variables, the primary problem is you're supposed to put the return statement in the call method of the class CustomModel. That's why it's throwing the exception as TypeError: 'KerasTensor' object is not callable because your CustomModel class is not returning a proper tensor object. here's the corrected one:

    import numpy as np
    import tensorflow as tf
    from tensorflow.keras import layers
    
    class CustomModel(tf.keras.Model):
        def __init__(self, num_hidden, max_x, max_y, n_tile_type):
            super(CustomModel, self).__init__()
            self.common = layers.Dense(num_hidden, activation="relu")
            self.x_probs = layers.Dense(max_x, activation="softmax")
            self.y_probs = layers.Dense(max_y, activation="softmax")
            self.tile_prob = layers.Dense(n_tile_type, activation="softmax")
            self.critic = layers.Dense(1)
    
        def call(self, inputs):
            common = self.common(inputs)
            x_probs = self.x_probs(common)
            y_probs = self.y_probs(common)
            tile_prob = self.tile_prob(common)
            critic = self.critic(common)
    
            return [x_probs, y_probs, tile_prob, critic]
    
    # Initialize and call
    max_x = 10
    max_y = 10
    max_tile_type = 5
    model = CustomModel(256, max_x, max_y, max_tile_type)
    
    state = np.full((max_y, max_x), -1)
    state = tf.convert_to_tensor(state, dtype=tf.float32)
    state = tf.expand_dims(state, 0)
    
    x_probs, y_probs, tile_probs, critic_value = model(state)
    
    # Print shapes of the outputs for verification
    print("x_probs shape:", x_probs.shape)
    print("y_probs shape:", y_probs.shape)
    print("tile_probs shape:", tile_probs.shape)
    print("critic_value shape:", critic_value.shape)
    

    The output is as follows:

    x_probs shape: (1, 10, 10)
    y_probs shape: (1, 10, 10)
    tile_probs shape: (1, 10, 5)
    critic_value shape: (1, 10, 1)
    

    I've also made some other adjustments. You don't need the unnecessary self.inputs layer and the tf.debugging.assert_shapes statements, as they are not necessary in this context. Also I properly instantiated the self.common layer with the __init__ method.

    Hope it helps!