我正在尝试创建一个简单的加权损失函数。
假设我的输入尺寸为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))
似乎可以完成此功能。因此,可能暗示将Keras张量用作权重矩阵会起作用。因此,我创建了损失函数的另一个版本。
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的概念;但是然后我必须将输入重塑为3d向量。
我认为该自定义损失函数确实应该微不足道。
在model.fit批量大小是默认32,这就是这个数字的来源。这是正在发生的事情:
model.fit
在custom_loss_1张量中K.abs(y_true-y_pred)有形状(batch_size=32, 5),而在numpy数组中weights有形状(100, 5)。这是无效的乘法,因为维数不一致并且无法应用广播。
custom_loss_1
K.abs(y_true-y_pred)
(batch_size=32, 5)
weights
(100, 5)
在custom_loss_2这个问题中不存在,因为您要乘以2个具有相同形状的张量(batch_size=32, 5)。
custom_loss_2
在custom_loss_3问题是相同custom_loss_1的,因为转换weights成Keras变量不改变它们的形状。
custom_loss_3
更新: 似乎您想对每个训练样本中的每个元素赋予不同的权重,因此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)