Numpy CNN keras自定义损失函数中的数据处理

Numpy CNN keras自定义损失函数中的数据处理,numpy,keras,conv-neural-network,tensor,loss-function,Numpy,Keras,Conv Neural Network,Tensor,Loss Function,我正试图为我正在工作的CNN用Keras编写一个自定义损失函数。Y_true和Y_pred都是灰度图像的张量,因此我希望形状为[a,x,Y,1],其中x和Y是图像的尺寸,a是批量大小 计划是: 根据Y_的平均像素强度对每个图像设置阈值 使用此遮罩的非零元素从Y_true和Y_pred获取像素值数组 测量这些数组的余弦相似性(使用内置的Keras损失函数),并返回批次的平均结果作为损失 我的主要问题是如何有效地实施这个过程? cosine\u similarity函数是否适用于1D数组 我知道我应

我正试图为我正在工作的CNN用Keras编写一个自定义损失函数。Y_true和Y_pred都是灰度图像的张量,因此我希望形状为
[a,x,Y,1]
,其中x和Y是图像的尺寸,a是批量大小

计划是:

  • 根据Y_的平均像素强度对每个图像设置阈值
  • 使用此遮罩的非零元素从Y_true和Y_pred获取像素值数组
  • 测量这些数组的余弦相似性(使用内置的Keras损失函数),并返回批次的平均结果作为损失
  • 我的主要问题是如何有效地实施这个过程?
    cosine\u similarity
    函数是否适用于1D数组

    我知道我应该避免使用for循环来保持效率,但这是实现此功能的唯一方法。使用Keras后端或numpy是否有更有效的方法来实现此功能

    编辑

    使用此函数编译模型时出现基本实现和意外错误:

    def masked_cosine_similarity(y_true, y_pred):
        loss = 0
        for i in range(y_true.shape[0]):
            true_y = y_true[i,:,:,0]
            pred_y = y_pred[i,:,:,0]
            mask = true_y > np.mean(true_y)
            elements = np.nonzero(mask)
            true_vals = np.array([true_y[x,y] for x, y in zip(elements[0], elements[1])])
            pred_vals = np.array([pred_y[x,y] for x, y in zip(elements[0], elements[1])])
            loss += cosine_similarity(true_vals, pred_vals)
        return loss / y_true.shape[0]
    
    错误消息:

         64     loss = 0
    ---> 65     for i in range(y_true.shape[0]):
         66         true_y = y_true[i,:,:,0]
         67         pred_y = y_pred[i,:,:,0]
    
    TypeError: 'NoneType' object cannot be interpreted as an integer
    

    Keras/TF中张量的形状通常是
    [无、高度、宽度、通道]
    。 这是由于支持任意批量大小,所以您不希望构建仅适用于特定批量大小的模型。因此,您的代码在以下位置崩溃:

    for i in range(y_true.shape[0]):
    
    因为
    y\u true.shape[0]==None

    你为什么要在批次上循环?你不需要这么做。 例如,给定某个元素wize损耗函数(MSE/余弦损耗等),您可以执行以下操作:

    def my_loss(y_true, y_pred):
        mask = tf.keras.backend.cast(y_true >= tf.math.reduce_mean(y_true, axis=[1,2], keepdims=True), 'float32') 
        masked_loss = K.sum(mask * elementwize_loss(y_true, y_pred), axis=-1)
        num_valid_pixels = K.maximum(1.0, K.cast(K.sum(mask), 'float32'))
        return masked_loss / num_valid_pixels
    

    我已经实现了您的答案,并且得到了一个
    无效arguminterror:不兼容的形状:[210241024,1]vs.[210241024]
    ,如果我使用1的批处理大小,则不会发生这种情况。您可能会先使用“通道”?请详细说明您从何处获得错误。。。如果我必须猜测,可能您需要将参数“axis=-1”添加到K.sum()操作中。此外,我注意到您希望对每个通道执行平均值,因此请查看对我原始注释的编辑(指定axis=[1,2]独立执行每个示例的平均值+添加“keepdims=True”操作符以保持输入的4维)。尝试了更新的代码。同样的错误:
    invalidargumeinterror:不兼容的形状:[810241024,1]与[810241024]
    当将元素wize_损失设置为简单的欧几里德距离(y_true-y_pred)时,具有完全相同代码的虚拟示例对我有效。我的猜测是,您对cosine_相似性的实现使最后一个维度(值为1,表示单个通道)消失。尝试使用“重塑”(-1,h,w,1))或类似的方法来确保不改变尺寸的数量。