Dimension mismatch in keras - python

I was trying to run a 10 fold cross validation on my dataset.I had reshaped my data before training as follows
data = data.reshape(500,1,1028,1)
data_y = np_utils.to_categorical(data_y, 3)
After this i described my model
for train,test in kf.split(data):
fold+=1
print("Fold #{}".format(fold))
x_train = data[train]
y_train = data_y[train]
x_test = data[test]
y_test = data_y[test]
print(x_train.shape)
model.add(Conv2D(32, (1, 3),input_shape=(1,1028,1)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
#model.add(MaxPooling2D(pool_size=(1,2)))
model.add(Conv2D(34, (1, 4)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(1,2)))
model.add(Conv2D(64,(1, 3)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
#model.add(MaxPooling2D(pool_size=(1,2)))
model.add(Conv2D(64, (1, 4)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(1,2)))
model.add(Flatten())
#fully connected for new model
model.add(Dense(550))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(250))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(100))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(25))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(3))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])
model.fit(x_train.reshape(450,1,1028,1), y_train,
batch_size=5,
epochs=1,
verbose=1,
validation_data=(x_test, y_test))
pred = model.predict(x_test)
oos_y.append(y_test)
pred = np.argmax(pred, axis=1) # raw probabilities to chosen class (highest probability)
oos_pred.append(pred)
# Measure this fold's accuracy
y_compare = np.argmax(y_test, axis=1) # For accuracy calculation
score = metrics.accuracy_score(y_compare, pred)
print("Fold score (accuracy): {}".format(score))
The problem is that when I run my code the code runs properly for fold 1 but for fold 2 it gives me the following error
ValueError: Input 0 is incompatible with layer conv2d_5: expected ndim=4, found ndim=2
When I checked the dimensions of x_train it was (450, 1, 1028, 1)
I am not sure what the error is.

You are adding model layers inside loop over and over. The error was produced when you try to add convolutional layer(for second iteration of loop) after softmax activation layer(the last layer for first iteration of the loop). After careful inspection I've come to the following solution to your question.
First split the dataset into train and test
for train_index, test_index in kf.split(data):
X_train, X_test = data[train_index], data[test_index]
y_train, y_test = data_y[train_index], data_y[test_index]
then add layers to model outside of the loop.
model.add(Conv2D(32, (1, 3),input_shape=(1,1028,1)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
#model.add(MaxPooling2D(pool_size=(1,2)))
model.add(Conv2D(34, (1, 4)))
model.add(BatchNormalization(axis=-1))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(1,2)))
# ... The reset of the code

Related

keras face recognition accuracy not going above 50%

I'm pretty new to deep learning and i'm trying to make a face recognizer for anime faces. This is my current code
CNN
model = Sequential()
model.add(Convolution2D(32, 3, 3, padding='same', input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3, padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), padding='same'))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, padding='same'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3, padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), padding='same'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes, activation='sigmoid'))
return model
Training CNN
def run():
(X_train, y_train), (X_test, y_test) = datasets.load_data(img_rows=32, img_cols=32)
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
model = CNN(input_shape=X_train.shape[1:], nb_classes=nb_classes)
csv_logger = CSVLogger('../log/cnn.log')
model.compile(loss='categorical_crossentropy', optimizer = 'rmsprop', metrics=['accuracy'])
X_test = preprocess_input(X_test)
checkpointer = ModelCheckpoint(filepath="../resources/weights.hdf5", monitor="val_accuracy", verbose=1, save_best_only=True)
datagen = ImageDataGenerator(
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=0,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True,
vertical_flip=False ,
preprocessing_function=preprocess_input
)
datagen.fit(X_train)
history = model.fit(
datagen.flow(X_train, Y_train, batch_size=batch_size),
steps_per_epoch= round(X_train.shape[0] / batch_size),
epochs=nb_epoch,
validation_data=(X_test, Y_test),
callbacks=[csv_logger, checkpointer], batch_size=batch_size
)
With this I don't go above 50% accuracy sometimes not even 10%
When i change the CNN to this, the accuracy goes to 65% and doesn't increase further
model = Sequential()
model.add(Convolution2D(32, 3, 3, padding='same', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2), padding='same'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes, activation='sigmoid')
return model
How would i improve this to get atleast 90% accuracy
More Info over the Model
nb_epoch = 200
batch size = 10
nb_classes = 83
The dataset in total has around 3000 files.

My Input shape is correct but I stil l get the following err.: Input 0 of layer sequential is incompatible with the layer: : expected min_ndim=4,

