Почему мой val_accuracy стоит на уровне 0,0000e+00, в то время как мой val_loss увеличивается с самого начала?

Я тренирую модель классификации для классификации клеток, и моя модель основана на этой статье: https://www.nature.com/articles/s41598-019-50010-9. Поскольку мой набор данных состоит всего из 10 изображений, я выполнил увеличение изображения, чтобы искусственно увеличить размер набора данных до 3000 изображений, которые затем были разделены на 2400 обучающих изображений и 600 проверочных изображений.

Однако в то время как потери при обучении и точность улучшались при большем количестве итераций, потери при проверке быстро увеличивались, в то время как точность проверки оставалась неизменной на уровне 0,0000e+00.

Сильно ли переоснащает мою модель с самого начала?

Код, который я использовал, показан ниже:

import keras
import tensorflow as tf
from tensorflow.keras import backend as K
from tensorflow.keras.models import Model, load_model, Sequential, model_from_json, load_model
from tensorflow.keras.layers import Input, BatchNormalization, Activation, Flatten, Dense, LeakyReLU
from tensorflow.python.keras.layers.core import Lambda, Dropout
from tensorflow.python.keras.layers.convolutional import Conv2D, Conv2DTranspose, UpSampling2D
from tensorflow.python.keras.layers.pooling import MaxPooling2D, AveragePooling2D
from tensorflow.python.keras.layers.merge import Concatenate, Add
from tensorflow.keras import backend as K
from tensorflow.keras.callbacks import ModelCheckpoint, LearningRateScheduler, ReduceLROnPlateau, EarlyStopping
from tensorflow.keras.optimizers import *

img_channel = 1
input_size = (512, 512, 1)
inputs = Input(shape = input_size)
initial_input = Lambda(lambda x: x) (inputs) #Ensure input value is between 0 and 1 to avoid negative loss

kernel_size = (3,3)
pad = 'same'
model = Sequential()
filters = 2

c1 = Conv2D(filters, kernel_size, padding = pad, kernel_initializer = 'he_normal')(initial_input)
b1 = BatchNormalization()(c1) 
a1 = Activation('elu')(b1)
p1 = AveragePooling2D()(a1)

c2 = Conv2D(filters, kernel_size, padding = pad, kernel_initializer = 'he_normal')(p1)
b2 = BatchNormalization()(c2) 
a2 = Activation('elu')(b2)
p2 = AveragePooling2D()(a2)

c3 = Conv2D(filters, kernel_size, padding = pad, kernel_initializer = 'he_normal')(p2)
b3 = BatchNormalization()(c3) 
a3 = Activation('elu')(b3)
p3 = AveragePooling2D()(a3)

c4 = Conv2D(filters, kernel_size, padding = pad, kernel_initializer = 'he_normal')(p3)
b4 = BatchNormalization()(c4) 
a4 = Activation('elu')(b4)
p4 = AveragePooling2D()(a4)

c5 = Conv2D(filters, kernel_size, padding = pad, kernel_initializer = 'he_normal')(p4)
b5 = BatchNormalization()(c5) 
a5 = Activation('elu')(b5)
p5 = AveragePooling2D()(a5)

f = Flatten()(p5)

d1 = Dense(128, activation = 'elu')(f)
d2 = Dense(no_of_img, activation = 'softmax')(d1)

model = Model(inputs = [inputs], outputs = [d2])
print(model.summary())

learning_rate = 0.001
decay_rate = 0.0001
model.compile(optimizer = SGD(lr = learning_rate, decay = decay_rate, momentum = 0.9, nesterov = False), 
      loss = 'categorical_crossentropy', metrics = ['accuracy'])

perf_lr_scheduler = ReduceLROnPlateau(monitor = 'val_loss', factor = 0.9, patience = 3,
        verbose = 1, min_delta = 0.01, min_lr = 0.000001)

model_earlystop = EarlyStopping(monitor = 'val_loss', min_delta = 0.001, patience = 10, restore_best_weights = True) 

#Convert labels to binary matrics
img_aug_label = to_categorical(img_aug_label, num_classes = no_of_img)

