首页 > 解决方案 > 使用具有多个输入的自定义 rnn 单元格的正确方法

问题描述

我正在尝试创建一个循环神经网络模型的自定义单元,其中单元接受 2 个张量作为输入。然后将 rnn 层链接到密集层。当我使用第二个输入来计算输出时,就会出现问题。事实上,如果我使用第二个输入来计算输出,我会得到错误

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]

而当我不使用它时,训练继续进行,没有任何错误。如何进行?

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

现在我调用模型

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=300,
                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)

调用方法中的形状

inside call method
w_in shape (2500, 300)
w_bias shape (300,)
w_rnn shape (2500, 300)
y_part shape (2500, 300)
inside call method
w_in shape (2500, 300)
w_bias shape (300,)
w_rnn shape (2500, 300)
y_part shape (2500, 300)

Epoch 1/10

inside call method
w_in shape (None, 300)
w_bias shape (300,)
w_rnn shape (None, 300)
y_part shape (None, 300)
inside call method
w_in shape (None, 300)
w_bias shape (300,)
w_rnn shape (None, 300)
y_part shape (None, 300)
inside call method
w_in shape (None, 300)
w_bias shape (300,)
w_rnn shape (None, 300)
y_part shape (None, 300)
inside call method
w_in shape (None, 300)
w_bias shape (300,)
w_rnn shape (None, 300)
y_part shape (None, 300)

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

所以我以最简单的方式创建了一个 colab 文件,试图在其他数据集上重现相同的错误,这是链接 https://colab.research.google.com/drive/1QbOk6c7ulo89n8gJ1hFBMtpDDkuDEJ_Z?usp=sharing

我从这里挑选了数据集https://colab.research.google.com/github/DJCordhose/ml-workshop/blob/master/notebooks/tf2/time-series-rnn-full-predict.ipynb#scrollTo=8xcZIPH- gqJC并应用了一个简单的自定义 rnn 单元来重现相同的错误

标签: tensorflowlstmrecurrent-neural-networkfunctional-api

解决方案


推荐阅读