【问题标题】:Implementing a custom objective function in Keras在 Keras 中实现自定义目标函数
【发布时间】:2016-10-22 10:35:56
【问题描述】:

我正在尝试实现自定义 Keras 目标函数:

在“直接内在函数:通过卷积回归学习反照率阴影分解”中,Narihira 等人。

这是上一张图片中方程(4)(6) 的总和。 Y* 是基本事实,Y 是预测图,y = Y* - Y

这是我的代码:

def custom_objective(y_true, y_pred):
  #Eq. (4) Scale invariant L2 loss
  y = y_true - y_pred
  h = 0.5 # lambda
  term1 = K.mean(K.sum(K.square(y)))
  term2 = K.square(K.mean(K.sum(y)))
  sca = term1-h*term2    
  #Eq. (6) Gradient L2 loss
  gra = K.mean(K.sum((K.square(K.gradients(K.sum(y[:,1]), y)) + K.square(K.gradients(K.sum(y[1,:]), y)))))
  return (sca + gra)

但是,我怀疑公式(6)没有正确实现,因为结果不好。我计算对了吗?

谢谢!

编辑:

我正在尝试用 Prewitt 过滤器近似 (6) 卷积。它适用于我的输入是一大块图像,即y[batch_size, channels, row, cols],但不适用于y_truey_pred(类型为TensorType(float32, 4D))。

我的代码:

def cconv(image, g_kernel, batch_size):
  g_kernel = theano.shared(g_kernel)
  M = T.dtensor3()
  conv = theano.function(
      inputs=[M],
      outputs=conv2d(M, g_kernel, border_mode='full'),
  )
  accum = 0
  for curr_batch in range (batch_size):
      accum = accum + conv(image[curr_batch])
  return accum/batch_size


def gradient_loss(y_true, y_pred):
  y = y_true - y_pred

  batch_size = 40

  # Direction i
  pw_x = np.array([[-1,0,1],[-1,0,1],[-1,0,1]]).astype(np.float64)
  g_x = cconv(y, pw_x, batch_size)

  # Direction j
  pw_y = np.array([[-1,-1,-1],[0,0,0],[1,1,1]]).astype(np.float64)
  g_y = cconv(y, pw_y, batch_size)

  gra_l2_loss = K.mean(K.square(g_x) + K.square(g_y))

  return (gra_l2_loss)

崩溃发生在:

    accum = accum + conv(image[curr_batch])

...错误描述如下:

*** TypeError: ('在索引 0(基于 0)处名称为“custom_models.py:836”的 theano 函数的输入参数错误', '期望类似数组 对象,但找到了一个变量:也许你正在尝试调用一个函数 在(可能是共享的)变量而不是数字数组上?')

如何使用 y (y_true - y_pred) 作为 numpy 数组,或者如何解决这个问题?

【问题讨论】:

    标签: image-processing deep-learning keras


    【解决方案1】:

    SIL2

    term1 = K.mean(K.square(y))
    term2 = K.square(K.mean(y))
    [...]
    

    代码中的一个错误是,当您在方程式中看到(1/n * sum()) 时,它是一个均值。不是总和的平均值。

    渐变

    在阅读了您的评论并对其进行了更多思考之后,我认为对渐变存在混淆。至少我感到困惑。

    渐变符号有两种解释方式:

    1. gradient of a vector 其中y 应根据模型的参数(通常是神经网络的权重)进行区分。在之前的编辑中,我开始朝这个方向写作,因为这是用于训练模型的那种方法(例如梯度下降)。但我认为我错了。
    2. 图片中的像素强度梯度,正如您在评论中提到的那样。每个方向上每个像素与其相邻像素的差异。在这种情况下,我想您必须将您提供的示例翻译成 Keras。

    综上所述,K.gradients()numpy.gradient() 的使用方式不同。因为 numpy 隐含地将(i, j)(行和列索引)视为两个输入变量,而当您将 2D 图像输入神经网络时,每个像素都是输入变量。希望我很清楚。

    【讨论】:

    • 我设法解决了 eq。 4通过删除你所说的总和,但我仍然坚持使用eq。 6.问题是我不知道如何在Keras语法中获取我的y(RGB图像)的i和j方向。使用 numpy 计算 y 的 i 和 j 的梯度是这样的: w, h = 128,128 pw, ph = w+2,h+2 padded_img = np.zeros((3,ph,pw)) padded_img[: ,1:ph-1,1:pw-1] = pic pad_i = padded_img[:,:,1:pw-1] - padded_img[:,:,0:pw-2] pad_j = padded_img[:,1: ph-1,:] - padded_img[:,0:ph-2,:] g_i = pad_i[:,1:ph-1,:] g_j = pad_j[:,:,1:pw-1]
    • 感谢您的评论,它为我最初错过了一个最重要的概念这一事实提供了一个非常受欢迎的启示:y 是 3D 的!相应地编辑了我的答案
    • 感谢您的时间@Arnaud P!为了更容易,我尝试使用带有 Prewitt 过滤器的 2D 卷积来近似梯度,它在我加载 RGB 图像但因 y_true 和 y_pred 变量崩溃时工作(我编辑了我的问题)。
    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 2016-10-06
    • 2016-02-24
    • 2018-04-15
    • 2018-05-25
    相关资源
    最近更新 更多