【问题标题】:Resume training with different loss function使用不同的损失函数恢复训练
【发布时间】:2019-08-19 17:29:12
【问题描述】:

我想实施一个两步学习过程,其中:

  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(…)

请注意,优化器保持不变,只有损失函数发生变化。我想顺利地继续训练,但损失函数不同。根据this post,重新编译模型会丢失优化器状态。问题:

a) 即使我使用 same 优化器(例如 Adam),我是否会丢失优化器状态?
b) 如果 a) 的答案是肯定的,关于如何在不重置优化器状态的情况下将损失函数更改为新函数的任何建议?

编辑:
正如 Simon Caby 所建议并基于this thread,我创建了一个自定义损失函数,其中包含两个取决于时期数的损失计算。但是,它对我不起作用。我的做法:

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)])

回调在每个 epoch 正确更新 self.current_epoch。但是更新没有达到自定义损失函数。相反,current_epoch 永远保持初始化值,而loss_2 永远不会执行。

欢迎提出建议,谢谢!

【问题讨论】:

  • 我也有同样的问题,请问您找到解决方案了吗?

标签: keras loss-function


【解决方案1】:

我的答案: a) 是的,您可能应该制作自己的学习率调度程序以保持对它的控制:

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

b) 是的,您可以创建自己的损失函数,包括在两种不同损失方法之间波动的损失函数。请参阅:“高级 Keras  — 构建复杂的自定义损失和指标” https://towardsdatascience.com/advanced-keras-constructing-complex-custom-losses-and-metrics-c07ca130a618

【讨论】:

    【解决方案2】:

    如果你改变:

    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(...) 时进行更新。我对这些 hack 不满意,希望可以在回调中设置 model.loss 而无需在之后重新编译 model.compile(...)(此后优化器状态被重置)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 2019-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 2020-08-26
      • 2021-12-27
      相关资源
      最近更新 更多