我一直在尝试在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级,但对于'loss_9 / dense_25_loss / Tile'(op:'Tile'),输入形状为[?],[2]的形状必须为2级。
我将其解释为无法对占位符张量进行操作……而我试图对此类张量使用专用功能。
有人对我可以做些什么来改进此代码以使我的损失功能运行有任何想法吗?
有关此问题的一些更新。我在互联网上找到此页面: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作为损失函数。当然,结果就是神经网络没有学到任何东西。
有人知道我在做什么错吗?
OK,我终于明白了!
问题出在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能够实际学习某些东西。它仍然不是完美的,因为“无罚”部分应该改进,但仍然可以工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句