简体   繁体   English

在 Keras 训练期间动态更改损失函数,无需重新编译其他模型属性,如优化器

[英]Change loss function dynamically during training in Keras, without recompiling other model properties like optimizer

Is it possible to set model.loss in a callback without re-compiling model.compile(...) after (since then the optimizer states are reset), and just recompiling model.loss , like for example:是否可以在回调中设置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?

To expand more with previous examples on stackoverflow:要使用之前关于 stackoverflow 的示例进行更多扩展:

To achieve a loss function which depends on the epoch number, like (as in this stackoverflow question ):要实现依赖于纪元数的损失函数,例如(如在这个 stackoverflow 问题中):

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

where "current_epoch" is a Keras variable updated with a callback:其中“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)

One can essentially turn python code into compositions of backend functions for the loss to work as follows:从本质上讲,可以将 python 代码转换为后端函数的组合,使损失工作如下:

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.

I am not satisfied with these hacks, and wonder, is it possible to set model.loss in a callback without re-compiling model.compile(...) after (since then the optimizer states are reset), and just recompiling model.loss ?我对这些 hack 不满意,想知道是否可以在回调中设置model.loss而无需重新编译model.compile(...)之后(从那时起优化器状态被重置),而只是重新编译model.loss

I hope you have found a solution to your problem by now but using tensorflow I think you can solve this by building a custom training loop ( here is the doc ).我希望您现在已经找到了解决问题的方法,但是使用 tensorflow 我认为您可以通过构建自定义训练循环来解决此问题( 这是文档)。 this will not override the loss attribute as you requested however you can probably achieve what you are looking for.这不会按照您的要求覆盖 loss 属性,但是您可能可以实现您想要的。

example例子

initializing variable初始化变量

modifying the example from the documentation, with a model and dataset as such:修改文档中的示例,使用模型和数据集:

inputs = tf.keras.Input(shape=(784,), name="digits")
x1 = tf.keras.layers.Dense(64, activation="relu")(inputs)
x2 = tf.keras.layers.Dense(64, activation="relu")(x1)
outputs = tf.keras.layers.Dense(10, name="predictions")(x2)
model = tf.keras.Model(inputs=inputs, outputs=outputs)


# Prepare the training dataset.
batch_size = 64
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = np.reshape(x_train, (-1, 784))
x_test = np.reshape(x_test, (-1, 784))
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size)

we can define our two loss functions (the two I chose make no sense from a scientific point of view but allow us to check the code works)我们可以定义我们的两个损失函数(我选择的两个从科学的角度来看没有意义,但允许我们检查代码是否有效)

# Instantiate an optimizer.
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
# Instantiate a loss function.
loss_1 = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
loss_2 = lambda y_true, y_pred: -1 * loss_1(y_true, y_pred)

training loop训练循环

we can then execute our custom training loop:然后我们可以执行我们的自定义训练循环:

epochs = 10
for epoch in range(epochs):
    print("\nStart of epoch %d" % (epoch,))

    # Iterate over the batches of the dataset.
    for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):

        # Open a GradientTape to record the operations run
        # during the forward pass, which enables auto-differentiation.
        loss_fn = loss_1 if epoch % 2 else loss_2
        with tf.GradientTape() as tape:

            # Run the forward pass of the layer.
            # The operations that the layer applies
            # to its inputs are going to be recorded
            # on the GradientTape.
            logits = model(x_batch_train, training=True)  # Logits for this minibatch

            # Compute the loss value for this minibatch.
            loss_value = loss_fn(y_batch_train, logits)

        # Use the gradient tape to automatically retrieve
        # the gradients of the trainable variables with respect to the loss.
        grads = tape.gradient(loss_value, model.trainable_weights)

        # Run one step of gradient descent by updating
        # the value of the variables to minimize the loss.
        optimizer.apply_gradients(zip(grads, model.trainable_weights))
         # Log every 200 batches.
        if step % 200 == 0:
            print(
                "Training loss (for one batch) at step %d: %.4f"
                % (step, float(loss_value))
            )
            print("Seen so far: %s samples" % ((step + 1) * 64))

and we check the output is what we want (alternate positive and negative losses)我们检查输出是我们想要的(交替的正负损失)

Start of epoch 0
Training loss (for one batch) at step 0: -96.1003
Seen so far: 64 samples
Training loss (for one batch) at step 200: -3383849.5000
Seen so far: 12864 samples
Training loss (for one batch) at step 400: -40419124.0000
Seen so far: 25664 samples
Training loss (for one batch) at step 600: -149133008.0000
Seen so far: 38464 samples
Training loss (for one batch) at step 800: -328322816.0000
Seen so far: 51264 samples

Start of epoch 1
Training loss (for one batch) at step 0: 580457984.0000
Seen so far: 64 samples
Training loss (for one batch) at step 200: 297710528.0000
Seen so far: 12864 samples
Training loss (for one batch) at step 400: 213328544.0000
Seen so far: 25664 samples
Training loss (for one batch) at step 600: 159328976.0000
Seen so far: 38464 samples
Training loss (for one batch) at step 800: 105737024.0000
Seen so far: 51264 samples

drawbacks and further improvments缺点和进一步改进

the problem with writing custom loops as such is that you will loose the convenience of keras's fit method.编写自定义循环的问题在于,您将失去 keras 的fit方法的便利性。 I think you can manage this by defining a custom model and overriding the train_step as shown here in the documentation我想你可以通过定义自定义模型并重写管理这个train_step如图所示这里的文档

If you really need to have the loss attribute of your model changed, you can set the compiled_loss attribute using a keras.engine.compile_utils.LossesContainer ( here is the reference) and set model.train_function to model.make_train_function() (so that the new loss gets taken into account).如果你真的需要有loss模型的属性改变,你可以设置compiled_loss使用属性keras.engine.compile_utils.LossesContainer这里为基准),并设置model.train_functionmodel.make_train_function()以便新的损失被考虑在内)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以在训练期间动态更改损失函数? - Is it possible to change the loss function dynamically during training? 如何在训练期间替换损失函数 tensorflow.keras - How to replace loss function during training tensorflow.keras 在 Keras 训练期间如何在损失函数内打印? - How do I print inside the loss function during training in Keras? 训练 Keras 模型会产生多个优化器错误 - Training a Keras model yields multiple optimizer errors 联合损失函数的多输出Keras模型训练 - Training of multi-output Keras model on a joint loss function Keras 训练期间损失的移动平均 - Moving averaging of Loss during Training in Keras 编译 Keras model 时出现错误 function - Error during compiling a Keras model with own loss function Keras 功能 API:我的 model 仅针对一个损失函数进行优化,而不是训练损失函数 ZC1C425268E68385D14AB5074C17A - Keras functional API: My model is only optimizing for one loss function instead of 2 loss functions while training 在 Keras 中训练多输出模型期间仅显示总损失 - Only show total loss during training of a multi-output model in Keras tensorflow.keras model 准确度、损失和验证指标在训练期间保持 ZA81259CEF8E959C2297DF1D456EZ5 - tensorflow.keras model accuracy, loss, and validation metrics remain static during 30 epochs of training
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM