Keras fit_generator и результаты подгонки разные - PullRequest
0 голосов
/ 02 октября 2018

Я тренирую Сверточную Нейронную Сеть, используя набор данных изображений лица.Набор данных имеет 10 000 изображений размером 700 x 700. Моя модель имеет 12 слоев.Я использую функцию генератора для чтения изображений в функцию Keras fit_generator, как показано ниже.

train_file_names ==> Список Python, содержащий имена файлов учебных примеровtrain_class_labels ==> Массив массивов меток класса с горячим кодированием ([0, 1, 0], [0, 0, 1] и т. д.)train_data ==> Множество обучающих примеровtrain_steps_epoch ==> 16 (размер пакета равен 400, и у меня есть 6400 экземпляров для обучения. Следовательно, для одного прохода всего набора данных требуется 16 итераций)batch_size ==> 400call_made ==> Когда генератор достигает конца обучающих экземпляров, он сбрасывает индексы для загрузки данных из первого индекса в следующую эпоху.

Я передаю этот генератор в качестве аргумента функции keras 'fit_generator', чтобы сгенерировать новый пакет данных для каждой эпохи.

val_data, val_class_labels ==> Проверочные массивы данныхэпох ==> Количество эпох

Использование Keras fit_generator :

model.fit_generator(generator=train_generator, steps_per_epoch=train_steps_per_epoch, epochs=epochs, use_multiprocessing=False, validation_data=[val_data, val_class_labels], verbose=True, callbacks=[history, model_checkpoint], shuffle=True, initial_epoch=0) 

Код

def train_data_generator(self):     
    index_start = index_end = 0 
    temp = 0
    calls_made = 0

    while temp < train_steps_per_epoch:
        index_end = index_start + batch_size
        for temp1 in range(index_start, index_end):
            index = 0
            # Read image
            img = cv2.imread(str(TRAIN_DIR / train_file_names[temp1]), cv2.IMREAD_GRAYSCALE).T
            train_data[index]  = cv2.resize(img, (self.ROWS, self.COLS), interpolation=cv2.INTER_CUBIC)
            index += 1       
        yield train_data, self.train_class_labels[index_start:index_end]
        calls_made += 1
        if calls_made == train_steps_per_epoch:
            index_start = 0
            temp = 0
            calls_made = 0
        else:
            index_start = index_end
            temp += 1  
        gc.collect()

Выход fit_generator

Эпоха 86/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,5739 - согласно: 0,2991 - val_loss: 12.0076 - val_acc: 0.2110Эпоха 87/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,6010 - согласно: 0,2549 - val_loss: 11.6689 - val_acc: 0.2016Эпоха 88/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,5750 - согласно: 0,2391 - val_loss: 10.2663 - val_acc: 0.2004Эпоха 89/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,5526 - в соответствии с 0,2641 - val_loss: 11.8809 - val_acc: 0,2249Эпоха 90/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,5867 - согласно: 0,2602 - val_loss: 12.0392 - val_acc: 0.2010Эпоха 91/30016/16 [==============================] - 16 с 1 с / шаг - потеря: 1,5524 - согласно: 0,2609 - val_loss: 12.0254 - val_acc: 0,2027

Моя проблема в том, что при использовании 'fit_generator' с вышеуказанной функцией генератора, как указано выше, потери в моей модели не улучшаются, а точность проверки очень низкая.Но когда я использую функцию «подгонки» keras, как показано ниже, потери в модели уменьшаются, а точность проверки намного выше.

Использование функции подбора Keras без использования генератора

model.fit(self.train_data, self.train_class_labels, batch_size=self.batch_size, epochs=self.epochs, validation_data=[self.val_data, self.val_class_labels], verbose=True, callbacks=[history, model_checkpoint])    

Выход при обучении с использованием функции подгонки

Epoch 25 /3006400/6400 [==============================] - 20 с 3 мс / шаг - потеря: 0,0207 - согласно: 0,9939 - val_loss: 4.1009 - val_acc: 0.4916Эпоха 26/3006400/6400 [==============================] - 20 с 3 мс / шаг - потеря: 0,0197 - согласно: 0,9948 - val_loss: 2,4758 - val_acc: 0,5568Эпоха 27/3006400/6400 [====================================] - 20 с 3 мс / шаг - потеря: 0,0689 - согласно: 0,9800 - val_loss: 1.2843 - val_acc: 0.7361Эпоха 28/3006400/6400 [====================================] - 20 с 3 мс / шаг - потеря: 0,0207 - согласно: 0,9947 - val_loss: 5.6979 - val_acc: 0.4560Эпоха 29/3006400/6400 [==============================] - 20 с 3 мс / шаг - потеря: 0,0353 - согласно: 0,9988 - val_loss: 1.0801 - val_acc: 0.7817Эпоха 30/3006400/6400 [====================================] - 20 с 3 мс / шаг - потеря: 0,0362 - согласно: 0,9896 - val_loss: 3.7851 - val_acc: 0.5173Эпоха 31/3006400/6400 [====================================] - 20 с 3 мс / шаг - потеря: 0,0481 - согласно: 0,9896 - val_loss: 1.1152 - val_acc: 0.7795Эпоха 32/3006400/6400 [==============================] - 20 с 3 мс / шаг - потеря: 0,0106 - согласно: 0,9969 - val_loss: 1,4803 - val_acc: 0,7372

1 Ответ

0 голосов
/ 29 января 2019

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

Источник: https://github.com/keras-team/keras/issues/2389 и собственный опыт.

...