TensorFlow实例(5.3)--MNIST手写数字进阶算法(卷积神经网络CNN) 之 最大池化tf.nn.max_pool

在这个文章里,将通过数据的变化,来演示卷积神经网络中最大池化(MaxPooling),

最大池化(MaxPooling)是卷积神经网络的第二步,

而本文的目的仅仅只是为了说明ksize、strides与padding参数


TensorFlow实例(5.3)--MNIST手写数字进阶算法(卷积神经网络CNN) 文章中,

第一层经网络用到下列句子

tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')  


第二个参数x,为传入量,也就是卷积神经网络的第一步卷积(Convolution)的输出量
x的shape必须为[batch, height, width, channels],
batch:在卷积的传入量可能是一张图片,也可能是N张图片,这里可以理解为图片数量,后面的例子都为1
height:图片的高度
width:图片的宽度
channels:通道数量,在Mnist中的第一步卷积,产生的是32个通道数量
本文的目的只是为了讲解MaxPooling,而不是神经网络,因为我会用一个函数构建x

第二个参数ksize:池化窗口的大小,shape也是[batch, height, width,channels],
在batch和channels上我们都设为1,当后面理解了height, width所代表的意思,batch和channels也就明白了

第三个参数strides:步长,一般也是[1, stride,stride, 1],参数和ksize差不多,功能不同

第四个参数padding:只能取'VALID' 或者'SAME'这两个值,但有什么差别,在后面的例子中演示


# -*- coding: utf-8 -*-
import numpy as np
import tensorflow as tf
def createData(height,width,channels):
    ''' 辅助函数一
    为了能更清晰的演示,建立这个函数,目的创建数据,即第一个参数x
    因为多张图片的传入量不好表示,batch值就固定为1
    返回值类型为numpy.array  
    '''
    size=height*width
    tmp=[]
    for i in range(size):
        item=[]
        for j in range(channels):
            item.append(j*size+i+1)
        tmp.append(item)
    tmp=np.array([tmp]).reshape(-1,height,width,channels)
    return tmp

def printData(npArr,message=""):
    '''辅助函数二
    打印出图片数据
    多通道图片都是模排显示,如果宽度及通道数太大,
    会每行宽度的原因自动换行,
    '''
    npArr=npArr[0]
    print("-"*40 + " 开始:"+message)
    print("图像信息:高:%d; 宽:%d; 通道:%d。以下为图像数据"%(len(npArr),len(npArr[0]),len(npArr[0][0])))
    print("");
    for i in npArr:
        tmp=i.T
        strtmp='';
        for j in tmp:
            strItem=''.join([x.rjust(4) for x in j.astype(np.str).tolist()])
            strtmp=strtmp+("" if strtmp=='' else " |")+strItem
        print(strtmp)
    print("-"*40 + " 结束:"+message)
    print("")


def max_pool(data,ksize,strides,padding):
    '''辅助函数三,目的是最大池化后返回numpy.array'''
    tmp=tf.nn.max_pool(data,ksize=ksize,strides=strides,padding=padding)
    return tf.Session().run(tmp)

#printData(createData(3,4,2));#测试以上两个函数结果如下:用|分割每个通道
   #1   2   3   4 |  13  14  15  16
   #5   6   7   8 |  17  18  19  20
   #9  10  11  12 |  21  22  23  24

#以下代码不再列出计算结果,要不整个代码显示很零散,自行运行后理解
data=createData(4,7,2)
printData(data,'案例一数据构建')

pool=max_pool(data,ksize=[1,2,2,1],strides=[1,1,1,1],padding="SAME")
printData(pool,"设置ksize值,可以看到每个通到都从图片的(2,2)的位值开始取值")

pool=max_pool(data,ksize=[1,1,1,1],strides=[1,2,2,1],padding="SAME")
printData(pool,"设置strides步长值,ksize从图片的(1,1) 每隔两位取值")
#从步长的取值,就可以知道,图片的缩放是由strides这个参数决定的

pool=max_pool(data,ksize=[1,2,2,1],strides=[1,3,3,1],padding="SAME")
printData(pool,"请先自行验证你推出的数据是否与显示的相同")

#错了吧,
#如最开始的 
# 9  12  14 |  37  40  42
#23  26  28 |  51  54  56

#data中宽为 7 ,步长为3,所以应该 取3个值  int(7/3)+1=3  整除就不有+1了
#               因为我们从2位开始取,,第3个值应该是8,超出了宽,第3个值就用最后一列补
#同理
#高为4 ,步长为3,取2个值,从2行开始取,第2个值应取第5行,超出了高,第2个值就用最后一行补


pool=max_pool(data,ksize=[1,2,2,1],strides=[1,3,3,1],padding="VALID")
printData(pool,"这才是你算出来的值,VALID简单的说就是超出不补")


data=createData(2,2,6)
printData(data,'案例二简单试试通道')
#注意,通道的取值方式和高宽一致但有地方不同
#1、当ksize中的channel=1,一定是取全部通道,
#2、padding没有什么用

#当ksize中的  channel!=1  时两个条件,
#1、输入的通道数 能整除ksize中的channel, 即12 mod 2=0
#2、产生的ksize中的channel,与 strides 中channel必须相同
pool=max_pool(data,ksize=[1,1,1,2],strides=[1,1,1,2],padding="SAME")
printData(pool)



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值