在 Keras 中实现自定义 objective 函数
Implementing a custom objective function in Keras
我正在尝试实现自定义 Keras objective 函数:
in 'Direct Intrinsics: Learning Albedo-Shading Decomposition by Convolutional Regression', Narihira et al.
这是上一张图片中方程 (4)
和 (6)
的总和。 Y*
是ground truth,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_true
和 y_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: ('Bad input argument to theano function with name "custom_models.py:836" at index 0 (0-based)', 'Expected an array-like
object, but found a Variable: maybe you are trying to call a function
on a (possibly shared) variable instead of a numeric array?')
如何将 y (y_true - y_pred) 用作 numpy 数组,或者如何解决这个问题?
SIL2
term1 = K.mean(K.square(y))
term2 = K.square(K.mean(y))
[...]
代码中的一个错误是,当您在方程式中看到 (1/n * sum())
时,它是一个 均值 。不是总和的平均值。
渐变
在阅读了您的评论并进行了更多思考后,我认为渐变存在混淆。至少我糊涂了。
渐变符号有两种解读方式:
- gradient of a vector 其中
y
应该根据模型的参数(通常是神经网络的权重)进行区分。在之前的编辑中,我开始朝这个方向写作,因为这是用于训练模型的那种方法(例如梯度下降)。但我想我错了。
- 正如您在评论中提到的,图片中的像素强度梯度。每个像素与其相邻像素在每个方向上的差异。在这种情况下,我想你必须将你给出的例子翻译成 Keras。
综上所述,K.gradients()
和numpy.gradient()
的用法不一样。因为 numpy 隐含地将 (i, j)
(行和列索引)视为两个输入变量,而当您将 2D 图像馈送到神经网络时,每个像素 是 一个输入多变的。希望我说清楚了。
我正在尝试实现自定义 Keras objective 函数:
in 'Direct Intrinsics: Learning Albedo-Shading Decomposition by Convolutional Regression', Narihira et al.
这是上一张图片中方程 (4)
和 (6)
的总和。 Y*
是ground truth,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_true
和 y_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: ('Bad input argument to theano function with name "custom_models.py:836" at index 0 (0-based)', 'Expected an array-like object, but found a Variable: maybe you are trying to call a function on a (possibly shared) variable instead of a numeric array?')
如何将 y (y_true - y_pred) 用作 numpy 数组,或者如何解决这个问题?
SIL2
term1 = K.mean(K.square(y))
term2 = K.square(K.mean(y))
[...]
代码中的一个错误是,当您在方程式中看到 (1/n * sum())
时,它是一个 均值 。不是总和的平均值。
渐变
在阅读了您的评论并进行了更多思考后,我认为渐变存在混淆。至少我糊涂了。
渐变符号有两种解读方式:
- gradient of a vector 其中
y
应该根据模型的参数(通常是神经网络的权重)进行区分。在之前的编辑中,我开始朝这个方向写作,因为这是用于训练模型的那种方法(例如梯度下降)。但我想我错了。 - 正如您在评论中提到的,图片中的像素强度梯度。每个像素与其相邻像素在每个方向上的差异。在这种情况下,我想你必须将你给出的例子翻译成 Keras。
综上所述,K.gradients()
和numpy.gradient()
的用法不一样。因为 numpy 隐含地将 (i, j)
(行和列索引)视为两个输入变量,而当您将 2D 图像馈送到神经网络时,每个像素 是 一个输入多变的。希望我说清楚了。