Точность, которую выводит генератор подгонки в Keras, отличается от точности, рассчитанной вручную

Это работало нормально, когда я использовал fit, но когда я использовал fit_generator, у меня возникла проблема.

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

Однако точность, полученная из матрицы путаницы, и точность проверки, выводимая из keras, различаются.

Точность, которую выводит генератор подгонки в Keras, отличается от точности, рассчитанной вручную

Мой код ниже.

    metrics = Valid_checker(model_name, args.patience, (x_valid, y_valid), x_length_valid)       
    model.compile(optimizer=optimizers.RMSprop(lr=args.lr),
      loss=[first_loss],
      loss_weights=[1.],
      metrics = {'capsnet': 'accuracy'})
    callback_list = [lr_decay, metrics]

    model.fit_generator(
                no_decoder_generator(x_train, y_train),
                steps_per_epoch=len(x_train),
                epochs=args.epochs,
                validation_data=no_decoder_generator(x_valid, y_valid),
                validation_steps=len(x_valid),
                callbacks=callback_list,
                #class_weight=class_weights,
                verbose=1)

Valid check — мой метод обратного вызова. no_decoder_generator — мой генератор декодеров. и мой размер партии поезда и проверки равен 1.

Это мой Valid_check класс. (ниже)

class Valid_checker(keras.callbacks.Callback):
        def __init__(self, model_name, patience, val_data, x_length):
            super().__init__()
            self.best_score = 0
            self.patience = patience
            self.current_patience = 0 
            self.model_name = model_name
            self.validation_data = val_data
            self.x_length = x_length


        def on_epoch_end(self, epoch, logs = {}):
            X_val, y_val = self.validation_data
            if args.decoder==1:
                y_predict, x_predict = model.predict_generator(no_decoder_generator(X_val, y_val), steps=len(X_val))
                y_predict = np.asarray(y_predict)
                x_predict = np.asarray(x_predict)                       

            else:
                y_predict = np.asarray(model.predict_generator(predict_generator(X_val), steps=len(X_val)))

            y_val, y_predict = get_utterence_label_pred(y_val, y_predict, self.x_length )
            cnf_matrix = get_accuracy_and_cnf_matrix(y_val, y_predict)[1]
            val_acc_custom =  get_accuracy_and_cnf_matrix(y_val, y_predict)[0]
            war = val_acc_custom[0]
            uar = val_acc_custom[1]
            score = round(0.2*war+0.8*uar,2)

            loss_message=''
            # custom ModelCheckpoint & early stopping by using UAR            
            loss_message='loss: %s - acc: %s - val_loss: %s - val_acc: %s'%(round(logs.get('loss'),4), round(logs.get('acc'),4), round(logs.get('val_loss'),4), round(logs.get('val_acc'),4))
            log('[Epoch %03d/%03d]'%(epoch+1, args.epochs))
            log(loss_message)
            log('Confusion matrix:')
            log('%s'%cnf_matrix)
            log('Valid [WAR] [UAR] [Custom] : %s [%s]'%(val_acc_custom,score))

            if score > self.best_score :
                model.save_weights(model_name)
                log('Epoch %05d: val_uar_acc improved from %s to %s saving model to %s'%(epoch+1, self.best_score, score, self.model_name))
                self.best_score = score
                self.current_patience = 0

            else :
                self.current_patience+=1

            # early stopping
            if self.current_patience == (self.patience-1):
                self.model.stop_training = True
                log('Epoch %05d: early stopping' % (epoch + 1)) 
            return        

Он должен быть равен val_acc выходу keras и war. Однако значение другое. Почему это происходит? Я подтвердил, что проблем с get_utterence_label_pred и get_accuracy_and_cnf_matrix нет. Это хорошо работает, когда я использую функцию подгонки.

Мой генератор ниже.

def predict_generator(x):
while True:
    for index in range(len(x)):
        feature = x[index]
        feature = np.expand_dims(x[index],-1)
        feature = np.expand_dims(feature,0) # make (1,input_height,input_width,1) 
        yield (feature)

def no_decoder_generator(x, y):
while True:
    indexes = np.arange(len(x))
    np.random.shuffle(indexes)
    for index in indexes:
        feature = x[index]
        feature = np.expand_dims(x[index],-1)
        feature = np.expand_dims(feature,0) # make (1,input_height,input_width,1) 
        label = y[index]
        label = np.expand_dims(label,0)
        yield (feature, label)

Epoch 1/70
1858/1858 [==============================] - 558s 300ms/step - loss: 1.0708 - acc: 0.5684 - val_loss: 0.9087 - val_acc: 0.6244 [Epoch 001/070]
loss: 1.0708 - acc: 0.5684 - val_loss: 0.9087 - val_acc: 0.6244
Confusion matrix:
[[ 0. 28. 68. 4. ]
[ 0. 13.33 80. 6.67]
[ 0.96 2.88 64.42 31.73]
[ 0. 0. 3.28 96.72]]
Valid [WAR] [UAR] [Custom] : [62.44 43.62] [47.38]

Epoch 2/70 1858/1858 [==============================] - 262s 141ms/step - loss: 0.9526 - acc: 0.6254 - val_loss: 1.1998 - val_acc: 0.4537 [Epoch 002/070]
loss: 0.9526 - acc: 0.6254 - val_loss: 1.1998 - val_acc: 0.4537
Confusion matrix:
[[ 36. 12. 24. 28. ]
[ 20. 0. 46.67 33.33]
[ 4.81 0.96 24.04 70.19]
[ 0. 0. 0. 100. ]]
Valid [WAR] [UAR] [Custom] : [46.34 40.01] [41.28]

Обычно эта проблема связана с тем, что что-то отличается, например, не применяется нормализация к вашим данным в генераторе. Пожалуйста, проверьте это.

Dr. Snoopy 10.04.2019 07:45

@MatiasValdenegro На самом деле я уже выполнил предварительную обработку данных. x_valid — это уже предварительно обработанные данные. Или вы говорите о пакетной нормализации?

Jeonghwa Yoo 10.04.2019 08:43

@MatiasValdenegro, это правда, что вы говорите, но в этом случае (а также в моем и во многих других) проблема связана с fit_generator. В моем случае результаты, полученные с помощью fit_generator, были лучше, чем при ручном тестировании с помощью model.predict() на моем наборе test_dataset.

Timbus Calin 10.10.2019 15:09
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
1 418
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я решил эту проблему, используя последовательность вместо генератора.

Я могу узнать, почему это явление происходит в следующих источниках.

https://github.com/keras-team/keras/issues/11878

Простой пример использования последовательности показан ниже.

https://medium.com/datadriveninvestor/keras-training-on-large-datasets-3e9d9dbc09d4

я знаю! Это может быть связано с тем, что ваша модель хранит точность последней эпохи, а не лучшую историческую точность. Поэтому точность ручного расчета не является оптимальной точностью. Вы можете кодировать так

1. Сохраните оптимальную модель в файл

callbacks= [callback_list.ModelCheckpoint(
        filepath='best_model.{epoch:02d}-{val_acc:.2f}.h5',
        monitor='val_acc', save_best_only=True,verbose=1)]

2. Загрузите модель

model = load_model('best_model.03-0.69.h5')

Другие вопросы по теме