在Keras中实现自定义目标函数

时间:2016-10-22 10:35:56

标签: image-processing deep-learning keras

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

  <直接内在学:通过卷积回归学习反照率分解',Narihira等人

(4) and (6)

这是上一张图片中等式(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)没有正确实施,因为结果不好。我计算这个吗?

谢谢!

编辑:

我试图近似(6)与Prewitt过滤器进行卷积。当我输入的是一大块图像(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 :('ofano函数的错误输入参数,名称为“custom_models.py:836”,索引0(从0开始)','预期类似于数组   对象,但找到了一个变量:也许你正试图调用一个函数   在一个(可能是共享的)变量而不是数字数组?')

如何将y(y_true-y_pred)用作numpy数组,或者如何解决此问题?

1 个答案:

答案 0 :(得分:0)

SIL2

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

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

梯度

在阅读你的评论并进行更多思考之后,我认为对渐变感到困惑。至少我很困惑。

有两种解释渐变符号的方法:

  1. gradient of a vector其中y应根据模型的参数(通常是神经网络的权重)进行区分。在以前的编辑中,我开始写这个方向,因为这是用于训练模型的那种方法(例如,梯度下降)。但我认为我错了。
  2. 图片中的像素强度渐变,正如您在评论中提到的那样。每个像素的差异与每个方向上的邻居。在这种情况下,我猜你必须将你给出的例子翻译成Keras。
  3. 总而言之,K.gradients()numpy.gradient()的使用方式不同。因为numpy隐式地将(i, j)(行和列索引)视为两个输入变量,而当您将2D图像提供给神经网络时,每个像素 是输入变量。希望我很清楚。