Keras 上的自定义损失函数

Posted

技术标签:

【中文标题】Keras 上的自定义损失函数【英文标题】:Custom loss function on Keras 【发布时间】:2020-02-27 14:30:07 【问题描述】:

我有一个数据集,其中包含一个特征矩阵 X 和一个大小为 N 的标签矩阵 y,其中每个元素 y_i 属于 [0,1]。我有以下损失函数

其中g(.) 是一个依赖于输入矩阵 X 的函数。 我知道 Keras 自定义损失函数必须采用 customLoss(y_true,y_predicted) 的形式,但是,我在将术语 g(X) 合并到损失函数中时遇到了困难,因为这取决于输入矩阵。

对于我数据集中的每个数据点,我的输入格式为 X_i = (H, P),其中这两个参数是矩阵,函数 g 为每个数据点定义为 g(X_i) = H x P。我可以在损失函数中传递a = (H, P),因为这取决于每个示例,还是我需要通过连接它们来一次传递所有矩阵?

编辑(基于丹尼尔的回答):

original_model_inputs = keras.layers.Input(shape=X_train.shape[1])
y_true_inputs = keras.layers.Input(shape=y_train.shape[1])
hidden1 = keras.layers.Dense(256, activation="relu")(original_model_inputs)
hidden2 = keras.layers.Dense(128, activation="relu")(hidden1)
output = keras.layers.Dense(K)(hidden2)

def lambdaLoss(x):
    yTrue, yPred, alpha = x
    return (K.log(yTrue) - K.log(yPred))**2+alpha*yPred

loss = Lambda(lambdaLoss)(y_true_inputs, output, a)

model = Keras.Model(inputs=[original_model_inputs, y_true_inputs], outputs=[output], loss)

def dummyLoss(true, pred):
    return pred

model.compile(loss = dummyLoss, optimizer=Adam())

train_model = model.fit([X_train, y_train], None, batch_size = 32, 
      epochs = 50, 
      validation_data = ([X_valid, y_valid], None), 
      callbacks=callbacks)

【问题讨论】:

你能具体谈谈你面临的困难吗? @ravikt:我已经更新了关于您的问题的帖子。谢谢。 我已经更新了答案 在这里回答,a 将是g: ***.com/questions/58566096/… @DanielMöller:在你提到我的答案中,你写了model.fit([x_train, y_train], anything_maybe_None_or_np_zeros ,....)。现在,我知道[x_train, y_train] 被视为模型的输入,但我应该使用y_train 而不是anything_maybe_None_or_np_zeros。我真的不明白你为什么说我们可以放anything_maybe_None_or_np_zeros。是否可以解释这一点?谢谢! 【参考方案1】:

修正对我答案的理解:

original_model_inputs = keras.layers.Input(shape=X_train.shape[1:]) #must be a tuple, not an int
y_true_inputs = keras.layers.Input(shape=y_train.shape[1:]) #must be a tuple, not an int

hidden1 = keras.layers.Dense(256, activation="relu")(original_model_inputs)
hidden2 = keras.layers.Dense(128, activation="relu")(hidden1)
output = keras.layers.Dense(K)(hidden2)

你需要做一些事情g(X),我不知道它是什么,但你需要在某个地方做。 是的,你需要一次通过整个张量,你不能让x_i 和其他所有东西。

def g(x):
    return something

gResults = Lambda(g)(original_model_inputs)

继续我的回答:

def lambdaLoss(x):
    yTrue, yPred, G = x

    .... #wait.... where is Y_true in your loss formula?

loss = Lambda(lambdaLoss)([y_true_inputs, output, gResults]) #must be a list of inputs including G

您需要一个模型进行训练,另一个模型来获得输出,因为我们正在做一个弗兰肯斯坦模型,因为损失不同。

training_model = keras.Model(inputs=[original_model_inputs, y_true_inputs], outputs=loss)
prediction_model = keras.Model(original_model_inputs, output) 

只需要编译训练模型:

def dummyLoss(true, pred):
    return pred

training_model.compile(loss = dummyLoss, optimizer=Adam())

training_model = model.fit([X_train, y_train], None, batch_size = 32, 
      epochs = 50, 
      validation_data = ([X_valid, y_valid], None), 
      callbacks=callbacks)

使用其他模型获取结果数据:

results = prediction_model.predict(some_x)

【讨论】:

【参考方案2】:

看起来像是某种 GAN。我将(x)称为“x_input”,两种方法:

方法一)从tf.keras.model类继承,自己写(不推荐,不展示)

方法 2) 从 tf.keras.losses.Loss 类继承。并返回(自定义)tf.keras.losses.Loss 实例和 tf.keras.layers.Layer 的元组,它们只不过充当外壳来抓取并保存 x_input (x) 的副本。然后可以将此层实例添加为模型的顶层。 (自定义)tf.keraslosses。然后损失实例可以按需访问输入。这种方法在 Tensorflow 的整个生命周期中也有最好的未来支持。

首先,创建自定义层和自定义损失类:

class Acrylic_Layer(tf.keras.layers.Layer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.x_input = None
        
    def build(self, *args, **kwargs):
        pass

    def call(self, input):
        self.x_input = input
        return input # Pass input directly through to next layer

class Custom_Loss(tf.keras.losses.Loss):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.input_thief = Acrylic_Layer() # <<< Magic, python is pass by reference!

    def __call__(self, y_true, y_pred, sample_weight=None):
        x_input = self.input_thief.x_input # <<< x_input pulled from model

二、给模型添加层和损失函数

loss_fn = Custom_Loss(*args, **kwargs)
input_thief = loss_fn.input_thief

model = tf.keras.models.Sequential([
    input_thief, # <<< transparent layer
    Other_layers,
])

model.fit(loss=loss_fn) # <<< loss function

最后,我是正在寻找 ML/python 角色的市场,大声呼喊。

【讨论】:

以上是关于Keras 上的自定义损失函数的主要内容,如果未能解决你的问题,请参考以下文章

Keras 中基于输入数据的自定义损失函数

Keras 中具有样本权重的自定义损失函数

Keras 中的自定义损失函数 - 遍历 TensorFlow

图像分割 - Keras 中的自定义损失函数

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

Keras 中的自定义损失函数应该返回批次的单个损失值还是训练批次中每个样本的一系列损失?