#StackBounty: #tensorflow #lstm #recurrent-neural-network #functional-api Correct way to use custom rnn cells with multiple inputs

Bounty: 100

I’m trying to create a custom cell of a recurrent neural network model where the cell accepts 2 tensors as input. The rnn layer is then linked to a dense layer. The problems occurs when I use the second input to calculate the output. In fact if I use the second input to calculate the output I get the error

InvalidArgumentError:  Trying to access element 10 in a list with 10 elements.
     [[{{node my_model/rnn/while/body/_1/my_model/rnn/while/TensorArrayV2Read_1/TensorListGetItem}}]] [Op:__inference_train_function_972]

while when I don’t use it the training continues without any errors. How to proceed?

class MyCell(keras.layers.Layer):
    def __init__():
        #other stuff
        
        self.scaling = 1.
        self.use_y = True
        super().__init__(**kwargs)

    def build(self, input_shape):
        #other stuff
        
        self.W_y = tf.random.uniform(shape=[input_shape[1][-1], self.units], minval=-1, maxval=1) *self.scaling
        self.bias = tf.random.uniform(shape=(self.units,), minval=-1, maxval=1, name="bias") * self.scaling

        self.built = True
        
    def call(self, inputs, states):
        prev_output = states[0]
        w_in = tf.matmul(inputs[0], self.kernel)
        w_rnn = tf.matmul(prev_output, self.rnn_kernel)
        
        if self.use_y:
            #if I calculate the output this way I get the error during the fit, the build method works well
            y_part = tf.matmul(inputs[1], self.W_y)
            output = prev_output + tf.nn.tanh(w_in + self.bias + w_rnn + y_part)
            print("inside call method")
            print("w_in shape", self.w_in.shape)
            print("w_bias shape", self.bias.shape)
            print("w_rnn shape", self.w_rnn.shape)
            print("y_part shape", y_part.shape)
        else:
            #if I calculate the ouput I get no error and the fit continues
            output = prev_output + tf.nn.tanh(w_in + self.bias + w_rnn)
        return output, [output]


class MyModel(keras.Model):
    def __init__(units=100,
                 x_train=None,
                 y_train=None,
                 **kwargs):
        super().__init__(**kwargs)
        
        #other stuff
        
        
        self.units = units
        
        self.x_input = tf.keras.layers.Input(shape=x_train.shape, name="x_train")
        self.y_input = tf.keras.layers.Input(shape=y_train.shape, name="y_train_teacher")
        self.rnn = tf.keras.layers.RNN(cell=MyCell())
        
    

        self.out = Sequential()
        self.out.add(tf.keras.layers.Dense(10))
        self.out.compile(loss="mse", optimizer="adam")

    def call(self, inputs):
        input_x = inputs[0]
        input_y = inputs[1]
        r = self.rnn((input_x, input_y))
        y = self.out(r)
        return y

Now I call the model

x_train, x_valid, y_train, y_valid = train_test_split(X_train,y_train,test_size=0.2,random_state=67)

#x_train.shape -> [2500, 250, 25][n_samples, n_timestep, n_features]
#y_train.shape -> [2500, 1][n_samples, n_timestep] 

#adds a dimensions since lstm wants 3d arryas
y_train_t = y_train.reshape(y_train.shape[0], y_train.shape[1], 1)
y_valid_t = y_valid.reshape(y_valid.shape[0], y_valid.shape[1], 1) 
  
model = MyModel(units=100,
                x_train = x_train,
                y_train = y_train_t,
                )
  
model.build(input_shape=[(x_train.shape), (y_train_t.shape)])

model.compile(loss="mse", optimizer='adam')
history = model.fit((x_train,y_train_t),
        y_train,
        validation_data=((x_valid, y_valid_t), y_valid),
        epochs=10,
        verbose=1)

Shapes inside call method

inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (2500, 300)
inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (2500, 300)
Epoch 1/10
inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (None, 300)
inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (None, 300)
inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (None, 300)
inside call method
w_in shape (25, 300)
w_bias shape (300,)
w_rnn shape (300, 300)
y_part shape (None, 300)

#and then the InvalidArgumentError
#I noticed sometime is Trying to access element 10 in a list with 10 elements.
#sometimes is Trying to access element 31 in a list with 10 elements.


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.