tensorflow一文弄懂cnn中的padding参数(代码片段)

white-xzx white-xzx     2022-12-23     172

关键词:

在深度学习的图像识别领域中,我们经常使用卷积神经网络CNN来对图像进行特征提取,当我们使用TensorFlow搭建自己的CNN时,一般会使用TensorFlow中的卷积函数和池化函数来对图像进行卷积和池化操作,而这两种函数中都存在参数padding,该参数的设置很容易引起错误,所以在此总结下。

1.为什么要使用padding

在弄懂padding规则前得先了解拥有padding参数的函数,在TensorFlow中,主要使用tf.nn.conv2d()进行(二维数据)卷积操作,tf.nn.max_pool()、tf.nn.avg_pool来分别实现最大池化和平均池化,通过查阅官方文档我们知道其需要的参数如下:

tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None,name=None)
tf.nn.max_pool_with_argmax(input, ksize, strides, padding, Targmax=None, name=None)
tf.nn.max_pool(value, ksize, strides, padding, name=None)

这三个函数中都含有padding参数,我们在使用它们的时候需要传入所需的值,padding的值为字符串,可选值为‘SAME‘ 和 ‘VALID‘ ;

padding参数的作用是决定在进行卷积或池化操作时,是否对输入的图像矩阵边缘补0,‘SAME‘ 为补零,‘VALID‘ 则不补,其原因是因为在这些操作过程中过滤器可能不能将某个方向上的数据刚好处理完,如下所示:

当步长为5,卷积核尺寸为6×6时,当padding为VALID时,则可能造成数据丢失(如左图),当padding为SAME时,则对其进行补零(如右图),

技术分享图片技术分享图片

2. padding公式

首先,定义变量:

输入图片的宽和高:i_w 和 i_h

输出特征图的宽和高:o_w 和 o_h

过滤器的宽和高:f_w 和 f_h

宽和高方向的步长:s_w 和 s_h

宽和高方向总的补零个数:pad_w 和 pad_h

顶部和底部的补零个数:pad_top 和 pad_bottom

左部和右部的补零个数:pad_left 和 pad_right

 1.VALID模式

    输出的宽和高为

o_w = (i_w - f_w + 1)/ s_w #(结果向上取整)
o_h = (i_h - f_h + 1)/ s_h  #(结果向上取整)

 

2. SAME模式

    输出的宽和高为

o_w = i_w / s_w#(结果向上取整)
o_h = i_h / s_h#(结果向上取整)

 

    各个方向的补零个数为:max()为取较大值,

pad_h = max(( o_h -1 ) × s_h + f_h - i_h , 0)
 pad_top = pad_h / 2  # 注意此处向下取整
 pad_bottom = pad_h - pad_top
 pad_w = max(( o_w -1 ) × s_w + f_w - i_w , 0)
 pad_left = pad_w / 2 # 注意此处向下取整
 pad_right = pad_w - pad_left

3.卷积padding的实战分析

接下来我们通过在TensorFlow中使用卷积和池化函数来分析padding参数在实际中的应用,代码如下:

# -*- coding: utf-8 -*-
import tensorflow as tf

# 首先,模拟输入一个图像矩阵,大小为5*5
# 输入图像矩阵的shape为[批次大小,图像的高度,图像的宽度,图像的通道数]
input = tf.Variable(tf.constant(1.0, shape=[1, 5, 5, 1]))

# 定义卷积核,大小为2*2,输入和输出都是单通道
# 卷积核的shape为[卷积核的高度,卷积核的宽度,图像通道数,卷积核的个数]
filter1 = tf.Variable(tf.constant([-1.0, 0, 0, -1], shape=[2, 2, 1, 1]))

