首页 / 资讯中心 / 文章详情

【Tensorflow实战系列】Tensoeflow:Tensorflow的padding到底是怎么一回事?(‘valid’和‘same’,附源码解释)

【Tensorflow实战系列】Tensoeflow:Tensorflow的padding到底是怎么一回事?(‘valid’和‘same’,附源码解释) ★ FEATURED ARTICLE
tensorflow的padding到底是怎么一回事之前设计网络的时候就大概算了一下feature map的输入输出的形状padding呢一般就是两种一种是‘valid’的方式另外一种是‘same’方式特别具体的怎么计算都记不太清了结果转caffe model的时候发现两种的padding方式是不同的于是想在弄弄清楚tensorflow到底是怎么个padding方式结果网上一堆各个博客的公式还都不一样算了自己看源码吧。首先我们先进行实验直接调用接口看一下这个比较直观。importnumpyasnpimporttensorflowastf testnp.random.random([1,10,10,3])valid_padtf.layers.average_pooling2d(test,pool_size[3,3],strides3,paddingvalid)same_padtf.layers.average_pooling2d(test,pool_size[3,3],strides3,paddingsame)print(valid_pad.get_shape)print(same_pad.get_shape)bound method Tensor.get_shape of tf.Tensor average_pooling2d_11/AvgPool:0 shape(1, 3, 3, 3) dtypefloat64 bound method Tensor.get_shape of tf.Tensor average_pooling2d_12/AvgPool:0 shape(1, 4, 4, 3) dtypefloat64可以看到‘valid’和‘same’确实是不一样的那么pad到底是怎么计算它的输出长度的呢defconv_output_length(input_length,filter_size,padding,stride,dilation1):Determines output length of a convolution given input length. Arguments: input_length: integer. filter_size: integer. padding: one of same, valid, full, causal stride: integer. dilation: dilation rate, integer. Returns: The output length (integer). ifinput_lengthisNone:returnNoneassertpaddingin{same,valid,full,causal}dilated_filter_sizefilter_size(filter_size-1)*(dilation-1)ifpaddingin[same,causal]:output_lengthinput_lengthelifpaddingvalid:output_lengthinput_length-dilated_filter_size1elifpaddingfull:output_lengthinput_lengthdilated_filter_size-1return(output_lengthstride-1)//stride在不用膨胀卷积的时候我们可以认为dilated_filter_size filter_size那么对于‘same’的模式下计算就应该是output_length input_length res (output_length stride - 1) // stride 我们把上面例子中input_length10, filter_size 3, stride3带入到上面式子中可以得到 (103-1) // 3 4那么对于‘valid’的模式呢output_length input_length - dilated_filter_size 1 res (output_length stride - 1) // stride 我们把上面例子中input_length10, filter_size 3, stride3带入到上面式子中可以得到 (10-313-1) // 3 3我们再试一个例子呢testnp.random.random([1,127,127,3])valid_padtf.layers.average_pooling2d(test,pool_size[5,5],strides3,paddingvalid)same_padtf.layers.average_pooling2d(test,pool_size[5,5],strides3,paddingsame)print(valid_pad.get_shape)print(same_pad.get_shape)bound method Tensor.get_shape of tf.Tensor average_pooling2d_13/AvgPool:0 shape(1, 41, 41, 3) dtypefloat64 bound method Tensor.get_shape of tf.Tensor average_pooling2d_14/AvgPool:0 shape(1, 43, 43, 3) dtypefloat64小伙伴可以按照上述的公式计算一下答案是正确的LZ觉得所有的根据以事实说话那么我们会计算输出的维度但是具体的padding‘same’是怎么padding的呢testnp.random.randint(1,5,[1,5,5,1]).astype(np.float32)print(np.squeeze(test))valid_padtf.layers.average_pooling2d(test,pool_size[2,2],strides2,paddingvalid)same_pad_1tf.layers.average_pooling2d(test,pool_size[2,2],strides2,paddingsame)same_pad_0tf.layers.average_pooling2d(test,pool_size[2,2],strides3,paddingsame)same_pad_2tf.layers.average_pooling2d(test,pool_size[3,3],strides4,paddingsame)same_pad_3tf.layers.average_pooling2d(test,pool_size[4,4],strides4,paddingsame)print(valid_pad.get_shape)print(same_pad_0.get_shape)print(same_pad_1.get_shape)print(same_pad_2.get_shape)print(same_pad_3.get_shape)sesstf.Session()print(valid_pad: ,np.squeeze(sess.run(valid_pad)))print(same_pad_0: ,np.squeeze(sess.run(same_pad_0)))print(same_pad_1: ,np.squeeze(sess.run(same_pad_1)))print(same_pad_2: ,np.squeeze(sess.run(same_pad_2)))print(same_pad_3: ,np.squeeze(sess.run(same_pad_3)))[[4. 2. 1. 1. 3.] [4. 3. 4. 1. 2.] [1. 1. 3. 1. 3.] [4. 4. 4. 4. 1.] [4. 4. 2. 4. 4.]] bound method Tensor.get_shape of tf.Tensor average_pooling2d_22/AvgPool:0 shape(1, 2, 2, 1) dtypefloat32 bound method Tensor.get_shape of tf.Tensor average_pooling2d_24/AvgPool:0 shape(1, 2, 2, 1) dtypefloat32 bound method Tensor.get_shape of tf.Tensor average_pooling2d_23/AvgPool:0 shape(1, 3, 3, 1) dtypefloat32 bound method Tensor.get_shape of tf.Tensor average_pooling2d_25/AvgPool:0 shape(1, 2, 2, 1) dtypefloat32 bound method Tensor.get_shape of tf.Tensor average_pooling2d_26/AvgPool:0 shape(1, 2, 2, 1) dtypefloat32 valid_pad: [[3.25 1.75] [2.5 3. ]] same_pad_0: [[3.25 1.75] [4. 3.25]] same_pad_1: [[3.25 1.75 2.5 ] [2.5 3. 2. ] [4. 3. 4. ]] same_pad_2: [[3.25 1.75] [4. 3.25]] same_pad_3: [[2.5555556 1.8333334] [3.6666667 3.25 ]]下面LZ来总结下到底tensorflow的padding到底是怎么一回事‘VALID’valid很简单就是丢如果kernel_size超过了feature map剩下没有处理过的维度那就丢掉但是这样就会产生信息的丢失最好还是用‘same’比较好‘SAME’same是要把feature map上的信息都用上并且会在feature map周围进行补零操作。如果pad的数量为1也就是在feature map的右边和下边各补充一列和一行零如果pad的数量为2 也就是在feature map的上下左右各补充一列和一行零如果pad的数量为3会在上和左边补一行和一列而在右边和下边补两列两行…以此类推如果pad的维度为偶数上下左右补零的维度相同如果pad的维度为奇数则右边和下边补零的维度比左边和上边补零的维度多1网上博客都是个人理解如果真正想弄明白自己动手试一试
阅读完成 · 觉得有帮助?
咨询建站