用于编译网络 (CNN) 的 Keras 自定义损失函数中的错误

Posted

技术标签:

【中文标题】用于编译网络 (CNN) 的 Keras 自定义损失函数中的错误【英文标题】:Error in Keras Custom Loss Function for Compile the Network (CNN) 【发布时间】:2020-04-09 01:05:54 【问题描述】:

在 Keras 中定义自定义损失函数以编译我的 CNN 网络时,我遇到了 2 个主要问题。我正在通过 CNN 进行 2D 图像配准(对齐一对 2D 图像以最适合彼此)。网络的输出将是一个 5 维浮点型数组,作为网络的预测。 (1 次缩放,2 次平移和 2 次在 x 和 y 上的缩放)。配准问题有两个主要的损失函数(以及指标),称为 Dice Coefficient 和 TRE(目标配准误差,它是医生标记的标志点对之间距离的总和)。顺便说一句,我需要实现这两个损失函数。对于骰子系数:

1- 首先,我需要知道优化器正在考虑哪个样本,以便我可以读取该样本的内容并计算 Dice,而自定义损失函数中仅定义了 y_true 和 y_pred在 Keras 文档中。

2- 我将以下代码作为我的损失函数编写到 1)首先,扭曲第一张图像,2)其次,使两个图像二进制(每个样本由 2 个图像组成:一个是运动图像,另一个是固定图像图像),3)第三,返回成对图像(扭曲和固定)之间的骰子系数。

由于自定义损失函数的参数限制为y_true和y_pred,并且考虑的样本没有索引,而且我的问题是无监督的(即不需要任何标签),所以我使用了样本的索引作为标签馈送到CNN,并尝试使用y_true[0]作为CNN正在考虑的训练样本的索引,并将batch-size设置为1。

def my_loss_f(y_true,y_pred):
    from scipy.spatial import distance as dis
    a = y_true[0]
    nimg1=warping(Train_DataCT[a],y_pred) # line 83 in CNN1.py
    return dis.dice(BW(nimg1).flatten(),BW(Train_DataMR[a]).flatten())

def warping(nimg,x):
    import scipy.ndimage as ndi
    nimg1 = ndi.rotate(nimg, x[0], reshape=False)
    nimg1 = ndi.shift(nimg1, [x[1], x[2]])
    nimg1 = clipped_zoom(nimg1, [x[3], x[4]])
    return nimg1

def BW(nimg1):
    hist = ndi.histogram(nimg1, 0, 255, 255)
    som = ndi.center_of_mass(hist)
    bwnimg = np.where(nimg1 > som, 1, 0)
    return bwnimg

但是,我经常收到不同的错误,如下所示。有人告诉我用 TensorFlow 或 Keras-backend 来重写我自己的损失函数,但我需要 Numpy 和 SciPy 并且无法跳入这种低级编程,因为我完成项目的时间非常有限。

主要问题是 y_true 是空的(它只是一个占位符而不是具有值的实变量),并且不能用作 Train_DataCT[y_true[0]] 的索引,因为错误是:索引应该是整数, :, Boolean 等和张量不能用作索引!我尝试了多种方法,例如将 y_true 转换为 ndarray 或使用 y_true.eval() 对其进行初始化,但我得到了错误:会话错误,没有默认会话。

先谢谢了,请有人帮助我。


Traceback (most recent call last):
  File "D:/Python/Reg/Deep/CNN1.py", line 83, in <module>
    model.compile(optimizer='rmsprop',loss=my_loss_f)
  File "C:\Users\Hamidreza\Anaconda3\lib\site-packages\keras\engine\training.py", line 342, in compile
    sample_weight, mask)
  File "C:\Users\Hamidreza\Anaconda3\lib\site-packages\keras\engine\training_utils.py", line 404, in weighted
    score_array = fn(y_true, y_pred)
  File "D:/Python/Reg/Deep/CNN1.py", line 68, in my_loss_f
    nimg1=warping(Train_DataCT[1],y_pred)
  File "D:/Python/Reg/Deep/CNN1.py", line 55, in warping
    nimg1 = ndi.rotate(nimg, x[0], reshape=False)
  File "C:\Users\Hamidreza\Anaconda3\lib\site-packages\scipy\ndimage\interpolation.py", line 703, in rotate
    m11 = math.cos(angle)
TypeError: must be real number, not Tensor

Process finished with exit code 1

【问题讨论】:

你 Train_DataCT[1] 。 y_pred 它们中的任何一个都是张量,而不是实际值。尝试将其转换为列表并计算其余部分。它应该工作。另请编辑错误日志,使其更具可读性。 Train_DataCT 是一个 ndarray,但 y_pred 和 y_true 是张量。他们应该转换为ndarray,但是如何?我不知道,因为 y_pred.numpy() 不能实时工作(在损失函数中)。 【参考方案1】:

您的损失函数应该适用于您后端的张量类型。如果您将 keras 与 tf 后端一起使用,则以下函数可能有助于结合高级 numpy/scipy 函数和张量:

https://www.tensorflow.org/api_docs/python/tf/numpy_function?version=stable

您还可以在下面找到更多有用的东西:

How to make a custom activation function with only Python in Tensorflow?

【讨论】:

【参考方案2】:

让我细化我的问题:我需要输入的样本数据来计算损失函数。有/无批次,我应该知道 CNN 正在考虑的样本的索引,以便计算损失,例如一对输入图像之间的骰子系数。

由于我的问题是无监督学习,作为替代解决方案,我使用 y_true 作为样本的索引,但是当例如在 tf.flatten 之后,我使用 y_true[0] 例如 Train_DataCT[y_true[0]],我得到错误:索引不能是张量!

如何在自定义损失函数中使用 .run() 或 .eval() 以便 y_true 可以获取值,以便我可以将其转换为例如数组???

【讨论】:

以上是关于用于编译网络 (CNN) 的 Keras 自定义损失函数中的错误的主要内容,如果未能解决你的问题,请参考以下文章

对比学习用 Keras 搭建 CNN RNN 等常用神经网络

[Python图像识别] 五十.Keras构建AlexNet和CNN实现自定义数据集分类详解

在 CNN 的 keras 自定义损失函数中操作数据

使用预训练 vgg19 tensorflow,Keras 在 CNN 自动编码器中定义自定义损失(感知损失)

Keras 自定义损失函数 dtype 错误

如何在 Keras 中使用预训练的 CNN 实现连体网络?