2.1 TensorFlow实践-入门与数字识别示例解析(1)

本章节中准备写一些TensorFlow的入门示例,但是这并不是意味着第一章写完了,第一章会一直写下去,因为我一直认为数学基础是应该贯穿整个学习过程的,但是愿意看的人很少。很多人都以为神经网络只要会用一些框架并搭建现有网络解决问题就够了,但抱着这种思想其实也不能说是错,但是其实以这种思想的话其他一些比如贝叶斯算法、ID3、EM等一些简单的算法也可以完成任务,未来的神经网络应用范围可能没有想象的那么广,或者说只有拥有大量数据的公司才搞得起来,但是补足基础,过渡到其他简单的数据挖掘算法就足以应付中小公司的数据处理工作了。

本章中我们需要构建一个TensorFlow的基础,所谓基础就是我们可以搭建简单的神经网络,保存模型、并验证模型。

基础部分第一章已经说过了,这里我们在重复一下,下面是TensorFlow官方手写识别版本的简化,并修改了一些函数,为了入门讲解更加方便修改了一些函数。

#example 2.1
#by cangye
#引入库
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
#获取数据
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#构建网络模型
#x,label分别为图形数据和标签数据
x = tf.placeholder(tf.float32, [None, 784])
label = tf.placeholder(tf.float32, [None, 10])
#构建单层网络中的权值和偏置
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
#本例中无非线性激活函数
y = tf.matmul(x, W) + b
#定义损失函数为欧氏距离
loss = tf.reduce_mean(tf.square(y-label))
#用梯度迭代算法
train_step = tf.train.GradientDescentOptimizer(0.005).minimize(loss)
#用于验证
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(label, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
#定义会话
sess = tf.Session()
#初始化所有变量
sess.run(tf.global_variables_initializer())
#迭代过程
for itr in range(3000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, label: batch_ys})
    if itr % 10 == 0:
        print("step:%6d accuracy:"%itr, sess.run(accuracy, feed_dict={x: mnist.test.images,
                                        label: mnist.test.labels}))

首先来看下搭建的网络模型:

《2.1 TensorFlow实践-入门与数字识别示例解析(1)》
《2.1 TensorFlow实践-入门与数字识别示例解析(1)》

当然我一直以为用数学手段描述更为简单:

《2.1 TensorFlow实践-入门与数字识别示例解析(1)》

下面来一步一步的讲解,

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

首先是import两个python库,其中tensorflow.examples.tutorials.mnist的目的在于产生数据,也就是手写识别的图片和标签。其中标签数字为一个长度为10的向量,加入数字为7则向量的第七个数字为1其余数字为0。图片是一个28*28的图片而存储方式为一个长度为784的一维数组如下:

《2.1 TensorFlow实践-入门与数字识别示例解析(1)》
《2.1 TensorFlow实践-入门与数字识别示例解析(1)》

为了方便理解,将绘图过程的程序写到下面:

import matplotlib.pyplot as plt
import numpy as np
#获取数据
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#分别读取数据中的图片数据和标签数据
batch_xs, batch_ys = mnist.train.next_batch(100)
#绘图过程
fig = plt.figure()
ax = fig.add_subplot(221)
ax.matshow(np.reshape(batch_xs[1],[28,28]), cmap=plt.get_cmap("Purples"))
ax = fig.add_subplot(222)
ax.matshow(np.reshape(batch_xs[2],[28,28]), cmap=plt.get_cmap("Purples"))
ax = fig.add_subplot(223)
ax.matshow(np.reshape(batch_xs[3],[28,28]), cmap=plt.get_cmap("Purples"))
ax = fig.add_subplot(224)
ax.matshow(np.reshape(batch_xs[4],[28,28]), cmap=plt.get_cmap("Purples"))
plt.show()

之后进行的操作为定义向量,第一步中定义的向量为:

#x,label分别为图形数据和标签数据
x = tf.placeholder(tf.float32, [None, 784])
label = tf.placeholder(tf.float32, [None, 10])

