MLIST为ML初学者

 

 

 

原文链接 : https://www.tensorflow.org/get_started/mnist/beginners

译文链接 : http://www.apache.wiki/pages/viewpage.action?pageId=10029423

贡献者 : 片刻 ApacheCN Apache中文网

本教程适用于新来的机器学习和TensorFlow的读者。如果你已经知道MNIST是什么,以及什么softmax(多项式逻辑)回归,那么你可能更喜欢这个 更快节奏的教程。在开始任一教程之前,请务必 安装TensorFlow

当学习如何编程时,有一个传统,你所做的第一件事是打印“Hello World”。就像编程有Hello World,机器学习有MNIST。

MNIST是一个简单的计算机视觉数据集。它由以下手写数字的图像组成:

image2017-6-7%2020%3A23%3A40.png?version=1&modificationDate=1496838226000&api=v2

它还包括每个图像的标签,告诉我们哪个数字。例如,上述图像的标签是5,0,4和1。

在本教程中,我们将训练一个模型来查看图像并预测它们的数字。我们的目标不是训练一个真正精致的模型,而是实现最先进的性能 - 尽管我们稍后会给你代码! - 而是将趾部浸入使用TensorFlow。因此,我们将从一个非常简单的模型开始,称为Softmax回归。

本教程的实际代码很短,所有有趣的东西都发生在三行。然而,了解其背后的想法是非常重要的:TensorFlow如何运作和核心机器学习概念。因此,我们将非常仔细地编写代码。

 

关于本教程

本教程将 逐行解释mnist_softmax.py代码中发生的情况。

您可以通过以下几种不同的方式使用本教程,其中包括:

  • 当您阅读每行的说明时,将每个代码段逐行复制并粘贴到Python环境中。

  •  mnist_softmax.py在阅读说明之前或之后运行整个Python文件,并使用本教程来了解不清楚的代码行。

我们将在本教程中完成什么:

  • 了解MNIST数据和softmax回归

  • 基于查看图像中的每个像素,创建一个用于识别数字的模型的函数

  • 使用TensorFlow来训练模型来识别数字,方法是将其“查看”成千上万个示例(并运行我们的第一个TensorFlow会话)

  • 使用我们的测试数据检查型号的精度

 

MNIST数据

MNIST数据托管在 Yann LeCun的网站上。如果您在本教程的代码中复制和粘贴,请从这两个代码开始,这两行代码将自动下载和读取数据:

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True

MNIST数据分为三个部分:训练数据(mnist.train),5500个数据点,10,000个测试数据点(mnist.test)和5,000个验证数据点mnist.validation。这种分裂是非常重要的:在机器学习中,我们有独立的数据,我们不学习,因此我们可以确保我们所学到的知识实际上被概括!

如前所述,每个MNIST数据点都有两部分:手写数字的图像和相应的标签。我们将调用图像“x”和标签“y”。训练集和测试集都包含图像及其相应的标签; 例如训练图像mnist.train.images 和训练标签mnist.train.labels

每个图像是28像素×28像素。我们可以把它解释为一大批数字:

image2017-6-7%2020%3A24%3A26.png?version=1&modificationDate=1496838266000&api=v2

我们可以把这个数组变成一个28×28 = 784数字的向量。只要我们在图像之间保持一致,那么我们如何平坦化数组并不重要。从这个角度来看,MNIST图像只是一个784维向量空间中的一个点,结构 非常丰富 (警告:计算密集的可视化)。

平铺数据会丢弃有关图像2D结构的信息。不是那么糟糕吗 那么,最好的计算机视觉方法会利用这个结构,我们将在后面的教程中。但是我们将在这里使用的简单方法,一个softmax回归(下面定义)不会。

结果是mnist.train.images具有形状的张量(n维阵列)[55000, 784]。第一个维度是图像列表中的索引,第二个维度是每个图像中每个像素的索引。对于特定图像中的特定像素,张量中的每个条目是0和1之间的像素强度。

