一、基础知识

基础知识可以跳过,可以直接看后面的代码实现

MNIST数据集

MNIST数据集的官网是Yann LeCun’s website。可以使用下面的python代码自动下载数据集。

#已经下载input_data.py
#import input_data
#没有下载input_data.py
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

下载下来的数据集被分成两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test)。这样的切分很重要,在机器学习模型设计时必须有一个单独的测试数据集不用于训练而是用来评估这个模型的性能,从而更加容易把设计的模型推广到其他数据集上(泛化)。
每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。我们把这些图片设为“xs”,把这些标签设为“ys”。训练数据集和测试数据集都包含xs和ys,比如训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels。

每一张图片包含28像素X28像素。我们可以用一个数字数组来表示这张图片:

我们把这个数组展开成一个向量,长度是 28x28 = 784。如何展开这个数组(数字间的顺序)不重要,只要保持各个图片采用相同的方式展开。从这个角度来看,MNIST数据集的图片就是在784维向量空间里面的点, 并且拥有比较复杂的结构 (提醒: 此类数据的可视化是计算密集型的)。

展平图片的数字数组会丢失图片的二维结构信息。这显然是不理想的,最优秀的计算机视觉方法会挖掘并利用这些结构信息,我们会在后续教程中介绍。但是在这个教程中我们忽略这些结构,所介绍的简单数学模型,softmax回归(softmax regression),不会利用这些结构信息。

一般的计算机视觉会先把图像转为图像矩阵,然后再转化为一维向量,处理图片过程如下:

from PIL import Image
#打开图像
image = Image.open("smallpi.jpg")
#转化成灰度图像,这一步不是必须的,但为了效率一般都会处理
image_gray = image.convert("L")
#Image对象转化成图像矩阵
image_array = np.array(image_gray )
#flatten可以将矩阵转化成一维序列
image_vectors = image_array.flatten()
#归一化处理到0-1范围内
image_vectors_float = image_vectors/255

因此,在MNIST训练数据集中,mnist.train.images 是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0和1之间。

相对应的MNIST数据集的标签是介于0到9的数字,用来描述给定图片里表示的数字。为了用于这个教程,我们使标签数据是"one-hot vectors"。 一个one-hot向量除了某一位的数字是1以外其余各维度数字都是0。所以在此教程中,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels 是一个 [60000, 10] 的数字矩阵。

我们可以通过下面的python代码查看mnist这个数据集的情况:

print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.labels.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)

其中mnist.train.images返回训练集的图片信息,minist.test返回测试集的图片信息,mnist.validation.images返回测试集的图片信息。而labels就是图片标签:0-9shape就是矩阵数据的维度,比如 [[2,3],[3,5],[1,5]]通过shape运算就返回(3,2)。
以上运行结果为:

(55000, 784) (55000, 10)
(10000, 784) (10000, 10)
(5000, 784) (5000, 10)

Softmax回归

softmax用于多分类过程中,它将多个神经元的输出,映射到(0,1)区间内,可以看成概率来理解,从而来进行多分类!
假设我们有一个数组,V,Vi表示V中的第i个元素,那么这个元素的softmax值就是
si=ei∑jejs_i = \dfrac{e^i}{\sum_j e^j} si​=∑j​ejei​
更形象的如下图表示:

