第三节,TensorFlow 使用CNN实现手写数字识别

上一节,我们已经讲解了使用全连接网络实现手写数字识别,其正确率大概能达到98%,着一节我们使用卷积神经网络来实现手写数字识别,

其准确率可以超过99%,程序主要包括以下几块内容

  • [1]: 导入数据,即测试集和验证集
  • [2]: 引入 tensorflow 启动InteractiveSession(比session更灵活)
  • [3]: 定义两个初始化w和b的函数,方便后续操作
  • [4]: 定义卷积和池化函数,这里卷积采用padding,使得
  • 输入输出图像一样大,池化采取2x2,那么就是4格变一格
  • [5]: 分配输入x_和y_
  • [6]: 修改x的shape
  • [7]: 定义第一层卷积的w和b
  • [8]: 把x_image和w进行卷积,加上b,然后应用ReLU激活函数,最后进行max-pooling
  • [9]: 第二层卷积,和第一层卷积类似
  • [10]: 全连接层
  • [11]: 为了减少过拟合,可以在输出层之前加入dropout。(但是本例子比较简单,即使不加,影响也不大)
  • [12]: 由一个softmax层来得到输出
  • [13]: 定义代价函数,训练步骤,用Adam来进行优化
  • [14]: 使用测试集样本进行测试
# -*- coding: utf-8 -*-
"""
Created on Mon Apr  2 18:32:47 2018

@author: Administrator
"""

‘‘‘
这里我们没有定义一个实现CNN的类,实际上我们可以定义一个CNN的类,并且把每一层也定义成一个类

利用CNN实现手写数字识别

In [1]: 导入数据,即测试集和验证集

In [2]: 引入 tensorflow 启动InteractiveSession(比session更灵活)

In [3]: 定义两个初始化w和b的函数,方便后续操作

In [4]: 定义卷积和池化函数,这里卷积采用padding,使得输入输出图像一样大,池化采取2x2,那么就是4格变一格

In [5]: 分配输入x_和y_

In [6]: 修改x的shape

In [7]: 定义第一层卷积的w和b

In [8]: 把x_image和w进行卷积,加上b,然后应用ReLU激活函数,最后进行max-pooling

In [9]: 第二层卷积,和第一层卷积类似

In [10]: 全连接层

In [11]: 为了减少过拟合,可以在输出层之前加入dropout。(但是本例子比较简单,即使不加,影响也不大)

In [12]: 由一个softmax层来得到输出

In [13]: 定义代价函数,训练步骤,用Adam来进行优化 

In [14]: 使用测试集样本进行测试

‘‘‘

import tensorflow as tf
import numpy as np

‘‘‘
一 导入数据
‘‘‘
from tensorflow.examples.tutorials.mnist import input_data

#mnist是一个轻量级的类,它以numpy数组的形式存储着训练,校验,测试数据集  one_hot表示输出二值化后的10维
mnist = input_data.read_data_sets(‘MNIST-data‘,one_hot=True)

print(type(mnist)) #<class ‘tensorflow.contrib.learn.python.learn.datasets.base.Datasets‘>

print(‘Training data shape:‘,mnist.train.images.shape)           #Training data shape: (55000, 784)
print(‘Test data shape:‘,mnist.test.images.shape)                #Test data shape: (10000, 784)
print(‘Validation data shape:‘,mnist.validation.images.shape)    #Validation data shape: (5000, 784)
print(‘Training label shape:‘,mnist.train.labels.shape)          #Training label shape: (55000, 10)

#设置tensorflow对GPU使用按需分配
config = tf.ConfigProto()
config.gpu_options.allow_growth = True

sess = tf.InteractiveSession(config=config)

‘‘‘
二 构建网络
‘‘‘
‘‘‘
初始化权值和偏重
为了创建这个模型,我们需要创建大量的权重和偏置项。这个模型中的权重在初始化时应该加入少量的噪声来
打破对称性以及避免0梯度。由于我们使用的是ReLU神经元,因此比较好的做法是用一个较小的正数来初始化
偏置项,以避免神经元节点输出恒为0的问题(dead neurons)。为了不在建立模型的时候反复做初始化操作
,我们定义两个函数用于初始化。
‘‘‘
def weight_variable(shape):
    #使用正太分布初始化权值
    initial = tf.truncated_normal(shape,stddev=0.1)    #标准差为0.1
    return tf.Variable(initial)

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

