tensorfllow MNIST机器学习入门

MNIST机器学习入门

这个教程的目标读者是对机器学习和TensorFlow都不太了解的新手。若是你已经了解MNIST和softmax回归(softmax regression)的相关知识,你能够阅读这个快速上手教程html

当咱们开始学习编程的时候,第一件事每每是学习打印"Hello World"。就比如编程入门有Hello World,机器学习入门有MNIST。python

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

它也包含每一张图片对应的标签,告诉咱们这个是数字几。好比,上面这四张图片的标签分别是5,0,4,1。github

在此教程中,咱们将训练一个机器学习模型用于预测图片里面的数字。咱们的目的不是要设计一个世界一流的复杂模型 -- 尽管咱们会在以后给你源代码去实现一流的预测模型 -- 而是要介绍下如何使用TensorFlow。因此,咱们这里会从一个很简单的数学模型开始,它叫作Softmax Regression。web

对应这个教程的实现代码很短,并且真正有意思的内容只包含在三行代码里面。可是,去理解包含在这些代码里面的设计思想是很是重要的:TensorFlow工做流程和机器学习的基本概念。所以,这个教程会很详细地介绍这些代码的实现原理。算法

MNIST数据集

MNIST数据集的官网是Yann LeCun's website。在这里,咱们提供了一份python源代码用于自动下载和安装这个数据集。你能够下载这份代码,而后用下面的代码导入到你的项目里面,也能够直接复制粘贴到你的代码文件里面。编程

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.labelsapi

每一张图片包含28像素X28像素。咱们能够用一个数字数组来表示这张图片:数组

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

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

所以,在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] 的数字矩阵。

如今,咱们准备好能够开始构建咱们的模型啦!

Softmax回归介绍

咱们知道MNIST的每一张图片都表示一个数字,从0到9。咱们但愿获得给定图片表明每一个数字的几率。好比说,咱们的模型可能推测一张包含9的图片表明数字9的几率是80%可是判断它是8的几率是5%(由于8和9都有上半部分的小圆),而后给予它表明其余数字的几率更小的值。

这是一个使用softmax回归(softmax regression)模型的经典案例。softmax模型能够用来给不一样的对象分配几率。即便在以后,咱们训练更加精细的模型时,最后一步也须要用softmax来分配几率。

softmax回归(softmax regression)分两步:第一步

为了获得一张给定图片属于某个特定数字类的证据(evidence),咱们对图片像素值进行加权求和。若是这个像素具备很强的证听说明这张图片不属于该类,那么相应的权值为负数,相反若是这个像素拥有有利的证据支持这张图片属于这个类,那么权值是正数。

下面的图片显示了一个模型学习到的图片上每一个像素对于特定数字类的权值。红色表明负数权值,蓝色表明正数权值。

咱们也须要加入一个额外的偏置量(bias),由于输入每每会带有一些无关的干扰量。所以对于给定的输入图片 x 它表明的是数字 i 的证据能够表示为

其中 表明权重, 表明数字 i 类的偏置量,j 表明给定图片 x 的像素索引用于像素求和。而后用softmax函数能够把这些证据转换成几率 y

这里的softmax能够当作是一个激励(activation)函数或者连接(link)函数,把咱们定义的线性函数的输出转换成咱们想要的格式,也就是关于10个数字类的几率分布。所以,给定一张图片,它对于每个数字的吻合度能够被softmax函数转换成为一个几率值。softmax函数能够定义为:

展开等式右边的子式,能够获得:

可是更多的时候把softmax模型函数定义为前一种形式:把输入值当成幂指数求值,再正则化这些结果值。这个幂运算表示,更大的证据对应更大的假设模型(hypothesis)里面的乘数权重值。反之,拥有更少的证据意味着在假设模型里面拥有更小的乘数系数。假设模型里的权值不能够是0值或者负值。Softmax而后会正则化这些权重值,使它们的总和等于1,以此构造一个有效的几率分布。(更多的关于Softmax函数的信息,能够参考Michael Nieslen的书里面的这个部分,其中有关于softmax的可交互式的可视化解释。)

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

若是把它写成一个等式,咱们能够获得:

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

更进一步,能够写成更加紧凑的方式:

实现回归模型

为了用python实现高效的数值计算,咱们一般会使用函数库,好比NumPy,会把相似矩阵乘法这样的复杂运算使用其余外部语言实现。不幸的是,从外部计算切换回Python的每个操做,仍然是一个很大的开销。若是你用GPU来进行外部计算,这样的开销会更大。用分布式的计算方式,也会花费更多的资源用来传输数据。