image2017-6-7%2020%3A24%3A39.png?version=1&modificationDate=1496838279000&api=v2

MNIST中的每个图像都具有相应的标签,0到9之间的数字表示图像中绘制的数字。

为了本教程的目的,我们将要将我们的标签称为“一个热向量”。一个热矢量是一个向量,在大多数维度上为0,在一个维度上为1。在这种情况下, ñ第三位将被表示为1中的向量  ñ维度。例如,3将是  [0,0,0,1,0,0,0,0,0,0]。因此,mnist.train.labels是 [55000, 10]一系列的浮标。

image2017-6-7%2020%3A24%3A51.png?version=1&modificationDate=1496838291000&api=v2

我们现在准备实际制作我们的模型!

 

Softmax回归

我们知道MNIST中的每个图像都是零到九之间的手写数字。所以给定的图像只能有十个可能的东西。我们希望能够看到一个图像,并给出它是每个数字的概率。例如,我们的模型可能会看到一个九分之一的图片,80%的人肯定它是一个九,但是给它一个5%的几率是八分之一(因为顶级循环),并有一点概率所有其他,因为它不是100%确定。

这是一个经典的情况,其中softmax回归是一种自然简单的模型。如果要将概率分配给几个不同的东西之一的对象,softmax是要做的事情,因为softmax给出了一个0到1之间的值加起来为1的列表。稍后,当我们训练更复杂型号,最后一步将是一层softmax。

softmax回归有两个步骤:首先我们将我们的输入的证据加在某些类中,然后将该证据转换成概率。

为了统计给定图像在特定类中的证据,我们进行像素强度的加权和。如果具有高强度的像素是针对该类中的图像的证据,那么权重是负的,如果它是有利的证据则为正。

下图显示了为每个类学习的一个模型的权重。红色代表负重,而蓝色代表负重。

image2017-6-7%2020%3A25%3A5.png?version=1&modificationDate=1496838305000&api=v2

我们还增加了一些称为偏见的额外证据。基本上,我们希望能够说一些事情更可能独立于输入。结果是一个类的证据 i 给了一个输入  X 是:

image2017-6-7%2020%3A25%3A23.png?version=1&modificationDate=1496838323000&api=v2                                               

哪里  wi 是重量和  bi 是上课的偏见  i,和  j 是用于对输入图像中的像素求和的索引  X。然后,将证据数据转换成我们预测的概率  y 使用“softmax”功能:

image2017-6-7%2020%3A26%3A51.png?version=1&modificationDate=1496838411000&api=v2

这里,softmax用作“激活”或“链接”功能,将我们的线性函数的输出整形为我们想要的形式 - 在这种情况下,概率分布超过10个。您可以将其视为将证据的一切转化为我们在每个类中的输入概率。它定义为:                            

image2017-6-7%2020%3A27%3A7.png?version=1&modificationDate=1496838427000&api=v2

如果你扩展这个方程式,你得到:

image2017-6-7%2020%3A27%3A22.png?version=1&modificationDate=1496838442000&api=v2

但是通过第一种方式来考虑softmax通常更有帮助:对其输入进行指数化,然后对它们进行归一化。取幂意味着一个单位的证据增加了任何假设乘以的权重。相反,拥有一个较少的证据单位意味着一个假设得到其早期重量的一小部分。没有假设有零或负重。Softmax然后对这些权重进行归一化,使它们加起来一个,形成有效的概率分布。(要获得更多关于softmax功能的直觉,请参阅Michael Nielsen的书中的 部分内容,并附有交互式可视化文件。)

 

您可以将我们的softmax回归图像看起来像以下,虽然有更多的xs。对于每个输出,我们计算x的加权和,添加偏差,然后应用softmax。

image2017-6-7%2020%3A27%3A41.png?version=1&modificationDate=1496838461000&api=v2

