Home > Enterprise >  fit() method returns ValueError when using Keras subclassing API
fit() method returns ValueError when using Keras subclassing API

Time:04-19

I am trying to tidy up my code by moving from the Keras functional API to the subclassing API. The class I came up with so far is below:

class FeedForwardNN(Model):
    def __init__(self, params):

        super().__init__()
        self.params = params
        self.layout = params['layout']

        # Define layers
        self.dense = Dense(units=params['layout'][1],
                           activation=params['activation'],
                           kernel_initializer=params['initializer'])
        
        self.output_layer = Dense(units=params['layout'][-1],
                            kernel_initializer=params['initializer'])
        
        self.dropout = Dropout(params['dropout'])
        self.batch_norm = BatchNormalization()
    
    def call(self, x):

        for layer in self.layout[1:-1]:
            x = self.dropout(self.dense(x))

            if self.params['batch_norm']:
                x = self.batch_norm(x)
        
        x = self.output_layer(x)
        
        return x

Where layout is a list of the neurons in each layer (including input and output layers).

However, when fitting the model, the following error is raised:

        ValueError: Input 0 of layer "dense" is incompatible with the layer: expected axis -1 of input shape to have value 5, but received input with shape (None, 100)
    
    
    Call arguments received:
      • x=tf.Tensor(shape=(None, 5), dtype=float32)

which seems to occur on the line:

x = self.dropout(self.dense(x))

I checked the shape of the training data X that is passed to the fit() method, and it appears to have the right shape i.e. (number of observations, number of predictors).

Does anyone have an idea of where my mistake is?

CodePudding user response:

The problem is that you are using same self.dense layer over and over again in your for loops

for layer in self.layout[1:-1]:
    x = self.dropout(self.dense(x))

After the first loop, x has shape (batch, 100). Then in the second loop, instead of passing this x to the second Dense layer (which you don't seem to have created in the first place), you re-pass it to the first Dense layer, which expects shape (batch, 5), causing the error.

You can create a list of dense layer as follows in __init__

self.denses = [Dense(units=self.layout[i],
                   activation=params['activation'],
                   kernel_initializer=params['initializer']) for i in self.layout[1:-1]]

and call them in sequence

for dense_layer in self.denses:
    x = self.dropout(dense_layer(x))
  • Related