计算过程如下(用了四舍五入,保留2位有效数字):
y1=ez1∑j=13ezj=ez1ez1+ez2+ez3y_1=\dfrac{e^{z_1}}{\sum_{j=1}^3e^{z_j}}=\dfrac{e^{z_1}}{e^{z_1}+e^{z_2}+e^{z_3}}y1​=∑j=13​ezj​ez1​​=ez1​+ez2​+ez3​ez1​​=e3e3+e1+e−3=2020+2.7+0.05=0.88=\dfrac{e^3}{e^3+e^1+e^{-3}} =\dfrac{20}{20+2.7+0.05}=0.88=e3+e1+e−3e3​=20+2.7+0.0520​=0.88
y2=ez2∑j=13ezj=ez2ez1+ez2+ez3y_2=\dfrac{e^{z_2}}{\sum_{j=1}^3e^{z_j}}=\dfrac{e^{z_2}}{e^{z_1}+e^{z_2}+e^{z_3}}y2​=∑j=13​ezj​ez2​​=ez1​+ez2​+ez3​ez2​​=e1e3+e1+e−3=2.720+2.7+0.05=0.12=\dfrac{e^1}{e^3+e^1+e^{-3}} =\dfrac{2.7}{20+2.7+0.05}=0.12=e3+e1+e−3e1​=20+2.7+0.052.7​=0.12
y3=ez3∑j=13ezj=ez3ez1+ez2+ez3y_3=\dfrac{e^{z_3}}{\sum_{j=1}^3e^{z_j}}=\dfrac{e^{z_3}}{e^{z_1}+e^{z_2}+e^{z_3}}y3​=∑j=13​ezj​ez3​​=ez1​+ez2​+ez3​ez3​​=e−3e3+e1+e−3=0.0520+2.7+0.05=0=\dfrac{e^{-3}}{e^3+e^1+e^{-3}} =\dfrac{0.05}{20+2.7+0.05}=0=e3+e1+e−3e−3​=20+2.7+0.050.05​=0
其中:
z1=w11×x1+w21×x2+w31×x3z_1=w_{11} \times x_1+w_{21} \times x_2+w_{31} \times x_3 z1​=w11​×x1​+w21​×x2​+w31​×x3​
z2=w12×x1+w22×x2+w32×x3z_2=w_{12} \times x_1+w_{22} \times x_2+w_{32} \times x_3 z2​=w12​×x1​+w22​×x2​+w32​×x3​
z3=w13×x1+w23×x2+w33×x3z_3=w_{13} \times x_1+w_{23} \times x_2+w_{33} \times x_3 z3​=w13​×x1​+w23​×x2​+w33​×x3​
softmax直白来说就是将原来输出是3,1,-3通过softmax函数一作用,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标!

对于softmax回归模型可以用下面的图解释,对于输入的xs加权求和,再分别加上一个偏置量,最后再输入到softmax函数中:

如果把它写成一个等式,我们可以得到:

我们也可以用向量表示这个计算过程:用矩阵乘法和向量相加。这有助于提高计算效率。(也是一种更有效的思考方式)

更进一步,可以写成更加紧凑的方式:
y=softmax(Wx+b)y=softmax(Wx+b)y=softmax(Wx+b)

二、使用 TensorFlow 实现Softmax回归模型

1、定义x,y两个Placeholder,所谓Placehoder,初学者可以理解为一种容器,后面我们将会把上面的训练集数据mnist.train.images及minst.train.labels输入到x,y中。
我们希望能够输入任意数量的MNIST图像,每一张图展平成784维的向量。我们用2维的浮点数张量来表示这些图,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度可以是任何长度的。)

import tensorflow as tf#定义两个placeholder
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])

这里的参数x将会是输入的图片数据即为[None,784],None就是图片的数量,因为我们训练的时候并不是一张一张图片输入的,因为一张一张输入的效率低,而且会因为一张噪音图片的对整个网络造成巨大影响,正确的训练方法应该是将100张图片组成的数据集[100,784]输入神经网络进行训练(当然,这里的100也可以是其他数值)。然后得到神经网络的输出prediction,这里的prediction就是标签y的预测值,也是一个10维的向量,例如[0.12,0.22,0.21,0.86,0.33,0.01,0.81,0.15,0.54,0.13]

2、接下来我们定义权重值和偏置量。

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

在这里,我们都用全为零的张量来初始化W和b。因为我们要学习W和b的值,它们的初值可以随意设置。一般的情况下我们都是采用随机设置。

3、创建模型。

prediction = tf.nn.softmax(tf.matmul(x,W)+b)

用tf.matmul(​​X,W)表示矩阵xxx乘以矩阵WWW,对应之前等式里面的WxWxWx,这里x是一个2维张量拥有多个输入。然后再加上矩阵bbb,把和输入到tf.nn.softmax函数里面。

4、定义损失函数(也叫成本函数)和优化算法。
这里定义二次损失函数和梯度优化算法,我们的目的就是通过更新神经网络参数W,b来让loss的最小,而更新WWW,bbb的操作就是train_step.

#二次代价函数
loss = tf.reduce_mean(tf.square(y-prediction))
#使用梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)

