我正在使用 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]])>
我可能做错了什么。或者我的思维过程总体上是错误的
我尝试按如下方式重现您的实验:
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_within_range = tf.zeros_like(y_pred_average)
作为损失函数的组成部分之一是一个坏主意。它独立于 y_pred(除了它的形状)。如果 tf.where 选择其值作为损失函数的最终值,则将无法计算梯度。