Tensoflow Model.fit adds extra dimension when training with custom model

Viewed 66

I made this colab so that you can play around with the code.

tldr; The shape of my x_data is (# of examples, 12, 1, 100, 1 ) and when the data is passed to the model, the shape of each example becomes (None, 12, 1, 100, 1 ). How do I get rid of the None?


I'm trying to train a series of examples with the following data structure:

import numpy as np

x_train = np.reshape(np.random.rand(200, 12, 100),(200, 12, 1, 100, 1)) #X training data (see dimensions in output)
y_train =  np.random.rand(200, 20) #Y training data (see dimensions in output)
n_class = np.shape(y_train)[1] #Number of classes in the classification task

print(np.shape(x_train))
print(np.shape(y_train))
____________
(200, 12, 1, 100, 1)
(200, 20)

x_train dimensions explained:

  • There are 200 examples. Each x_train example has a corresponding y_train example with a one-hot encoded 20 dim vector representing the class it belongs to.

  • Each example contains 12-time series. Each time series is 100 units long and we want to convolve over them separately.

  • We have shaped each time series as (1, 100, 1) because of the Conv1D keras documentation.

  • As per the link above, the input dimensions should be: (batch_size, (steps, input_dim))

    batch_size = 1, steps = 100, input_dim = 1

The model is as follows (it can also be found in the colab):

def custom_model(x_data, n_class):
    """
    This is the custom model used to convolve over the data
    We want to convolve over each dimension independently
    """
    conv_inputs = []
    conv_outputs = []
    amount_of_filters = np.shape(x_data[0])[0] 
    # Let's create a separate convolution channel for each one of the dims in x_data
    for i in range(amount_of_filters):
        x0 = keras.Input(batch_shape=(1, 100, 1))
        # conv_inputs will therefore have a size of (12, 1, 100, 1)
        conv_inputs.append(x0)
        x0 = Conv1D(filters=20,kernel_size=10,strides=2,padding="same",data_format="channels_last")(x0)
        x0 = MaxPool1D(pool_size=6, data_format="channels_last")(x0)
        x0 = Conv1D(filters=20, kernel_size=4, padding="same", data_format="channels_last")(x0)
        x0 = MaxPool1D(pool_size=3, data_format="channels_last", padding="same")(x0)
        x0 = Flatten()(x0)
        x0 = Dense(100, activation="relu")(x0)
        x0 = Dropout(0.2)(x0)
        x0 = Dense(10, activation="relu")(x0)
        conv_outputs.append(x0)
    # Convolving all outputs from the above convolutions. 
    x1 = concatenate(conv_outputs)
    x1 = Dense(100, activation="relu")(x1)
    x1 = Dense(100, activation="relu")(x1)
    out = Dense(n_class)(x1)

    modelConv = keras.Model(inputs=conv_inputs, outputs=out)

    return modelConv

When running the model:

model = custom_model(x_train, n_class)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
history = model.fit(x_train, y_train, epochs=250, verbose=1, shuffle=True)

The following error comes up:

ValueError: Layer model expects 12 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, 12, 1, 100, 1) dtype=float32>]

You can see that the input shape is (None, 12, 1, 100, 1 ). How do I get rid of the None? As shown above, when printing the shape of x_train, the None dimension does not appear. My question is how do I feed in the x_data with each example being (12, 1, 100, 1) dimensional?

Thank you!

0 Answers
Related