初入tensorflow一览(2)

来源:互联网 发布:淘宝靠谱电玩店 编辑:程序博客网 时间:2024/06/15 05:33

初入tensorflow一览(2)

目录
- 1.简单程序运行详解
- 2.MNIST例子解析
—– 2.1输入源代码解析
—– 2.2MNIST训练流程解析
—– 2.3训练结果检验


1.简单程序运行详解

上一篇文章中安装了tensorflow之后,并尝试打印了“hello tensorflow”。基于一般编程语言的了解,大致流程是这样的:

  1. 在通过tf.constant()创建了一个名为hello的字符串常量对象;
  2. 并通过tf.Session()创建了一个会话;
  3. 最后通过sess.run(hello)来实现了返回得到一个可打印的hello。

在tensorflow中,上述描述一点也不“专业”。要从tensorflow的编程框架角度去理解,应该是这样的:

  1. 创建一系列的操作节点(op),或者叫计算节点更容易理解,根据各操作节点的数据来源,可以得到一个计算图。
  2. 然后通过tf.Session()方法来启动一个计算会话,通过sess.run()来运行某个操作节点。

对于hello的例子,只有一个操作节点:tf.constant(“Hello Tensorflow!”).通过tf.constant()创建的op可以称为源op。可以作为整个计算图的输入来源。当然,还可以通过其他方法来创建其他的源op。所以对于该例子来说,计算图如下,不过理论上下图中的End都不是存在的,此处只是为了说明而已。

Created with Raphaël 2.1.0源op(hello)End

对于创建的每个op,都是一个tensor实例。因此,所有创建的op,可以理解为一个op的描述,创建实例时不会有任何运算。而需要通过创建会话来执行op。hello例子中的sess.run(hello),就是对源op的运算,结果会得到一个可以print的数据类型,一般为np.array类型。下面以官方指导中的MNIST例子来描述下如何利用外部文件的数据来创建、运行计算图。


2.MNIST例子解析

2.1 输入源代码解析

在tensorflow中文社区中,MNIST需要额外下载input_data.py来实现输入的导入。但是tensorflow后面的版本已经将该学习样例导入数据的源码放在/tensorflow /examples/tutorials/mnist/下了,所以可以直接通过如下方式直接获取MNIST例子的数据源。

from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

去看/tensorflow/examples.tutorials/mnist/input_data.py,只是import了read_data_sets

from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets

再看/tensorflow/contrib/learn/python/learn/datasets/mnist.py
。read_data_sets函数中,定义了七个入参,我仔细研究了这七个入参,认为对后续自己编写导入数据的代码或者可以更好地直接调用这部分代码。

参数表:

参数 含义 train_dir 下载数据放置的本地目录,为运行程序的相对路径 fake _data 默认为False,为True则返回一个空的训练、验证和测试集合 one _hot 将原来label标记为具体的数值(标量)转换成一个数组,除了原来数值下标位置的值为1,其余均为0。比如label值为4,所有label可能取的值为0~9,则转换之后为[0,0,0,1,0,0,0,0,0] dtype 用于标志数据的类型,默认为dtypes.float32,dtypes为tensorflow的类型,dtypes.float32对应numpy.float32 reshape 用于标志是否需要对数据进行重新调整形状 validation_size 验证集合的大小,默认为5000,如果该大小不在[0, 训练集的数据大小]范围之内,则raise一个ValueError,本函数通过取训练集合前validation_size个数据为验证集。 seed 用于random_seed.get_seed(),默认为None

1.该函数首先判断fake_data,如果为True,则返回一个无意义的训练、验证和测试集合;
2.fake_data为False时,指定了训练数据、标签文件名字;测试数据、标签文件名字,并通过如下调用,下载四个文件:

SOURCE_URL = 'https://storage.googleapis.com/cvdf-datasets/mnist/'  local_file = base.maybe_download('target-file-name', train_dir,SOURCE_URL + 'target-file-name')

3.对每个下载的文件,都通过open(‘file-name’, ‘rb’)打开,因为下载的文件为gz压缩的二进制文件,所以还通过gzip.GzipFile(fileobj=’file-name’)打开,并通过_read32()函数将二进制数据转换成uint32型数据读出来,函数如下:

def _read32(bytestream):  dt = numpy.dtype(numpy.uint32).newbyteorder('>')  return numpy.frombuffer(bytestream.read(4), dtype=dt)[0]

MNIST例子中的数据文件开头四个UINT32数字分别为魔术字(校验数字),num_images, rows,cols。读完3个UINT32数字之后,通过bytestream.read(rows * cols * num_images),将所有数据读入内存,再通过numpy.frombuffer(buf, dtype=numpy.uint8)转换成1-D的array再reshape得到 num_images * rows * cols 的3-D array。

4.选训练集的前5000个作为验证集,和测试集合一起,分别作为参数,创建Data对象,这个对象主要做的事情就是把3-D array再转换成num_images*(rows*cols) 的2-D array。最后,由三者得到一个mnist对象,其实就是三个Data对象的合体而已。可以通过mnist.train, mnist.validation, mnist.test分别访问三个数据集合。

