我正在使用keras开发机器学习模型,并且注意到可用的损失函数无法在我的测试集上提供最佳结果。
我正在使用Unet架构,在该架构中,我输入(16,16,3)图像,并且网络也输出(16,16,3)图片(自动编码器)。我注意到,也许改进模型的一种方法是使用损失函数,将净输出和地面实况之间的梯度(拉普拉斯)上的像素进行比较。但是,我没有找到任何可以处理此类应用程序的教程,因为它需要在网络上的每个输出图像上使用opencv laplacian函数。
损失函数如下:
def laplacian_loss(y_true, y_pred):
# y_true already is the calculated gradients, only needs to compute on the y_pred
# calculates the gradients for each predicted image
y_pred_lap = []
for img in y_pred:
laplacian = cv2.Laplacian( np.float64(img), cv2.CV_64F )
y_pred_lap.append( laplacian )
y_pred_lap = np.array(y_pred_lap)
# mean squared error, according to keras losses documentation
return K.mean(K.square(y_pred_lap - y_true), axis=-1)
有人做过类似的事情来计算损失吗?
答案 0 :(得分:1)
考虑到上面的代码,在考虑均方误差之前,这似乎等同于将Lambda()层用作在图像中应用该变换的输出层。
无论它是作为Lambda()层还是在损失函数中实现的;转换必须使Tensorflow理解如何计算梯度。最简单的方法是使用Tensorflow数学运算来重新实现cv2.Laplacian计算。
为了直接使用cv2库,您需要创建一个函数来计算cv2库内部发生的变化的梯度;似乎更容易出错。
梯度下降优化依赖于能够计算从输入到损耗的梯度。然后回来。中间的任何操作都必须是可区分的;而且Tensorflow必须了解数学运算才能自动进行微分运算;或者您需要手动添加它们。
答案 1 :(得分:0)
我设法达成一个简单的解决方案。主要特征是梯度计算实际上是2D滤波器。有关此信息的更多信息,请遵循关于拉普拉斯内核的link。在这种情况下,有必要让我的网络输出由拉普拉斯内核过滤。为此,我创建了一个具有固定权重的额外卷积层,该层与拉普拉斯内核完全相同。之后,网络将有两个输出(一个是所需的图像,另一个是渐变的图像)。因此,定义两个损耗也是必要的。
为了更加清楚,我将举例说明。在网络的末端,您将得到类似的东西:
channels = 3 # number of channels of network output
lap = Conv2D(channels , (3,3), padding='same', name='laplacian') (net_output)
model = Model(inputs=[net_input], outputs=[net_out, lap])
定义如何计算每个输出的损耗:
# losses for output, laplacian and gaussian
losses = {
"enhanced": "mse",
"laplacian": "mse"
}
lossWeights = {"enhanced": 1.0, "laplacian": 0.6}
编译模型:
model.compile(optimizer=Adam(), loss=losses, loss_weights=lossWeights)
定义拉普拉斯内核,将其值应用于上述卷积层的权重,并将可训练的值设置为False(这样就不会更新)。
bias = np.asarray([0]*3)
# laplacian kernel
l = np.asarray([
[[[1,1,1],
[1,-8,1],
[1,1,1]
]]*channels
]*channels).astype(np.float32)
bias = np.asarray([0]*3).astype(np.float32)
wl = [l,bias]
model.get_layer('laplacian').set_weights(wl)
model.get_layer('laplacian').trainable = False
训练时,请记住您需要两个基本事实值:
model.fit(x=X, y = {"out": y_out, "laplacian": y_lap})
观察:不要利用BatchNormalization层!如果您使用它,那么拉普拉斯图层中的权重将被更新!