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

时间:2019-12-16 14:38:22

标签: python tensorflow keras conv-neural-network loss-function

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

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

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

由于自定义损失函数的参数限制为y_true和y_pred,并且考虑中的样本没有索引,并且我的问题不受监督(即,不需要任何标签),因此我使用了样本索引馈入CNN作为标签,并尝试使用y_true [0]作为CNN考虑下的火车样本的索引,并将批次大小设置为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]]的索引,因为错误是:索引应为整数, :,布尔值等,并且张量不能用作索引!我尝试了多种方法,例如将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

2 个答案:

答案 0 :(得分: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?

答案 1 :(得分:0)

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

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

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