Это моя первая попытка сделать что-то с CNN, поэтому я, вероятно, делаю что-то очень глупое - но не могу понять, в чем я не прав ...
Модель, кажется, учится хорошо,но точность проверки не улучшается (никогда - даже после первой эпохи), и потеря проверки со временем фактически увеличивается.Это не похоже на то, что я перегружаюсь (после 1 эпохи?) - мы должны отключиться каким-то другим способом.
типичное поведение сети
Я тренирую CNNсеть - у меня есть ~ 100 тыс. изображений различных растений (1000 классов), и я хочу настроить ResNet50 для создания классификатора муликласса.Изображения имеют разные размеры, я загружаю их так:
from keras.preprocessing import image
def path_to_tensor(img_path):
# loads RGB image as PIL.Image.Image type
img = image.load_img(img_path, target_size=(IMG_HEIGHT, IMG_HEIGHT))
# convert PIL.Image.Image type to 3D tensor with shape (IMG_HEIGHT, IMG_HEIGHT, 3)
x = image.img_to_array(img)
# convert 3D tensor to 4D tensor with shape (1, IMG_HEIGHT, IMG_HEIGHT, 3) and return 4D tensor
return np.expand_dims(x, axis=0)
def paths_to_tensor(img_paths):
list_of_tensors = [path_to_tensor(img_path) for img_path in img_paths] #can use tqdm(img_paths) for data
return np.vstack(list_of_tensors)enter code here
База данных велика (не помещается в память) и должна была создать собственный генератор, чтобы обеспечить как чтение с диска, так и увеличение.(Я знаю, что у Keras есть .flow_from_directory () - но мои данные не структурированы таким образом - это просто дамп 100k изображений, смешанных с файлами 100k метаданных).Возможно, мне следовало бы создать сценарий, чтобы лучше их структурировать, а не создавать собственные генераторы, но проблема, скорее всего, где-то в другом месте.
В приведенной ниже версии генератора пока не делается никаких дополнений - просто масштабируется:
def generate_batches_from_train_folder(images_to_read, labels, batchsize = BATCH_SIZE):
#Generator that returns batches of images ('xs') and labels ('ys') from the train folder
#:param string filepath: Full filepath of files to read - this needs to be a list of image files
#:param np.array: list of all labels for the images_to_read - those need to be one-hot-encoded
#:param int batchsize: Size of the batches that should be generated.
#:return: (ndarray, ndarray) (xs, ys): Yields a tuple which contains a full batch of images and labels.
dimensions = (BATCH_SIZE, IMG_HEIGHT, IMG_HEIGHT, 3)
train_datagen = ImageDataGenerator(
rescale=1./255,
#rotation_range=20,
#zoom_range=0.2,
#fill_mode='nearest',
#horizontal_flip=True
)
# needs to be on a infinite loop for the generator to work
while 1:
filesize = len(images_to_read)
# count how many entries we have read
n_entries = 0
# as long as we haven't read all entries from the file: keep reading
while n_entries < (filesize - batchsize):
# start the next batch at index 0
# create numpy arrays of input data (features)
# - this is already shaped as a tensor (output of the support function paths_to_tensor)
xs = paths_to_tensor(images_to_read[n_entries : n_entries + batchsize])
# and label info. Contains 1000 labels in my case for each possible plant species
ys = labels[n_entries : n_entries + batchsize]
# we have read one more batch from this file
n_entries += batchsize
#perform online augmentation on the xs and ys
augmented_generator = train_datagen.flow(xs, ys, batch_size = batchsize)
yield next(augmented_generator)
Вот как я определяю свою модель:
def get_model():
# define the model
base_net = ResNet50(input_shape=DIMENSIONS, weights='imagenet', include_top=False)
# Freeze the layers which you don't want to train. Here I am freezing all of them
for layer in base_net.layers:
layer.trainable = False
x = base_net.output
#for resnet50
x = Flatten()(x)
x = Dense(512, activation="relu")(x)
x = Dropout(0.5)(x)
x = Dense(1000, activation='softmax', name='predictions')(x)
model = Model(inputs=base_net.input, outputs=x)
# compile the model
model.compile(
loss='categorical_crossentropy',
optimizer=optimizers.Adam(1e-3),
metrics=['acc'])
return model
Итак, в результате у меня есть 1 562 088 обучаемых параметров для примерно 70 тыс. Изображений
Затем я использую5-кратная перекрестная проверка, но модель не работает ни в одном из сгибов, поэтому я не буду включать здесь полный код, уместно следующее:
trial_fold = temp_model.fit_generator(
train_generator,
steps_per_epoch = len(X_train_path) // BATCH_SIZE,
epochs = 50,
verbose = 1,
validation_data = (xs_v,ys_v),#valid_generator,
#validation_steps= len(X_valid_path) // BATCH_SIZE,
callbacks = callbacks,
shuffle=True)
Я сделал разные вещи- удостоверился, что мой генератор действительно работает, попытался поиграть с последними несколькими слоями сети, уменьшив размер полностью подключенного слоя, попробовал увеличение - ничего не помогает ...
Я не думаю, чтоколичество параметров в сети слишком велико - я знаю, что другие люди сделали то же самое и получили точность ближе к 0,5, но мои модели, кажется, перегруженыкак сумасшедшийЛюбые идеи о том, как решить эту проблему, будут высоко оценены!
Обновление 1:
Я решил прекратить переизобретать материал и сортировать по файлам для работы с .flow_from_directory () процедура.Чтобы убедиться, что я импортирую правильный формат (вызванный комментарием Ioannis Nasios ниже) - я позаботился о preprocessing_unit () из приложения keras resnet50.
Я также решил проверить, действительно ли модель производитчто-то полезное - я вычислил возможности Botleneck для своего набора данных, а затем использовал случайный лес для прогнозирования классов.Это сработало, и я получил точность около 0,4
Итак, я думаю, что у меня определенно была проблема с форматом ввода моих изображений.В качестве следующего шага я уточню модель (с новым верхним слоем), чтобы увидеть, остается ли проблема ...
Обновление 2:
Iдумаю, что проблема была с предварительной обработкой изображения.В итоге я не смог выполнить точную настройку, а просто извлек слой «ботлнек» и обучил linear_SVC () - получил точность около 60% поезда и около 45% наборов тестовых данных.