keras 中带有 train_on_batch 的自定义 Loss fnc 用于重放学习

Posted

技术标签:

【中文标题】keras 中带有 train_on_batch 的自定义 Loss fnc 用于重放学习【英文标题】:custom Loss fnc with train_on_batch in keras for replay learning 【发布时间】:2021-04-10 08:57:41 【问题描述】:

学习者,

我想用 mini-batches using a custom loss function 训练一个 NN。每个小批量包含n new samples and m replay samples。回放样本用于回放以避免遗忘。

我的损失 fnc 看起来像:

loss=mse(new_samples_truth, new_samples_pred) + factor*mse(replay_samples_truth, replay_sampls_pred)

如您所见,损失是为新样本和重放样本分别计算的两个 mse 的加权和。 这意味着每当我想训练一个批次时,我想分离新数据点和重放数据点并计算整个批次的标量损失。

如何在Keras 中实现此损失函数并将其与 train_on_batch 一起使用? Keras 的 train_on_batch 方法似乎使用损失函数分别计算小批量中每个数据点的损失。由于我的批次包含新的和重放数据点,​​这将不起作用。 So how can I Keras make calculate the Loss for the entire batch at once and return only once scalar? 另外,Keras 似乎单独评估了每个数据点的损失 fnc,并将每个样本的损失保存在一个数组中。但是,我想获得整个批次的损失。有人了解 Keras 是如何实际处理批次的损失计算的吗?

这是我的伪代码

    batch=pd.concat([new_samples, replay_samples]) #new_samples and replay_samples are pd.dataframes
    #len(batch) = 20

   def my_replay_loss(factor):
       def loss(y_true, y_pred): #y_true and y_pred come from keras 

           y_true_new_samples = y_true.head(10)
           y_pred_new_samples = y_pred.head(10)
           y_true_replay_samples = y_true.tail(10)
           y_pred_replay_samples = y_pred.tail(10)
           
           calc_loss = mse(y_true_new_samples, y_pred_new_samples) + factor*mse(y_true_replay_samples, y_pred_replay_samples)
           return calc_loss

        return loss

'''

【问题讨论】:

【参考方案1】:

您可以像以前一样定义自定义损失函数,但您需要使用 tf 操作构造一个 tf 图,这里是一个示例:

def my_replay_loss(factor):
    def loss(y_true, y_pred):
        calc_loss = tf.math.add(tf.keras.losses.mse(y_true[:10, :], y_pred[:10, :]), 
                                tf.math.multiply(factor, tf.keras.losses.mse(y_true[-10:, :], y_pred[-10:, :])))
        return calc_loss
    return loss

然后你可以编译你的模型:

loss=my_replay_loss(factor=tf.constant(0.5, dtype=tf.float32))

但是,在您的情况下,我建议不要根据批处理中数据点的顺序构建损失函数,但我建议构建一个具有 2 个输入和 2 个输出的模型 (最终共享模型架构)并以 2 个损失编译它们。 Keras 模型支持 loss_weights 参数,可让您根据需要对两种损失进行加权。

loss_weights: 可选的列表或字典,指定标量系数(Python 浮点数)以加权不同模型输出的损失贡献。然后,模型将最小化的损失值将是所有单个损失的加权总和,由 loss_weights 系数加权。如果是列表,则预计与模型的输出有 1:1 的映射关系。如果是 dict,则应将输出名称(字符串)映射到标量系数。

这里是一个简单的例子:

import tensorflow as tf

def get_compiled_model(input_shape):
    
    input1 = tf.keras.Input(input_shape)
    input2 = tf.keras.Input(input_shape)

    conv_layer = tf.keras.layers.Conv2D(128, 3, activation='relu')
    flatten_layer = tf.keras.layers.Flatten()
    dense_layer = tf.keras.layers.Dense(1, activation='softmax')

    x1 = conv_layer(input1)
    x1 = flatten_layer(x1)
    output1 = dense_layer(x1)

    x2 = conv_layer(input2)
    x2 = flatten_layer(x2)
    output2 = dense_layer(x2)
    
    model = tf.keras.Model(inputs=[input1, input2], outputs=[output1, output2])
    
    model.compile(optimizer=tf.keras.optimizers.Adam(), 
                  loss=[tf.keras.losses.mse, tf.keras.losses.mse],
                  loss_weights=[1, 0.5])
    return model

model = get_compiled_model(input_shape=x_train[0].shape)
model.fit([x_train1, x_train2],  [y_train1, y_train2], epochs=5, batch_size=10)

【讨论】:

以上是关于keras 中带有 train_on_batch 的自定义 Loss fnc 用于重放学习的主要内容,如果未能解决你的问题,请参考以下文章

keras 在train_on_batch中启用tensorboard

Keras 中带有附加变量输入的自定义损失/目标函数

Keras中带有权重的自定义损失函数

Keras 中带有 LSTM 的多层 Seq2Seq 模型

在 keras 中制作自定义损失函数

损失函数中带有 SVM 的最后一层 CNN