‘‘‘
卷积和赤池化
TensorFlow在卷积和池化上有很强的灵活性。我们怎么处理边界?步长应该设多大?在这个实例里,我们会
一直使用vanilla版本。我们的卷积使用1步长(stride size),0边距(padding size)的模板,保证输
出和输入是同一个大小。我们的池化用简单传统的2x2大小的模板做max pooling。为了代码更简洁,我们把
这部分抽象成一个函数。
‘‘‘
#定义卷积层
def conv2d(x,W):
    ‘‘‘默认 strides[0] = strides[3] = 1,strides[1]为x方向步长,strides[2]为y方向步长
     Given an input tensor of shape `[batch, in_height, in_width, in_channels]`
     and a filter / kernel tensor of shape `[filter_height, filter_width, in_channels,
     out_channels]`
    ‘‘‘
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding = ‘SAME‘)

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

#我们通过为输入图像和目标输出类别创建节点,来开始构建计算题  None表示数值不固定,用来指定batch的大小
x_ = tf.placeholder(tf.float32,[None,784])
y_ = tf.placeholder(tf.float32,[None,10])

#把x转换为卷积所需要的形式  batch_size张手写数字,每张维度为1x28x28
‘‘‘
为了用这一层,我们把x变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数
(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3)。
‘‘‘
X = tf.reshape(x_,shape=[-1,28,28,1])

‘‘‘
现在我们可以开始实现第一层了。它由一个卷积接一个max pooling完成。卷积在每个5x5的patch中算出
32个特征。卷积的权重张量形状是[5, 5, 1, 32],前两个维度是patch的大小,接着是输入的通道数目,
最后是输出的通道数目。 而对于每一个输出通道都有一个对应的偏置量。
‘‘‘
#第一层卷积,32个滤波器,卷积和为1*5*5  h_conv1.shape=[-1,28,28,32]
w_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(X,w_conv1) + b_conv1)

#第一个pooling层 最大值池化层2x2 [-1,28,28,28]->[-1,14,14,32]
h_pool1 = max_pooling(h_conv1)

#第二层卷积,64个滤波器,卷积和为32*5*5  h_conv2.shape=[-1,14,14,64]
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)

#第二个pooling层 最大值池化层2x2 [-1,14,14,64]->[-1,7,7,64]
h_pool2 = max_pooling(h_conv2)

‘‘‘
全连接层
现在,图片尺寸减小到7x7,我们加入一个有1024个神经元的全连接层,用于处理整个图片。我们把池化层输
出的张量reshape成一些向量,乘上权重矩阵,加上偏置,然后对其使用ReLU。
‘‘‘
h_poo2_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_poo2_falt,w_h) + b_h)

‘‘‘
加入弃权,把部分神经元输出置为0
为了减少过拟合,我们在输出层之前加入dropout。我们用一个placeholder来代表一个神经元的输出在
dropout中保持不变的概率。这样我们可以在训练过程中启用dropout,在测试过程中关闭dropout。
TensorFlow的tf.nn.dropout操作除了可以屏蔽神经元的输出外,还会自动处理神经元输出值的scale。
所以用dropout的时候可以不用考虑scale。
‘‘‘
keep_prob = tf.placeholder(tf.float32)    #弃权概率
hidden_drop = tf.nn.dropout(hidden,keep_prob)

‘‘‘
输出层
最后,我们添加一个softmax层,就像前面的单层softmax regression一样。
‘‘‘
w_o = weight_variable([1024,10])
b_o = bias_variable([10])
output = tf.nn.softmax(tf.matmul(hidden_drop,w_o) + b_o)

‘‘‘
三 设置对数似然损失函数
‘‘‘
#代价函数 J =-(Σy.logaL)/n    .表示逐元素乘
cost = -tf.reduce_sum(y_*tf.log(output))

‘‘‘
四 求解
‘‘‘
train = tf.train.AdamOptimizer(0.0001).minimize(cost)

#预测结果评估
#tf.argmax(output,1)  按行统计最大值得索引
correct = tf.equal(tf.argmax(output,1),tf.argmax(y_,1))       #返回一个数组 表示统计预测正确或者错误
accuracy = tf.reduce_mean(tf.cast(correct,tf.float32))        #求准确率

#创建list 保存每一迭代的结果
training_accuracy_list = []
test_accuracy_list = []
training_cost_list=[]
test_cost_list=[]

