tf.nn.conv2d中padding=same规则介绍

本文介绍了在TensorFlow的卷积操作tf.nn.conv2d中,如何使用padding='SAME'进行边缘填充,详细解析了填充规则,并通过实例验证了计算方法。内容包括VALID和SAME两种情况的计算,以及不同填充数量对输出的影响。
部署运行你感兴趣的模型镜像

由于项目需要需要自己实现卷积算法的逻辑,下面介绍padding填充规则,并且可以用最后面的数据进行简单的验证。

padding属性的意义是定义元素边框和元素内容之间的空间。

在tf.nn.conv2d函数中,当变量padding为VALID和SAME,函数具体是怎么计算的呢?其实是有公式的。为了方便演示,先定义几个变量:

  • 输入的尺寸高和宽定义成:in_height,in_width
  • 卷积核的高和宽定义成filter_height、filter_width
  • 输入的尺寸中高和宽定义成output_height、out_width
  • 步长的高宽方向定义成strides_height、strides_width.

一 VALID情况:边缘不填充

输入宽和高的公式分别为:
output_width=(in_width-filter_width+1)/strides_width #(结果向上取整)
output_height=(in_height-filter_height+1)/strides_height #(结果向上取整)

二 SAME情况:边缘填充

# 输出的宽和高将与卷积核没关系,具体公式如下:
output_width=in_width/strides_width #(结果向上取整)

output_height=in_height/strides_height #(结果向上取整)

# 这里有一个很重要的知识点——补零的规则,见如下公式:
pad_height=max((out_height-1)*strides_height+filter_height-in_height,0)

pad_width=max((out_width-1)*strides_width+filter_width-in_width,0)

pad_top=pad_height/2

pad_bottom=pad_height-pad_top

pad_left=pad_width/2

pad_right=pad_width-pad_left

上面公式中

  • pad_height:代表高度方向上要填充0的行数。
  • pad_width:代表宽度方向要填充0的列数。
  • pad_top、pad_bottom、pad_left、pad_right分别代表上、下、左、右这4个方向填充0的行、列数。
  • *填充为偶数时,左右和上下对称填充,奇数时优先填充右侧和下侧。

三 规则举例

下面通过一个例子来理解一下padding规则。

假设用一个一维数据来举例,输入是13,filter是6,步长是5,对于padding的取值有如下表示:

3.1 当padding='VALID’

生成宽度为(13-6+1)/5=2(向上取整)个数字。

inputs:

(1 2 3 4 5 6) 7 8 9 10 11 12 13
1 2 3 4 5 (6 7 8 9 10 11) 12 13

12和13丢弃

3.2 当padding=‘SAME’,

生成的宽度为13/5=3(向上取整)

Padding的方式可以如下计算:

Pad_width=(3-1)*5+6-13=3
Pad_left=pad_width/2=3/2=1
Pad_rigth=Pad_width-pad_left=2
在左边补一个0,右边补2个0

input:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 0
(0 1 2 3 4 5) 6 7 8 9 10 11 12 13 0 0
0 1 2 3 4 (5 6 7 8 9 10) 11 12 13 0 0
0 1 2 3 4 5 6 7 8 9 (10 11 12 13 0 0)

四 验证

首先,使用这样的输入:

输入的图片是 20*20*1 的,filter的尺寸是 5*5*1, stride是5,这时候是可以直接进行处理的,不需要进行填充:

import tensorflow as tf

b = tf.Variable(tf.ones([1,20,20,1]))
wc1 = tf.Variable(tf.ones([5,5,1,1]))

op1 = tf.nn.conv2d(b, wc1, strides=[1,5,5,1], padding='SAME')

init_op = tf.global_variables_initializer()


with tf.Session() as sess:
    sess.run(init_op)
    res = sess.run(op1)
    h = res.shape[1]
    w = res.shape[2]
    print(res.shape)
    print(sess.run(tf.reshape(res, [h, w])))

输出如下:

(1, 4, 4, 1)
[[25. 25. 25. 25.]
 [25. 25. 25. 25.]
 [25. 25. 25. 25.]
 [25. 25. 25. 25.]]

接下来,试验一下最后少了一个元素:

将输入图像的的shape改成 24*24*1 ,这样的话移动完第4次之后,会剩下4个元素,这样就会缺少一个元素,filter和stride不变(接下来这两个都不变),也就是:

b = tf.Variable(tf.ones([1,24,24,1]))

这时候的输出是:

(1, 5, 5, 1)
[[25. 25. 25. 25. 20.]
 [25. 25. 25. 25. 20.]
 [25. 25. 25. 25. 20.]
 [25. 25. 25. 25. 20.]
 [20. 20. 20. 20. 16.]]

在右侧和下面分别填充了一列(行)0,也就是:

1 1 1 ...1 1 0
1 1 1 ...1 1 0
1 1 1 ...1 1 0
1 1 1 ...1 1 0
0 0 0 ...0 0 0

所以这样才会出现 20 跟 16 这两种值。

接着调整输入,这次来看如果 最后差两个元素:

b = tf.Variable(tf.ones([1,23,23,1]))

输出:

(1, 5, 5, 1)
[[16. 20. 20. 20. 16.]
 [20. 25. 25. 25. 20.]
 [20. 25. 25. 25. 20.]
 [20. 25. 25. 25. 20.]
 [16. 20. 20. 20. 16.]]

这次的输出结果像是有些对称,上下左右各增加了一行(列)0:

0 0 0 ...0 0 0
0 1 1 ...1 1 0
0 1 1 ...1 1 0
0 1 1 ...1 1 0
0 0 0 ...0 0 0

接下来看如果最后少3个元素:

b = tf.Variable(tf.ones([1,22,22,1]))

 输出:

(1, 5, 5, 1)
[[16. 20. 20. 20. 12.]
 [20. 25. 25. 25. 15.]
 [20. 25. 25. 25. 15.]
 [20. 25. 25. 25. 15.]
 [12. 15. 15. 15.  9.]]

 

最后缺少3个元素的时候,在前面(左边和上边)会添加一行(列)0, 在后边(下边和右边)会增加两行(列)0:

0 0 0 ...0 0 0
0 1 1 ...1 0 0
0 1 1 ...1 0 0
0 1 1 ...1 0 0
0 0 0 ...0 0 0

 

最后缺少4个元素,按照上面的规律会在前后都增加两行(列):

b = tf.Variable(tf.ones([1,21,21,1]))

输出:

(1, 5, 5, 1)
[[ 9. 15. 15. 15.  9.]
 [15. 25. 25. 25. 15.]
 [15. 25. 25. 25. 15.]
 [15. 25. 25. 25. 15.]
 [ 9. 15. 15. 15.  9.]]

注:如果最后需要补全的数量是n:

    n 如果是奇数,那么前面增加 (n-1)/2,后面增加(n+1)/2
    n 如果是偶数,那么前后都增加 n/2

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值