# 卷积操作 strides为[批次大小,高度方向的移动步长,宽度方向的移动步长,通道数]
# SAME
op1_conv_same = tf.nn.conv2d(input, filter1, strides=[1,2,2,1],padding=SAME)
# VALID
op2_conv_valid = tf.nn.conv2d(input, filter1, strides=[1,2,2,1],padding=VALID)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print("op1_conv_same:
", sess.run(op1_conv_same))
    print("op2_conv_valid:
", sess.run(op2_conv_valid))

VALID模式的分析:

技术分享图片

SAME模式分析:

o_w = i_w  / s_w = 5/2 = 3
o_h = i_h / s_h = 5/2 = 3

pad_w = max ( (o_w - 1 ) × s_w + f_w -  i_w , 0 )
      =  max ( (3 - 1 ) × 2 + 2 - 5 , 0 )  = 1
pad_left = 1 / 2 =0
pad_right = 1 - 0 =0
# 同理
pad_top = 0
pad_bottom = 1

技术分享图片

运行代码后的结果如下:

技术分享图片

技术分享图片

 4.池化padding的实战分析

这里主要分析最大池化和平均池化两个函数,函数中padding参数设置和矩阵形状计算都与卷积一样,但需要注意的是:

1. 当padding=‘SAME‘,计算avg_pool时,每次的计算是除以图像被filter框出的非零元素的个数,而不是filter元素的个数,如下图,第一行第三列我们计算出的结果是除以2而非4,第三行第三列计算出的结果是除以1而非4;

技术分享图片

2. 当计算全局池化时,即与图像矩阵形状相同的过滤器进行一次池化,此情况下无padding,即在边缘没有补0,我们直接除以整个矩阵的元素个数,而不是除以非零元素个数(注意与第一点进行区分)

池化函数的代码示例如下:

# -*- coding: utf-8 -*-
import tensorflow as tf

# 首先,模拟输入一个特征图,大小为5*5
# 输入图像矩阵的shape为[批次大小,图像的高度,图像的宽度,图像的通道数]
input = tf.Variable(tf.constant(1.0, shape=[1, 5, 5, 1]))


# 最大池化操作 strides为[批次大小,高度方向的移动步长,宽度方向的移动步长,通道数]
# ksize为[1, 池化窗口的高,池化窗口的宽度,1]
# SAME
op1_max_pooling_same = tf.nn.max_pool(input, [1,2,2,1], strides=[1,2,2,1],padding=SAME)
# VALID
op2_max_pooling_valid = tf.nn.max_pool(input, [1,2,2,1], strides=[1,2,2,1],padding=VALID)

# 平均池化
op3_avg_pooling_same = tf.nn.avg_pool(input, [1,2,2,1], strides=[1,2,2,1],padding=SAME)
# 全局池化,filter是一个与输入矩阵一样大的过滤器
op4_global_pooling_same = tf.nn.avg_pool(input, [1,5,5,1], strides=[1,5,5,1],padding=SAME)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print("op1_max_pooling_same:
", sess.run(op1_max_pooling_same))
    print("op2_max_pooling_valid:
", sess.run(op2_max_pooling_valid))
    print("op3_max_pooling_same:
", sess.run(op3_avg_pooling_same))
    print("op4_global_pooling_same:
", sess.run(op4_global_pooling_same))

运行结果如下:

技术分享图片 技术分享图片

 5.总结

在搭建CNN时,我们输入的图像矩阵在网络中需要经过多层卷积和池化操作,在这个过程中,feature map的形状会不断变化,如果不清楚padding参数引起的这些变化,程序在运行过程中会发生错误,当然在实际写代码时,可以将每一层feature map的形状打印出来,了解每一层Tensor的变化。

 

转载请注明出处:https://www.cnblogs.com/White-xzx/p/9497029.html

 

 

 

 

    

一文弄懂神经网络中的反向传播法——backpropagation

最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进行补充... 查看详情

一文弄懂神经网络中的反向传播法——backpropagation(代码片段)

  最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进行... 查看详情

tensorflow实现cnn中的维度问题

使用TensorFlow实现cnn,其中tf.nn.conv2d(input_tensor…)input_tensor的格式要求是[batch,in_height,in_width,in_channels]但是python中四维矩阵是[batch,in_channels,in_height,in_width]使用transpose即可 查看详情

tensorflow实现cnn中的维度问题

使用TensorFlow实现cnn,其中tf.nn.conv2d(input_tensor…)input_tensor的格式要求是[batch,in_height,in_width,in_channels]但是python中四维矩阵是[batch,in_channels,in_height,in_width]使用transpose即可 查看详情

一文带你弄懂c++中的ansiunicode和utf8三种字符编码(代码片段)

目录1、概述2、VisualStudio中的字符编码3、ANSI窄字节编码4、Unicode宽字节编码5、UTF8编码6、如何使用字符编码7、三种字符编码之间的相互转换(附源码) 7.1、ANSI编码与Unicode编码之间的转换 7.2、UTF8编码与Unicode编码之间... 查看详情

根据输入形状的计算是不是存在差异? (带有 Tensorflow 的 Python 中的 CNN)

】根据输入形状的计算是不是存在差异?(带有Tensorflow的Python中的CNN)【英文标题】:Isthereadifferenceincomputationaccordingtoinputshape?(CNNinPythonwithTensorflow)根据输入形状的计算是否存在差异?(带有Tensorflow的Python中的CNN)【发布时间... 查看详情

一文弄懂hadoop与jdk的安装(亲测有效!)(代码片段)

一文弄懂hadoop与jdk的安装(亲测有效!)提示:有问题可以私信我或者加我QQ:932403551文章目录一文弄懂hadoop与jdk的安装(亲测有效!)前言一、安装好SSH二、安装java环境三、Hadoop安装3.1下载安装文件3.2... 查看详情

基于tensorflow+opencv实现cnn自定义图像分类

摘要:本篇文章主要通过Tensorflow+Opencv实现CNN自定义图像分类案例,它能解决我们现实论文或实践中的图像分类问题,并与机器学习的图像分类算法进行对比实验。本文分享自华为云社区《​​Tensorflow+Opencv实现CNN自定义图像分... 查看详情

cnn中的卷积核及tensorflow中卷积的各种实现

声明:1.我和每一个应该看这篇博文的人一样,都是初学者,都是小菜鸟,我发布博文只是希望加深学习印象并与大家讨论。2.我不确定的地方用了“应该”二字首先,通俗说一下,CNN的存在是为了解决两个主要问题:1.权值太多... 查看详情

尝试使用 Tensorflow 理解用于 NLP 教程的 CNN

】尝试使用Tensorflow理解用于NLP教程的CNN【英文标题】:TryingtounderstandCNNsforNLPtutorialusingTensorflow【发布时间】:2017-05-3015:01:04【问题描述】:我关注thistutorial是为了了解NLP中的CNN。尽管我面前有代码,但仍有一些我不明白的事情... 查看详情

一文带你弄懂cdn技术的原理

对于CDN这个东西,相信大家都有耳闻,感觉既陌生但又熟悉。最近深入了解了一下CDN,这才发现原来CDN如此重要!今天就跟大家科普一下CDN是什么,以及为啥要有CDN,最后再讲一下CDN的工作过程!浏览器的网络请求要理解CDN这件... 查看详情

一文带你弄懂kubernetes应用配置管理

不论什么样的应用,基本都有配置文件,在企业中,大部分会用到配置中心,比如apollo、nacos等,也有一些公司直接使用Kubernetes自带的配置管理,主要有:SecretConfigMapSecret如果把配置信息保存在Secret中,其会被加密存放到Etcd中... 查看详情

训练的 Tensorflow CNN 回归 MSE 高于测试

】训练的TensorflowCNN回归MSE高于测试【英文标题】:TensorflowCNNregressionMSEhigherfortrainthantest【发布时间】:2018-09-2601:02:56【问题描述】:我正在向CNN提供图片以预测回归设置中的值。Input:[NUM_EXAMPLES,HEIGHT,WIDTH,CHANNELS]->[NUM_EXAMPLES,YPRE... 查看详情

一文弄懂区块链技术原理(代码片段)

前言近期由于工作需要,于是对区块链相关技术展开了大量的研究和学习.本文将以开发者的角度,对整个区块链行业技术的发展做一次全面的总结和归纳.文章宗旨是为了帮助大家理解区块链技术出现的目的、能够解决什么问题还... 查看详情

一文让你完全弄懂stegosaurus(代码片段)

国内关于Stegosaurus的介绍少之又少,一般只是单纯的工具使用的讲解之类的,并且本人在学习过程中也是遇到了很多的问题,基于此种情况下写下此文,也是为我逝去的青春时光留个念想吧~Stegosaurus是什么?在了解Stegosaurus是什... 查看详情

基于tensorflow+opencv实现cnn自定义图像分类(代码片段)

摘要:本篇文章主要通过Tensorflow+Opencv实现CNN自定义图像分类案例,它能解决我们现实论文或实践中的图像分类问题,并与机器学习的图像分类算法进行对比实验。本文分享自华为云社区《Tensorflow+Opencv实现CNN自... 查看详情

一文彻底弄懂“commonjs”与“esmodule”区别(代码片段)

简介文章中就不具体解释什么是“CommonJs”与“EsModule”了,我们先简单的描述一下“CommonJs”与“EsModule”的区别。它们有三个重大差异。CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。CommonJS模块是运行... 查看详情

使用 OpenCV 3.4 加载 CNN tensorflow 模型时出错

】使用OpenCV3.4加载CNNtensorflow模型时出错【英文标题】:ErrorwhileloadingCNNtensorflowmodelwithOpenCV3.4【发布时间】:2019-03-1214:08:54【问题描述】:我目前正在尝试使用OpenCV加载类似tensorflow的U-net模型。该模型是使用Tensorflow1.12.0使用Python3... 查看详情