Я тренирую предварительно обученную модель, чтобы предсказать клиническую значимость медицинских изображений. Я получил хорошую подготовку и точность проверки (около 90%), но плохую точность тестирования (точность прогноза 50%). Набор данных, который я использовал для обучения модели, содержит 3000 образцов с метками «True» или «False». Этот набор данных несбалансирован, доля False в 3 раза больше, чем доля истинных выборок. Поэтому я устанавливаю class_weight при подгонке модели к соотношению 1: 3.
Это код
from keras import models
from keras import layers
from keras.utils import np_utils, generic_utils
from keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras.applications import VGG19
from sklearn.model_selection import KFold
from keras.optimizers import adam
import pickle
import numpy as np
### CNN model and training ###
base_model = VGG19(weights='imagenet', include_top=False, input_shape=(224,224,3))
# Define the K-fold Cross Validator
kfold = KFold(n_splits=5, shuffle=True)
acc_per_fold = [] # Define per-fold score containers
loss_per_fold = [] # Define per-fold score containers
fold_no = 1
for train, val in kfold.split(xtrain, ytrain):
X_train = xtrain[train]
X_val = xtrain[val]
X_train = X_train.astype('float32')
X_val = X_val.astype('float32')
y_train = ytrain[train]
y_val = ytrain[val]
### Model architecture
model = models.Sequential()
model.add(base_model)
model.add(layers.Conv2D(64,(3,3), activation = 'relu', padding = 'same'))
model.add(layers.MaxPooling2D((2,2), strides=(2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(2, activation='softmax'))
for layer in base_model.layers:
layer.trainable = False
model.summary()
### Compile the model
opt = adam(lr=0.0001)
model.compile(loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy'])
print('------------------------------------------------------------------------')
print(f'Training for fold {fold_no} ...')
Epochs_no = 20
BS = 64
CB = CSVLogger('VGG19_Test1_Fold'+str(fold_no)+'_CB.csv',separator = ',', append=False)
class_weights = {0:1, 1:3}
# Train the model
history = model.fit(X_train, y_train, epochs=Epochs_no, batch_size=BS,validation_data=(X_val,y_val), callbacks = [CB], class_weight = class_weights, verbose=1)
Сводка модели
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
vgg19 (Model) (None, 7, 7, 512) 20024384
_________________________________________________________________
conv2d_1 (Conv2D) (None, 5, 5, 64) 294976
_________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 2, 2, 64) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 256) 0
_________________________________________________________________
dense_1 (Dense) (None, 256) 65792
_________________________________________________________________
dense_2 (Dense) (None, 256) 65792
_________________________________________________________________
dense_3 (Dense) (None, 2) 514
=================================================================
Total params: 20,451,458
Trainable params: 427,074
Non-trainable params: 20,024,384
_________________________________________________________________
Мой тестовый набор данных был предварительно обработан тем же методом, что и данные обучения (повторная выборка, нормализация ...). Половина тестовых данных - True, а другая половина - False. Тем не менее, обученная модель предсказывает намного больше «Ложь», хотя я уже установил class_weight, поэтому модель должна уделять больше внимания меньшинству (истинному классу) в обучении.
Я не мог понять, почему модель не прошла тестирование, может, у кого-нибудь есть предложения по этой проблеме. Большое спасибо!