这里的向量是一个placeholder,因为x和label是在训练过程中需要不断的进行更改填入神经网络之中的。由于TensorFlow是无法接利用python的列表(list),或者numpy的array的,而在训练的过程中需要不断的改变x和y的值,这就需要一个placeholder,用以不断的接受list或array。对于x的参数[None, 784],代表placeholder的shape,其中第一个为None代表每次输入的训练数据的个数是不确定的。也就是可以为任意多个数字。而每次输入训练数据的个数称之为batch_size,这是一个非常重要的概念,数学章节我们可以看到,训练过程是以梯度迭代的方式进行的,但是梯度取决于我们的输入数据,由于数据具有一定的随机性,那么梯度也必然带有一定的随机性,所以在训练的每一次迭代过程中我们可以一次输入多个样本,通过多个样本的估计可以更好的约束梯度迭代的方向,使得梯度迭代过程减少一定的随机性,这个过程称之为批量学习,而数据的量的大小称之为批尺寸(batch_size)。相应的我们在数学章节中的学习过程称之为在线学习也就是每次输入一个样本进行学习

可以看下单层神经网络的公式

#构建单层网络中的权值和偏置
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
#本例中无非线性激活函数
y = tf.matmul(x, W) + b

这个部分就是我们构建单层神经网络的过程,其中常说的神经网络权值就是一个二维矩阵W,偏置b,这两个量实际上就是我们整个神经网络中需要确定的东西。对于这种需要确定的量,用Variable来表示。tf.Variable(tf.zeros([784, 10]))返回的量就是TensorFlow中的Tensor可以将其当做矩阵,其实也就是矩阵。

定义两个矩阵的乘法tf.matmul(x, W),y就是输出的预测结果。

由于还没有具体的讲信息熵的概念,二者接近程度用欧氏距离来表示:

#定义损失函数为欧氏距离
loss = tf.reduce_mean(tf.square(y-label))

其中label就是我们已知结果,y是神经网络预测结果,我们的期望是二者越接近越好。这就需要定义迭代过程:

#用梯度迭代算法
train_step = tf.train.GradientDescentOptimizer(0.005).minimize(loss)

这里需要用到的算法就是梯度迭代算法,其中迭代步长为0.005(这并不是最好的步长),这个步长的选取是十分重要的呃,过大的步长会使得梯度迭代发散,也就是loss函数不仅没有减少反而一直增大,但是大步长会使得迭代速度加快。而过小的迭代会使得收敛速度缓慢。如何平衡是一个不断试验的过程。而迭代优化器的目标在于求解最优的W和b。

实际上到此为止计算过程都没有执行,我们只是在“描述”这个计算过程,TensorFlow中称之为计算图。TensorFlow的优点就在于此,其并没有直接利用python语言去执行计算,因为python是计算速度很慢的语言,而是用python去描述计算图,而具体的执行则需要放到c++的框架之中。因此需要一个回话来执行所有描述的过程:

#定义会话
sess = tf.Session()
#初始化所有变量
sess.run(tf.global_variables_initializer())

同样的,我们在描述计算过程的过程中,甚至于都没有为运算过程的向量分配内存空间,所以在整个程序运行过程中需要进行变量的初始化工作。在用会话(session)来执行这个过程,再次提醒,我们提到的绝大部分操作都需要利用会话去执行,否则只是描述了需要进行相应的计算而已。

最后来看一下迭代过程:

#迭代过程
for itr in range(3000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, label: batch_ys})
    if itr % 10 == 0:
        print("step:%6d accuracy:"%itr, sess.run(accuracy, feed_dict={x: mnist.test.images,
                                        label: mnist.test.labels}))

可以看到我们执行的每个过程都需要sess.run函数去运行。TensorFlow采取feed机制,也就是执行过程中不断的输入相应训练数据,此时placeholder的作用就体现了出来,它用来接收我们传入的量,这个量可以是numpy的array或者是python的list。这里feed的量用字典来表示feed_dict={x: batch_xs, label: batch_ys}。

可以看到在迭代500次后准确率达到了80%,当然继续迭代准确率还会更高,准确率有极限:

《2.1 TensorFlow实践-入门与数字识别示例解析(1)》

如果想要看权值W一些数值,我们需要获取w的值

W.value()

但是前面说到,到此只是描述了计算,并没有执行,因此需要会话来进行操作:

W_value = sess.run(W.value())

将标签0-3的权值绘制一下:

《2.1 TensorFlow实践-入门与数字识别示例解析(1)》
《2.1 TensorFlow实践-入门与数字识别示例解析(1)》

可以大致看到权值代表什么

    原文作者:如是
    原文地址: https://zhuanlan.zhihu.com/p/28439661
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