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

Manipulating data in keras custom loss function for CNN

我正尝试在 Keras 中为我正在处理的 CNN 编写自定义损失函数。 Y_true 和 Y_pred 都是灰度图像的张量,所以我希望形状为 [a, x, y, 1],其中 x 和 y 是图像的尺寸,a 是批量大小。

计划是:

  1. 根据平均像素强度
  2. 对Y_true的每个图像进行阈值处理
  3. 使用此掩码的非零元素从 Y_true 和 Y_pred
  4. 中获取像素值数组
  5. 测量这些数组的余弦相似度(使用内置的 Keras 损失函数)和return batch 的平均结果作为损失

我的主要问题是如何有效地实施这个过程? cosine_similarity 函数是否适用于一维数组?

我知道我应该避免 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中张量的形状通常是[None, height, width, channels]。 这是由于支持任意批量大小,您不想构建仅适用于特定批量大小的模型。因此,您的代码崩溃于:

for i in range(y_true.shape[0]):

因为 y_true.shape[0] == None.

为什么要遍历批处理?你不需要这样做。 例如,给定一些元素大小的损失函数(MSE/cosine 损失等)你可以这样做:

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