Tensorflow实践:CNN实现MNIST手写识别模型

来源:36大数据 作者:网友

前言

本文假设大家对CNN、softmax原理已经比较熟悉,着重点在于使用Tensorflow对CNN的简单实践上。所以不会对算法进行详细介绍,主要针对代码中所使用的一些函数定义与用法进行解释,并给出最终运行代码。

数据集

数据集是MNIST,一个入门级的计算机视觉数据集,它包含各种手写数字图片:

大数据

每张图片包含28X28个像素点,标签即为图片中的数字。

问题

使用MNIST数据集进行训练,识别图片中的手写数字(0到9共10类)。

思路

使用一个简单的CNN网络结构如下,括号里边表示tensor经过本层后的输出shape:

  • 输入层(28 * 28 * 1)

  • 卷积层1(28 * 28 * 32)

  • pooling层1(14 * 14 * 32)

  • 卷积层2(14 * 14 * 64)

  • pooling层2(7 * 7 * 64)

  • 全连接层(1 * 1024)

  • softmax层(10)

具体的参数看后边的代码注释。

函数说明

在撸代码前,先对几个会用到的主要函数中的主要参数进行说明。

tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)

随机产生一个形状为shape的服从截断正态分布(均值为mean,标准差为stddev)的tensor。截断的方法根据官方API的定义为,如果单次随机生成的值偏离均值2倍标准差之外,就丢弃并重新随机生成一个新的数。

tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)

  • input
    input是一个形状为 [batch, in_height, in_width, in_channels] 的tensor:


    • batch
      每次batch数据的数量。

    • in_height,in_width
      输入矩阵的高和宽,如输入层的图片是28*28,则in_height和in_width就都为28。

    • in_channels
      输入通道数量。如输入层的图片经过了二值化,则通道为1,如果输入层的图片是RGB彩色的,则通道为3;再如卷积层1有32个通道,则pooling层1的输入(卷积层1的输出)即为32通道。

  • filter
    filter是一个形状为 [filter_height, filter_width, in_channels, out_channels]的tensor:


    • filter_height, filter_width
      卷积核的高与宽。如卷积层1中的卷积核,filter_height, filter_width都为28。

    • in_channels
      输入通道数量。

    • out_channels
      输出通道的数量。如输入数据经过卷积层1后,通道数量从1变为32。

  • strides
    strides是指滑动窗口(卷积核)的滑动规则,包含4个维度,分别对应input的4个维度,即每次在input tensor上滑动时的步长。其中batch和in_channels维度一般都设置为1,所以形状为 [1, stride, stride, 1] 。

  • padding
    这个在之前的文章中说过,这里不再复述,看这里回顾。

tf.nn.max_pool(value, ksize, strides, padding, data_format=’NHWC’, name=None)

  • value
    以tf.nn.conv2d()函数的参数input理解即可。

  • ksize
    滑动窗口(pool)的大小尺寸,这里注意这个大小尺寸并不仅仅指2维上的高和宽,ksize的每个维度同样对应input的各个维度(只是大小,不是滑动步长),同样的,batch和in_channels维度多设置为1。如pooling层1的ksize即为 [1, 2, 2, 1] ,即用一个2*2的窗口做pooling。

  • strides
    同tf.nn.conv2d()函数的参数strides。

  • padding
    看 这里 。

tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)

这里不对dropout的算法进行描述,如果不知道自行百度。

  • x
    输入tensor。

  • keep_prob
    x中每个元素的输出概率,输出为原值或0。

代码

talk is cheap, show me the code.

#coding:utf-8import tensorflow as tfimport MNIST_data.input_data as input_dataimport time"""
权重初始化
初始化为一个接近0的很小的正数
"""def weight_variable(shape):
   initial = tf.truncated_normal(shape, stddev = 0.1)    return tf.Variable(initial)def bias_variable(shape):
   initial = tf.constant(0.1, shape = shape)    return tf.Variable(initial)"""
卷积和池化,使用卷积步长为1(stride size),0边距(padding size)
池化用简单传统的2x2大小的模板做max pooling
"""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, data_format=None, name=None)
   # x(input)  : [batch, in_height, in_width, in_channels]
   # W(filter) : [filter_height, filter_width, in_channels, out_channels]
   # strides   : The stride of the sliding window for each dimension of input.
   #             For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1]def max_pool_2x2(x):
   return tf.nn.max_pool(x, ksize = [1, 2, 2, 1],
                         strides = [1, 2, 2, 1], padding = 'SAME')    # tf.nn.max_pool(value, ksize, strides, padding, data_format='NHWC', name=None)
   # x(value)              : [batch, height, width, channels]
   # ksize(pool大小)        : A list of ints that has length >= 4. The size of the window for each dimension of the input tensor.
   # strides(pool滑动大小)   : A list of ints that has length >= 4. The stride of the sliding window for each dimension of the input tensor.start = time.clock() #计算开始时间mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #MNIST数据输入"""