TensorFlow也把复杂的计算放在python以外完成,可是为了不前面说的那些开销,它作了进一步完善。Tensorflow不单独地运行单一的复杂计算,而是让咱们能够先用图描述一系列可交互的计算操做,而后所有一块儿在Python以外运行。(这样相似的运行方式,能够在很多的机器学习库中看到。)

使用TensorFlow以前,首先导入它:

import tensorflow as tf 

咱们经过操做符号变量来描述这些可交互的操做单元,能够用下面的方式建立一个:

x = tf.placeholder("float", [None, 784]) 

x不是一个特定的值,而是一个占位符placeholder,咱们在TensorFlow运行计算时输入这个值。咱们但愿可以输入任意数量的MNIST图像,每一张图展平成784维的向量。咱们用2维的浮点数张量来表示这些图,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度能够是任何长度的。)

咱们的模型也须要权重值和偏置量,固然咱们能够把它们当作是另外的输入(使用占位符),但TensorFlow有一个更好的方法来表示它们:Variable 。 一个Variable表明一个可修改的张量,存在在TensorFlow的用于描述交互性操做的图中。它们能够用于计算输入值,也能够在计算中被修改。对于各类机器学习应用,通常都会有模型参数,能够用Variable表示。

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

咱们赋予tf.Variable不一样的初值来建立不一样的Variable:在这里,咱们都用全为零的张量来初始化Wb。由于咱们要学习Wb的值,它们的初值能够随意设置。

注意,W的维度是[784,10],由于咱们想要用784维的图片向量乘以它以获得一个10维的证据值向量,每一位对应不一样数字类。b的形状是[10],因此咱们能够直接把它加到输出上面。

如今,咱们能够实现咱们的模型啦。只须要一行代码!

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

首先,咱们用tf.matmul(​​X,W)表示x乘以W,对应以前等式里面的,这里x是一个2维张量拥有多个输入。而后再加上b,把和输入到tf.nn.softmax函数里面。

至此,咱们先用了几行简短的代码来设置变量,而后只用了一行代码来定义咱们的模型。TensorFlow不只仅可使softmax回归模型计算变得特别简单,它也用这种很是灵活的方式来描述其余各类数值计算,从机器学习模型对物理学模拟仿真模型。一旦被定义好以后,咱们的模型就能够在不一样的设备上运行:计算机的CPU,GPU,甚至是手机!

训练模型

为了训练咱们的模型,咱们首先须要定义一个指标来评估这个模型是好的。其实,在机器学习,咱们一般定义指标来表示一个模型是坏的,这个指标称为成本(cost)或损失(loss),而后尽可能最小化这个指标。可是,这两种方式是相同的。

一个很是常见的,很是漂亮的成本函数是“交叉熵”(cross-entropy)。交叉熵产生于信息论里面的信息压缩编码技术,可是它后来演变成为从博弈论到机器学习等其余领域里的重要技术手段。它的定义以下:

y 是咱们预测的几率分布, y' 是实际的分布(咱们输入的one-hot vector)。比较粗糙的理解是,交叉熵是用来衡量咱们的预测用于描述真相的低效性。更详细的关于交叉熵的解释超出本教程的范畴,可是你颇有必要好好理解它

为了计算交叉熵,咱们首先须要添加一个新的占位符用于输入正确值:

y_ = tf.placeholder("float", [None,10]) 

而后咱们能够用 计算交叉熵:

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

