首页 > 解决方案 > 了解 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")

在非常简单的二维数组上对其进行测试后,我发现它并没有达到我的预期(原始数据和合并数据):

原始数据

汇总数据

您可以看到,合并后的单个总和(根据平均合并)在边界附近最终的总和大于实际总和,即 1。(在这种情况下可以使用最大值,但实际数据更复杂,我们需要求和)这意味着靠近边界的平均值不是来自填充数据而是来自原始数据。或者这是我对填充的误解?我需要在 1.1, 1.2, 1.4 的索引上有一个。为什么会这样,我该如何解决这样的问题?

请注意,我不想手动设置正确的总和,所以我正在寻找一种在 keras 池本身中实现这一点的方法。

标签: pythontensorflowkerasmax-pooling

解决方案


“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")

图像结果:

左边输入,右边输出。 输入显示一个空的 32x32 矩阵,在位置 (7,16) 处有一个值为 1。 输出显示一个空的 32x32 矩阵,在位置 (2,11) 和 (12,21) 之间有一个正方形


编辑:我在 Github 上创建了一个关于该问题的问题。


推荐阅读