自定义损失函数中的张量索引

时间:2017-09-13 14:24:07

标签: tensorflow neural-network keras

基本上,我希望我的自定义丢失函数在通常的MSE和从不同索引中减去值的自定义MSE之间交替。

为了澄清,假设我的y_pred张量为[1,2,4,5],y_true张量为[2,5,1,3]。在通常的MSE中,我们应该得到:

return K.mean(K.squared(y_pred - y_true))

这会做到以下几点:

[1,2,4,5] - [2,5,1,3] = [-1,-3,3,2]

[ - 1,-3,3,2]²= [1,9,9,4]

平均值([1,9,9,4])= 5.75

我需要我的自定义损失函数来选择此均值和其他从y_pred张量中切换索引1和3的最小值,即:

[1,5,4,2] - [2,5,1,3] = [-1,0,3,1]

[ - 1,0,3,1]²= [1,0,9,1]

平均值([1,0,9,1])= 2.75

所以,我的自定义损失将返回2.75,这是两种方法之间的最小值。为此,我尝试在numpy数组中转换y_true和y_pred张量,完成所有与数学相关的操作:

def new_mse(y_true, y_pred):
    sess = tf.Session()

    with sess.as_default():
        np_y_true = y_true.eval()
        np_y_pred = y_pred.eval()

        np_err_mse = np.empty(np_y_true.shape)
        np_err_mse = np.square(np_y_pred - np_y_true)

        np_err_new_mse = np.empty(np_y_true.shape)
        l0 = np.square(np_y_pred[:, 2] - np_y_true[:, 0])   
        l1 = np.square(np_y_pred[:, 3] - np_y_true[:, 1])
        l2 = np.square(np_y_pred[:, 0] - np_y_true[:, 2])
        l3 = np.square(np_y_pred[:, 1] - np_y_true[:, 3])   
        l4 = np.square(np_y_pred[:, 4] - np_y_true[:, 4])
        l5 = np.square(np_y_pred[:, 5] - np_y_true[:, 5])
        np_err_new_mse = np.transpose(np.vstack(l0, l1, l2, l3, l4, l5))

        np_err_mse = np.mean(np_err_mse)
        np_err_new_mse = np.mean(np_err_new_mse)

        return np.amin([np_err_mse, np_err_new_mse])

问题是我不能在y_true和y_pred张量中使用eval()方法,不知道为什么。最后,我的问题是:

  1. 是否有更简单的方法来处理张量和损失函数内的索引?我一般是Tensorflow和Keras的新手,我坚信在numpy数组中转换所有内容根本不是最佳方法。
  2. 与问题不完全相关,但当我尝试用K.shape(y_true)打印y_true tensor的形状时,我得到了“Tensor(”Shape_1:0“,shape =(2,),dtype = int32)”。这让我感到困惑,因为我正在使用等于(7032,6)的y.shape,这是7032张图像,每张图片有6个标签。可能是与损失函数使用的y和y_pred相关的一些误解。

2 个答案:

答案 0 :(得分:2)

通常你只使用backend functions,你永远不会试图知道张量的实际值。

from keras.losses import mean_square_error

def new_mse(y_true,y_pred): 

    #swapping elements 1 and 3 - concatenate slices of the original tensor
    swapped = K.concatenate([y_pred[:1],y_pred[3:],y_pred[2:3],y_pred[1:2]])
    #actually, if the tensors are shaped like (batchSize,4), use this:
    #swapped = K.concatenate([y_pred[:,:1],y_pred[:,3:],y_pred[:,2:3],Y_pred[:,1:2])

    #losses
    regularLoss = mean_squared_error(y_true,y_pred)
    swappedLoss = mean_squared_error(y_true,swapped)

    #concat them for taking a min value
    concat = K.concatenate([regularLoss,swappedLoss])

    #take the minimum
    return K.min(concat)

所以,对于你的物品:

  1. 你完全正确。在张量操作(损失函数,激活,自定义图层等)中不惜一切代价避免使用numpy。

  2. K.shape()也是一个张量。它可能有形状(2,),因为它有两个值,一个值为7032,另一个值为6.但是当你评估这个张量时,你只能看到这些值。在损失函数内执行此操作通常是个坏主意。

答案 1 :(得分:1)

如果使用Keras 2,则应仅使用K.gather函数执行索引编制。

丹尼尔·莫勒(DanielMöller)的答案变成:

from keras.losses import mean_square_error

def reindex(t, perm):
    K.concatenate([K.gather(t, i) for i in perm])

def my_loss(y_true,y_pred):

    #losses
    regularLoss = mean_squared_error(y_true, y_pred)
    swappedLoss = mean_squared_error(y_true, reindex(y_pred, [0,3,2,1]))

    #concat them for taking a min value
    concat = K.concatenate([regularLoss,swappedLoss])

    #take the minimum
    return K.min(concat)