我一直试图在Keras中建立自己的自定义损失,并遇到一些错误。
我的需求如下:我想在一个稳定的时间序列上建立一个分类器:它必须确定曲线的上升趋势还是下降趋势趋势,这意味着如果导数为负对于2或3个时间步长,它必须保持“上升”分类,而不是在短时间内切换到后代。输入数据是上下文数据,可以帮助NN检测时间序列方向上的当前变化是否可能持续。
为此,我设想构建一个自定义损失函数,该函数将为参考上方或下方的每次分类更改增加罚款。
我首先想在预测和参考张量上使用np.where,但是我知道浏览论坛是不可能的,因为损失函数使用占位符张量。我必须留在keras后端的功能空间内。
由于这个原因,我使用了在该论坛上找到的一些代码来构建以下损失函数:
import keras.backend as kb
def roll_reg(x):
length = kb.int_shape(x)[0]
x_tile = kb.tile(x, [2, 1])
x_roll = x_tile[length - 1:-1]
return kb.sum(kb.abs(x - x_roll))
def custom_loss(y_actual,y_predicted):
posact=kb.flatten(y_actual)
pospred=kb.flatten(y_predicted)
na=roll_reg(posact)
np=roll_reg(pospred)
loss_cust=kb.mean(((y_actual-y_predicted)**2)**0.5/(kb.max(y_actual)-kb.min(y_actual)))+abs(na-np)/kb.int_shape(posact)*10
return loss_cust
但我仍然收到此错误:
ValueError:形状必须为1级,但必须为2级 输入形状为[?],[2]的“ loss_9 / dense_25_loss / Tile”(操作项:“ Tile”)。
我将其解释为无法在占位符张量上进行操作……而我试图对此类张量使用专用功能。
有人对我可以做些什么来改进此代码以使损失函数运行有任何想法吗?
有关此问题的一些更新。我在互联网上找到此页面:https://medium.com/@j.ali.hab/on-custom-loss-functions-in-keras-3af88cf59e48,其中使用tf.math库解决了相同的问题。
所以我将代码更新为:
def custom_loss(y_actual,y_predicted):
na=kb.tf.math.cumsum(y_actual,axis=0)
np=kb.tf.math.cumsum(y_predicted,axis=0)
penalty=kb.abs(kb.sum(np-na))/118319#/kb.int_shape(y_actual)[0]
loss_nico=penalty
return loss_nico
现在代码正在编译,但是在每个纪元的最后我都得到了Nan作为损失函数。当然,神经网络并没有因此而学到任何东西。
有人知道我在做什么错吗?
答案 0 :(得分:1)
好,我终于明白了!
问题出在te kb.abs()中:不需要,因为kb.sum()返回标量。
所以最终有效的代码是:
def custom_loss(y_actual,y_predicted):
na=kb.tf.math.cumsum(y_actual,axis=0)
np=kb.tf.math.cumsum(y_predicted,axis=0)
penalty=abs(kb.sum(na-np))
loss_nico=kb.sum(((y_actual-y_predicted)))/1000+penalty/1000
return loss_nico
这可以编译并使RN能够实际学习某些东西。它仍然不是完美的,因为“无罚”部分应该改进,但仍然可以工作。