DragonKeeper
DragonKeeper

Reputation: 13

Keras Error: Please provide data which shares the same first dimension

I try to use a customize layer in keras. It's a simple layer just a matmul with trainable params.

from tensorflow import keras
import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input
from tensorflow.keras.optimizers import RMSprop
from keras.layers import Layer
from tensorflow.keras import backend as K

class MultiLayer(Layer):
    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MultiLayer, self).__init__(**kwargs)
    def build(self, input_shape):
        # Create a trainable weight variable for this layer
        if self.output_dim[0] != input_shape[1]:
            raise Exception("expect input shape with [{},?], but get input with shape {}".format(self.output_dim[0],input_shape), input_shape)
        self.kernel = self.add_weight(name='kernel', 
                                      shape=(input_shape[2], self.output_dim[0]),
                                      initializer='uniform',
                                      trainable=True)
        super(MultiLayer, self).build(input_shape)  # Be sure to call this at the end
    def call(self, x):
        return K.dot(x, self.kernel)
    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

x_fake = np.random.random((10,28,28))
y_fake = [np.diag(np.ones(28))]*10
input_shape = np.shape(x_fake)[1:]
print(input_shape)
ipt = Input(name='inputs',shape=input_shape)
layer = MultiLayer((input_shape[0],input_shape[0]),name="dev")(ipt)
#layer = Flatten()(layer)
model = Model(inputs=ipt,outputs=layer)
model.summary()
rms = RMSprop()
model.compile(loss="rms", optimizer=rms, metrics=['accuracy'])
model.fit(x_fake,y_fake)

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
inputs (InputLayer)          [(None, 28, 28)]          0         
_________________________________________________________________
dev (MultiLayer)             (None, 28, 28)            784       
=================================================================
Total params: 784
Trainable params: 784
Non-trainable params: 0
_________________________________________________________________

but when I fit this model, error occurs.

ValueError: Data cardinality is ambiguous:
  x sizes: 10
  y sizes: 28, 28, 28, 28, 28, 28, 28, 28, 28, 28

Please provide data which shares the same first dimension.

I don't know what the sizes mean.

How to fix it?

Upvotes: 0

Views: 5423

Answers (1)

OverLordGoldDragon
OverLordGoldDragon

Reputation: 19806

model.output_shape must match y_fake.shape; your [np.diag(np.ones((28,28)))]*10 is a list of 10 arrays, each of shape (28, 28), so TF thinks you have 10 outputs. I presume you intended np.stack(... * 10).

Next, ensure all imports are consistent (either from tensorflow.keras or from keras). Lastly, "rms" isn't a supported loss, I replaced it with "mse". All fixes below.


import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.layers import Layer
from tensorflow.keras import backend as K

class MultiLayer(Layer):
    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MultiLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer
        if self.output_dim[0] != input_shape[1]:
            raise Exception(("expect input shape with [{},?], but get input with "
                             "shape {}").format(self.output_dim[0],input_shape),
                            input_shape)
        self.kernel = self.add_weight(name='kernel',
                                      shape=(input_shape[2], self.output_dim[0]),
                                      initializer='uniform',
                                      trainable=True)
        super(MultiLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return K.dot(x, self.kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

x_fake = np.random.random((10,28,28))
y_fake = np.stack([np.diag(np.ones((28)))]*10)  # (10, 28, 28)
input_shape = np.shape(x_fake)[1:]
print(input_shape)

ipt = Input(name='inputs', shape=input_shape)
layer = MultiLayer((input_shape[0],input_shape[0]),name="dev")(ipt)
model = Model(inputs=ipt, outputs=layer)

model.summary()
rms = RMSprop()
model.compile(loss="mse", optimizer=rms, metrics=['accuracy'])

model.fit(x_fake, y_fake)

Upvotes: 1

Related Questions