我正在尝试创建一个简单的加权损失函数。
比如,我的输入尺寸是100*5,输出尺寸也是100*5。我还有一个相同维度的权重矩阵。
如下所示:

import numpy as np
train_X = np.random.randn(100, 5)
train_Y = np.random.randn(100, 5)*0.01 + train_X

weights = np.random.randn(*train_X.shape)

定义自定义损失函数
def custom_loss_1(y_true, y_pred):
    return K.mean(K.abs(y_true-y_pred)*weights)

定义模型
from keras.layers import Dense, Input
from keras import Model
import keras.backend as K

input_layer = Input(shape=(5,))
out = Dense(5)(input_layer)
model = Model(input_layer, out)

使用现有度量进行测试工作良好
model.compile('adam','mean_absolute_error')
model.fit(train_X, train_Y, epochs=1)

用我们的自定义丢失功能测试不起作用
model.compile('adam',custom_loss_1)
model.fit(train_X, train_Y, epochs=10)

它提供以下堆栈跟踪:
InvalidArgumentError (see above for traceback): Incompatible shapes: [32,5] vs. [100,5]
 [[Node: loss_9/dense_8_loss/mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"](loss_9/dense_8_loss/Abs, loss_9/dense_8_loss/mul/y)]]

32号从哪里来?
用重量作为角膜张量测试损失函数
def custom_loss_2(y_true, y_pred):
    return K.mean(K.abs(y_true-y_pred)*K.ones_like(y_true))

这个功能似乎完成了工作。因此,可能表明角膜张量作为一个重量矩阵是可行的。所以,我创建了另一个版本的loss函数。
损失功能尝试3
from functools import partial

def custom_loss_3(y_true, y_pred, weights):
    return K.mean(K.abs(y_true-y_pred)*K.variable(weights, dtype=y_true.dtype))

cl3 = partial(custom_loss_3, weights=weights)

使用CL3拟合数据会产生与上述相同的误差。
InvalidArgumentError (see above for traceback): Incompatible shapes: [32,5] vs. [100,5]
     [[Node: loss_11/dense_8_loss/mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"](loss_11/dense_8_loss/Abs, loss_11/dense_8_loss/Variable/read)]]

我想知道我错过了什么!我本来可以在喀拉斯使用样本重量的概念,但后来我必须重新调整输入到三维矢量。
我认为这个自定义丢失函数应该是微不足道的。

最佳答案

model.fit中,批大小默认为32,这就是这个数字的来源。以下是发生的事情:
custom_loss_1中,张量的形状为K.abs(y_true-y_pred),而numpy数组的形状为(batch_size=32, 5)。这是一个无效的乘法,因为维度不一致,无法应用广播。
weights中,这个问题不存在,因为你将两个张量乘以相同的形状。
(100, 5)中,问题与custom_loss_2中的问题相同,因为将(batch_size=32, 5)转换为keras变量不会改变它们的形状。
更新:似乎您希望为每个训练样本中的每个元素赋予不同的权重,因此custom_loss_3数组的形状应为custom_loss_1确实。
在这种情况下,我将在模型中输入权重数组,然后在损失函数中使用这个张量:

import numpy as np
from keras.layers import Dense, Input
from keras import Model
import keras.backend as K
from functools import partial


def custom_loss_4(y_true, y_pred, weights):
    return K.mean(K.abs(y_true - y_pred) * weights)


train_X = np.random.randn(100, 5)
train_Y = np.random.randn(100, 5) * 0.01 + train_X
weights = np.random.randn(*train_X.shape)

input_layer = Input(shape=(5,))
weights_tensor = Input(shape=(5,))
out = Dense(5)(input_layer)
cl4 = partial(custom_loss_4, weights=weights_tensor)
model = Model([input_layer, weights_tensor], out)
model.compile('adam', cl4)
model.fit(x=[train_X, weights], y=train_Y, epochs=10)

关于python - Keras中的自定义加权损失功能用于称量每个元素,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48082655/

10-11 21:43
查看更多