简体   繁体   中英

How to fix validation_data getting passed into input_1 argument in model.fit_generator?

I'm trying write a hybrid model on the functional API with multiple inputs. The problem is when training the model I get the ValueError after one epoch:

ValueError: Error when checking input: expected input_1 to have shape (168, 5) but got array with shape (5808, 5)

What I'm confused is that is that how did the validation_data (shape (5808,5)) get passed to the input_1 (shape (168,5)) argument in the model.fit_generator?

I've rollbacked to a sequential model to see and confirm if this problem exists, but it trains just fine.

This is the model fit func:

%%time
model.fit_generator(generator=generator,
                    epochs=10,
                    steps_per_epoch=30,
                    validation_data=validation_data,
                    callbacks=callbacks)

Its the same as in the sequential data case which works.

The model itself:

# first input model
input_1 = Input(shape=((168,5)))
dense_1 = Dense(50)(input_1)

# second input model
input_2 = Input(shape=((168,7)))
lstm_1 = LSTM(units=64, return_sequences=True, input_shape=(None, 7,))(input_2)

# merge input models
merge = concatenate([dense_1, lstm_1])
output = Dense(num_y_signals, activation='sigmoid')(merge)
model = Model(inputs=[input_1, input_2], outputs=output)
# summarize layers
print(model.summary())

The model summary:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 168, 5)]     0                                            
__________________________________________________________________________________________________
input_2 (InputLayer)            [(None, 168, 7)]     0                                            
__________________________________________________________________________________________________
dense (Dense)                   (None, 168, 50)      300         input_1[0][0]                    
__________________________________________________________________________________________________
lstm (LSTM)                     (None, 168, 64)      18432       input_2[0][0]                    
__________________________________________________________________________________________________
concatenate (Concatenate)       (None, 168, 114)     0           dense[0][0]                      
                                                                 lstm[0][0]                       
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 168, 1)       115         concatenate[0][0]                
==================================================================================================

The validation data:

validation_data = ([np.expand_dims(x_test1_scaled, axis=0),
                    np.expand_dims(x_test2_scaled, axis=0)],
                   np.expand_dims(y_test_scaled, axis=0))

Note that I do have to pass the entire test data which has 5808 observations.

data_generator

def batch_generator(batch_size, sequence_length):
    """
    Generator function for creating random batches of training-data.
    """

    # Infinite loop.
    while True:
        # Allocate a new array for the batch of input-signals.
        x_shape = (batch_size, sequence_length, num_x_signals)
        x_batch = np.zeros(shape=x_shape, dtype=np.float16)

        # Allocate a new array for the batch of output-signals.
        y_shape = (batch_size, sequence_length, num_y_signals)
        y_batch = np.zeros(shape=y_shape, dtype=np.float16)

        # Fill the batch with random sequences of data.
        for i in range(batch_size):
            # Get a random start-index.
            # This points somewhere into the training-data.
            idx = np.random.randint(num_train - sequence_length)

            # Copy the sequences of data starting at this index.
            x_batch[i] = x_train_scaled[idx:idx+sequence_length]
            y_batch[i] = y_train_scaled[idx:idx+sequence_length]

        x_batch_1 = x_batch[ :, :, 0:5]
        x_batch_2 = x_batch[ :, :, 5:12]
        yield ([x_batch_1, x_batch_2], y_batch)
batch_size = 32
sequence_length = 24 * 7
generator = batch_generator(batch_size=batch_size,
                            sequence_length=sequence_length)

https://github.com/Joichiro666/depo/blob/master/LSTM-DNN%20Problem.ipynb

I expect that the validation_data gets passed to the validation_data argument, not the input_1.

When you are doing a fit with some validation_data , this validation data will do a forward pass in the network (that's why validation is passed at some point through input_1 ). Therefore it must fit the requirements of your model, in which you specified that the input data must have a shape of (168, 5) , which in numpy arrays is going to be (batch_size, 168, 5) . I think you may have been confused a bit and added the batch_size in the input shape of your network (I can tell not only by your question but also because you are applying a dense layer on a 2D input). In keras you don't need to do that, you should just specify the shape on an instance basis. I think if you do that you won't have to expand the dimensions of your inputs anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM