我正在尝试实现自定义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)没有正确实施,因为结果不好。我计算这个吗?
谢谢!
编辑:
我试图近似(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 :('ofano函数的错误输入参数,名称为“custom_models.py:836”,索引0(从0开始)','预期类似于数组 对象,但找到了一个变量:也许你正试图调用一个函数 在一个(可能是共享的)变量而不是数字数组?')
如何将y(y_true-y_pred)用作numpy数组,或者如何解决此问题?
答案 0 :(得分:0)
term1 = K.mean(K.square(y))
term2 = K.square(K.mean(y))
[...]
在代码中传播的一个错误是,当您在方程式中看到(1/n * sum())
时,它是平均值。不是一笔金额的平均值。
在阅读你的评论并进行更多思考之后,我认为对渐变感到困惑。至少我很困惑。
有两种解释渐变符号的方法:
y
应根据模型的参数(通常是神经网络的权重)进行区分。在以前的编辑中,我开始写这个方向,因为这是用于训练模型的那种方法(例如,梯度下降)。但我认为我错了。总而言之,K.gradients()
和numpy.gradient()
的使用方式不同。因为numpy隐式地将(i, j)
(行和列索引)视为两个输入变量,而当您将2D图像提供给神经网络时,每个像素 是输入变量。希望我很清楚。