Возобновить обучение с другой функцией потери - PullRequest
2 голосов
/ 28 марта 2019

Я хочу реализовать двухэтапный процесс обучения, где:
1) предварительно обучить модель для нескольких эпох, используя функцию потерь loss_1
2) измените функцию потерь на loss_2 и продолжите обучение тонкой настройке

В настоящее время мой подход:

model.compile(optimizer=opt, loss=loss_1, metrics=['accuracy'])
model.fit_generator(…)
model.compile(optimizer=opt, loss=loss_2, metrics=['accuracy’])
model.fit_generator(…)

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

a) Потеряю ли я состояние оптимизатора, даже если использую тот же оптимизатор , например, Adam?
б) если ответ на а) положительный, какие-либо предложения о том, как изменить функцию потерь на новую без сброса состояния оптимизатора?

EDIT:
По предложению Саймона Кэби и основываясь на этой теме , я создал собственную функцию потерь с двумя расчетами потерь, которые зависят от числа эпох. Тем не менее, это не работает для меня. Мой подход:

def loss_wrapper(t_change, current_epoch):
    def custom_loss(y_true, y_pred):
       c_epoch = K.get_value(current_epoch)
       if c_epoch < t_change:
           # compute loss_1
       else:
           # compute loss_2
    return custom_loss

И я компилирую следующим образом, после инициализации current_epoch:

current_epoch = K.variable(0.)
model.compile(optimizer=opt, loss=loss_wrapper(5, current_epoch), metrics=...)

Чтобы обновить current_epoch, я создаю обратный вызов:

class NewCallback(Callback):
    def __init__(self, current_epoch):
        self.current_epoch = current_epoch

    def on_epoch_end(self, epoch, logs={}):
        K.set_value(self.current_epoch, epoch)

model.fit_generator(..., callbacks=[NewCallback(current_epoch)])

Обратный вызов корректно обновляет self.current_epoch каждую эпоху. Но обновление не достигает пользовательской функции потери. Вместо этого current_epoch сохраняет значение инициализации навсегда, а loss_2 никогда не выполняется.

Любые предложения приветствуются, спасибо!

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Мои ответы: а) да, и вам, вероятно, следует создать свой собственный планировщик скорости обучения, чтобы контролировать его:

keras.callbacks.LearningRateScheduler(schedule, verbose=0)

б) да, вы можете создать свою собственную функцию потерь, включая однуэто колеблется между двумя различными методами потери.см .: «Advanced Keras - Построение сложных пользовательских потерь и метрик» https://towardsdatascience.com/advanced-keras-constructing-complex-custom-losses-and-metrics-c07ca130a618

0 голосов
/ 04 мая 2019

Если вы измените:

def loss_wrapper(t_change, current_epoch):
    def custom_loss(y_true, y_pred):
        c_epoch = K.get_value(current_epoch)
        if c_epoch < t_change:
            # compute loss_1
        else:
            # compute loss_2
    return custom_loss

до:

def loss_wrapper(t_change, current_epoch):
    def custom_loss(y_true, y_pred):
        # compute loss_1 and loss_2
        bool_case_1=K.less(current_epoch,t_change)
        num_case_1=K.cast(bool_case_1,"float32")
        loss = (num_case_1)*loss_1 + (1-num_case_1)*loss_2
        return loss
    return custom_loss

это работает.

Мы, по сути, обязаны превратить код Python в композиции бэкэнд-функций, чтобы потеря работала без обновления при повторной компиляции model.compile(...). Я не удовлетворен этими взломами и хотел бы установить model.loss в обратном вызове без повторной компиляции model.compile(...) после (с тех пор состояния оптимизатора сбрасываются).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...