【发布时间】:2019-09-22 13:16:45
【问题描述】:
是否可以在回调中设置model.loss 而无需在之后重新编译model.compile(...)(此后优化器状态被重置),而只需重新编译model.loss,例如:
class NewCallback(Callback):
def __init__(self):
super(NewCallback,self).__init__()
def on_epoch_end(self, epoch, logs={}):
self.model.loss=[loss_wrapper(t_change, current_epoch=epoch)]
self.model.compile_only_loss() # is there a version or hack of
# model.compile(...) like this?
要扩展更多关于 stackoverflow 的示例:
要实现一个依赖于纪元数的损失函数,比如(如this stackoverflow question):
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”是一个使用回调更新的 Keras 变量:
current_epoch = K.variable(0.)
model.compile(optimizer=opt, loss=loss_wrapper(5, current_epoch),
metrics=...)
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)
基本上可以将 python 代码转换为后端函数的组合,以便 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
it works.
我对这些 hack 不满意,并且想知道,是否可以在回调中设置 model.loss 而无需在之后重新编译 model.compile(...)(此后优化器状态被重置),而只需重新编译 model.loss?
【问题讨论】:
-
你解决了吗?您需要保持整个优化器状态还是只保留权重?如果只是权重,也许保存它们,重新编译,然后加载它们。有 Model.load_weights(..., by_name=True) 可以加载到与保存它们不同的模型中。还有像stackoverflow.com/questions/49503748/… 这样的保存/加载整个状态,但我不确定它是否允许您更改架构。
-
您找到解决方案了吗?我也有同样的问题。
-
我认为使用动态计算图或
eager execution模式与tf 2.0将解决这个问题eager execution -
根据您的最后一种方法,我不觉得有一个单一的损失函数太难了。您也可以使用 model.add_loss() 来做类似的事情,而无需使用包装器。
标签: python keras callback epoch loss