我正在开发一个超分辨率 (5x) CNN,它对具有输入形状的单 channel 图像进行操作(None, None, None, 1)
假设图像的顶行为
[x, x, x, x, x, y, y, y, y, y]
缩小 5 倍后会变成
[x, y]
考虑一个由单个 Conv2DTranspose
层(步幅为 5x5)和单个常量矩阵 9x9 滤波器组成的网络。将其应用于 [x, y]
会产生
[x, x, x, x, X, x+y, x+y, x+y, x+y, Y, y, y, y, y]
(这里的X
,Y
表示从x
,y
生成的像素集的中心)
所以我们已经从 2 列矩阵变为 14 列矩阵。
将此放大输出与原始图像进行比较的一种方法是在原始图像的每一侧填充 (filter_size - stride_size)/2 = (9-5)/2 =2
条目
[0, 0, x, x, x, x, x, y, y, y, y, y, 0, 0]
然后与我们缩小图像的放大版本很好地对齐
[x, x, x, x, X, x+y, x+y, x+y, x+y, Y, y, y, y, y]
此时,我已准备好计算这两行之间的差异并计算损失。
然而,人为的4个边界点会造成损失。我显然不关心这个人工边界区域中的错误。我如何确保这些值不包含在损失中?
我考虑过自定义损失、切片和掩蔽层,但问题是输入的大小是可变的。如果输入具有固定大小,我可以创建一个掩蔽张量或根据固定大小更新值,但对于可变输入大小,我需要创建一个可变掩蔽张量。
import keras
import numpy as np
model = keras.Sequential()
model.add(keras.layers.Conv2DTranspose(1, (9,9), strides=(5,5), input_shape=(None, None, 1),
kernel_initializer='ones', bias_initializer='zeros'))
#x is downscaled image
x = np.zeros([1,2,2,1])
x[0,0,0,0] = 1
x[0,0,-1,0] = .5
#y is original image
y = np.zeros([1,10,10,1])
y[0,0,:,0]= [1,1,1,1,1,.5,.5,.5,.5,.5]
y_pred = model.predict(x)
paddings = ((0,0),(2,2),(2,2),(0,0))
y_pad = np.pad(y, paddings, mode='constant')
# want keras to calculate loss of
# y_pad[:,2:-2,2:-2,:] - y_pred[:,2:-2,2:-2,:]```
最佳答案
看起来修剪填充层的最简单方法是使用具有固定内核和偏差且无填充的 Conv2D 层。
depad_kernel = np.zeros([2*padding+1,2*padding+1])
depad_kernel[padding, padding,0,0] = 1
depad_bias = np.zeros([1])
depadded_output = model.add_layer(
keras.layers.Conv2D(1, (2*padding+1, 2*padding+1), strides=(1,1),
weights=[depad_kernel, depad_bias], trainable=False))
更新
看起来有一种更简单的方法,可以将裁剪层应用于模型的输出,这可以用于删除无关生成的点。
https://www.tensorflow.org/api_docs/python/tf/keras/layers/Cropping2D
关于python - Keras 可变大小的掩模或切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58668832/