3

So the val_accuracy of my CNN model does not change. In fact is is always the same value. I have six classes with 190 samples each. A total of approx. 1250 samples. Normal loss decreases, but very slowly. Could it have something to do with the fact that I have too few samples?

the structure looks as follows:

X_train, X_test, y_train, y_test = train_test_split(final, y, test_size=0.25, random_state=42, stratify=y)

X_train = tf.expand_dims(X_train, axis=-1)
X_test = tf.expand_dims(X_test, axis=-1)

num_classes = 6

# convert class vectors to binary class matrices - this is for use in the
# categorical_crossentropy loss below
y_train = keras.utils.np_utils.to_categorical(y_train-1, num_classes)
y_test = keras.utils.np_utils.to_categorical(y_test-1, num_classes)

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(100, 400, 1)))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))


model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))

opt = SGD(learning_rate=0.0000001)

model.compile(loss = "categorical_crossentropy", optimizer = opt, metrics=['accuracy'])

history = model.fit(X_train, y_train, epochs=200, validation_data=(X_test, y_test), batch_size=4, shuffle=True)

Output looks as follows:

Epoch 1/200
213/213 [==============================] - 13s 63ms/step - loss: 31.1534 - accuracy: 0.1529 - val_loss: 49.1441 - val_accuracy: 0.1690
Epoch 2/200
213/213 [==============================] - 13s 62ms/step - loss: 28.5760 - accuracy: 0.1741 - val_loss: 25.3026 - val_accuracy: 0.1690

Epoch 30/200
213/213 [==============================] - 13s 62ms/step - loss: 13.4533 - accuracy: 0.1835 - val_loss: 24.9576 - val_accuracy: 0.1690
Epoch 31/200
213/213 [==============================] - 13s 62ms/step - loss: 13.2200 - accuracy: 0.1671 - val_loss: 27.3058 - val_accuracy: 0.1690

Epoch 105/200
213/213 [==============================] - 13s 62ms/step - loss: 5.3484 - accuracy: 0.1518 - val_loss: 5.4915 - val_accuracy: 0.1690
Epoch 106/200
213/213 [==============================] - 13s 62ms/step - loss: 5.1911 - accuracy: 0.1706 - val_loss: 7.9073 - val_accuracy: 0.1690


I tried the following things: -Change Adam optimizer to SGD

-Decrease/Change learning rate

-Decrease batch size

-Shuffe=True

Any more ideas?

Adler Müller
  • 248
  • 1
  • 14
  • check [this](https://stackoverflow.com/questions/43499199/tensorflow-loss-decreasing-but-accuracy-stable), decrease in loss doesn't imply necessarily increase in accuracy.. – Mohamed abdelmagid Oct 04 '21 at 13:14
  • Your accuracy and validation accuracy are both low and relatively close, you need a deeper network, consider also using transfer learning for your small dataset. – Mohamed abdelmagid Oct 04 '21 at 13:19

1 Answers1

0

from my experience I think having 190 sample per class with 6 classes should give a reasonable result although more samples is always better. Depending on the nature of the classification your model might not be deep enough so consider adding another layer or two of convolution and pooling. One thing is your learning rate is very low at 0.0000001. Try using a learning rate of .001 first. If the performance does not improve then add layers to the model. Unless your images are very large I would also consider increasing the batch size to say 30 which is adequate for images like 224 X 224. If these things do not work you can try transfer learning using the code below for your model

model_name='EfficientNetB3'
base_model=tf.keras.applications.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max') 
x=base_model.output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
                bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
x=Dropout(rate=.45, seed=123)(x)        
output=Dense(class_count, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adamax(lr=.001), loss='categorical_crossentropy', metrics=['accuracy']) 

Note EfficientNet models expect images with pixel values in the range 0 to 255 so you do not have to scale the images. By the way did you scale the images in your code, ie img=img/255?

Gerry P
  • 7,662
  • 3
  • 10
  • 20