在pspnet中有adaptive_pooling操作,可以将当前size大小的图像pool成任意大小。比方说将8×8的图像pool成5×3大小。所以现在是已知input_size和output_size,求出kernel和stride大小,就可以利用现有的pooling操作进行了。
import tensorflow as tf
from tensorflow.keras.layers import MaxPooling2D
def adapmaxpooling(x,outsize):
x_shape=x.shape
batchsize,dim1,dim2,channel=x_shape
stride1=tf.cast(tf.math.floor(dim1/outsize[0]),dtype="int32")
stride2=tf.cast(tf.math.floor(dim2/outsize[1]),dtype="int32")
kernel1=dim1-(outsize[0]-1)*stride1
kernel2=dim2-(outsize[1]-1)*stride2
adpooling=MaxPooling2D(pool_size=(kernel1,kernel2),strides=(stride1,stride2))(x)
return adpooling
x = tf.random.normal(shape=[2,8,8,3])
x = adapmaxpooling(x,(5,3))
print(x.shape)
(2, 5, 3, 3)
class AdaptiveMaxPooling2D(Layer):
"""
功能: 实现任意大小的MaxPooling2D, 例如[8,8]->[5,3]
inputs: 4D tensor, [b,h,w,c]
outputs: 4D tensor, [b,out_size[0],out_size[1],c]
"""
def __init__(self,out_size:list,**kwargs):
super(AdaptiveMaxPooling2D,self).__init__(**kwargs)
self.out_size = out_size
def get_config(self):
config = super(AdaptiveMaxPooling2D,self).get_config()
config.update({"out_size":self.out_size})
return config
def build(self, input_shape):
_,h,w,c = input_shape
self.stride_1 = math.floor(h/self.out_size[0])
self.stride_2 = math.floor(w/self.out_size[1])
self.kernel_1 = (h - (self.out_size[0]-1)*self.stride_1)
self.kernel_2 = (w - (self.out_size[1]-1)*self.stride_2)
def call(self,inputs):
outputs = MaxPooling2D((self.kernel_1,self.kernel_2),(self.stride_1,self.stride_2))(inputs)
return outputs
# x = Input(shape=[64,64,256])
# x = AdaptiveMaxPooling2D([1,1])(x)
# print(x.shape)