其中二次代价函数(也称为方差)为
loss=12N∑n=1N(y−prediction)2loss = \dfrac{1}{2N}\sum_{n=1}^N(y - prediction)^2 loss=2N1​n=1∑N​(y−prediction)2
从sigmoid函数的图像就会发现,它的两侧几乎就是平的,导致它的方差在大部分情况下很小,这样在训练参数的时候收敛地就会很慢,交叉熵就是用来解决这个问题的。它的定义如下:
Hy′(y)=−∑iyi′log(yi)H_{y'}(y)=-\sum_iy'_ilog(y_i)Hy′​(y)=−i∑​yi′​log(yi​)
其中,y 是我们预测的概率分布, y’ 是实际的分布。
所以损失函数如下:
loss=−∑ylog(prediction)loss = -\sum ylog(prediction )loss=−∑ylog(prediction)
代码如下:

loss = -tf.reduce_sum(y*tf.log(prediction))

5、计算准确率
这里的tf.argmax(y,1),tf.argmax(prediction,1)就是计算10维向量y及prediction中元素的最大值,也就是说预测的标签和实际标签相等时tf.equal返回真,否则返回假。最终预测正确的信息被保存到correct_prediction布尔型列表中,在通过tf.cast转化为float型,然后通过tf.reduce_mean求平均求出准确率。

#结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#argmax返回一维张量中最大的值所在的位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

6、接着就进入正式训练了
首先通过init初始化变量,接着for循环训练40个回合。batch_size为每个批次的大小,n_batch为批次数。在每次训练一个回合后计算出测试集的准确率acc,并输出。

# 每个批次的大小
batch_size = 100
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_sizewith tf.Session() as sess:init = tf.global_variables_initializer()sess.run(init)for epoch in range(40):for batch in range(n_batch):batch_xs, batch_ys = mnist.train.next_batch(batch_size)sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
Iter 0,Testing Accuracy 0.8335
Iter 1,Testing Accuracy 0.8706
Iter 2,Testing Accuracy 0.8815
Iter 3,Testing Accuracy 0.889
Iter 4,Testing Accuracy 0.8936
Iter 5,Testing Accuracy 0.8968
Iter 6,Testing Accuracy 0.8994
Iter 7,Testing Accuracy 0.9019
Iter 8,Testing Accuracy 0.9022
Iter 9,Testing Accuracy 0.9052
Iter 10,Testing Accuracy 0.9066

以上是程序的运行的结果,可以看到最终准确率为91.94%,这并不是很高的准确率,但却是一个入门的经典例子,后面我们将会讲到如何提高准确率.

全部代码为:

#coding: utf-8
#载入数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.labels.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)import tensorflow as tf#定义两个placeholder
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])#创建一个简单的神经网络
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
prediction = tf.nn.softmax(tf.matmul(x, W) + b)#二次代价函数
loss = tf.reduce_mean(tf.square(y - prediction))
#使用梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)#结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#argmax返回一维张量中最大的值所在的位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
#每个批次的大小
batch_size = 100
#计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_sizewith tf.Session() as sess:init = tf.global_variables_initializer()sess.run(init)for epoch in range(40):for batch in range(n_batch):batch_xs, batch_ys = mnist.train.next_batch(batch_size)sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))

参考:
http://www.tensorfly.cn/tfdoc/tutorials/mnist_beginners.html
https://blog.csdn.net/qq_36389843/article/details/78166622