#使用会话执行图
sess.run(tf.global_variables_initializer())   #初始化变量

#开始迭代 使用Adam优化的随机梯度下降法
for i in range(1000):   #一个epoch需要迭代次数计算公式:测试集长度 / batch_size
    x_batch,y_batch = mnist.train.next_batch(batch_size = 64)
    #开始训练
    train.run(feed_dict={x_:x_batch,y_:y_batch,keep_prob:1.0})
    if (i+1)%200 == 0:
         #输出训练集准确率
        #training_accuracy = accuracy.eval(feed_dict={x_:mnist.train.images,y_:mnist.train.labels})
        training_accuracy,training_cost = sess.run([accuracy,cost],feed_dict={x_:x_batch,y_:y_batch,keep_prob:1.0})
        training_accuracy_list.append(training_accuracy)
        training_cost_list.append(training_cost)
        print(‘Step {0}:Training set accuracy {1},cost {2}.‘.format(i+1,training_accuracy,training_cost))

#全部训练完成做测试  分成200次,一次测试50个样本
#输出测试机准确率   如果一次性全部做测试,内容不够用会出现OOM错误。所以测试时选取比较小的mini_batch来测试
#test_accuracy = accuracy.eval(feed_dict={x_:mnist.test.images,y_:mnist.test.labels})
for i in range(200):
    x_batch,y_batch = mnist.train.next_batch(batch_size = 50)
    test_accuracy,test_cost = sess.run([accuracy,cost],feed_dict={x_:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0})
    test_accuracy_list.append(test_accuracy)
    test_cost_list.append(test_cost)
    print(‘Step {0}:Test set accuracy {1},cost {2}.‘.format(i+1,test_accuracy,test_cost))
print(‘Test accuracy:‘,np.mean(test_accuracy_list))

‘‘‘
图像操作
‘‘‘
import matplotlib.pyplot as plt
#随便取一张图像
img = mnist.train.imgaes[0]
label = mnist.train.labels[0]

print(‘图像像素值:{0},对应的标签{1}‘,img.reshape(28,28),np.argmax(label,axis=1))

plt.figure()

#子图1
plt.subplot(1,2,1)
plt.imshow(img.reshape(28,28))                #显示的是热度图片
plt.axis(‘off‘)                               #不显示坐标轴

#子图2
plt.subplot(1,2,2)
plt.imshow(img.reshape(28,28),cmap=‘gray‘)    #显示灰度图片
plt.axis(‘off‘)

plt.show()

‘‘‘
显示卷积和池化层结果
‘‘‘
plt.figure()
#显示第一个卷积层之后的结果  (1,28,28,32)
conv1 = h_conv1.eval(feed_dict={x_:img,y_:label,keep_prob:1.0})
print(‘conv1 shape‘,conv1.shape)

for i in range(32):
    show_image = conv1[:,:,:,1]
    show_image.shape = [28,28]
    plt.subplot(4,8,i)
    plt.imshow(show_image,cmap=‘gray‘)
    plt.axis(‘off‘)
plt.show()   

plt.figure()
#显示第一个池化层之后的结果  (1,14,14,32)
pool1 = h_pool1.eval(feed_dict={x_:img,y_:label,keep_prob:1.0})
print(‘conv1 shape‘,pool1.shape)

for i in range(32):
    show_image = pool1[:,:,:,1]
    show_image.shape = [28,28]
    plt.subplot(4,8,i)
    plt.imshow(show_image,cmap=‘gray‘)
    plt.axis(‘off‘)
plt.show()     

原文地址:https://www.cnblogs.com/zyly/p/8697985.html

时间: 2024-10-20 09:33:32

第三节,TensorFlow 使用CNN实现手写数字识别的相关文章

Tensorflow实战 手写数字识别(Tensorboard可视化)

一.前言 为了更好的理解Neural Network,本文使用Tensorflow实现一个最简单的神经网络,然后使用MNIST数据集进行测试.同时使用Tensorboard对训练过程进行可视化,算是打响学习Tensorflow的第一枪啦. 看本文之前,希望你已经具备机器学习和深度学习基础. 机器学习基础可以看我的系列博文: https://cuijiahua.com/blog/ml/ 深度学习基础可以看吴恩达老师的公开课: http://mooc.study.163.com/smartSpec/

