I have been given a task to implement a Convolutional neural network that can evaluate hand-written digits found in the MNIST dataset with the architecture of the network looking like this:
I have implemented a CNN that matches the architecture, unfortunately it only has about a 10% accuracy to it. I've looked online and tried other example CNNs to make sure if anything else causing the issue, however they seem to work fine and give me a ~99% accuracy. I've placed both CNNs in my code and made a boolean switch to show the difference between the two:
import tensorflow
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
batch_size = 128
num_classes = 10
epochs = 1
img_rows, img_cols = 28, 28
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
y_train = tensorflow.keras.utils.to_categorical(y_train, num_classes)
y_test = tensorflow.keras.utils.to_categorical(y_test, num_classes)
exampleModel = False # Use to toggle which CNN goes into the model
if exampleModel: # An example CNN that I found for MNIST
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
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(num_classes, activation='softmax'))
else: # The CNN I created
input_layer = tensorflow.keras.layers.Input(shape=input_shape)
conv1 = Conv2D(32, (1, 1), activation='relu')(input_layer)
pool1 = MaxPooling2D(2, 2)(conv1)
conv2_1 = Conv2D(64, (1, 1), activation='relu', padding='same')(pool1)
pool2_1 = MaxPooling2D(2, 2)(conv2_1)
drop2_1 = Dropout(0.5)(pool2_1)
conv2_2 = Conv2D(64, (1, 1), activation='relu', padding='same')(pool1)
pool2_2 = MaxPooling2D(2, 2)(conv2_2)
drop2_2 = Dropout(0.5)(pool2_2)
conv3_1 = Conv2D(256, (1, 1), activation='relu', padding='same')(drop2_1)
conv3_2 = Conv2D(256, (1, 1), activation='relu', padding='same')(drop2_2)
merged = tensorflow.keras.layers.concatenate([conv3_1, conv3_2], axis=-1)
merged = Dropout(0.5)(merged)
merged = Flatten()(merged)
fc1 = Dense(1000, activation='relu')(merged)
fc2 = Dense(500, activation='relu')(fc1)
out = Dense(10)(fc2)
model = tensorflow.keras.models.Model(input_layer, out)
model.compile(loss=tensorflow.keras.losses.categorical_crossentropy,
optimizer=tensorflow.keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(x_train, 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)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
In order to complete my task, I believe I have to convert my example CNN piece-by-piece into the required architecture. Although I have no idea how to do this, they look completely different from each other (one is purely sequential, the other uses parallel layers and merging). I'm a beginner in machine learning so there might be something that I'm missing although I can't find and resource online that goes into this conversion process. Any help with this is appreciated.
You simply have to add an softmax activation to the last, out layer:
out = Dense(10, activation="softmax")(fc2)
Thus your model in completed form:
input_layer = tensorflow.keras.layers.Input(shape=input_shape)
conv1 = Conv2D(32, (1, 1), activation='relu')(input_layer)
pool1 = MaxPooling2D(2, 2)(conv1)
conv2_1 = Conv2D(64, (1, 1), activation='relu', padding='same')(pool1)
pool2_1 = MaxPooling2D(2, 2)(conv2_1)
drop2_1 = Dropout(0.5)(pool2_1)
conv2_2 = Conv2D(64, (1, 1), activation='relu', padding='same')(pool1)
pool2_2 = MaxPooling2D(2, 2)(conv2_2)
drop2_2 = Dropout(0.5)(pool2_2)
conv3_1 = Conv2D(256, (1, 1), activation='relu', padding='same')(drop2_1)
conv3_2 = Conv2D(256, (1, 1), activation='relu', padding='same')(drop2_2)
merged = tensorflow.keras.layers.concatenate([conv3_1, conv3_2], axis=-1)
merged = Dropout(0.5)(merged)
merged = Flatten()(merged)
fc1 = Dense(1000, activation='relu')(merged)
fc2 = Dense(500, activation='relu')(fc1)
out = Dense(10, activation="softmax")(fc2)
Out:
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/1
60000/60000 [==============================] - 25s 416us/step - loss: 0.6394 - acc: 0.7858 - val_loss: 0.2956 - val_acc: 0.9047
Test loss: 0.29562548571825026
Test accuracy: 0.9047
Related
This is my train & test split shape:
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
----------------------
(120000, 72)
(12000, 72)
(120000, 6)
(12000, 6)
I reshape the data for CNN:
X_train = X_train.reshape(len(X_train), X_train.shape[1], 1)
X_test = X_test.reshape(len(X_test), X_test.shape[1], 1)
X_train.shape, X_test.shape
-------------------------------------------------------------------
((120000, 72, 1), (12000, 72, 1))
Making the deep learning function:
def model():
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=6, activation='relu',
padding='same', input_shape=(72, 1)))
model.add(BatchNormalization())
# adding a pooling layer
model.add(MaxPooling1D(pool_size=(3), strides=2, padding='same'))
model.add(Conv1D(filters=64, kernel_size=6, activation='relu',
padding='same', input_shape=(72, 1)))
model.add(BatchNormalization())
model.add(MaxPooling1D(pool_size=(3), strides=2, padding='same'))
model.add(Conv1D(filters=64, kernel_size=6, activation='relu',
padding='same', input_shape=(72, 1)))
model.add(BatchNormalization())
model.add(MaxPooling1D(pool_size=(3), strides=2, padding='same'))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
When i fit it shows error: Shapes (32, 6) and (32, 3) are incompatible
model = model()
model.summary()
logger = CSVLogger('logs.csv', append=True)
his = model.fit(X_train, y_train, epochs=30, batch_size=32,
validation_data=(X_test, y_test), callbacks=[logger])
---------------------------------------------------------------
ValueError: Shapes (32, 6) and (32, 3) are incompatible
What problem and how can i solve it?
Your targets are 6 dimensional, but your prediction is 3 dimensional, thus the mismatch. You should have Dense(6) as the last layer of your model, not Dense(3)
I am trying to do Image Recognition in Python with TensorFlow and Keras and I have followed below blog for the same.
https://stackabuse.com/image-recognition-in-python-with-tensorflow-and-keras/
I need to find the output of each layer and at the same time I am also trying to predict an image.
Please see my code below. I am not able to predict and image that I am providing
Any help and inputs here to get this fixed is much appreciated.
import numpy
from keras import models
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, BatchNormalization, Activation
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.constraints import maxnorm
from keras.utils import np_utils
from matplotlib import pyplot
# Create dictionary of target classes
label_dict = {
0: 'T-shirt/top',
1: 'Trouser',
2: 'Pullover',
3: 'Dress',
4: 'Coat',
5: 'Sandal',
6: 'Shirt',
7: 'Sneaker',
8: 'Bag',
9: 'Ankle boot',
}
# example of loading the mnist dataset
from keras.datasets import fashion_mnist
from matplotlib import pyplot
# load dataset
#trainX, trainy), (testX, testy) = fashion_mnist.load_data()
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
# summarize loaded dataset
print('Train: X=%s, y=%s' % (X_train.shape, y_train.shape))
print('Test: X=%s, y=%s' % (X_test.shape, y_test.shape))
# plot first few images
for i in range(9):
# define subplot
pyplot.subplot(330 + 1 + i)
# plot raw pixel data
pyplot.imshow(X_train[i], cmap=pyplot.get_cmap('gray'))
# show the figure
pyplot.show()
# normalize the inputs from 0-255 to between 0 and 1 by dividing by 255
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train / 255.0
X_test = X_test / 255.0
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
class_num =10
numpy.max(X_train[0])
numpy.min(X_train[0])
X_train[0][500:]
y_train[:500][0]
y_train[:500][0]
X_train.shape, X_test.shape
y_train.shape, y_test.shape
# Reshape training and testing image
X_train = X_train.reshape(-1, 28, 28, 1)
X_test = X_test.reshape(-1,28,28,1)
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=X_train.shape[1:], padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3), input_shape=(3, 32, 32), activation='relu', padding='same'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), padding='same', name='test1'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), padding='same', name='test2'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Conv2D(128, (3, 3), padding='same', name='test3'))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(256, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Dense(128, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Dense(class_num))
model.add(Activation('softmax'))
epochs = 2
optimizer = 'adam'
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)
# Model evaluation
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))
# This I am predicting from test images
image_index = 430
pyplot.imshow(X_test[image_index].reshape(28, 28,1),cmap='Greys')
pred = model.predict(X_test[image_index].reshape(-1, 28, 28, 1))
print(pred.argmax())
I am trying to predict model using image below
Trying to predict this image using the above trained model
I have written below code
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
img_path = 'data/img.jpg'
img = image.load_img(img_path, target_size=(28, 28))
img_tensor = image.img_to_array(img)
img_tensor = numpy.expand_dims(img_tensor, axis=0)
img_tensor /= 255.
pyplot.imshow(img_tensor[0])
pyplot.show()
print(img_tensor.shape)
pred = model.predict(img_tensor.reshape(-1, 28, 28, 28))
print(pred.argmax())
With the above model.predict, I am getting below error
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-125-965f3e01bc73> in <module>
----> 1 pred = model.predict(img_tensor.reshape(-1, 28, 28, 28))
2 print(pred.argmax())
**ValueError: cannot reshape array of size 2352 into shape (28,28,28)**
I have tried all options but not getting the right results.
Can any one help me to get the right results please?
Your input is of size (28,28,3) but you are transforming it into (28,28,28) which is wrong. Try:
pred = model.predict(img_tensor.reshape(-1, 28, 28, 3))
I tried to use CNN LSTM to classify but I got this error message: strides should be of length 1, 3 or 5 but was 2 for 2D CNN - LSTM. Here is my code:
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1],X_train.shape[2],X_train.shape[3] ))
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1], X_test.shape[2],X_test.shape[3]))
print("build model...")
model = Sequential()
model.add(TimeDistributed(Conv2D(64, (3,3), padding='same', activation='relu',data_format="channels_last"),
input_shape = X_train.shape))
model.add(TimeDistributed( Conv2D(64, (3,3), padding='same', activation='relu')))
model.add(TimeDistributed(MaxPooling2D((2))))
model.add(TimeDistributed(Flatten()))
model.add(Dropout(0.5))
model.add(LSTM(256, return_sequences=False, dropout=0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer=keras.optimizers.Adadelta(),metrics=['accuracy'])
model.fit(X_train, y_train, batch_size=10, epochs=70, validation_data=(X_test, y_test))
Please help me fix it. Thanks!
Please help. I'm getting this error on running the training code on colab
want to do multi label classification (7 distinct output labels)
ValueError: Error when checking target: expected dense_9 to have shape (7,) but got array with shape (1,)
My code is as follows:
with open("data/fer2013/fer2013.csv") as f:
x_train = np.array(x_train, 'float32')
y_train = np.array(y_train, 'float32')
x_test = np.array(x_test, 'float32')
y_test = np.array(y_test, 'float32')
x_train /= 255 #normalize inputs between [0, 1]
x_test /= 255
x_train = x_train.reshape(x_train.shape[0], 48, 48, 1)
x_train = x_train.astype('float32')
x_test = x_test.reshape(x_test.shape[0], 48, 48, 1)
x_test = x_test.astype('float32')
model.add(BatchNormalization(input_shape=(48,48,1)))
#1st convolution layer
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2, 2)))
#2nd convolution layer
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2, 2)))
#3rd convolution layer
model.add(Conv2D(256, (2, 2), activation='relu'))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2, 2)))
#4th convolution layer
model.add(Conv2D(512, (2, 2), activation='relu'))
model.add(Conv2D(512, (2, 2), activation='relu'))
model.add(MaxPooling2D(pool_size=(1,1), strides=(2, 2)))
model.add(Flatten())
#fully connected neural networks
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(7, activation='softmax'))
## Start the training
#model.fit(x_train, y_train, epochs=epochs, validation_split=0.0, shuffle=True) #train for all trainset
model.fit_generator(train_generator, steps_per_epoch=batch_size, epochs=epochs, validation_data=(x_test,y_test)) #train for randomly selected one
score = model.evaluate(x_test, y_test, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], score[1]*100))
##########################------------------------############################
# serialize model to JSON
model_json = model.to_json()
with open("model/model.json", "w") as json_file:
json_file.write(model_json)
# serialize weights to HDF5
model.save_weights("model/weights.h5")
print("Saved model to disk")
############################---------------------###############################
want to do multi label classification (7 distinct output labels)
I'm expecting a json file model.json
but i'm getting an error
ValueError: Error when checking target: expected dense_9 to have shape (7,) but got array with shape (1,)
I am having an issue with Keras where evaluate function gives different training loss (way higher) and accuracy(way lower) value as compared to the value that I get during training. I am aware that this question has already been asked at several places (here, here), but I think my issue is different and still not answered in those forums.
Explanation of the Task
It is supposed to be a very simple task. All I am doing is to overfit to my own dataset of 256 images (29x29x3) with 256 output classes (one for each image).
Dataset
Case 1
x_train = All the pixel values in the image = i where i goes from 0 to 255.
y_train = i
Case 2
x_train = Centre 5*5 patch of the pixel values in the image = i where i goes from 0 to 255. All the other pixel values are same for all the images.
y_train = i
This gives me 256 images in total for the training data in each case. (It would be more clear if you just have a look at the code)
Here is my code to reproduce the issue -
from __future__ import print_function
import os
import keras
from keras.datasets import mnist
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D, Activation
from keras.layers.normalization import BatchNormalization
from keras.callbacks import ModelCheckpoint, LearningRateScheduler, Callback
from keras import backend as K
from keras.regularizers import l2
import matplotlib.pyplot as plt
import PIL.Image
import numpy as np
from IPython.display import clear_output
# The GPU id to use, usually either "0" or "1"
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]="1"
# To suppress the warnings
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
## Hyperparamters
batch_size = 256
num_classes = 256
l2_reg=0.0
epochs = 500
## input image dimensions
img_rows, img_cols = 29, 29
## Train Image (I took a random image from ImageNet)
train_img_name = 'n01871265_279.JPEG'
ret = PIL.Image.open(train_img_name) #Opening the image
ret = ret.resize((img_rows, img_cols)) #Resizing the image
img = np.asarray(ret, dtype=np.uint8).astype(np.float32) #Converting it to numpy array
print(img.shape) # (29, 29, 3)
## Creating the training data
#############################
x_train = np.zeros((256, img_rows, img_cols, 3))
y_train = np.zeros((256,), dtype=int)
for i in range(len(y_train)):
temp_img = np.copy(img)
## Case1 of dataset
# temp_img[:, :, :] = i # changing all the pixel values
## Case2 of dataset
temp_img[12:16, 12:16, :] = i # changing the centre block of 5*5 pixels
x_train[i, :, :, :] = temp_img
y_train[i] = i
##############################
## Common stuff in Keras
if K.image_data_format() == 'channels_first':
print('Channels First')
x_train = x_train.reshape(x_train.shape[0], 3, img_rows, img_cols)
input_shape = (3, img_rows, img_cols)
else:
print('Channels Last')
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 3)
input_shape = (img_rows, img_cols, 3)
## Normalizing the pixel values
x_train = x_train.astype('float32')
x_train /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
## convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
## Model definition
def model_toy(mom):
model = Sequential()
model.add( Conv2D(filters=64, kernel_size=(7, 7), strides=(1,1), input_shape=input_shape, kernel_regularizer=l2(l2_reg)) )
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
#Default parameters kept same as PyTorch
#Meaning of PyTorch momentum is different from Keras momentum.
# PyTorch mom = 0.1 is same as Keras mom = 0.9
model.add( Conv2D(filters=128, kernel_size=(7, 7), strides=(1, 1), kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
model.add(Conv2D(filters=256, kernel_size=(5, 5), strides=(1, 1), kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
model.add(Conv2D(filters=512, kernel_size=(5, 5), strides=(1, 1), kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
model.add(Conv2D(filters=1024, kernel_size=(5, 5), strides=(1, 1), kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
model.add( Conv2D( filters=2048, kernel_size=(3, 3), strides=(1, 1), kernel_regularizer=l2(l2_reg) ) )
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
model.add(Conv2D(filters=4096, kernel_size=(3, 3), strides=(1, 1), kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
# Passing it to a dense layer
model.add(Flatten())
model.add(Dense(1024, kernel_regularizer=l2(l2_reg)))
model.add(Activation('relu'))
model.add(BatchNormalization(momentum=mom, epsilon=0.00001))
# Output Layer
model.add(Dense(num_classes, kernel_regularizer=l2(l2_reg)))
model.add(Activation('softmax'))
return model
mom = 0.9 #0
model = model_toy(mom)
model.summary()
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adam(lr=0.001),
#optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, decay=0.0, nesterov=True),
metrics=['accuracy'])
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
shuffle=True,
)
print('Training results')
print('-------------------------------------------')
score = model.evaluate(x_train, y_train, verbose=1)
print('Training loss:', score[0])
print('Training accuracy:', score[1])
print('-------------------------------------------')
Small Note - I was able to successfully do this task in PyTorch. It is just that my actual task requires me to have a Keras model. That's why I have changed the default values of the BatchNorm layer (the root cause of the issue) according to the ones I used to train PyTorch model.
Here is the image that I used in my code.
Here are the results of training.
Case1 of the dataset
Case2 of the dataset
If you look at these two files, you would be able to notice the discrepancies in the training loss during training vs inference.
(I have set my batch size to be equal to the size of my training data so as to avoid some the reasons BatchNorm generally creates problems as mentioned here)
Next, I looked at the source code of the Keras to see if there is any way I can make the BatchNorm layer use the batch statistics instead of the running mean and variance.
Here is the update formula that Keras (backend - TF) uses to update the running mean and variance.
#running_stat -= (1 - momentum) * (running_stat - batch_stat)
So if I set the momentum value to be 0, it would mean that the value assigned to the runing_stat would always be equal to batch_stat during the training phase. Thus, the value it will use during inference mode will also be same (close) as batch/dataset statistics.
Here are the results for this little experiment with the same issue still occurring.
Case1 of the dataset
Case2 of the dataset
Programming Environment - Python-3.5.2, tensorflow-1.10.0, keras-2.2.4
I tried the same thing with tensorflow-1.12.0, keras-2.2.2 as well but it still did not solve the issue.