I have a dataset of about 160k images of 160 classes and I'm trying to classify them using CNN. Training on 120k images for 20 epochs i start with loss ~ 4.9 and val_loss ~ 4.6 which improves to about 3.3 and 3.2 after 20 epochs. I Really tried to read the documentation of Keras and understand what does that mean, but i couldn't, so I'm asking if someone would explain to me in the context of my model what does that mean for my model. I mean what does the loss score represent? What does it say for the model?
num_classes = 154
batch_size = 64
input_shape = (50,50,3)
epochs = 20
X, y = load_data()
# input image dimensions
img_rows, img_cols = 50, 50
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Conv2D(64, kernel_size=(5, 5),
activation='relu',
padding = 'same',
input_shape=input_shape))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.20))
model.add(Conv2D(128, (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'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
I think it will help to watch a few tutorials online on CNN, to begin with. Basically, you want your loss to reduce with the training epochs which is what is observed in your case. Typically we look at how both losses are evolving over the entire training period. Observing how the train and validation loss is changing helps us have an understand whether the model is overfitting or not. You can check This link for a basic explanation to detect overfitting.
Ideally, you would want both your training as well as test loss to reduce with iterations. It is a measure of the error committed by the model in classification (as accuracy increase you expect the loss to reduce)
Related
I am working on a CNN model for multi-class image classification, while both loss and accuracy show flatline and values stay almost same.
Could you please help have a look if any mistakes made and much appreciate if any advice? thanks a lot in advance.
Loss and accuracy:
Input data
(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
(24296, 32, 32, 1) (6075, 32, 32, 1) (24296, 6) (6075, 6)
X_train:
y_train:
CNN code
model
model = Sequential()
model.add(Conv2D(16, (2,2), activation = 'relu', input_shape = (32,32,1)))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(32, (2,2), activation = 'relu'))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(64, (2,2), activation = 'relu'))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(128, (2,2), activation = 'relu'))
model.add(MaxPooling2D((2,2)))
model.add(Flatten())
model.add(Dense(100, activation = 'relu'))
model.add(Dense(6, activation = 'softmax'))
compile
model.compile(loss = 'categorical_crossentropy',
optimizer = optimizers.RMSprop(learning_rate=0.001),
metrics = ['accuracy'])
early stopping and fit
es = EarlyStopping(patience = 5, verbose=2)
history = model.fit(X_train, y_train,
validation_split = 0.2,
callbacks=[es],
epochs=100,
batch_size=64)
I checked the community, tried different optimizer (adam, sgd and RMSprop), parameters like learning rate and also different layers, but similar result.I expect the loss drop and accuracy increase, no flatline.
For what I can see the model is not learning, it's returning the same predictions for all inputs.
Is it 6 classes you're trying to predict? model.add(Dense(6, activation = 'softmax'))
Is your dataset big enough? Without enough parameters to represent
your data the model will have high loss.
Also, when is your model supposed to stop? are you monitoring
val_accuracy or val_loss and the training phase is terminating
when these metrics stops increasing or decreasing?
Did you One-Hot-Encode your targets so to use
categorical_crossentropy ? Otherwise try
sparse_categorical_crossentropy?
I need to implement CNN for multi-class classification on Tabular Dataset.
My data has X_train.shape = (1534185, 81, 1) and Y_train = (1534185, 11)
Here is a sample from my dataset
DataSetImage
I tried to normalize the data, but values are too big to be added and stored in float64.
The CNN Model I implemented is below
batchSize = X_train.shape[0]
length = X_train.shape[1]
channel = X_train.shape[2]
n_outputs = y_train.shape[1]
#Initialising the CNN
model = Sequential()
#1.Multiple convolution and max pooling
model.add(Convolution1D(filters=64, kernel_size=3, activation="relu", input_shape=(length, channel)))
model.add(MaxPooling1D(strides=4))
model.add(Dropout(0.1))
model.add(BatchNormalization())
model.add(Convolution1D(filters= 32, kernel_size=3, activation='relu'))
model.add(MaxPooling1D(strides=4))
model.add(Dropout(0.1))
model.add(BatchNormalization())
model.add(Convolution1D(filters= 16, kernel_size=3, activation='relu'))
model.add(MaxPooling1D(strides=4))
model.add(Dropout(0.1))
model.add(BatchNormalization())
#2.Flattening
model.add(Dropout(0.2))
model.add(Flatten())
#3.Full Connection
model.add(Dense(30, activation='relu'))
model.add(Dense(n_outputs, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
If I try to change the kernel size I get following Error
ValueError: Negative dimension size caused by subtracting 2 from 1 for 'max_pooling1d_103/MaxPool' (op: 'MaxPool') with input shapes: [?,1,1,16].
When I try to train my Model using code below, I get no improvement in Accuracy with loss = Nan
history = model.fit(
X_train,
y_train,
batch_size=1000,
epochs=2,
validation_data=(X_test, y_test),
)
Loss: nan
Error:
Train on 1534185 samples, validate on 657509 samples
Epoch 1/2
956000/1534185 [=================>............] - ETA: 1:44 - loss: nan - accuracy: 0.0101
Need your Help
Try to check for inf values and replace them with nan and retry
X_train.replace([np.inf, -np.inf], np.nan,inplace=True)
X_train = X_train.fillna(0)
I'm trying to build a model to predict wether a picture has text in it using keras with Tensorflow backend.
This is my Model:
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(image_size, image_size, 3))) # 32?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # 0.5?
model.add(Conv2D(32, (3, 3))) # again, 32?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # again, 0.5?
model.add(Conv2D(64, (3, 3))) # again, 64?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # again, 0.5?
model.add(Flatten())
model.add(Dense(96))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1)) # binary
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
I've tried image sizes 128, 256, 384.
I train it with 9000 images, 4500 of cat 1 and 4500 of cat 2.
the training accuracy goes as high as 0.90.
but when I load the model and use it to predict the category of images of the two categories that I haven't trained it with, it always gives the score 0.
Any ideas why this is happenning?
p.s. cat 1 is images with text and cat 2 is images without text.
also this is my code for testing the model:
model = load_model(model_path)
test_data_generator = ImageDataGenerator(rescale=1. / 255)
test_generator = test_data_generator.flow_from_directory(
test_data_dir,
target_size=(image_size, image_size),
batch_size=batch_size,
class_mode=None,
shuffle=False)
prediction = model.predict_generator(
test_generator,
use_multiprocessing=True,
verbose=1) # verbose=1 makes it show a progress bar.
dst = []
for pred in prediction:
if int(round(pred)) == 0:
dst += [0]
else:
dst += [1]
dst is all 0's.
Apparently the problem was that I used keras' generators to feed the images I was testing and used shutil to iterate over them. So I'd get the predictions and iterate over them and the files in the directory using two different things and the order of them wasn't the same. shutil would list them in some random order whereas the generator would list them in ascending order by name. so I wasn't putting a label on the file it was generated for.
I want to train my model on video data for gesture recognition, proposed using LSTM's and TimeDistributed layers. Would this be ideal way to tackle my problem?
# Convolution
pool_size = 4
# LSTM
lstm_output_size = 1
print('Build model...')
model = Sequential()
model.add(TimeDistributed(Dense(62), input_shape=(img_width, img_height,3)))
model.add(Conv2D(32, (3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(32, (3, 3)))
model.add(MaxPooling2D(pool_size=pool_size))
# model.add(Dense(1))
model.add(TimeDistributed(Flatten()))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(lstm_output_size))
model.add(Dense(units = 1, activation = 'sigmoid'))
print('Train...')
model.summary()
# Run epochs of sampling data then training
For temporal sequence data LSTM networks are generally the right choice. If you want to analyze video then a combination with 2d convolutions sounds reasonable to me. However, you have to apply TimeDistributed on all layers which dont expect sequence data. In your example that means all laysers expect LSTM.
# Convolution
pool_size = 4
# LSTM
lstm_output_size = 1
print('Build model...')
model = Sequential()
model.add(TimeDistributed(Dense(62), input_shape=(img_width, img_height,3)))
model.add(TimeDistributed(Conv2D(32, (3, 3))))
model.add(Dropout(0.25))
model.add(TimeDistributed(Conv2D(32, (3, 3))))
model.add(TimeDistributed(MaxPooling2D(pool_size=pool_size)))
# model.add(Dense(1))
model.add(TimeDistributed(Flatten()))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(lstm_output_size))
model.add(Dense(units = 1, activation = 'sigmoid'))
print('Train...')
model.summary()
# run epochs of sampling data then training
The last Dense Layer can stay this way because the final lstm doesnt output a sequence.
This is my first time asking a question here (that's mean I'm really need help) and sorry for my bad English. I want to make a cnn-lstm layer for video classification in Keras but I have a problem on making my y_train. I will describe my problem after this.
I have videos dataset (1 video has 10 frames) and I converted the videos to images.
First I splited the dataset to xtrain, xtest, ytrain, and ytest (20% test, 80% train) and I did it.
X_train, X_test = img_data[:trainco], img_data[trainco:]
y_train, y_test = y[:trainco], y[trainco:]
X_train shape : (2280, 64, 64, 1) -> I have 2280 images, 64x64 height x widht, 1 channel
y_train shape : (2280, 26) -> 26 classes
And then I must reshape them before entering the cnn-lstm process. *note : I do the same thing with x_test and y_test
time_steps = 10 (because I have 10 frames per video)
X_train = X_train.reshape(int(X_train.shape[0] / time_steps), time_steps, X_train.shape[1], X_train.shape[2], X_train.shape[3])
y_train = y_train.reshape(int(y_train.shape[0] / time_steps), time_steps, y_train.shape[1])
X_train shape : (228, 10, 64, 64, 1), y_train shape : (228, 10, 26)
And then this is my model :
model = Sequential()
model.add(TimeDistributed(Conv2D(32, (3, 3), strides=(2, 2), activation='relu', padding='same'), input_shape=X_train.shape[1:]))
model.add(TimeDistributed(MaxPooling2D((2, 2), strides=(2, 2))))
model.add(TimeDistributed(Conv2D(32, (3, 3), padding='same', activation='relu')))
model.add(TimeDistributed(MaxPooling2D((2, 2), strides=(2, 2))))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(256, return_sequences=False, input_shape=(64, 64)))
model.add(Dense(128))
model.add(Dense(64))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=["accuracy"])
checkpoint = ModelCheckpoint(fname, monitor='acc', verbose=1, save_best_only=True, mode='max', save_weights_only=True)
hist = model.fit(X_train, y_train, batch_size=num_batch, nb_epoch=num_epoch, verbose=1, validation_data=(X_test, y_test), callbacks=[checkpoint])
But I got an error that says
ValueError: Error when checking target: expected dense_3 to have 2 dimensions, but got array with shape (228, 10, 26)
Like it says expected to have 2 dimensions. I changed the code to
y_train = y_train.reshape(int(y_train.shape[0] / time_steps), y_train.shape[1])
And I got an error again that says
ValueError: cannot reshape array of size 59280 into shape (228,26)
And then I change the code again to
y_train = y_train.reshape(y_train.shape[0], y_train.shape[1])
And I still got an error
ValueError: Input arrays should have the same number of samples as target arrays. Found 228 input samples and 2280 target samples.
What should I do? I know the problem but I don't know how to solve it. Please help me.
I recreated a slightly simplified version of your situation to reproduce the problem. Basically, it appears that the LSTM layer is only putting out one result for the entire sequence of time steps, thereby reducing the dimension from 3 to 2 in the output. If you run my program below, I've added the model.summary() which provides details of the architecture.
from keras import Sequential
from keras.layers import TimeDistributed, Dense, Conv2D, MaxPooling2D, Flatten, LSTM
import numpy as np
X_train = np.random.random((228, 10, 64, 64, 1))
y_train = np.random.randint(2, size=(228, 10, 26))
num_classes = 26
# Create the model
model = Sequential()
model.add(TimeDistributed(Conv2D(32, (3, 3), strides=(2, 2), activation='relu', padding='same'), input_shape=X_train.shape[1:]))
model.add(TimeDistributed(MaxPooling2D((2, 2), strides=(2, 2))))
model.add(TimeDistributed(Conv2D(32, (3, 3), padding='same', activation='relu')))
model.add(TimeDistributed(MaxPooling2D((2, 2), strides=(2, 2))))
model.add(TimeDistributed(Flatten(),name='Flatten'))
model.add(LSTM(256, return_sequences=False, input_shape=(64, 64)))
model.add(Dense(128))
model.add(Dense(64))
model.add(Dense(num_classes, activation='softmax', name='FinalDense'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=["accuracy"])
#
model.summary()
# hist = model.fit(X_train, y_train, epochs=1)
I believe you'll need to decide if you want to reduce the dimension of the y_train (target) data to be consistent with the model, or change the model. I hope this helps.