python - Keras 中的自定义加权损失函数,用于对每个元素进行加权

标签 python tensorflow keras loss-function

我正在尝试创建一个简单的加权损失函数。

比如说,我的输入维度是 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 是从哪里来的?

使用权重作为 Keras 张量测试损失函数

def custom_loss_2(y_true, y_pred):
    return K.mean(K.abs(y_true-y_pred)*K.ones_like(y_true))

这个函数似乎可以完成工作。因此,可能表明 Keras 张量作为权重矩阵是可行的。因此,我创建了另一个版本的损失函数。

损失函数尝试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)]]

我想知道我错过了什么!我本可以在 Keras 中使用 sample_weight 的概念;但随后我必须将我的输入 reshape 为 3d 矢量。

我认为这个自定义损失函数真的应该是微不足道的。

最佳答案

model.fit 中,批量大小默认为 32,这就是这个数字的来源。这是正在发生的事情:

  • custom_loss_1 中,张量 K.abs(y_true-y_pred) 的形状为 (batch_size=32, 5),而numpy 数组 weights 的形状为 (100, 5)。这是一个无效的乘法,因为维度不一致并且无法应用广播。

  • custom_loss_2 中不存在此问题,因为您将 2 个具有相同形状的张量相乘 (batch_size=32, 5)

  • custom_loss_3 中的问题与 custom_loss_1 中的问题相同,因为将 weights 转换为 Keras 变量不会改变它们形状。


更新:您似乎想为每个训练样本中的每个元素赋予不同的权重,因此 weights 数组的形状应为 (100, 5 ) 的确如此。 在这种情况下,我会把你的权重数组输入到你的模型中,然后在损失函数中使用这个张量:

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/

相关文章:

python - 如何在 Python 中将字符串转换为 utf-8

python - 从 python 中的数据帧矩阵打印标题值

machine-learning - 训练tensorflow模型会自动保存参数吗?

tensorflow - 从 TensorBoard 中删除图像输出

tensorflow - 从源代码构建TensorFlow时-c opt和--config = opt有什么区别?

python - Keras减肥

python - 导入Python文件和导入*同一文件的区别

python - 使用子图和循环按组绘制 Pandas

keras - 在 PyTorch 中准备序列到序列网络的解码器

python-3.x - Keras 在每个 epoch 中占用的内存量无限增加