在 CNN 的 keras 自定义损失函数中操作数据
Posted
技术标签:
【中文标题】在 CNN 的 keras 自定义损失函数中操作数据【英文标题】:Manipulating data in keras custom loss function for CNN 【发布时间】:2020-09-05 06:34:09 【问题描述】:我正在尝试在 Keras 中为我正在研究的 CNN 编写自定义损失函数。 Y_true 和 Y_pred 都将是灰度图像的张量,所以我希望形状为 [a, x, y, 1]
,其中 x 和 y 是我的图像的尺寸,a 是批量大小。
计划是:
-
通过平均像素强度对 Y_true 的每个图像进行阈值化
使用此掩码的非零元素从 Y_true 和 Y_pred 获取像素值数组
测量这些数组的余弦相似度(使用内置的 Keras 损失函数),并将批次的平均结果作为损失返回
我的主要问题是如何有效地实施这个过程?
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
【问题讨论】:
【参考方案1】:Keras/TF 中张量的形状通常为[None, height, width, channels]
。
这是由于支持任意批量大小,您不想构建仅适用于特定批量大小的模型。因此,您的代码会崩溃:
for i in range(y_true.shape[0]):
自y_true.shape[0] == None
.
为什么要循环批处理?你不需要这样做。 例如,给定一些元素级损失函数(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
【讨论】:
我已经实现了您的答案,并且收到了InvalidArgumentError: Incompatible shapes: [2,1024,1024,1] vs. [2,1024,1024]
,如果我使用 1 的批量大小,则不会发生这种情况
您可以使用“channel_first”吗?请详细说明您到底在哪里得到了错误...如果我必须猜测,也许您需要在 K.sum() 操作中添加参数“axis=-1”。
另外,我注意到您想要执行每个通道的平均值,所以请查看对我原始评论的编辑(指定axis = [1,2]以独立执行每个示例的平均值+添加"keepdims=True" 运算符保持输入的 4 维)。
尝试了更新的代码。同样的错误:InvalidArgumentError: Incompatible shapes: [8,1024,1024,1] vs. [8,1024,1024]
当将 elementwize_loss 设置为简单的欧几里德距离时,一个具有完全相同代码的虚拟示例对我有用:(y_true-y_pred)。我的猜测是您对 cosine_similarity 的实现使最后一个维度(其值为 1 并代表单个通道)消失了。尝试使用 reshape((-1, h,w,1)) 或类似的方法来确保你不改变维度的数量。以上是关于在 CNN 的 keras 自定义损失函数中操作数据的主要内容,如果未能解决你的问题,请参考以下文章
使用预训练 vgg19 tensorflow,Keras 在 CNN 自动编码器中定义自定义损失(感知损失)
如何在 Keras 中创建这个自定义损失函数并确保它是可微的?