Search code examples
python-3.xkerasdeep-learningconv-neural-networkdimension

Keras CNN's input dimension error: expected 4-dim, but found 3-dim


I have a question about coding CNN using Keras.

The shape of input data(adj) is (20000, 50, 50); 20000 is the number of samples, 50 x 50 are 2-D data (like images). Batch size is 100. (actually, there are two inputs: adj=(20000, 50, 50), features=(20000, 50, 52).

The issued part is like below:

from keras.layers import Conv2D, MaxPool2D, Flatten

adj_visible1 = Input(shape=(50, 50, 1))
conv11 = Conv2D(16, kernel_size=5, activation='relu')(adj_visible1)
pool11 = MaxPool2D(pool_size=(2, 2))(conv11)
conv12 = Conv2D(8, kernel_size=5, activation='relu')(pool11)
pool12 = MaxPool2D(pool_size=(2, 2))(conv12)
flat1 = Flatten()(pool12)

But an error message occurred like below:

ValueError: Input 0 is incompatible with layer conv2d_1: expected ndim=4, found ndim=3

I found similar cases that print the same message, however, most of the reason is that they didn't consider the filter like (50, 50), not (50, 50, "1") for input shape.

In my case, I used the shape (50, 50, 1) not (50, 50). However, it still prints the same error message.

What should I do?

I'm attaching the full code as follows:

from sklearn.cross_validation import train_test_split
from keras.models import Sequential
from keras.layers.core import Dense, Dropout
from keras.optimizers import RMSprop, Adam, Adadelta
from keras.utils import plot_model
from keras.models import Model
from keras.layers import Input, Flatten, MaxPool2D
from keras.layers.convolutional import Conv2D
from keras.layers.merge import concatenate
from keras.callbacks import CSVLogger

#Settings
epoch = 100
batch_size = 100
test_size = 10000

# Load data
adj = np.load('adj.npy')   #(20000, 50, 50)
features = np.load('features.npy')    #(20000, 50, 52)
Prop = np.load('Properties.npy')     #(20000, 1)

database = np.dstack((adj, features))    #(20000, 50, 102)


#Train/Test split
X_tr, X_te, Y_tr, Y_te = train_test_split(database, Prop, test_size=test_size)

X_tr_adj, X_tr_features = X_tr[:, :, 0:50], X_tr[:, :, 50:]
X_te_adj, X_te_features = X_te[:, :, 0:50], X_te[:, :, 50:]


def create_model():

    # first input model
    adj_visible1 = Input(shape=(50, 50, 1))
    conv11 = Conv2D(16, kernel_size=5, activation='relu')(adj_visible1)
    pool11 = MaxPool2D(pool_size=(2, 2))(conv11)
    conv12 = Conv2D(8, kernel_size=5, activation='relu')(pool11)
    pool12 = MaxPool2D(pool_size=(2, 2))(conv12)
    flat1 = Flatten()(pool12)

    # second input model
    features_visible2 = Input(shape=(50, 52, 1))
    conv21 = Conv2D(16, kernel_size=5, activation='relu')(features_visible2)
    pool21 = MaxPool2D(pool_size=(2, 2))(conv21)
    conv22 = Conv2D(8, kernel_size=5, activation='relu')(pool21)
    pool22 = MaxPool2D(pool_size=(2, 2))(conv22)
    flat2 = Flatten()(pool22)

    # merge input models
    merge = concatenate([flat1, flat2])

    # interpretation model
    hidden1 = Dense(128, activation='relu')(merge)
    hidden2 = Dense(32, activation='relu')(hidden1)
    output = Dense(1, activation='linear')(hidden2)
    model = Model(inputs=[adj_visible1, features_visible2], outputs=output)
    model.compile(loss='mean_squared_error', optimizer=Adam())
    # summarize layers
    print(model.summary())

    return model

def train_model(batch_size = 100, nb_epoch = 20):
    model = create_model()
    csv_logger = CSVLogger('CNN trial.csv')
    history = model.fit([X_tr_adj, X_tr_features], Y_tr,
                        batch_size=batch_size,
                        epochs=nb_epoch,
                        verbose=1,
                        validation_data=([X_te_adj, X_te_features], Y_te),
                        callbacks=[csv_logger])

    predictions_valid = model.predict(X_te_adj, X_te_features, batch_size=batch_size, verbose=1)

    return model

train_model(nb_epoch = epoch)

I wrote the code with reference to the following material: https://machinelearningmastery.com/keras-functional-api-deep-learning/


Solution

  • You have to use conv1D and MaxPool1D instead of conv2D and MaxPool2D cause your dataset is a single-channel image instead of 3 channel image. In conv1D layer expect the input to be in format Batch X Height X Width, while in conv2D it expects the input to dimension = 4 i.e Batch X Height X Width X Channels.

    from sklearn.model_selection import train_test_split
    from keras.models import Sequential
    from keras.layers.core import Dense, Dropout
    from keras.optimizers import RMSprop, Adam, Adadelta
    from keras.utils import plot_model
    from keras.models import Model
    from keras.layers import Input, Flatten, MaxPool1D
    from keras.layers.convolutional import Conv1D
    from keras.layers.merge import concatenate
    from keras.callbacks import CSVLogger
    import numpy as np
    epoch = 100
    batch_size = 100
    test_size = 10000
    
    
    adj = np.random.randint(0,high=100, size=(20000, 50, 50))      #(20000, 50, 50)
    features = np.random.randint(0,high=100, size=(20000, 50, 52))    #(20000, 50, 52)
    Prop = np.random.randint(0,high=100, size=(20000,))     #(20000, 1)
    
    database = np.dstack((adj, features))    #(20000, 50, 102)
    
    print( " shape of database :", database.shape)
    
    
    t
    X_tr, X_te, Y_tr, Y_te = train_test_split(database, Prop, test_size=test_size)
    
    X_tr_adj, X_tr_features = X_tr[:, :, 0:50], X_tr[:, :, 50:]
    X_te_adj, X_te_features = X_te[:, :, 0:50], X_te[:, :, 50:]
    
    
    def create_model():
    
        # first input model
        adj_visible1 = Input(shape=(50, 50))
        conv11 = Conv1D(16, kernel_size=5, activation='relu')(adj_visible1)
        pool11 = MaxPool1D(pool_size=2)(conv11)
        conv12 = Conv1D(8, kernel_size=5, activation='relu')(pool11)
        pool12 = MaxPool1D(pool_size=2)(conv12)
        flat1 = Flatten()(pool12)
    
        # second input model
        features_visible2 = Input(shape=(50, 52))
        conv21 = Conv1D(16, kernel_size=5, activation='relu')(features_visible2)
        pool21 = MaxPool1D(pool_size=2)(conv21)
        conv22 = Conv1D(8, kernel_size=5, activation='relu')(pool21)
        pool22 = MaxPool1D(pool_size=2)(conv22)
        flat2 = Flatten()(pool22)
    
        # merge input models
        merge = concatenate([flat1, flat2])
    
        # interpretation model
        hidden1 = Dense(128, activation='relu')(merge)
        hidden2 = Dense(32, activation='relu')(hidden1)
        output = Dense(1, activation='linear')(hidden2)
        model = Model(inputs=[adj_visible1, features_visible2], outputs=output)
        model.compile(loss='mean_squared_error', optimizer=Adam())
        # summarize layers
        print(model.summary())
    
        return model
    
    def train_model(batch_size = 100, nb_epoch = 20):
        model = create_model()
        csv_logger = CSVLogger('CNN trial.csv')
        history = model.fit([X_tr_adj, X_tr_features], Y_tr,
                            batch_size=batch_size,
                            epochs=nb_epoch,
                            verbose=1,
                            validation_data=([X_te_adj, X_te_features], Y_te),
                            callbacks=[csv_logger])
    
        return model
    
    train_model(nb_epoch = 10)