Tensorflow实践 mnist手写数字识别

minst数据集                                         tensorflow的文档中就自带了mnist手写数字识别的例子,是一个很经典也比较简单的入门tensorflow的例子,非常值得自己动手亲自实践一下.由于我用的不是tensorflow中自带的mnist数据集,而是从kaggle的网站下载下来的,数据集有些不太一样,所以直接按照tensorflow官方文档上的参数训练的话还是踩了一些坑,特此记录. 首先从kaggle网站下载mnist数据集,一份是

tensorflow 基础学习五:MNIST手写数字识别

MNIST数据集介绍: from tensorflow.examples.tutorials.mnist import input_data # 载入MNIST数据集,如果指定地址下没有已经下载好的数据,tensorflow会自动下载数据 mnist=input_data.read_data_sets('.',one_hot=True) # 打印 Training data size:55000. print("Training data size: {}".format(mnist.

第二节,TensorFlow 使用前馈神经网络实现手写数字识别

一 感知器      感知器学习笔记:https://blog.csdn.net/liyuanbhu/article/details/51622695      感知器(Perceptron)是二分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1.这种算法的局限性很大: 只能将数据分为 2 类 数据必须是线性可分的 虽然有这些局限,但是感知器是 ANN 和 SVM 的基础,理解了感知器的原理,对学习ANN 和 SVM 会有帮助,所以还是值得花些时间的. 感知器可以表示为

Kaggle竞赛丨入门手写数字识别之KNN、CNN、降维

引言 这段时间来,看了西瓜书.蓝皮书,各种机器学习算法都有所了解,但在实践方面却缺乏相应的锻炼.于是我决定通过Kaggle这个平台来提升一下自己的应用能力,培养自己的数据分析能力. 我个人的计划是先从简单的数据集入手如手写数字识别.泰坦尼克号.房价预测,这些目前已经有丰富且成熟的方案可以参考,之后关注未来就业的方向如计算广告.点击率预测,有合适的时机,再与小伙伴一同参加线上比赛. 数据集 介绍 MNIST ("Modified National Institute of Standards an

Tensorflow快速入门2--实现手写数字识别

Tensorflow快速入门2–实现手写数字识别 环境: 虚拟机ubuntun16.0.4 Tensorflow(仅使用cpu版) Tensorflow安装见: http://blog.csdn.net/yhhyhhyhhyhh/article/details/54429034 或者: http://www.tensorfly.cn/tfdoc/get_started/os_setup.html 本文将利用Tensorflow以softmax回归和卷积神经网络两种模型简单测试MNIST数据集,快

【PaddlePaddle系列】手写数字识别

  最近百度为了推广自家编写对深度学习框架PaddlePaddle不断推出各种比赛.百度声称PaddlePaddle是一个"易学.易用"的开源深度学习框架,然而网上的资料少之又少.虽然百度很用心地提供了许多文档,而且还是中英双语具备,但是最关键的是报错了很难在网上找到相应的解决办法.为了明年备战百度的比赛,便开始学习以下PaddlePaddle. 1.安装 PaddlePaddle同样支持CUDA加速运算,但是如果没有NVIDIA的显卡,那就还是装CPU版本. CPU版本安装:pip

CNN-mnist手写数字识别

Tensorflow+CNN下的mnist数据集手写数字识别 加载数据集 MNIST数据集包含55000个训练样本,10000个测试样本,还有5000个交叉验证数据样本. 输入:加载的每个手写数字图像是28 x 28像素大小的灰度图像.为了简化起见,将28x28的像素点展开为一维数据(shape=784). 输出:每张测试图片的预测结果y为一个10维数组,数组中值的取值范围为[0,1],使用tf.argmax(y,1),取出数组中最大值的下标,再用独热表示以及模型输出转换成数字标签.      

深度学习面试题12:LeNet(手写数字识别)

目录 神经网络的卷积.池化.拉伸 LeNet网络结构 LeNet在MNIST数据集上应用 参考资料 LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务.自那时起,CNN的最基本的架构就定下来了:卷积层.池化层.全连接层.如今各大深度学习框架中所使用的LeNet都是简化改进过的LeNet-5(-5表示具有5个层),和原始的LeNet有些许不同,比如把激活函数改为了现在很常用的ReLu. 神经网络的卷积.池化.拉伸 前面讲了卷积和池化,卷积层可以从图像中提取特