我正在尝试在Keras中实现一个相当简单的自定义损失函数。
我正在尝试让网络预测错误的输入情况(即无法预测正确的输出)以及正确的输出。为此,我使用了损耗函数,该函数允许网络“选择”恒定损耗(8)而不是电流损耗(由MAE确定)。
loss = quality * output + (1-quality) * 8
从S形输出质量的地方,所以在[0,1]
我如何在Keras中正确设计这样的损失函数?
具体来说,在基本情况下,网络会获得输出的多个预测,以及已知或认为与预测质量相关的度量。 (小型)网络的作用是使用这些指标来确定平均这些不同预测时要赋予的权重。这足够好用。
但是,在某些情况下(例如5-10%),输入数据是如此糟糕,以至于所有预测变量都是错误的。在这种情况下,我要输出“?”给用户,而不是错误的答案。
我的代码抱怨1个数组与2个数组(大概是预期的y_true和y_pred数目相同,但我没有这些)。
model = Model(inputs=[ain, in1, in2, in3, in4, in5, x], outputs=[pred,qual])
model.compile(loss=quality_loss, optimizer='adam', metrics=['mae'])
model.fit([acc, hrmet0, hrmet1, hrmet2, hrmet3, hrmet4, hrs], ref, epochs=50, batch_size=5000, verbose=2, shuffle=True)
似乎有两个输出导致每个输出独立调用损失函数。
ValueError: Error when checking model target: the list of Numpy arrays that you
are passing to your model is not the size the model expected. Expected to see 2
array(s), but instead got the following list of 1 arrays:
这是通过传递串联数组来解决的。
def quality_loss(y_true, y_pred):
qual = y_pred[:,0]
hr = y_pred[:,1]
const = 8
return qual * mean_absolute_error(y_true,hr) + (1 - qual) * const
def my_mae(y_true,y_pred):
return mean_absolute_error(y_true,y_pred[:,1])
model = Model(inputs=[xin, in1, in2, in3, in4, in5, hr], outputs=concatenate([qual, pred_hr]))
model.compile(loss=quality_loss, optimizer='adam', metrics=[my_mae])
网络代码:
xin = Input(shape=(1,))
in1 = Input(shape=(4,))
net1 = Dense(3,activation='tanh')( Dense(6,activation='tanh')(in1) )
in2 = Input(shape=(4,))
net2 = Dense(3,activation='tanh')( Dense(6,activation='tanh')(in2) )
in3 = Input(shape=(4,))
net3 = Dense(3,activation='tanh')( Dense(6,activation='tanh')(in3) )
in4 = Input(shape=(4,))
net4 = Dense(3,activation='tanh')( Dense(6,activation='tanh')(in4) )
in5 = Input(shape=(4,))
net5 = Dense(3,activation='tanh')( Dense(6,activation='tanh')(in5) )
smweights = Dense(5, activation='softmax')( concatenate([xin, net1, net2, net3, net4, net5]) )
qual = Dense(1, activation='sigmoid')( Dense(3, activation='tanh')( concatenate([xin, net1, net2, net3, net4, net5]) ) )
x = Input(shape=(5,))
pred = dot([x, smweights], axes=1)
运行,但是收敛到loss = const和mae> 25(而这里简单的mae损失很容易达到3-4)。损失函数仍然有些不正确。由于损失函数中y_true / y_pred的形状给出(?),因此很难跟踪确切传递的内容。
答案 0 :(得分:2)
此问题实际上不是由您的自定义损失函数引起的,而是由其他原因引起的:该问题是由于您如何调用fit函数而引起的。
定义模型时,给它提供7
输入和2
输出:
model = Model(inputs=[ain, in1, in2, in3, in4, in5, x], outputs=[pred,qual])
当您最终调用fit
函数时,您将给出一个列表7
数组作为网络的输入,但是只有1
个目标输出值称为ref
:>
model.fit([acc, hrmet0, hrmet1, hrmet2, hrmet3, hrmet4, hrs], ref, ...)
这将不起作用。您必须为fit
函数提供与模型定义中声明的相同数量的输入和输出。
编辑:我认为您的方法存在一些概念性问题:您实际上如何计划定义预测的质量?您为什么在想,添加网络的一个分支来判断网络预测的质量实际上将有助于对其进行训练?网络将收敛到损失函数的局部最小值。损失函数的可能性越高,它实际上就不会收敛到您实际希望的状态,而是收敛到其他一些局部最小值而不是全局最小值。您可以尝试使用不同的优化器和学习率进行试验-也许这有助于您的培训。