Keras 中包含梯度的自定义损失函数

数据挖掘 Python 喀拉斯 美国有线电视新闻网 损失函数
2022-03-09 06:33:23

我想做一个自定义的损失函数。具体来说,我在 Keras 中使用了 2D 卷积神经网络。到目前为止,我已经通过添加 loss.py 来制作各种自定义损失函数。但是,在这种情况下,我遇到了稍后解释的问题。

我试图为图像任务制作回归器。输入和输出的数据形状都是 (1,128,128,2),其中 1 是 mini-batch 大小,128 是像素数,2 是通道数。

无论如何,我想为这个任务添加新的损失函数。我想计算答案和预测值之间的像素梯度差异并添加到损失函数中。我试着像下面这样。

def continuity(y_true, y_pred):
    import tensorflow as tf
    import numpy as np
    dx = dy = 1/128
    gridSetting = (128,128)

    u_true = y_true[0,:,:,0]
    v_true = y_true[0,:,:,1]
    u_pred = y_pred[0,:,:,0]
    v_pred = y_pred[0,:,:,1]

    cont_true = np.zeros((127,127))

    for j in range(127):
        for i in range(127):
            cont_true[i,j] = (u_true[i+1,j]-u_true[i,j])/dx + (v_true[i,j+1]-v_true[i,j])/dy

    cont_pred = np.zeros((127,127))
    for j in range(127):
        for i in range(127):
            cont_pred[i,j] = (u_pred[i+1,j]-u_pred[i,j])/dx + (v_pred[i,j+1]-v_pred[i,j])/dy

    cont_true = K.variable(value=cont_true, dtype='float64')
    cont_pred = K.variable(value=cont_pred, dtype='float64')
    cont = K.mean(K.abs(cont_true - cont_pred), axis=-1)
    mse = K.mean(K.square(y_pred - y_true), axis=-1)
    cont_mse = cont+mse
    return cont_mse

错误写如下。

Traceback (most recent call last):
File "DSC_multi-scale_2D.py", line 107, in <module>
autoencoder.compile(optimizer='adam', loss='continuity')
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/engine/training.py", line 332, in compile
sample_weight, mask)
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/engine/training_utils.py", line 403, in weighted
score_array = fn(y_true, y_pred)
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/losses.py", line 86, in continuity
cont_true[i,j] = (u_true[i+1,j]-u_true[i,j])/dx + (v_true[i,j+1]-v_true[i,j])/dy
ValueError: setting an array element with a sequence.

可能在 loss.py 中,数据类型u_true, v_true... 不支持 numpy。

如何调试/修复此问题?

2个回答

我认为有必要使用后端版本执行所有操作,让 Keras 对函数的每一步执行反向传播。例如,您使用 common +.... try K.add,它应该可以工作(基于tensorflow backend 的可用算术运算)。

另外,请查看一个相关问题,其中讨论了在 Keras 中创建自定义损失函数的一些机制。

您的函数中计算梯度的两个主要循环应该是 vecotisation 的候选者,您可以在其中计算一个操作中的差异。尝试以下方式:

diffs = K.subtract(u_true[i+1, j], u_true[i, j])

然后是第二次运算中的商:

quot = K.divide(diffs, dx)

当然对于v_trueand也是一样的dy

@n1k31t4

感谢您的回复,我尝试了您的建议。但是这些错误输出如下;

AttributeError: module 'keras.backend' has no attribute 'subtract'.

根据您建议的引用,存在 tf.subtract 或 tf.divide 所以我尝试按照稍后解释的方式重写,然后遇到以下错误;

def continuity(y_true, y_pred):
    import tensorflow as tf
    import numpy as np
    dx = dy = 1/128
    gridSetting = (128,128)

    u_true = y_true[0,:,:,0]
    v_true = y_true[0,:,:,1]
    u_pred = y_pred[0,:,:,0]
    v_pred = y_pred[0,:,:,1]

    cont_true = tf.zeros((127,127))
    for j in range(127):
        for i in range(127):
            diff_true_u = tf.subtract(u_true[i+1, j], u_true[i, j])
            cont_true_u = tf.divide(diff_true_u, dx)
            diff_true_v = tf.subtract(v_true[i, j+1], v_true[i, j])
            cont_true_v = tf.divide(diff_true_v, dy)
            cont_true_sum = cont_true_u + cont_true_v
            cont_true[i,j] = cont_true_sum

错误如下;

File "DSC_multi-scale_2D.py", line 107, in <module>
autoencoder.compile(optimizer='adam', loss='continuity')
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/engine/training.py", line 332, in compile
sample_weight, mask)
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/engine/training_utils.py", line 403, in weighted
score_array = fn(y_true, y_pred)
File "/home/----/anaconda3/envs/tensorflow-only/lib/python3.6/site-packages/keras/losses.py", line 91, in continuity
cont_true[i,j] = cont_true_sum
TypeError: 'Tensor' object does not support item assignment

我想将“cont_true_sum”替换为 cont_true[i,j]。我该如何解决?