首页 > 解决方案 > 乘以输出自定义损失函数

问题描述

所以我的问题是,如果我有类似的东西:

model = Model(inputs = input, outputs = [y1,y2])

model.compile(loss = my_loss ...) 

我只看到my_loss了独立损失的字典,然后,最终损失被定义为这些的总和。但是,我可以在多任务模型中定义一个损失函数来获取所有预测/真实值,然后我可以将它们相乘(例如)吗?

这是我试图定义的损失:

def my_loss(y_true1, y_true2, y_pred1, y_pred2):
   final_loss = binary_crossentropy(y_true1, y_pred1) + y_true1 * categorical_crossentropy(y_true2, y_pred2)
   return final_loss

通常,您的参数y_true, y_pred在损失函数中,其中y_predisy1y2。但是现在我都需要计算损失,那么我该如何定义这个损失函数并将所有参数传递给函数:y_true1, y_true2, y_pred1, y_pred2.

我想改变它的损失的当前模型:

x = Input(shape=(n, ))
shared = Dense(32)(x)
sub1 = Dense(16)(shared)
sub2 = Dense(16)(shared)
y1 = Dense(1)(sub1, activation='sigmoid')
y2 = Dense(4)(sub2, activation='softmax')

model = Model(inputs = input, outputs = [y1,y2])

model.compile(loss = ['binary_crossentropy', 'categorical_crossentropy'] ...) #THIS LINE I WANT TO CHANGE IT

谢谢!

标签: pythonkeras

解决方案


我不确定我是否理解正确,但我会尝试。

损失函数必须同时包含预测数据和实际数据——这是一种衡量模型预测数据与真实数据之间误差的方法。然而,预测数据和实际数据不需要是一维的。您可以制作y_pred一个同时包含y_pred1和的张量y_pred2。同样,y_true可以是同时包含y_true1和的张量y_true2

据我所知,损失函数应该返回一个数字。这就是为什么损失函数通常有一个平均值或一个总和来将单个数据点的所有损失相加。

这是一个适用于一维以上的均方误差示例:

import keras.backend as K

def my_loss(y_true, y_pred):
    # this example is mean squared error
    # works if if y_pred and y_true are greater than 1D
    return K.mean(K.square(y_pred - y_true))

这是我认为更接近您的问题的损失函数的另一个示例(尽管我无法评论它是否是一个好的损失函数):

def my_loss(y_true, y_pred):
    # calculate mean(abs(y_pred1*y_pred2 - y_true1*ytrue2)) 
    # this will work for 2D inputs of y_pred and y_true
    return K.mean(K.abs(K.prod(y_pred, axis = 1) - K.prod(y_true, axis = 1)))

更新:

您可以使用 将两个输出连接成一个张量keras.layers.Concatenate。这样你仍然可以有一个只有两个参数的损失函数。

在您上面编写的模型中,y1输出形状为(None, 1)y2输出形状为(None, 4)。这是一个如何编写模型的示例,以便输出是一个连接y1y1形成形状的单个张量(None, 5)

from keras import Model
from keras.layers import Input, Dense
from keras.layers import Concatenate

input_layer = Input(shape=(n, ))
shared = Dense(32)(input_layer)
sub1 = Dense(16)(shared)
sub2 = Dense(16)(shared)
y1 = Dense(1, activation='sigmoid')(sub1)
y2 = Dense(4, activation='softmax')(sub2)
mergedOutput = Concatenate()([y1, y2])

下面,我将展示一个示例,说明如何重写损失函数。我不确定要调用输出的 5 列中的哪一列y_true1vs. y_true2,所以我猜那y_true1是第 1 列,y_true2是剩下的 4 列。相同的列结构将适用于y_pred1y_pred2

from keras import losses

def my_loss(y_true, y_pred):
    final_loss = (losses.binary_crossentropy(y_true[:, 0], y_pred[:, 0]) + 
                    y_true[:, 0] * 
                  losses.categorical_crossentropy(y_true[:, 1:], y_pred[:,1:]))
    return final_loss

最后,您可以编译模型,而无需对正常情况进行任何重大更改:

model.compile(optimizer='adam', loss=my_loss)

推荐阅读