【问题标题】:Creating a complex custom loss in Keras for a seq2seq problem在 Keras 中为 seq2seq 问题创建复杂的自定义损失
【发布时间】:2022-01-10 01:59:42
【问题描述】:

我想为 seq2seq 问题编写一个自定义损失函数。 我的输入 (X) 具有形状 (N, M),即 N 个长度为 M 的序列。每个序列有 M/2 个数字(从 1 到 M/2),随机重复两次。这里,是一个 M=200 的例子:

X = array([[ 60.,  71.,  15., ...,  73.,  64.,  71.],
       [ 71.,  37.,  19., ...,  78.,  34.,  65.],
       [ 50.,  41.,  91., ...,  57.,  59.,   4.],
       ...,
       [  2.,  66.,  79., ...,  25.,  66.,  13.],
       [ 16.,  25.,  11., ...,  83.,  74.,  38.],
       [ 73., 100.,  91., ...,  48.,  61.,  51.]]) 
y = array([[1., 1., 1., ..., 0., 0., 0.],
       [1., 1., 1., ..., 1., 1., 1.],
       [0., 0., 0., ..., 1., 1., 1.],
       ...,
       [0., 0., 0., ..., 0., 1., 1.],
       [1., 1., 1., ..., 0., 1., 1.],
       [0., 0., 0., ..., 1., 1., 1.]])

我将它们重塑为

X_ = X.reshape(X.shape[0],1,X.shape[1])
y_ = y.reshape(y.shape[0],1,y.shape[1])

我希望根据 y_pred(和 y)序列发生变化的次数来计算损失。例如,如果我的输出是 y_pred = [ 1, 0, 1, 1, 1, 0, 0, 0, 1, 1 ],则从 0 变为 1(或反之亦然)的次数为 4。

这是我的网络:

model = Sequential()
model.add(LSTM(400,input_shape =(1,X_.shape[2]), activation='relu',return_sequences=True))
model.add(LSTM(350,activation='relu',return_sequences=False))
model.add(Dense(200, activation='softmax'))
model.compile(loss=my_loss_fn, optimizer='Adam') 

这是我尝试写的损失函数:

def my_loss_fn(y, y_pred):
    import tensorflow as tf
    c1 = tf.math.count_nonzero(tf.experimental.numpy.diff(y)!=0)
    c2 = tf.math.count_nonzero(tf.experimental.numpy.diff(y_pred)!=0)
    return tf.math.subtract(c1, c2)

问题是当我拟合模型时出现此错误:

ValueError: No gradients provided for any variable

这很可能是因为 numpy.diff 不可区分,正如此处 (Numpy or SciPy Derivative function for non-uniform spacing?) 和此处 (https://discuss.pytorch.org/t/differentiable-version-of-numpy-diff/89347/4) 指出的那样。

如何创建函数的可微分版本?

【问题讨论】:

    标签: tensorflow keras loss


    【解决方案1】:

    问题是我需要使用可微分运算。我在 Tensorflow (https://www.tensorflow.org/api_docs/python/tf/raw_ops) 中找到了可微分运算的列表,并相应地修改了自定义损失函数:

    def loss_fn(y_true, y_):
        a1 = tf.roll(y_true, shift=1, axis=1)
        c1 = tf.subtract(a1, y_true)
        
        a2 = tf.roll(y_, shift=1, axis=1)
        c2 = tf.subtract(a1, y_)
        
        return tf.math.reduce_mean(tf.square(c1 - c2))
    
    

    【讨论】:

      猜你喜欢
      • 2021-07-20
      • 2018-03-18
      • 2020-05-05
      • 2021-02-22
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多