首先,用 tf.log 计算 y 的每一个元素的对数。接下来,咱们把 y_ 的每个元素和 tf.log(y_) 的对应元素相乘。最后,用 tf.reduce_sum 计算张量的全部元素的总和。(注意,这里的交叉熵不只仅用来衡量单一的一对预测和真实值,而是全部100幅图片的交叉熵的总和。对于100个数据点的预测表现比单一数据点的表现能更好地描述咱们的模型的性能。

如今咱们知道咱们须要咱们的模型作什么啦,用TensorFlow来训练它是很是容易的。由于TensorFlow拥有一张描述你各个计算单元的图,它能够自动地使用反向传播算法(backpropagation algorithm)来有效地肯定你的变量是如何影响你想要最小化的那个成本值的。而后,TensorFlow会用你选择的优化算法来不断地修改变量以下降成本。

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

在这里,咱们要求TensorFlow用梯度降低算法(gradient descent algorithm)以0.01的学习速率最小化交叉熵。梯度降低算法(gradient descent algorithm)是一个简单的学习过程,TensorFlow只需将每一个变量一点点地往使成本不断下降的方向移动。固然TensorFlow也提供了其余许多优化算法:只要简单地调整一行代码就可使用其余的算法。

TensorFlow在这里实际上所作的是,它会在后台给描述你的计算的那张图里面增长一系列新的计算操做单元用于实现反向传播算法和梯度降低算法。而后,它返回给你的只是一个单一的操做,当运行这个操做时,它用梯度降低算法训练你的模型,微调你的变量,不断减小成本。

如今,咱们已经设置好了咱们的模型。在运行计算以前,咱们须要添加一个操做来初始化咱们建立的变量:

init = tf.initialize_all_variables()

如今咱们能够在一个Session里面启动咱们的模型,而且初始化变量:

sess = tf.Session()
sess.run(init)

而后开始训练模型,这里咱们让模型循环训练1000次!

for i in range(1000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) 

该循环的每一个步骤中,咱们都会随机抓取训练数据中的100个批处理数据点,而后咱们用这些数据点做为参数替换以前的占位符来运行train_step

使用一小部分的随机数据来进行训练被称为随机训练(stochastic training)- 在这里更确切的说是随机梯度降低训练。在理想状况下,咱们但愿用咱们全部的数据来进行每一步的训练,由于这能给咱们更好的训练结果,但显然这须要很大的计算开销。因此,每一次训练咱们可使用不一样的数据子集,这样作既能够减小计算开销,又能够最大化地学习到数据集的整体特性。

评估咱们的模型

那么咱们的模型性能如何呢?

首先让咱们找出那些预测正确的标签。tf.argmax 是一个很是有用的函数,它能给出某个tensor对象在某一维上的其数据最大值所在的索引值。因为标签向量是由0,1组成,所以最大值1所在的索引位置就是类别标签,好比tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值,而 tf.argmax(y_,1) 表明正确的标签,咱们能够用 tf.equal 来检测咱们的预测是否真实标签匹配(索引位置同样表示匹配)。

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

这行代码会给咱们一组布尔值。为了肯定正确预测项的比例,咱们能够把布尔值转换成浮点数,而后取平均值。例如,[True, False, True, True] 会变成 [1,0,1,1] ,取平均值后获得 0.75.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 

最后,咱们计算所学习到的模型在测试数据集上面的正确率。

print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}) 

这个最终结果值应该大约是91%。

这个结果好吗?嗯,并不太好。事实上,这个结果是不好的。这是由于咱们仅仅使用了一个很是简单的模型。不过,作一些小小的改进,咱们就能够获得97%的正确率。最好的模型甚至能够得到超过99.7%的准确率!(想了解更多信息,能够看看这个关于各类模型的性能对比列表。)

比结果更重要的是,咱们从这个模型中学习到的设计思想。不过,若是你仍然对这里的结果有点失望,能够查看下一个教程,在那里你能够学习如何用FensorFlow构建更加复杂的模型以得到更好的性能!

原文地址:MNIST For ML Beginners 翻译:linbojin

 

 

 

深刻MNIST

TensorFlow是一个很是强大的用来作大规模数值计算的库。其所擅长的任务之一就是实现以及训练深度神经网络。

在本教程中,咱们将学到构建一个TensorFlow模型的基本步骤,并将经过这些步骤为MNIST构建一个深度卷积神经网络。

这个教程假设你已经熟悉神经网络和MNIST数据集。若是你还没有了解,请查看新手指南.

安装

在建立模型以前,咱们会先加载MNIST数据集,而后启动一个TensorFlow的session。

加载MNIST数据

为了方便起见,咱们已经准备了一个脚本来自动下载和导入MNIST数据集。它会自动建立一个'MNIST_data'的目录来存储数据。

import input_data mnist = input_data.read_data_sets('MNIST_data', one_hot=True) 

这里,mnist是一个轻量级的类。它以Numpy数组的形式存储着训练、校验和测试数据集。同时提供了一个函数,用于在迭代中得到minibatch,后面咱们将会用到。

运行TensorFlow的InteractiveSession

Tensorflow依赖于一个高效的C++后端来进行计算。与后端的这个链接叫作session。通常而言,使用TensorFlow程序的流程是先建立一个图,而后在session中启动它。

这里,咱们使用更加方便的InteractiveSession类。经过它,你能够更加灵活地构建你的代码。它能让你在运行图的时候,插入一些计算图,这些计算图是由某些操做(operations)构成的。这对于工做在交互式环境中的人们来讲很是便利,好比使用IPython。若是你没有使用InteractiveSession,那么你须要在启动session以前构建整个计算图,而后启动该计算图

