乘以输出自定义损失函数

时间:2019-09-27 16:10:20

标签: python keras

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

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_predy1y2。但是现在我既需要计算损失,又要如何定义此损失函数并将所有参数传递给该函数: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

谢谢!

1 个答案:

答案 0 :(得分:0)

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

损失函数必须同时包含预测数据和实际数据-这是一种衡量模型预测的数据与真实数据之间的误差的方法。但是,预测数据和实际数据不必是一维的。您可以使y_pred既包含y_pred1也包含y_pred2的张量。同样,y_true可以是同时包含y_true1y_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])

下面,我将展示一个示例,说明如何重写损失函数。我不确定要调用y_true1y_true2的输出的5列中的哪一列,因此我猜想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)