Я пытаюсь решить проблему в моей модели CNN.Я использую набор данных, который структурирован следующим образом: Мои данные организованы следующим образом:
- поезд
- тест
- паразитированный
- незараженный
- проверка
- паразитированный
- незараженный
Мой набор данных слишком велик, и я использую ImageDataGenerator для предварительной обработки изображений, а также загружаю их в пакетном режиме (для уменьшения вычислительных затрат).Сначала я настроил ImageDataGenerator следующим образом:
from keras.preprocessing.image import ImageDataGenerator
#Define a ImageDataGenerator for each dataset.
#This augmentation process is only to rescale each imagem to 1/255
datagen_train = ImageDataGenerator(rescale=1./255) #rescale=1./255
datagen_test = ImageDataGenerator(rescale=1./255)
datagen_valid = ImageDataGenerator(rescale=1./255)
#Define a batch_size parameter
batch_size=32
# Here .flow_from_directory is used to transform
train_generator = datagen_train.flow_from_directory(
'content/cell_images/train', #Train folder path
target_size=(150,150), #all images will be resized to 150x150
batch_size=batch_size,
class_mode='categorical') # We use categorical_crossentropy loss,
# we need categorical labels
test_generator = datagen_test.flow_from_directory(
'content/cell_images/test', #Test folder path
target_size=(150,150), #all images will be resized to 150x150
batch_size=batch_size,
class_mode='categorical')
valid_generator = datagen_valid.flow_from_directory(
'content/cell_images/valid',
target_size=(150,150),
batch_size=32,
class_mode='categorical')
Для подгонки модели использовались fit_generator и контрольная точка для сохранения лучших весов на основе validation_accuracy:
from keras.callbacks import ModelCheckpoint
# Define epochs number
epochs = 10
# Create a checkpointer to save only the best params
checkpointer = ModelCheckpoint(filepath='cnn_model.weights.best.hdf5',
verbose=1, save_best_only=True)
model.fit_generator(train_generator,
steps_per_epoch=train_generator.samples//batch_size,
epochs=epochs,
callbacks=[checkpointer],
validation_data=valid_generator,
validation_steps=valid_generator.samples//batch_size)
Инаконец, лучшие веса были загружены в модель.Модель была оценена с использованием test_set:
# load the weights that yielded the best validation accuracy
model.load_weights('cnn_model.weights.best.hdf5')
#evaluate and print test accuracy
score = model.evaluate_generator(test_generator,
test_generator.samples//batch_size)
print('\n', 'Test accuracy:', score[1])
Но вот моя проблема: каждый раз, когда я запускаю только model.evaluate_generator
, не тренируя модель снова (т.е. сохраняя те же веса), она возвращает разные оценки точности.
Я искал решение, читал много постов, чтобы получить некоторую информацию, и недавно я получил некоторый прогресс.
Недавно я обнаружил, основываясь на этом посте что если я установлю Shuffle=True
и batch_size=1
в test_generator:
test_generator = datagen_test.flow_from_directory(
'content/cell_images/test', #Test folder path
target_size=(150,150), #all images will be resized to 150x150
batch_size=1,
class_mode='categorical',
shuffle=False)`
и steps = test_generator.samples in test_generator
: score = model.evaluate_generator(test_generator, test_generator.samples)
значения больше не изменятся.
Я исследовал эффект от масштабирования 1./255 на основе этого поста .Для этого я использовал обратные вызовы с контрольной точкой, чтобы сохранить веса только для лучшей валидации.После этого я загрузил в модель лучшие веса и оценил их с помощью model.evaluate_generator, как упомянуто выше.Чтобы проверить согласованность баллов, я также использую балл валидации, чтобы проверить, совпадают ли значения, возвращаемые обратными вызовами для наилучших весов, с оценкой_генератором.Перед запуском метода define_generator с validation_set я использовал те же параметры набора тестов:
valid_generator = datagen_valid.flow_from_directory(
'content/cell_images/valid',
target_size=(150,150),
batch_size=1,
class_mode='categorical',
shuffle=False)
#evaluate and print test accuracy
score = model.evaluate_generator(valid_generator,
valid_generator.samples)
print('\n', 'Valid accuracy:', score[1])
#evaluate and print test accuracy
score = model.evaluate_generator(test_generator,
test_generator.samples)
print('\n', 'Test accuracy:', score[1])
Любопытно, что я заметил, что:
Когда я не использую масштабирование (1./ 255):
datagen_train = ImageDataGenerator()
datagen_test = ImageDataGenerator()
datagen_valid = ImageDataGenerator()
значение validation_score, отображаемое с помощью обратных вызовов (0,5), этоточно то же самое, полученное из model.evaluate_generator (0.5);Кроме того, тестовый набор возвращает оценку точности = 0,5.
Когда я использую масштабирование (1./255):
datagen_train = ImageDataGenerator(rescale=1./255)
datagen_test = ImageDataGenerator(rescale=1./255)
datagen_valid = ImageDataGenerator(rescale=1./255)
разница между значением validation_score, отображаемым обратными вызовами (0,9515):
Epoch 7/10
688/688 [==============================] - 67s 97ms/step - loss:
0.2017 - acc: 0.9496 - val_loss: 0.1767 - val_acc: 0.9515
Epoch 00007: val_loss improved from 0.19304 to 0.17671, saving model
to cnn_model.weights.best.hdf5
, и оценкой, полученной из model.evaluate_generator (Valid accuracy: 0.9466618287373004
) он очень маленький;Использование набора тестов - Test accuracy: 0.9078374455732946
Исходя из этой небольшой разницы между оценочными показателями, могу ли я сделать вывод, чтоя оценка_генератора работает корректно?И могу ли я сделать вывод, что оценка точности на test_set также является правильной?Или есть другой подход к решению этой проблемы?
Я разочарован этой проблемой.Извините за длинный пост, я пытаюсь быть более дидактическим, я могу.
Спасибо!