#Convert images to float to between 0 and 1
img_aug = np.float32(img_aug)/255

plt.imshow(img_aug[0,:,:,0])
plt.show()

#Train on augmented images
model.fit(
  img_aug, 
  img_aug_label, 
  batch_size = 4,
  epochs = 100, 
  validation_split = 0.2,
  shuffle = True,
  callbacks = [perf_lr_scheduler], 
  verbose = 2)

Вывод моей модели показан ниже:

Train on 2400 samples, validate on 600 samples
Epoch 1/100
2400/2400 - 12s - loss: 0.6474 - accuracy: 0.8071 - val_loss: 9.8161 - val_accuracy: 0.0000e+00
Epoch 2/100
2400/2400 - 10s - loss: 0.0306 - accuracy: 0.9921 - val_loss: 10.1733 - val_accuracy: 0.0000e+00
Epoch 3/100
2400/2400 - 10s - loss: 0.0058 - accuracy: 0.9996 - val_loss: 10.9820 - val_accuracy: 0.0000e+00
Epoch 4/100

Epoch 00004: ReduceLROnPlateau reducing learning rate to 0.0009000000427477062.
2400/2400 - 10s - loss: 0.0019 - accuracy: 1.0000 - val_loss: 11.3029 - val_accuracy: 0.0000e+00
Epoch 5/100
2400/2400 - 10s - loss: 0.0042 - accuracy: 0.9992 - val_loss: 11.9037 - val_accuracy: 0.0000e+00
Epoch 6/100
2400/2400 - 10s - loss: 0.0024 - accuracy: 0.9996 - val_loss: 11.5218 - val_accuracy: 0.0000e+00
Epoch 7/100

Epoch 00007: ReduceLROnPlateau reducing learning rate to 0.0008100000384729356.
2400/2400 - 10s - loss: 9.9053e-04 - accuracy: 1.0000 - val_loss: 11.7658 - val_accuracy: 0.0000e+00
Epoch 8/100
2400/2400 - 10s - loss: 0.0011 - accuracy: 1.0000 - val_loss: 12.0437 - val_accuracy: 0.0000e+00
Epoch 9/100

person Strider1994    schedule 22.04.2020    source источник
comment
Это, безусловно, очень раннее переобучение модели, поскольку у вас есть только 10 исходных изображений (3000 после увеличения). Но я не уверен, почему потери при проверке очень высоки, а val_accuracy равно 0. Можете ли вы заменить d2 = Dense(no_of_img, activation = 'softmax')(d1) на d2 = Dense(no_of_img)(d1) и посмотреть, есть ли какие-либо изменения в результатах?   -  person Vishnuvardhan Janapati    schedule 25.04.2020
comment
Привет @Janapati, спасибо за ваш комментарий. Я понял, что произошла ошибка, так как я не перетасовал данные вручную, прежде чем использовать их в качестве обучающих данных для модели. Я думал, что validation_split и shuffle будут происходить только во время обучения, но на самом деле это произошло до обучения. Перетасовка данных вручную перед подгонкой их к модели решила проблему.   -  person Strider1994    schedule 27.04.2020
comment
Можете добавить свою находку в ответ, чтобы она была полезна другим. Спасибо   -  person Vishnuvardhan Janapati    schedule 27.04.2020


Ответы (1)


Я понял, что произошла ошибка, так как я не перетасовал данные вручную, прежде чем использовать их в качестве обучающих данных для модели. Я думал, что аргументы validation_split и shuffle будут возникать только во время обучения, но на самом деле это произошло до обучения. Другими словами, функция подгонки сначала разделит ваши данные на наборы для обучения и проверки, а затем перетасует данные в каждом наборе (но не между ними).

Для моего расширенного набора данных разделение произошло в позиции, где проверочный набор содержал типы изображений, не найденные в обучающем наборе. Следовательно, модель выполняла проверку типов данных, которые она не видела в обучающем наборе, что приводило к плохим потерям и точности проверки. Ручная перетасовка данных перед их встраиванием в модель решила эту проблему.

person Strider1994    schedule 27.04.2020