TensorFlow入门之二:tensorflow手写数字识别相关推荐

  1. python cnn代码详解图解_基于TensorFlow的CNN实现Mnist手写数字识别

    本文实例为大家分享了基于TensorFlow的CNN实现Mnist手写数字识别的具体代码,供大家参考,具体内容如下 一.CNN模型结构 输入层:Mnist数据集(28*28) 第一层卷积:感受视野5* ...

  2. 基于TensorFlow和mnist数据集的手写数字识别系统 ,可识别电话号码,识别准确率高,有对比实验,两组模型,可讲解代码

    基于TensorFlow和mnist数据集的手写数字识别系统 ,可识别电话号码,识别准确率高,有对比实验,两组模型,可讲解代码

  3. 深度学习--TensorFlow(项目)Keras手写数字识别

    目录 效果展示 基础理论 1.softmax激活函数 2.神经网络 3.隐藏层及神经元最佳数量 一.数据准备 1.载入数据集 2.数据处理 2-1.归一化 2-2.独热编码 二.神经网络拟合 1.搭建 ...

  4. 机器学习入门-kNN算法实现手写数字识别

    实验环境 Python:3.7.0 Anconda:3-5.3.1 64位 操作系统:win10 开发工具:sublime text(非必要) 简介 本次实验中的重点为采用kNN算法进行手写数字识别, ...

  5. Kaggle入门预测赛,手写数字识别Digit Recognizer,使用Kaggle kernel作答,F=0.98

    1.问题和描述 直接在kaggle左边的competition竞赛中搜索Digit Recognizer即可进入赛题页面: https://www.kaggle.com/c/digit-recogni ...

  6. TensorFlow学习笔记(一):手写数字识别之softmax回归

    在Tensorflow中实现逻辑回归的步骤: 一般来讲,使用Tensorflow实现机器学习算法模型的步骤如下: 1.定义算法公式: 2.定义loss函数,选择优化器优化loss: 3.使用输入训练集 ...

  7. Python 3深度置信网络(DBN)在Tensorflow中的实现MNIST手写数字识别

    任何程序错误,以及技术疑问或需要解答的,请扫码添加作者VX:1755337994 使用DBN识别手写体 传统的多层感知机或者神经网络的一个问题: 反向传播可能总是导致局部最小值. 当误差表面(erro ...

  8. TensorFlow神经网络(四)手写数字识别

    内容来自mooc人工智能实践第五讲 一.MNIST数据集一些用到的基础函数语法 ############ warm up ! ############# 导入imput_data模块 from ten ...

  9. 吴裕雄 python 神经网络——TensorFlow实现AlexNet模型处理手写数字识别MNIST数据集...

    import tensorflow as tf# 输入数据 from tensorflow.examples.tutorials.mnist import input_datamnist = inpu ...

  10. python实现lenet_吴裕雄 python 神经网络TensorFlow实现LeNet模型处理手写数字识别MNIST数据集...

    importtensorflow as tf tf.reset_default_graph()#配置神经网络的参数 INPUT_NODE = 784OUTPUT_NODE= 10IMAGE_SIZE= ...

最新文章

  1. 修复mysql编码错乱的数据_关于MySQL数据库编码修复相关问题
  2. JavaScript 正则表达式的使用
  3. 学习CSS了解单位em和px的区别
  4. 7.泡妞与设计模式(八)模板模式
  5. 书呆子rico_寻找设计和类型书呆子的清道夫
  6. 前端笔记-thymeleaf获取及回显select数据(combox)
  7. vivo Y66的usb调试模式在哪里,打开vivo Y66usb调试模式的流程
  8. oracle+技术面试,Oracle技术面试问题
  9. 小米手机卡顿如何解决
  10. FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分
  11. python:random.randint 和 numpy.random.uniform
  12. Java中银行转账的一些问题
  13. stvd使用c语言编程,stm8编程tips(stvd)
  14. sola病毒批量恢复工具 —— 大一的回忆
  15. android:查询数据库 指定列 指定列名 并输出查询结果(如查询电话本,SMS的ContentResolver提供的)
  16. 【PC工具】文字文本朗读工具,语音朗读软件,TTS语音合成
  17. 在 IDEA 中的各种调试技巧,轻松定位 Bug(超级全面)
  18. ERP软件触发器判断单身数据为什么状态,如何执行
  19. 计算机之父 匈牙利“唯一的天才” 冯·诺依曼
  20. python客户端开发自行车租赁系统_python可视化--共享单车项目

热门文章

  1. ZOJ--1005:Jugs(dfs)
  2. HUAWEI交换机的Hybrid接口(混杂模式)详解与实验配置演示
  3. 网络工程师与网络管理员的区别和前景
  4. iOS swift5 手动导入SnapKit(不用cocoapods)
  5. 对计算机知识的掌握,计算机操作基本知识
  6. 10343 划分凸多边形(优先做)
  7. 能被3,4,5等数整除的数的特征
  8. linux运维笔记:动态网页资源
  9. 海康视频H5插件 v2.0.0开发总结
  10. c语言中哪个键是逐行运行的,c语言中的快捷键有哪些?