>>> print mnistDatasets(train=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x10e7cc350>, validation=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x111056690>, test=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x112ca1410>)>>> print mnist.train<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x10e7cc350>>>> print mnist.validation<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x111056690>>>> print mnist.test<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x112ca1410>>>> 

2.2 MNIST 流程解析

输入数据的来源有了,首先构建MNIST识别的计算图。主要是对流程中各op的描述声明。第一步,就是在计算图中,怎么把源op表示出来,虽然数据量不大(50000*784个float32的数据),但是训练的时候一次性导入训练模型,一次迭代的运算效率也可见而知。tensorflow针对这种情况,有一个叫占位符的源数据描述方法。

>>> import tensorflow as tf>>> x = tf.placeholder("float", shape=[None, 784])>>> y_ = tf.placeholder("float", shape=[None, 10])

个人对占位符的理解为,未初始化、无实际值的张量(tensor的中文翻译),但是做了一些规定,比如元素类型为”float32”,形状“大致”为横轴长度为784,横轴长度不定的2-D张量。占位符的实际是在sess.run()时,通过feed_dict参数传入,后面再讲。

然后,描述如何判断数据的op。这里采用最简单的Softmax回归模型。该方程为:y=softmax(Wx+b)。这里出现了变量 Wb。这两者为模型的实际参数,需要去反复训练,更新,因此,采用tensorflow中的专业术语:变量来描述。下面是创建Wb 的描述op和初始化op。

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

对于创建回归模型的op,只需要一行:

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

要训练该模型,还需要描述训练过程中的用于优化误差的目标函数,即最小化误差的损失函数。最简单的定义方式为:fcost=ylog(̂ y) 。其中,y为数据的实际标签,ŷ  为经过回归模型判断的结果。因为每次训练会使用大量数据,并且每个标签具有10个维度(0~9),因此需要通过tf.reduce_sum将所有值都相加起来。tf.reduce_sum的调用比较简单。最简单的用法如下:

# 'x' is [[1, 1, 1]]#         [1, 1, 1]]>>> tf.reduce_sum(x) ==> 6>>> tf.reduce_sum(x, 0) ==> [2, 2, 2]>>> tf.reduce_sum(x, 1) ==> [3, 3]>>> tf.reduce_sum(x, 1, keep_dims=True) ==> [[3], [3]]>>> tf.reduce_sum(x, [0, 1]) ==> 6

前面两步完成了模型op的定义,现在开始定义训练模型的op。tensorflow的NB之处就在于有内置方法能自动对模型进行微分。

>>> train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

tf.train.GradientDescentOptimizer方法采用梯度下降法,以最小化cross_entropy为目标,每运行一次会对参数以步长为0.01更新一次。至此,所有op已经定义完毕。可以通过sess.run()来执行训练op。该op会自动溯源到源op。执行一次计算图的计算。
计算图可以如下表示:

这里写图片描述
上面说通过sess.sun(train_step),计算图会自动溯源到源op,依次执行下来。但是这里要注意两点:
1. 源op:x,y_ 没有具体的值,此时,需要利用sess.run()的一个参数 feed_dict来指定两个array作为真正的输入:x, y_ 。
2. tensorflow中的所有变量,需要单独用sess.run(init)来进行初始化。否则会得到如下错误:

FailedPreconditionError (see above for traceback): Attempting to use uninitialized value Variable     [[Node: Variable/read = Identity[T=DT_FLOAT, _class=["loc:@Variable"], _device="/job:localhost/replica:0/task:0/cpu:0"](Variable)]]

如上总结,可以得到如下的训练模型的代码:

>>> sess.run(init)>>> for _ in range(500):...     batch_x, batch_y = mnist.train.next_batch(100)...     sess.run(train_step, feed_dict={x: batch_x, y_ : batch_y})

这里讲数据分成了500份,每次训练100份。每次循环结束都会对W,b进行更新。更新了500次之后的结果如何,我们可以通过如下方式来检验。


2.3 训练结果检验

基于以上的程序,可以通过在原来的计算图中增加一个计算模型正确率的op来实现。要比较y和y_,可以用tf.argmax()来获取张量中的最大值的下标来进行比较,(y_ 的每一行数据为[0,0,0,0,1,0,0,0,0,0],y的每一行数据可能为[0.0,0.002,0.1,0.0,0.81,0.20,0.08,0.09,0.11,0.0],此时tf.argmax(y) = tf.argmax(y_)=4)。

>>> correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

correct_prediction会得到[True, False, False,…]的结果。再用tf.reduce_mean()就可以计算得到True的占比,即模型的正确率。

>>> accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))>>> print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))0.9113

以上过程就是我学习tensorflow的中文社区和英文官网的MNIST入门教程的笔记。之前没有系统学习过机器学习相关的课程。要完全理解还是稍稍有点吃力。所以还要对各种模型再进行深入的学习。才能更好地使用、改进模型。

原创粉丝点击