padding和卷积的区别_TensorFlow笔记1——20.CNN卷积神经网络padding两种模式SAME和VALID...
第1种解说:(核心最后一张图,两种填充方式输出的形状尺寸计算公式)
在用tensorflow写CNN的时候,调用卷积核api的时候,会有填padding方式的参数,找到源码中的函数定义如下(max pooling也是一样):
def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
源码中对于padding参数的说明如下:
padding: A
string
from:"SAME", "VALID"
. The type of padding algorithm to use.
说了padding可以用“SAME”和“VALID”两种方式,但是对于这两种方式具体是什么并没有多加说明。 这里用Stack Overflow中的一份代码来简单说明一下,代码如下:
x = tf.constant([[1., 2., 3.],[4., 5., 6.]])
x = tf.reshape(x, [1, 2, 3, 1]) # give a shape accepted by tf.nn.max_pool
valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')print(valid_pad.get_shape())
print(same_pad.get_shape())
# 最后输出的结果为:
(1, 1, 1, 1)
(1, 1, 2, 1)
可以看出“SAME”的填充方式是比“VALID”的填充方式多了一列。 让我们来看看变量x是一个2x3的矩阵,max pooling窗口为2x2,两个维度的strides=2。 第一次由于窗口可以覆盖(橙色区域做max pool操作),没什么问题,如下:
接下来就是“SAME”和“VALID”的区别所在,由于步长为2,当向右滑动两步之后“VALID”发现余下的窗口不到2x2所以就把第三列直接去了,而“SAME”并不会把多出的一列丢弃,但是只有一列了不够2x2怎么办?填充!
如上图所示,“SAME”会增加第四列以保证可以达到2x2,但为了不影响原来的图像像素信息,一般以0来填充。(这里使用表格的形式展示,markdown不太好控制格式,明白意思就行),这就不难理解不同的padding方式输出的形状会有所不同了。
在CNN用在文本中时,一般卷积层设置卷积核的大小为n×k,其中k为输入向量的维度(即[n,k,input_channel_num,output_channel_num]),这时候我们就需要选择“VALID”填充方式,这时候窗口仅仅是沿着一个维度扫描而不是两个维度。可以理解为统计语言模型当中的N-gram。
我们设计网络结构时需要设置输入输出的shape,源码nn_ops.py中的convolution函数和pool函数给出的计算公式如下:
If padding == "SAME":output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides[i])If padding == "VALID":output_spatial_shape[i] =ceil((input_spatial_shape[i] -(spatial_filter_shape[i]-1) * dilation_rate[i])/ strides[i]).
dilation_rate为一个可选的参数,默认为1,这里我们可以先不管它。 整理一下,对于“VALID”,输出的形状计算如下:
参考<https://cloud.tencent.com/developer/article/1012365>
第2种解说:利用tf.nn.conv2d示例来理解 strides, padding效果
这里先再简单重复一下tf.nn.conv2d使用,其基本参数的使用规范同样也适用于其他CNN语句
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
- input : 输入的要做卷积的图片,要求为一个张量,shape为 [ batch, in_height, in_weight, in_channel ],其中batch为图片的数量,in_height 为图片高度,in_weight 为图片宽度,in_channel 为图片的通道数,灰度图该值为1,彩色图为3。(也可以用其它值,但是具体含义不是很理解)
- filter: 卷积核,要求也是一个张量,shape为 [ filter_height, filter_weight, in_channel, out_channels ],其中 filter_height 为卷积核高度,filter_weight 为卷积核宽度,in_channel 是图像通道数 ,和 input 的 in_channel 要保持一致,out_channel 是卷积核数量。
- strides: 卷积时在图像每一维的步长,这是一个一维的向量,[ 1, strides, strides, 1],第一位和最后一位固定必须是1
- padding: string类型,值为“SAME” 和 “VALID”,表示的是卷积的形式,是否考虑边界。"SAME"是考虑边界,不足的时候用0去填充周围,"VALID"则不考虑
- use_cudnn_on_gpu: bool类型,是否使用cudnn加速,默认为true
import tensorflow as tf
# case 1
# 输入是1张 3*3 大小的图片,图像通道数是5,卷积核是 1*1 大小,数量是1
# 步长是[1,1,1,1]最后得到一个 3*3 的feature map
# 1张图最后输出就是一个 shape为[1,3,3,1] 的张量
input = tf.Variable(tf.random_normal([1,3,3,5]))
filter = tf.Variable(tf.random_normal([1,1,5,1]))
op1 = tf.nn.conv2d(input, filter, strides=[1,1,1,1], padding='SAME')# case 2
# 输入是1张 3*3 大小的图片,图像通道数是5,卷积核是 2*2 大小,数量是1
# 步长是[1,1,1,1]最后得到一个 3*3 的feature map
# 1张图最后输出就是一个 shape为[1,3,3,1] 的张量
input = tf.Variable(tf.random_normal([1,3,3,5]))
filter = tf.Variable(tf.random_normal([2,2,5,1]))
op2 = tf.nn.conv2d(input, filter, strides=[1,1,1,1], padding='SAME')# case 3
# 输入是1张 3*3 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是1
# 步长是[1,1,1,1]最后得到一个 1*1 的feature map (不考虑边界)
# 1张图最后输出就是一个 shape为[1,1,1,1] 的张量
input = tf.Variable(tf.random_normal([1,3,3,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op3 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID') # case 4
# 输入是1张 5*5 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是1
# 步长是[1,1,1,1]最后得到一个 3*3 的feature map (不考虑边界)
# 1张图最后输出就是一个 shape为[1,3,3,1] 的张量
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op4 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID') # case 5
# 输入是1张 5*5 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是1
# 步长是[1,1,1,1]最后得到一个 5*5 的feature map (考虑边界)
# 1张图最后输出就是一个 shape为[1,5,5,1] 的张量
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op5 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME') # case 6
# 输入是1张 5*5 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是7
# 步长是[1,1,1,1]最后得到一个 5*5 的feature map (考虑边界)
# 1张图最后输出就是一个 shape为[1,5,5,7] 的张量
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op6 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME') # case 7
# 输入是1张 5*5 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是7
# 步长是[1,2,2,1]最后得到7个 3*3 的feature map (考虑边界)
# 1张图最后输出就是一个 shape为[1,3,3,7] 的张量
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op7 = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME') # case 8
# 输入是10 张 5*5 大小的图片,图像通道数是5,卷积核是 3*3 大小,数量是7
# 步长是[1,2,2,1]最后每张图得到7个 3*3 的feature map (考虑边界)
# 10张图最后输出就是一个 shape为[10,3,3,7] 的张量
input = tf.Variable(tf.random_normal([10,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op8 = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME') init = tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print('*' * 20 + ' op1 ' + '*' * 20)print(sess.run(op1))print('*' * 20 + ' op2 ' + '*' * 20)print(sess.run(op2))print('*' * 20 + ' op3 ' + '*' * 20)print(sess.run(op3))print('*' * 20 + ' op4 ' + '*' * 20)print(sess.run(op4))print('*' * 20 + ' op5 ' + '*' * 20)print(sess.run(op5))print('*' * 20 + ' op6 ' + '*' * 20)print(sess.run(op6))print('*' * 20 + ' op7 ' + '*' * 20)print(sess.run(op7))print('*' * 20 + ' op8 ' + '*' * 20)print(sess.run(op8))
# 运行结果
运行结果这里就省略了,太长了,所以不写这里了。复制语句到Jupyter中运行一下就懂了
参考<理解tf.nn.conv2d方法>
padding和卷积的区别_TensorFlow笔记1——20.CNN卷积神经网络padding两种模式SAME和VALID...相关推荐
- ebc是什么意思_UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别
UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别?很多电脑小白都搞不懂UEFI.GPT.BIOS.MBR到底是什么意思,下面跟随小白系统一起深入了解下UEFI+GPT和Legacy+ ...
- hash和history两种模式的区别+SpringBoot的特定配置
今天学习到vue-router有两种模式,一种是hash,一种是history模式 这两种模式对于后端来说有点区别 1,hash模式 这个模式是链接后拼接/#/这样的形式,在实际请求时并不加入#后面的 ...
- vue-router前端路由的两种模式的区别
一.前端路由存在的意义 前端路由主要应用在spa项目中. 核心---在无刷新(不向后端发送请求)的情况下,可以根据不同url更改视图. 二.浏览器提供hash 和history 两种模式支持(可以说, ...
- Vue-Router前端路由的两种模式、区别、原理?
vue路由有⼏种模式?有什么区别?原理是什么? 一.vue路由有几种模式? 二.两者区别 三.原理 一.vue路由有几种模式? vue的路由模式⼀共有两种,分别是哈希和history 二.两者区别 哈 ...
- Kafuka面试(整合Kafka两种模式区别)
整合Kafka两种模式说明 ★面试题:Receiver & Direct 开发中我们经常会利用SparkStreaming实时地读取kafka中的数据然后进行处理,在spark1.3版本后,k ...
- vue路由的两种模式:hash与history的区别
前言:众所周知,vue-router有两种模式,hash模式和history模式,下面来看看两者的区别. 一.基本情况 直观区别:hash模式url带#号,history模式不带#号. 1.hash模 ...
- JavaSE学习总结(八)常用类(上)Object类==与equals方法的区别浅克隆的特点Scanner类String类String两种创建对象方式的区别String类的各种功能
JavaSE学习总结(八)常用类(上)/Object类/==与equals方法的区别/浅克隆的特点/Scanner类/String类/String两种创建对象方式的区别/String类的各种功能 常用 ...
- 蓝牙播放Stereo和Hands-Free AG Audio两种模式的区别?
当使用蓝牙耳机时,发现电脑的播放设备显示了两种模式(如下图所示),Stereo模式下声音正常,而调到Hands-Free AG Audio模式下声音频带窄了很多且音质差,典型的电话音,下面具体说说这两 ...
- vue-router 两种模式的区别
vue-router有两种模式,hash模式和history模式,这里来谈谈两者的区别. **hash模式** hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事 ...
最新文章
- 机器学习中使用的交叉熵(cross entropy)透彻分析
- 线程池之CachedThreadPool学习
- 基于规则的应用程序开发实战(转载与MSDN)
- python xlwt模块生成excel文件并写入数据 xlrd读取数据
- svn merge 回滚
- android 前台服务自定义布局不显示_Android前台服务通知未显示
- 【专栏精选】Unity中的HTTP网络通信
- C# 人民币大小写转换正则表达式
- Python_继承_构造函数
- python怎么恢复默认窗口,如何恢复python编程环境spyder的窗口
- 文献笔记(5)(2017ISSCC 14.1)
- .net快速开发平台,learun敏捷开发框架
- GitLab版本升级
- dof景深matlab,Shader学习(三):DOF(景深)
- 手把手教你搭建SpringCloud项目(十)集成OpenFeign服务接口调用
- ftp连接21端口出现的问题的解决方案
- 域环境批量推送OUTLOOK签名
- ffmpeg里转场transition
- 2016年的不正式总结
- python千年虫问题enumerate函数