问题描述
我正在尝试创建一个简单的加权损失函数.
I'm trying to create a simple weighted loss function.
比如说,我的输入维度是 100 * 5,输出维度也是 100 * 5.我还有一个相同维度的权重矩阵.
Say, I have input dimensions 100 * 5, and output dimensions also 100 * 5. I also have a weight matrix of the same dimension.
类似于以下内容:
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)
它提供了以下堆栈跟踪:
It gives the following stack trace:
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 是从哪里来的?
Where is the number 32 coming from?
def custom_loss_2(y_true, y_pred):
return K.mean(K.abs(y_true-y_pred)*K.ones_like(y_true))
这个函数似乎可以完成工作.因此,可能表明将 Keras 张量作为权重矩阵会起作用.所以,我创建了另一个版本的损失函数.
This function seems to do the work. So, probably suggests that a Keras tensor as a weight matrix would work. So, I created another version of the loss function.
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 拟合数据会产生与上述相同的错误.
Fitting data using cl3 gives the same error as above.
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 的概念;但随后我必须将我的输入重塑为 3d 矢量.
I wonder what I'm missing! I could have used the notion of sample_weight in Keras; but then I'd have to reshape my inputs to a 3d vector.
我认为这个自定义损失函数应该很简单.
I thought that this custom loss function should really have been trivial.
推荐答案
在 model.fit
中,batch size 默认为 32,这就是这个数字的来源.这是发生的事情:
In model.fit
the batch size is 32 by default, that's where this number is coming from. Here's what's happening:
在
custom_loss_1
中,张量K.abs(y_true-y_pred)
的形状为(batch_size=32, 5)
,而numpy 数组weights
的形状为(100, 5)
.这是无效的乘法,因为维度不一致且无法应用广播.
In
custom_loss_1
the tensorK.abs(y_true-y_pred)
has shape(batch_size=32, 5)
, while the numpy arrayweights
has shape(100, 5)
. This is an invalid multiplication, since the dimensions don't agree and broadcasting can't be applied.
在 custom_loss_2
中不存在此问题,因为您将 2 个具有相同形状的张量相乘 (batch_size=32, 5)
.
In custom_loss_2
this problem doesn't exist because you're multiplying 2 tensors with the same shape (batch_size=32, 5)
.
在 custom_loss_3
中,问题与在 custom_loss_1
中相同,因为将 weights
转换为 Keras 变量不会改变它们的形状.
In custom_loss_3
the problem is the same as in custom_loss_1
, because converting weights
into a Keras variable doesn't change their shape.
更新:您似乎想为每个训练样本中的每个元素赋予不同的权重,因此 weights
数组应具有形状 (100, 5)
确实如此.在这种情况下,我会将您的权重数组输入您的模型,然后在损失函数中使用此张量:
UPDATE: It seems you want to give a different weight to each element in each training sample, so the weights
array should have shape (100, 5)
indeed.In this case, I would input your weights' array into your model and then use this tensor within the loss function:
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)
这篇关于Keras 中的自定义加权损失函数,用于对每个元素进行加权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!