如果我们把它写成方程式,我们得到:

image2017-6-7%2020%3A27%3A53.png?version=1&modificationDate=1496838474000&api=v2

我们可以“矢量化”这个过程,把它变成矩阵乘法和向量加法。这有助于计算效率。(这也是一个有用的思路。)

image2017-6-7%2020%3A28%3A4.png?version=1&modificationDate=1496838484000&api=v2

更紧凑,我们可以写:

 image2017-6-7%2020%3A28%3A20.png?version=1&modificationDate=1496838500000&api=v2

现在我们来看看TensorFlow可以使用的东西。

 

实现回归

为了在Python中进行有效的数值计算,我们通常使用像 NumPy这样的数据库,它们可以使用高效的代码来实现另一种语言,而使用昂贵的操作,比如Python之外的矩阵乘法。不幸的是,每次操作都需要重新切换到Python的开销很大。如果要在GPU上运行计算或以分布式方式运行计算,那么这种开销尤其糟糕,传输数据的成本很高。

TensorFlow也在Python之外做了很大的工作,但它需要进一步的工作来避免这种开销。TensorFlow不是独立于Python运行单独的昂贵操作,而是可以描述完全在Python之外运行的交互操作的图形。(这样的方法可以在几台机器学习库中看到。)

要使用TensorFlow,首先我们需要导入它。

import tensorflow as tf

我们通过操纵符号变量来描述这些交互操作。我们创建一个:

= tf.placeholder(tf.float32, [None784]) 

x不是具体的价值。这是一个placeholder值,当我们要求TensorFlow运行一个计算时,我们将输入一个值。我们希望能够输入任何数量的MNIST图像,每个图像被平铺成784维的向量。我们将其表示为具有形状的浮点数的2-D张量[None, 784]。(这里None表示尺寸可以是任意长度。)

我们还需要我们的模型的权重和偏差。我们可以想象,像其他输入一样处理这些信息,但是TensorFlow有一个更好的处理方式:Variable。A Variable是一个可修改的张量,居住在TensorFlow的交互操作图中。它可以被计算使用甚至修改。对于机器学习应用,一般通常有模型参数Variable

= tf.Variable(tf.zeros([78410]))

= tf.Variable(tf.zeros([10]))

我们Variable通过给出tf.Variable以下的初始值来 创建这些Variable:在这种情况下,我们初始化两者W并且b作为充满零的张量。既然我们要学习Wb,不要紧非常多他们最初是。

注意,W具有[784,10]的形状,因为我们要将784维图像向量乘以它,以产生差分类的10维证据向量。b具有[10]的形状,所以我们可以将其添加到输出。

我们现在可以实施我们的模型。它只需要一行来定义它!

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

首先,我们将x乘以W,表达式为tf.matmul(x,W)。 这是从我们的方程中乘以它们的方法翻转出来的,我们有Wx,作为处理x是具有多个输入的2D张量的小技巧。 然后我们添加b,最后应用tf.nn.softmax。

 而已。经过几个短暂的设置,我们只需要一行来定义我们的模型。这并不是因为TensorFlow的设计使得softmax的回归特别容易:它只是描述从机器学习模型到物理模拟的多种数值计算的非常灵活的方式。一旦定义,我们的型号可以在不同的设备上运行:您的计算机的CPU,GPU,甚至手机!

 

训练

为了训练我们的模型,我们需要定义模型是什么意思。那么实际上,在机器学习中,我们通常定义一个模型对于坏的意义。我们称之为成本或损失,它代表了我们的模型与我们所期望的结果有多远。我们尝试最小化这个错误,而且误差范围越小,我们的模型就越好。

确定模型损失的一个非常常见的非常好的功能称为“交叉熵”。交叉熵源于对信息理论中的信息压缩代码的思考,但是从赌博到机器学习在很多领域都是一个重要的思想。它定义为:image2017-6-7%2020%3A28%3A49.png?version=1&modificationDate=1496838529000&api=v2

