我想编写一个自定义的损失函数,用于对正目标值的低估进行加权惩罚。其工作原理类似于均方误差,唯一的区别是,在这种情况下,方差误差将乘以一个大于1的权重。
我编写了如下代码:
def wmse(ground_truth, predictions): square_errors = np.square(np.subtract(ground_truth, predictions)) weights = np.ones_like(square_errors) weights[np.logical_and(predictions < ground_truth, np.sign(ground_truth) > 0)] = 100 weighted_mse = np.mean(np.multiply(square_errors, weights)) return weighted_mse
然而,当我将它提供给使用tensorflow
作为后端的keras
中的Sequential模型时:
model.compile(loss=wmse,optimizer='rmsprop')
我得到了以下错误:
raise TypeError("Using a `tf.Tensor` as a Python `bool` is not allowed. TypeError: Using a `tf.Tensor` as a Python `bool` is not allowed. Use `if t is not None:` instead of `if t:` to test if a tensor is defined, and use TensorFlow ops such as tf.cond to execute subgraphs conditioned on the value of a tensor.
错误追踪指向wmse
中的这一行:
weights[np.logical_and(predictions < ground_truth, np.sign(ground_truth) > 0)] = 100
在此之前我从未使用过keras
或tensorflow
,所以如果有人能帮助我调整这个损失函数以适应keras
/tensorflow
框架,我将不胜感激。我尝试用tensorflow.logical_and
替换np.logical_and
,但没有效果,错误仍然存在。
回答:
正如@某人提到的,你必须使用仅Keras / TensorFlow操作来实现你的损失函数,这些操作需要有导数,因为这些框架无法通过其他操作(如numpy操作)进行反向传播。
一个仅使用Keras的实现可能如下所示:
from keras import backend as Kdef wmse(ground_truth, predictions): square_errors = (ground_truth - predictions) ** 2 weights = K.ones_like(square_errors) mask = K.less(predictions, ground_truth) & K.greater(K.sign(ground_truth), 0) weights = K.switch(mask, weights * 100, weights) weighted_mse = K.mean(square_errors * weights) return weighted_msegt = K.constant([-2, 2, 1, -1, 3], dtype="int32")pred = K.constant([-2, 1, 1, -1, 1], dtype="int32")weights, loss = wmse(gt, pred)sess = K.get_session()print(loss.eval(session=sess))# 100