Keras 指标不适用于自定义损失函数

问题描述 投票:0回答:1

我正在使用 keras 开发神经网络模型。

我的 y 值的形状如下:

(..., 2)

所以我的 y_pred 将具有相同的形状。 问题是 y 的值表示可能为 true 的一系列值(例如,在第 1 行中,1 到 2 之间的所有值都是可接受的)。

在我的自定义函数中,我需要检查这 2 个 y_pred 值的绝对值是否在 y_true 指示的范围之间,如果是,那么我的损失将为 0。 如果不在范围内,那么我会计算网络预测的值与最近端的偏差。

例如,假设我的

y_true= [[1, 2], [2, 3], [3, 4]]
还有我的
y_pred = [[1.5, 1.7], [2.3, 3.4], [7, 10]]

那么 y_pred 的绝对值就是 =

[1.6, 2.85, 8.5]

所以,最终第 0 行,我的损失将为 0(因为

1<1.6<2
) 对于第 1 行,我的损失将为 0(因为
2.3<2.85<3.4
) 对于第 2 行,我的损失将为 4.5(因为
4 < 8.5
)和
8.5-4 = 4.5

首先,我尝试用 for 循环来实现这个想法,但 keras 不喜欢那样。

然后我尝试使用 keras 后端函数(如 tf.abs 和 tf.where)来完成此操作,但我没有做出任何可靠的东西。

更新

我搜索了更多关于张量流函数的信息,我做了这个:

def custom_loss(y_true, y_pred):
    y_pred_average = tf.reduce_mean(y_pred, axis=1, keepdims=True)
    
    # Geta lower and upper bounds from y_true
    y_true_lower = y_true[:, 0:1]
    y_true_upper = y_true[:, 1:]
    
    # Check if y_pred_average values are within the range defined by y_true_lower and y_true_upper
    within_range_lower = y_true_lower <= y_pred_average
    within_range_upper = y_pred_average <= y_true_upper
    within_range = tf.logical_and(within_range_lower, within_range_upper)
    
    loss_within_range = tf.zeros_like(y_pred_average)
    loss_outside_range = tf.reduce_min(tf.stack([tf.abs(y_pred_average - y_true_lower), tf.abs(y_pred_average - y_true_upper)], axis=-1), axis=-1)
    
    loss = tf.where(within_range, loss_within_range, loss_outside_range)
    
    return loss

上面的函数,运行时返回一个二维损失数组 问题是指标不返回任何内容。 精度始终为 0,mse 始终为 nan

运行时的示例:

y_t = np.array([
    [1, 2],
    [3, 4],
    [5, 6]
])

y_p = np.array([
    [1.2, 1.5],
    [4.5, 4.7],
    [3.6, 4.8]
])

custom_loss_func(y_true=y_t, y_pred=y_p)

返回:

<tf.Tensor: shape=(3, 1), dtype=float64, numpy=
array([[0. ],
       [0.6],
       [0.8]])>

我可能做错了什么。或者我的思维过程总体上是错误的

python tensorflow keras neural-network
1个回答
0
投票

我尝试按如下方式重现您的实验:

y_t = tf.constant(np.array([
[1, 2],
[3, 4],
[5, 6]
]), dtype=tf.float32)

y_p = tf.Variable(np.array([
    [1.2, 1.5],
    [4.5, 4.7],
    [3.6, 4.8]
]), dtype=tf.float32)


losses = []
x = tf.Variable(3.0)
for _ in range(200):
    with tf.GradientTape(watch_accessed_variables=False) as tape:
        tape.watch(y_p)
        loss = custom_loss(y_true=y_t, y_pred=y_p)
    dy_dx = tape.gradient(loss, y_p)
    losses.append(loss.numpy().mean())
    y_p = y_p - dy_dx / 100.

plt.plot(losses)
plt.grid()

...我对此没有任何问题: Loss

但我怀疑使用

loss_within_range = tf.zeros_like(y_pred_average)
作为损失函数的组成部分之一是一个坏主意。它独立于 y_pred(除了它的形状)。如果 tf.where 选择其值作为损失函数的最终值,则将无法计算梯度。

© www.soinside.com 2019 - 2024. All rights reserved.