哪里  ÿ 是我们预测的概率分布,  ÿ“是真正的分布(带有数字标签的单热矢量)。在粗略的意义上,交叉熵正在衡量我们的预言是如何无效地描述真相。有关交叉熵的更多细节超出了本教程的范围,但它是非常值得 理解的。 

为了实现交叉熵,我们需要先添加一个新的占位符来输入正确答案:

y_ = tf.placeholder(tf.float32, [None10]) 

然后我们可以实现交叉熵函数,

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) 

首先,tf.log计算每个元素的对数y。接下来,我们相乘的每个元素y_与相应的元素tf.log(y)。然后tf.reduce_sum,由于该reduction_indices=[1]参数,在y的第二维中添加元素 。最后,tf.reduce_mean计算批次中所有示例的平均值。

请注意,在源代码中,我们不使用此公式,因为它在数值上是不稳定的。相反,我们应用tf.nn.softmax_cross_entropy_with_logits的非标准化logits(例如,我们称之为softmax_cross_entropy_with_logitstf.matmul(x, W) + b),因为这个数值上更稳定的内部函数计算SOFTMAX激活。在您的代码中,请考虑使用tf.nn.softmax_cross_entropy_with_logits 。

现在我们知道我们想要我们的模型做什么,很容易让TensorFlow训练它来做到这一点。因为TensorFlow知道您的计算的整个图形,它可以自动使用 反向传播算法来有效地确定变量如何影响您要求最小化的损失。那么它可以应用您选择的优化算法来修改变量并减少损失。

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

在这种情况下,我们要求TensorFlow cross_entropy使用 学习率为0.5 的 梯度下降算法进行最小化。梯度下降是一个简单的过程,其中TensorFlow简单地将每个变量在减少成本的方向上稍微移动一点。但是TensorFlow还提供了 许多其他优化算法:使用一个就像调整一行一样简单。

什么TensorFlow在这里,在幕后,是添加新的操作,您的图形实现反向传播和梯度下降。然后,它返回一个单一的操作,当运行时,进行梯度下降训练的步骤,稍微调整您的变量以减少损失。

我们现在可以在以下模式中启动InteractiveSession

sess = tf.InteractiveSession() 

我们首先必须创建一个操作来初始化我们创建的变量:

tf.global_variables_initializer().run() 

我们来训练 - 我们将运行1000次训练步骤!

for in range(1000):

  batch_xs, batch_ys = mnist.train.next_batch(100)

  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) 

循环的每一步,我们从训练集中得到一百个随机数据点的“批次”。我们运行train_step饲料中的批次数据来代替placeholders。

使用小批量的随机数据称为随机训练 - 在这种情况下,随机梯度下降。理想情况下,我们希望将所有数据用于培训的每个步骤,因为这样可以让我们更好地了解我们应该做什么,但这很贵。因此,我们每次使用不同的子集。这样做是便宜的,并且有很多同样的好处。

 

评估我们的模型

我们的模型做得如何?

那么首先我们来弄清楚我们预测正确的标签。tf.argmax 是一个非常有用的功能,它给出沿某个轴的张量中最高条目的索引。例如,tf.argmax(y,1)我们的模型认为是每个输入最有可能的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, tf.float32)) 

最后,我们要求我们对测试数据的准确性。

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

这应该是92%左右。

那好吗 嗯,不是真的 其实这很糟糕 这是因为我们使用的是非常简单的模型。有了一些小的变化,我们可以达到97%。最好的型号可以达到99.7%的精度!(有关更多信息,请查看此 列表的结果。)

重要的是我们从这个模式中学到了。不过,如果您对这些结果感到有些不解,请查看 下一个教程,我们做得更好,并学习如何使用TensorFlow构建更复杂的模型!

转载于:https://my.oschina.net/repine/blog/918278

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值