import tensorflow as tf sess = tf.InteractiveSession() 

计算图

为了在Python中进行高效的数值计算,咱们一般会使用像NumPy一类的库,将一些诸如矩阵乘法的耗时操做在Python环境的外部来计算,这些计算一般会经过其它语言并用更为高效的代码来实现。

但遗憾的是,每个操做切换回Python环境时仍须要不小的开销。若是你想在GPU或者分布式环境中计算时,这一开销更加可怖,这一开销主要多是用来进行数据迁移。

TensorFlow也是在Python外部完成其主要工做,可是进行了改进以免这种开销。其并无采用在Python外部独立运行某个耗时操做的方式,而是先让咱们描述一个交互操做图,而后彻底将其运行在Python外部。这与Theano或Torch的作法相似。

所以Python代码的目的是用来构建这个能够在外部运行的计算图,以及安排计算图的哪一部分应该被运行。详情请查看基本用法中的计算图表一节。

构建Softmax 回归模型

在这一节中咱们将创建一个拥有一个线性层的softmax回归模型。在下一节,咱们会将其扩展为一个拥有多层卷积网络的softmax回归模型。

占位符

咱们经过为输入图像和目标输出类别建立节点,来开始构建计算图。

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

这里的xy并非特定的值,相反,他们都只是一个占位符,能够在TensorFlow运行某一计算时根据该占位符输入具体的值。

输入图片x是一个2维的浮点数张量。这里,分配给它的shape[None, 784],其中784是一张展平的MNIST图片的维度。None表示其值大小不定,在这里做为第一个维度值,用以指代batch的大小,意即x的数量不定。输出类别值y_也是一个2维张量,其中每一行为一个10维的one-hot向量,用于表明对应某一MNIST图片的类别。

虽然placeholdershape参数是可选的,但有了它,TensorFlow可以自动捕捉因数据维度不一致致使的错误。

变量

咱们如今为模型定义权重W和偏置b。能够将它们看成额外的输入量,可是TensorFlow有一个更好的处理方式:变量。一个变量表明着TensorFlow计算图中的一个值,可以在计算过程当中使用,甚至进行修改。在机器学习的应用过程当中,模型参数通常用Variable来表示。

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

咱们在调用tf.Variable的时候传入初始值。在这个例子里,咱们把Wb都初始化为零向量。W是一个784x10的矩阵(由于咱们有784个特征和10个输出值)。b是一个10维的向量(由于咱们有10个分类)。

Before Variables can be used within a session, they must be initialized using that session. This step takes the initial values (in this case tensors full of zeros) that have already been specified, and assigns them to each Variable. This can be done for all Variables at once.

变量须要经过seesion初始化后,才能在session中使用。这一初始化步骤为,为初始值指定具体值(本例当中是全为零),并将其分配给每一个变量,能够一次性为全部变量完成此操做。

sess.run(tf.initialize_all_variables())

类别预测与损失函数

如今咱们能够实现咱们的回归模型了。这只须要一行!咱们把向量化后的图片x和权重矩阵W相乘,加上偏置b,而后计算每一个分类的softmax几率值。

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

能够很容易的为训练过程指定最小化偏差用的损失函数,咱们的损失函数是目标类别和预测类别之间的交叉熵。

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

注意,tf.reduce_sum把minibatch里的每张图片的交叉熵值都加起来了。咱们计算的交叉熵是指整个minibatch的。

训练模型

咱们已经定义好模型和训练用的损失函数,那么用TensorFlow进行训练就很简单了。由于TensorFlow知道整个计算图,它可使用自动微分法找到对于各个变量的损失的梯度值。TensorFlow有大量内置的优化算法 这个例子中,咱们用最速降低法让交叉熵降低,步长为0.01.

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

这一行代码其实是用来往计算图上添加一个新操做,其中包括计算梯度,计算每一个参数的步长变化,而且计算出新的参数值。

返回的train_step操做对象,在运行时会使用梯度降低来更新参数。所以,整个模型的训练能够经过反复地运行train_step来完成。

for i in range(1000): batch = mnist.train.next_batch(50) train_step.run(feed_dict={x: batch[0], y_: batch[1]}) 

每一步迭代,咱们都会加载50个训练样本,而后执行一次train_step,并经过feed_dictxy_张量占位符用训练训练数据替代。

