了解keras中的平均(总和)池填充
Understanding average (sum) pooling padding in keras
我在 keras tensorflow 中实现了一个简单的总和池,使用 AveragePooling2D*N*N
,因此它创建了具有某种形状的池中元素的总和,same
填充因此形状不会改变:
import numpy as np
import seaborn as sns
import matplotlib.pylab as plt
import tensorflow as tf
from tensorflow.keras.backend import square
#generating the example matrix
def getMatrixByDefinitions(definitions, width, height):
matrix = np.zeros((width, height))
for definition in definitions:
x_cor = definition[1]
y_cor = definition[0]
value = definition[2]
matrix.itemset((x_cor, y_cor), value)
return matrix
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
def avg_pool(pool):
return tf.keras.layers.AveragePooling2D(pool_size=(pool,pool), strides=(1, 1), padding='same')
def summer(pool, tensor):
return avg_pool(pool)(tensor)*pool*pool
def numpyToTensor(numpy_data):
numpy_as_array = np.asarray(numpy_data)
tensor_data = numpy_as_array.reshape(1, numpy_data.shape[1], numpy_data.shape[1], 1)
return tensor_data
data = numpyToTensor(generated)
pooled_data = summer(11, data)
def printMatrixesToHeatMap(matrixes, title):
# f = pyplot.figure() # width and height in inches
matrix_count = len(matrixes)
width_ratios = [4] * matrix_count + [0.2]
mergedMatrixes = matrixes[0][0]
for matrix in matrixes:
mergedMatrixes = np.concatenate((mergedMatrixes, matrix[0]), axis=0)
vmin = np.min(mergedMatrixes)
vmax = np.max(mergedMatrixes)
fig, axs = plt.subplots(ncols=matrix_count + 1, gridspec_kw=dict(width_ratios=width_ratios))
fig.set_figheight(20)
fig.set_figwidth(20 * matrix_count + 5)
axis_id = 0
for matrix in matrixes:
sns.heatmap(matrix[0], annot=True, cbar=False, ax=axs[axis_id], vmin=vmin, vmax=vmax)
axs[axis_id].set_title(matrix[1])
axis_id = axis_id + 1
#fig.colorbar(axs[1].collections[0], cax=axs[matrix_count])
fig.savefig(title+".pdf", bbox_inches='tight')
def tensorToNumpy(tensor):
width = tensor.get_shape()[1]
height = tensor.get_shape()[2]
output = tf.reshape(tensor, [width, height])
#output = output.eval(session=tf.compat.v1.Session())
output = output.numpy()
return np.array(output)
printMatrixesToHeatMap([[tensorToNumpy(pooled_data), "Pooled data"]],
"name")
在非常简单的二维数组上对其进行测试后,我发现它没有达到我的预期(原始数据和合并数据):
你可以看到,单一的 sum-pooled(根据平均池化)最终在边界附近的总和大于实际总和,即 1。 (在这种情况下可以使用 max,但实际数据更复杂,我们需要求和)这意味着平均近边界不是来自填充数据而是来自原始数据。或者这是我这边对 padding 的误解?我需要在 1.1、1.2、1.4 所在的索引上有一个。为什么会这样,我该如何解决这个问题?
请注意,我不想手动设置正确的总和,因此我正在寻找一种在 keras 池化本身中实现此目的的方法。
这似乎是“SAME”填充算法的问题。不幸的是,无法为 avg_pool2d 操作指定显式填充。不过,可以用 tf.pad
手动填充输入。这是一种非常简单的填充方法,适用于奇数形状的池过滤器和步幅大小 1 :
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
gen_nhwc = tf.constant(generated[np.newaxis,:,:,np.newaxis])
pool = 11
paddings = [[0,0],[pool//2,pool//2],[pool//2,pool//2],[0,0]]
gen_pad = tf.pad(gen_nhwc, paddings, "CONSTANT")
res = tf.nn.avg_pool2d(gen_pad, (pool,pool), (1,1),"VALID")*pool*pool
result = np.squeeze(res.numpy())
printMatrixesToHeatMap([[generated, "input"],[result, "output"]], "name")
图片结果:
编辑:我创建了一个关于这个问题的issue on Github。
我在 keras tensorflow 中实现了一个简单的总和池,使用 AveragePooling2D*N*N
,因此它创建了具有某种形状的池中元素的总和,same
填充因此形状不会改变:
import numpy as np
import seaborn as sns
import matplotlib.pylab as plt
import tensorflow as tf
from tensorflow.keras.backend import square
#generating the example matrix
def getMatrixByDefinitions(definitions, width, height):
matrix = np.zeros((width, height))
for definition in definitions:
x_cor = definition[1]
y_cor = definition[0]
value = definition[2]
matrix.itemset((x_cor, y_cor), value)
return matrix
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
def avg_pool(pool):
return tf.keras.layers.AveragePooling2D(pool_size=(pool,pool), strides=(1, 1), padding='same')
def summer(pool, tensor):
return avg_pool(pool)(tensor)*pool*pool
def numpyToTensor(numpy_data):
numpy_as_array = np.asarray(numpy_data)
tensor_data = numpy_as_array.reshape(1, numpy_data.shape[1], numpy_data.shape[1], 1)
return tensor_data
data = numpyToTensor(generated)
pooled_data = summer(11, data)
def printMatrixesToHeatMap(matrixes, title):
# f = pyplot.figure() # width and height in inches
matrix_count = len(matrixes)
width_ratios = [4] * matrix_count + [0.2]
mergedMatrixes = matrixes[0][0]
for matrix in matrixes:
mergedMatrixes = np.concatenate((mergedMatrixes, matrix[0]), axis=0)
vmin = np.min(mergedMatrixes)
vmax = np.max(mergedMatrixes)
fig, axs = plt.subplots(ncols=matrix_count + 1, gridspec_kw=dict(width_ratios=width_ratios))
fig.set_figheight(20)
fig.set_figwidth(20 * matrix_count + 5)
axis_id = 0
for matrix in matrixes:
sns.heatmap(matrix[0], annot=True, cbar=False, ax=axs[axis_id], vmin=vmin, vmax=vmax)
axs[axis_id].set_title(matrix[1])
axis_id = axis_id + 1
#fig.colorbar(axs[1].collections[0], cax=axs[matrix_count])
fig.savefig(title+".pdf", bbox_inches='tight')
def tensorToNumpy(tensor):
width = tensor.get_shape()[1]
height = tensor.get_shape()[2]
output = tf.reshape(tensor, [width, height])
#output = output.eval(session=tf.compat.v1.Session())
output = output.numpy()
return np.array(output)
printMatrixesToHeatMap([[tensorToNumpy(pooled_data), "Pooled data"]],
"name")
在非常简单的二维数组上对其进行测试后,我发现它没有达到我的预期(原始数据和合并数据):
你可以看到,单一的 sum-pooled(根据平均池化)最终在边界附近的总和大于实际总和,即 1。 (在这种情况下可以使用 max,但实际数据更复杂,我们需要求和)这意味着平均近边界不是来自填充数据而是来自原始数据。或者这是我这边对 padding 的误解?我需要在 1.1、1.2、1.4 所在的索引上有一个。为什么会这样,我该如何解决这个问题?
请注意,我不想手动设置正确的总和,因此我正在寻找一种在 keras 池化本身中实现此目的的方法。
这似乎是“SAME”填充算法的问题。不幸的是,无法为 avg_pool2d 操作指定显式填充。不过,可以用 tf.pad
手动填充输入。这是一种非常简单的填充方法,适用于奇数形状的池过滤器和步幅大小 1 :
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
gen_nhwc = tf.constant(generated[np.newaxis,:,:,np.newaxis])
pool = 11
paddings = [[0,0],[pool//2,pool//2],[pool//2,pool//2],[0,0]]
gen_pad = tf.pad(gen_nhwc, paddings, "CONSTANT")
res = tf.nn.avg_pool2d(gen_pad, (pool,pool), (1,1),"VALID")*pool*pool
result = np.squeeze(res.numpy())
printMatrixesToHeatMap([[generated, "input"],[result, "output"]], "name")
图片结果:
编辑:我创建了一个关于这个问题的issue on Github。