This is my model:
def make_model():
model = Sequential()
model.add(Conv2D(kernel_size=(3, 3), filters=16, input_shape=(32, 32,1), padding='same'))
model.add(LeakyReLU(0.1))
model.add(Conv2D(kernel_size=(3, 3), filters=32, padding='same'))
model.add(LeakyReLU(0.1))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(kernel_size=(3, 3), filters=32, padding='same'))
model.add(LeakyReLU(0.1))
model.add(Conv2D(kernel_size=(3, 3), filters=64, padding='same'))
model.add(LeakyReLU(0.1))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256))
model.add(LeakyReLU(0.1))
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))
return model
Compile part:
INIT_LR = 5e-3 # initial learning rate
BATCH_SIZE = 32
EPOCHS = 10
from tensorflow.keras import backend as K
K.clear_session()
model = make_model()
model.compile(
loss='categorical_crossentropy', # we train 10-way classification
optimizer=tf.keras.optimizers.Adamax(lr=INIT_LR), # for SGD
metrics=['accuracy'] # report accuracy during training
)
def lr_scheduler(epoch):
return INIT_LR * 0.9 ** epoch
# callback for printing of actual learning rate used by optimizer
class LrHistory(keras.callbacks.Callback):
def on_epoch_begin(self, epoch, logs={}):
print("Learning rate:", K.get_value(model.optimizer.lr))
Fitting:
model.fit(
X_train.reshape(-1, 32, 32, 1), y_train, # prepared data
batch_size=BATCH_SIZE,
epochs=EPOCHS,
callbacks=[keras.callbacks.LearningRateScheduler(lr_scheduler),
LrHistory(),
tfa.callbacks.TQDMProgressBar() ],
validation_data=(X_test, y_test),
shuffle=True,
verbose=0,
initial_epoch=None or 0
)
My Data_trainX shape:
My Data_trainy shape
My input shape is compatible with models Conv2D layer's input shape.
I've looked at other questions about this applied those solutions, but it didn't work.
It seems everything correct to me. Where am I doing wrong?
While you are reshaping the training data X_train to fit the model specifications, you are not doing this with the validation data X_test.
Reshape X_test as well and it should work fine:
model.fit(
X_train.reshape(-1, 32, 32, 1), y_train,
...
validation_data=(X_test.reshape(-1, 32, 32, 1), y_test), # <-- apply changes here
...
)

InvalidArgumentError while using Tensorboard

I was trying to use tensorboard to look at my model. But I get an InvalidArgumentError.
model = Sequential()
model.add(Conv2D(256, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(256, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.summary()
model.fit(x = X_train,
y = y_train,
epochs = 10,
validation_split = 0.1,
callbacks=[tensorboard_callback])
When I remove the callbacks=[tensorboard_callback] the model trains fine but when I include it, it spits out the following error.
InvalidArgumentError: You must feed a value for placeholder tensor 'conv2d_input' with dtype float and shape [?,50,50,1]
[[{{node conv2d_input}}]]

Replace MLP with CNN

I have built up a NN with following architecture:
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
print(X_train.shape, X_test.shape, Y_train.shape, Y_test.shape)
(1901, 456, 3) (476, 456, 3) (1901, 3, 3) (476, 3, 3)
model = Sequential()
model.add(Flatten(input_shape=(456,3)))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(3 * 3))
model.add(Reshape((3, 3)))
model.compile('adam', 'mse')
history = model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=100)
Now I want to replace this architecture with a analogue CNN which does the same; but when trying to implement this I always get problems with the dimensions of the different layers. And my error is always like this
ValueError: Error when checking input: expected conv2d_3_input to have 4 dimensions, but got array with shape (x, x, x)
the dataset remains the same, just the NN architecture changes and this is my first approach:
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=(1901,456,3)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3, activation='softmax'))
Can someone help me out to replace my first NN into a CNN?
Your network is well defined, the error you're getting is during the fit operation. And why is that the case.
Well Conv2D is looking for data with 4D shape as you can see here : doc
X_train shape must then be (samples, channels, rows, cols)
When you gave input_shape=(1901,456,3), you didn't have to specify the number of samples.
But during the fit operation you need to have a data shaped as (samples, channels, rows, cols) .
And now you see that you have a problem. Why is your X_train shaped like that, it seems that you only have one image. You can feed it by reshaping it using :
X_train = X_train.reshape((1, 1901, 456, 3))
But that seems odd, you're only feeding one image to your network.
Edit : after clarification on the comments, conv1D will be better in this type of case, here is how to do it:
model = Sequential()
model.add(Conv1D(32, kernel_size=3,
activation='relu',
input_shape=(456,3)))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(3 * 3, activation='softmax'))
model.add(Reshape((3, 3))
now everything worked with the architecture and there is also no problem when compiling the NN;
batch_size = 128
epochs = 12
model.compile(
optimizer='rmsprop',
loss=tf.keras.losses.MeanSquaredError(),
metrics=['mse'],
)
model.fit(X_test, Y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, verbose=0)
but when trying to fit I get following error :
ValueError: Input arrays should have the same number of samples as target
arrays. Found 476 input samples and 1901 target samples.
what am I missing here?

Unable to perform regression on CNN

I'm using Keras to build a a convolutional neural network which takes images with the shape (200, 200, 3) and should output a number representing the predicted amount of likes this image would get on social media. y_train and y_test are dimensional vectors. Here is my code so far:
model = Sequential()
model.add(Conv2D(10, 1, 1, input_shape=(200, 200, 3)))
model.add(Activation('relu'))
model.add(Conv2D(10, 1, 1))
model.add(Activation('relu'))
model.add(MaxPool2D())
# model.add(Flatten())
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(x_train, y_train)
score = model.evaluate(x_test, y_test)
I'm getting an error saying
expected activation_2 to have 4 dimensions, but got array with shape
(7, 1)
Where (7, 1) is the shape of y_train. Why is this happening?
Since you are using a fixed size input images, you can add fully connected layers
Categorical cross entropy is a function to compare probabilistic distributions (i.e.for classification problems not regression), you can use Mean Squared Error loss function instead.
Here is a sample code:
model = Sequential()
model.add(Conv2D(10, 1, 1, input_shape=(200, 200, 3)))
model.add(Activation('relu'))
model.add(Conv2D(10, 1, 1))
model.add(Activation('relu'))
model.add(MaxPooling2D())
model.add(Flatten())
model.add(Dense(50))
model.add(Activation('relu'))
model.add(Dense(1))
model.compile(loss='mse',optimizer='rmsprop')
model.fit(x_train, y_train)
test_mse = model.evaluate(x_test, y_test)
print('test set mse is {}'.format(test_mse))

Categories