注意,在计算图中,你能够用feed_dict来替代任何张量,并不只限于替换占位符

评估模型

那么咱们的模型性能如何呢?

首先让咱们找出那些预测正确的标签。tf.argmax 是一个很是有用的函数,它能给出某个tensor对象在某一维上的其数据最大值所在的索引值。因为标签向量是由0,1组成,所以最大值1所在的索引位置就是类别标签,好比tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值,而 tf.argmax(y_,1) 表明正确的标签,咱们能够用 tf.equal 来检测咱们的预测是否真实标签匹配(索引位置同样表示匹配)。

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

这里返回一个布尔数组。为了计算咱们分类的准确率,咱们将布尔值转换为浮点数来表明对、错,而后取平均值。例如:[True, False, True, True]变为[1,0,1,1],计算出平均值为0.75

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 

最后,咱们能够计算出在测试数据上的准确率,大概是91%。

print accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}) 

构建一个多层卷积网络

在MNIST上只有91%正确率,实在太糟糕。在这个小节里,咱们用一个稍微复杂的模型:卷积神经网络来改善效果。这会达到大概99.2%的准确率。虽然不是最高,可是仍是比较让人满意。

权重初始化

为了建立这个模型,咱们须要建立大量的权重和偏置项。这个模型中的权重在初始化时应该加入少许的噪声来打破对称性以及避免0梯度。因为咱们使用的是ReLU神经元,所以比较好的作法是用一个较小的正数来初始化偏置项,以免神经元节点输出恒为0的问题(dead neurons)。为了避免在创建模型的时候反复作初始化操做,咱们定义两个函数用于初始化。

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) 

卷积和池化

TensorFlow在卷积和池化上有很强的灵活性。咱们怎么处理边界?步长应该设多大?在这个实例里,咱们会一直使用vanilla版本。咱们的卷积使用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') def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') 

第一层卷积

如今咱们能够开始实现第一层了。它由一个卷积接一个max pooling完成。卷积在每一个5x5的patch中算出32个特征。卷积的权重张量形状是[5, 5, 1, 32],前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目。 而对于每个输出通道都有一个对应的偏置量。

W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) 

为了用这一层,咱们把x变成一个4d向量,其第二、第3维对应图片的宽、高,最后一维表明图片的颜色通道数(由于是灰度图因此这里的通道数为1,若是是rgb彩色图,则为3)。

x_image = tf.reshape(x, [-1,28,28,1]) 

We then convolve x_image with the weight tensor, add the bias, apply the ReLU function, and finally max pool. 咱们把x_image和权值向量进行卷积,加上偏置项,而后应用ReLU激活函数,最后进行max pooling。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

第二层卷积

为了构建一个更深的网络,咱们会把几个相似的层堆叠起来。第二层中,每一个5x5的patch会获得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_pool2 = max_pool_2x2(h_conv2) 

密集链接层

如今,图片尺寸减少到7x7,咱们加入一个有1024个神经元的全链接层,用于处理整个图片。咱们把池化层输出的张量reshape成一些向量,乘上权重矩阵,加上偏置,而后对其使用ReLU。

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

为了减小过拟合,咱们在输出层以前加入dropout。咱们用一个placeholder来表明一个神经元的输出在dropout中保持不变的几率。这样咱们能够在训练过程当中启用dropout,在测试过程当中关闭dropout。 TensorFlow的tf.nn.dropout操做除了能够屏蔽神经元的输出外,还会自动处理神经元输出值的scale。因此用dropout的时候能够不用考虑scale。

keep_prob = tf.placeholder("float") h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 

输出层

最后,咱们添加一个softmax层,就像前面的单层softmax regression同样。

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) 

训练和评估模型

这个模型的效果如何呢?

为了进行训练和评估,咱们使用与以前简单的单层SoftMax神经网络模型几乎相同的一套代码,只是咱们会用更加复杂的ADAM优化器来作梯度最速降低,在feed_dict中加入额外的参数keep_prob来控制dropout比例。而后每100次迭代输出一第二天志。

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i%100 == 0: train_accuracy = accuracy.eval(feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}) print "step %d, training accuracy %g"%(i, train_accuracy) train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}) print "test accuracy %g"%accuracy.eval(feed_dict={ x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}) 

以上代码,在最终测试集上的准确率大概是99.2%。

目前为止,咱们已经学会了用TensorFlow快捷地搭建、训练和评估一个复杂一点儿的深度学习模型。

原文地址:Deep MNIST for Experts 翻译:chenweican

相关文章
相关标签/搜索