tensorflow入门项目(二):手写数字识别之CNN模型(详解)

前言

在做实战项目时,最好有一定的基础。个人觉得吴恩达的视频讲解的很好,可以看一下打个基础。
 
 

内容

 
 
附上代码以及详细解析,也可跳过讲解,直接复制代码。代码里包含全部讲解!

 import tensorflow as tf import numpy as np from
tensorflow.examples.tutorials.mnist import input_data mnist =
input_data.read_data_sets('E:/program/tensorflow_learning/example/mnist_program/mnist',one_hot=True)

导入数据
 

print(type(mnist))
print('train image shape输入数据:',mnist.train.images.shape,'trian label shape:', mnist.train.labels.shape)#(55000, 784),(55000, 10)
print('val image shape:', mnist.validation.images.shape)#(5000, 784)
print('test image shape:', mnist.test.images.shape)#(10000, 784)

查看数据类型
 

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.InteractiveSession(config=config)

设置tensorflow对GPU使用按需分配
 

def weight_variable(shape):
    init = tf.truncated_normal(shape,stddev=0.1)
    return tf.Variable(init)

使用正态分布初始化权值。
 
tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
shape表示一维的张量,也是输出的张量。
mean是正态分布的均值
stddev是标准差
从截断的正态分布中输出随机值。 生成的值服从具有指定平均值和标准偏差的正态分布,如果生成的值大于平均值2个标准偏差的值则丢弃重新选择。
在tf.truncated_normal中如果init的取值在区间(μ-2σ,μ+2σ)之外则重新进行选择。这样保证了生成的值都在均值附近
 
tf.Variable(initializer,name)
参数initializer是初始化参数,
name是可自定义的变量名称
 

def bias_variable(shape):
    init = tf.constant(0.1,shape=shape)
    return tf.Variable(init)

tf.constant(value,dtype=None,shape=None,name=‘Const’,verify_shape=False)
创建一个常量tensor,按照给出value来赋值,可以用shape来指定其形状。value可以是一个数,也可以是一个list。 如果是一个数,那么这个常量中所有值的按该数来赋值。
如果是list,那么len(value)一定要小于等于shape展开后的长度。赋值时,先将value中的值逐个存入。如果len(value)小于shape展开后的长度,则全部存入value的最后一个值。
详情指路:https://blog.csdn.net/csdn_jiayu/article/details/82155224

 

#定义卷积层
def conv2d(x,w):
    return tf.nn.conv2d(x,w,strides=[1,1,1,1],padding='SAME')

 
tf.nn.conv2d(input,filter,strides,padding,use_cudnn_on_gpu=None,name=None)
input:指定需要做卷积的输入图像,它要求是一个Tensor,具有[batch,in_height,in_width,in_channels]这样的形状(shape),具体含义是"训练时一个batch的图片数量,图片高度,图片宽度,图片通道数",注意这是一个四维的Tensor,要求类型为float32或者float64.

filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height,filter_width,in_channels,out_channels]这样的shape,
具体含义是"卷积核的高度,卷积核的宽度,图像通道数,滤波器个数",要求类型与参数input相同。有一个地方需要注意,第三维in_channels,就是参数input中的第四维

strides:卷积时在图像每一维的步长,这是一个一维的向量,长度为4,与输入input对应,一般值为[1,x,x,1],x取步长。

padding:定义元素边框与元素内容之间的空间。string类型的量,只能是"SAME"和“VALID”其中之一,这个值决定了不同的卷积方式。"SAME"和“VALID”的不同详情指路 https://blog.csdn.net/wuzqChom/article/details/74785643

use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认是True.

name:指定名字

 

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

 
池化一般分为最大池化和平均池化
tf.nn.max_pool(input,ksize,strides,padding,name=None)
tf.nn.avg_pooll(input,ksize,strides,padding,name=None)

input:需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch,height,width,channels]这样的shape。

ksize:池化窗口的大小,取一个思维向量,一般是[1,height,width,1],因为我们不想在batch和channels上做池化,所以这两个维度设为1.