第一层 卷积层

x_image(batch, 28, 28, 1) -> h_pool1(batch, 14, 14, 32)
"""x = tf.placeholder(tf.float32,[None, 784])
x_image = tf.reshape(x, [-1, 28, 28, 1]) #最后一维代表通道数目,如果是rgb则为3 W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)# x_image -> [batch, in_height, in_width, in_channels]#            [batch, 28, 28, 1]# W_conv1 -> [filter_height, filter_width, in_channels, out_channels]#            [5, 5, 1, 32]# output  -> [batch, out_height, out_width, out_channels]#            [batch, 28, 28, 32]h_pool1 = max_pool_2x2(h_conv1)# h_conv1 -> [batch, in_height, in_weight, in_channels]#            [batch, 28, 28, 32]# output  -> [batch, out_height, out_weight, out_channels]#            [batch, 14, 14, 32]"""
第二层 卷积层

h_pool1(batch, 14, 14, 32) -> h_pool2(batch, 7, 7, 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)# h_pool1 -> [batch, 14, 14, 32]# W_conv2 -> [5, 5, 32, 64]# output  -> [batch, 14, 14, 64]h_pool2 = max_pool_2x2(h_conv2)# h_conv2 -> [batch, 14, 14, 64]# output  -> [batch, 7, 7, 64]"""
第三层 全连接层

h_pool2(batch, 7, 7, 64) -> h_fc1(1, 1024)
"""W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)"""
Dropout

h_fc1 -> h_fc1_drop, 训练中启用,测试中关闭
"""keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)"""
第四层 Softmax输出层
"""W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)"""
训练和评估模型

ADAM优化器来做梯度最速下降,feed_dict中加入参数keep_prob控制dropout比例
"""y_ = tf.placeholder("float", [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv)) #计算交叉熵train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) #使用adam优化器来以0.0001的学习率来进行微调correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1)) #判断预测标签和实际标签是否匹配accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))

sess = tf.Session() #启动创建的模型sess.run(tf.initialize_all_variables()) #旧版本#sess.run(tf.global_variables_initializer()) #初始化变量for i in range(5000): #开始训练模型,循环训练5000次
   batch = mnist.train.next_batch(50) #batch大小设置为50
   if i % 100 == 0:
       train_accuracy = accuracy.eval(session = sess,
                                      feed_dict = {x:batch[0], y_:batch[1], keep_prob:1.0})
       print("step %d, train_accuracy %g" %(i, train_accuracy))
   train_step.run(session = sess, feed_dict = {x:batch[0], y_:batch[1],
                  keep_prob:0.5}) #神经元输出保持不变的概率 keep_prob 为0.5print("test accuracy %g" %accuracy.eval(session = sess,
     feed_dict = {x:mnist.test.images, y_:mnist.test.labels,
                  keep_prob:1.0})) #神经元输出保持不变的概率 keep_prob 为 1,即不变,一直保持输出end = time.clock() #计算程序结束时间print("running time is %g s") % (end-start)


相关文档推荐

腾讯大数据基于StarRocks的向量检索探索.PDF

1737425434 赵裕隆 3.48MB 34页 积分6

B站一站式大数据集群管理平台.PDF

1737421412 刘明刚 1.37MB 30页 积分6

StarRocks在爱奇艺大数据场景的实践.PDF

1737365327 林豪 3.57MB 27页 积分5

农业农村大数据平台互联互通规范.PDF

1736163860  0.49MB 11页 积分5

工业大数据管理与治理智能制造的基座.PDF

1733702095 王宏志 3.83MB 54页 积分6

中国出海互联网公司数据保护合规对策.PDF

1732603379  2.22MB 14页 积分4

数据跨境现状调查与分析报告.PDF

1732603016  1.98MB 53页 积分5

企业数据合规指引个人信息保护指引.PDF

1732591271  15.22MB 23页 积分5

相关文章推荐

大数据开发流程及规范

网络收集 CIO之家的朋友 

大数据技术名词解释

51CTO CIO之家的朋友 

大数据常见问题之数据倾斜

CSDN CIO之家的朋友 

详解大数据批流处理中的两大架构

数仓宝贝库 韩锐、刘驰 

什么是大数据战略以及如何构建

51CTO CIO之家的朋友 

大数据的数据治理与应用场景

51CTO CIO之家的朋友