strides:和卷积参数含义类似,窗口在每一个维度上滑动的步长,一般也是[1,stride,stride,1]。

padding:和卷积参数含义一样,也是"VALID"或者"SAME"。

该函数返回一个Tensor。类型不变,shape仍然是[batch,height,width,channels]这种形式。
池化层一般都是接在卷积层后面,用于减少参数矩阵的维度,从而减小最后全连接层的参数数目

 

x_ = tf.placeholder(tf.float32,[None,784])
y_ = tf.placeholder(tf.float32,[None,10])

 
在 MNIST 数据集中的每张图片由 28 x 28 个像素点构成, 每个像素点用一个灰度值表示.
在这里, 我们将 28 x 28 的像素展开为一个一维的行向量, 这些行向量就是图片数组里的行(每行 784 个值, 或者说每行就是代表了一张图片).
mnist 函数返回的第二个数组(labels) 包含了相应的目标变量, 也就是手写数字的类标签(整数 0-9).None的取值代表了batch的大小,数值不固定。
 

tf.placeholder(dtype, shape=None, name=None)
TensorFlow中的占位符,用于feed_dict传入外部数据。
这里None是随便传入几个样本,784是每一个样本有784列,这是确定的(因为用来训练的数据集为[55000,784]),每行代表一张图,用None代表你可以指定传入多少图。
下面的y也是这样,10代表10个类别
dtype:数据类型。
shape:数据的维度。默认为None,表示没有限制
name:名称
返回类型:Tensor
 

x = tf.reshape(x_,shape=[-1,28,28,1])

 
将x_变为一个4d向量,其第2、第3维对应图片的高、宽,最后一维代表图片的颜色通道数(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3)。-1代表自动计算剩下的维度。在这里-1就是指含有28x28x1向量的个数,具体多少个要看x_的输入,然后计算。详情指路:https://blog.csdn.net/qq_41424519/article/details/81778984
 

w_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x,w_conv1)+b_conv1)
h_pool1 = max_pooling(h_conv1)

 
搭建第一层网络:它由一个卷积接一个max pooling完成。卷积在每个5x5的patch中算出32个特征。卷积的权重张量形状是[5, 5, 1, 32],前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目。 而对于每一个输出通道都有一个对应的偏置量b。32个过滤器。
 
卷积层:x输入为[-1,28,28,1],经过32个过滤器,共享权重矩阵为1x5x5的卷积,且滑动步长为[1,1,1,1],最后输出为[-1,28,28,32],因为长和宽上的滑动步长为1,1,且padding=‘SAME’,所以原图像的高宽不变为28,28.又经过32个过滤器,通道数变为32.
 
池化层:输入为:[-1,28,28,32],滑动步长为[1,2,2,1],长和宽上的步长为2,所以输出图像的长和宽减半,batch和channels都是1,不变。所以输出图像为[-1,14,14,32]
 
激活函数tf.nn.relu()
函数的目的是,将输入小于0的值赋值为0,输入大于0的值不变
 

w_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2)
h_pool2 = max_pooling(h_conv2)

 
第二层网络的搭建,64个过滤器,共享权重矩阵为32x5x5
 
卷积层:x输入为[-1,14,14,32],经过64个过滤器,共享权重矩阵为3255的卷积,且滑动步长为[1,1,1,1],最后输出为[-1,14,14,64],因为长和宽上的滑动步长为1,1,padding=‘SAME’,所以原图像的高宽不变为28,28.且经过64个过滤器,通道数变为64.
池化层:输入为:[-1,14,14,64],滑动步长为[1,2,2,1],长和宽上的步长为2,所以输出图像的长和宽减半,batch和channels都是1,不变。所以输出图像为[-1,7,7,64]
 

h_pool2_falt = tf.reshape(h_pool2,[-1,7*7*64])
w_h = weight_variable([7*7*64,1024])
b_h = bias_variable([1024])
hidden = tf.nn.relu(tf.matmul(h_pool2_falt,w_h) + b_h)

 
全连接层
现在,图片尺寸减小到7x7,我们加入一个有1024个神经元的全连接层,用于处理整个图片。我们把池化层

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值