数据科学引论-Python之道 第10课TensorFlow-深度学习实践 本节课将介绍如何利用TensorFlow框架建立一个简单的线性模型的基本工 作流程。在此特别感谢Hvass-Labs提供的教程,感兴趣的同学可以在github上 找到他们的教程。 首先介绍我们需要引入的模块。第一个matplotlib模块主要是用来辅助我们 画图,然后引入基本的TensorFlow模块,以及用于矩阵计算和其他一些数组计 算的numpy模块。本次教程使用的Python版本是3.6,TensorFlow的版本是 1.4.0。 In (1]:imatplotlib inlime import matplotlib.Pyplot as plt import tensorflov as tf import numpy as np /Users/chenhaopeng/anaconda/lib/python3.6/importlib/_bootstrap.py:205:Runtimewarning:compiletime version 3.5 of nod ule 'tensorflow.python.framework.fast_tensor_util'does not natch runtine version 3.6 r8tuEn【(*axg8,**灯ud8) 本教程使用3.6版本的Pythoni进行开发,Ten8 orFlowl库的版本是 In 12]:tf.veraion_ 0ut21:1.4.0' 在引入基本模块之后,我们需要将手写数字的图片,也就是我们此次简单线 性模型需要识别的图片加载进来。我们此次所用到的数据集是MNIST数据集, 它里面包含了7万张手写数字的图片,还包含它们对应的标签,它们的标签表示 的就是这些图片所对应的数字。TensorFlow直接提供了库函数,我们可以直接使 用它的库函数进行下载,例如第一个代码框里的两行代码,执行完这两行代码之 后会得到相应的输出信息,表明MNIST数据集已经加载完毕。整个MNST数据 集被分为三个不同的子数据集,包含训练数据集、测试数据集和验证数据集。本 次教程只使用训练数据集和测试数据集。通过pint函数打印出来的信息说明训 练数据集有55000张图片,测试数据集有10,000张图片,验证数据集有5000张 图片
数据科学引论-P瀌瀇h瀂瀁 之道 第 10 课 Te瀁瀆瀂瀅F濿瀂瀊-深度学习实践 本节课将介绍如何利用 Te瀁瀆瀂瀅F濿瀂瀊 框架建立一个简单的线性模型的基本工 作流程。在此特别感谢 H瀉a瀆瀆-Lab瀆 提供的教程,感兴趣的同学可以在 gi瀇h瀈b 上 找到他们的教程。 首先介绍我们需要引入的模块。第一个 瀀a瀇瀃濿瀂瀇濿ib 模块主要是用来辅助我们 画图,然后引入基本的 Te瀁瀆瀂瀅F濿瀂瀊 模块,以及用于矩阵计算和其他一些数组计 算的 瀁瀈瀀瀃瀌 模块。本次教程使用的 P瀌瀇h瀂瀁 版本是 3.6,Te瀁瀆瀂瀅F濿瀂瀊 的版本是 1.4.0。 在引入基本模块之后,我们需要将手写数字的图片,也就是我们此次简单线 性模型需要识别的图片加载进来。我们此次所用到的数据集是 MNIST 数据集, 它里面包含了 7 万张手写数字的图片,还包含它们对应的标签,它们的标签表示 的就是这些图片所对应的数字。Te瀁瀆瀂瀅F濿瀂瀊 直接提供了库函数,我们可以直接使 用它的库函数进行下载,例如第一个代码框里的两行代码,执行完这两行代码之 后会得到相应的输出信息,表明 MNIST 数据集已经加载完毕。整个 MNIST 数据 集被分为三个不同的子数据集,包含训练数据集、测试数据集和验证数据集。本 次教程只使用训练数据集和测试数据集。通过 瀃瀅i瀁瀇 函数打印出来的信息说明训 练数据集有 55000 张图片,测试数据集有 10,000 张图片,验证数据集有 5000 张 图片
载入数据 MNIST致据集大约12MB并且使用TensorFlow提供的库两数可以自动下载 data/dx-ubyte. /10 0y6+92 当你看到上在输出的信息时,MNST双据集已经加基完毕。MNST数据集一共有70000个图片并且有对应的标签(标签表示的是图片所对应的数乳,整个MNST数 据集会被分为3个不同的子数据集,包括刹练数据集、测试数据集和验证数据集,本教程只使用悠数据集和测试数据集。 In [4]1 print("Size of:") print("-Training-set:\t\t()".format(len(data.train.labels))) ion.labels))) size of: Training-set: vidation-et 5000 这个MNIST数据集是以One-Host编码方式进行加载的,这意味着标签从一 个单独的数字转换成了一个vector,而vector的长度等于所有可能类别的数量。 本次教程中一共有0到9十个数字,所以vector的长度就是10。每个vector中 只有一个代表第几个类别的元素是1,其他的元素都是0。例如,测试数据集前 五个图片标签中,第一行第七个坐标对应的数字是1,其他都是0,这也就意味 着第一个标签对应的图片就是7。 One-Hot编码 数据集以Oot的编码方式扣载,这意球着标签从一个单独的数字转为 ecto的长座等于所有可能类别的数量本教程中的vector长座是10,表示0型 g-共10个类别的数。每个v9cto中只有 个代表第几个类别的元素是1, 其他的元素都是0。例如我们展示的测试据集前五个图片的标签 In [5]:data.test.labels[0:5,:] array(I[..0.. 0 D.r 0 8 0 0. 0 0.j 1,0.0 0 . 0. 0. 0.j 【0,,0.。0,。 0.,1.,0,0.,0, 0.,0.111 为了比校和性能测试,我们还是需要把标益的类别表示为单个数字的,我们通过取出vec1or中最大元索的下标nde的方法将Oe-Hot端码的vector转换为单个的 数字。为了和Py0中的关键字s区分开,我们使用cs来命名表示为单个数字的标签类别,下面我们将测试数据集标签都转换为单个数字,并取出前五个标 签。第一个图片的标签类别是7,对应一个One-Hots编阳的vector中index为7的元素是1,其他的元素都是0, 0ut[51:array(【7,2,1,0,4]) 为了比较和性能测试,我们还是需要把标签的类别表示为单独的数字。因此, 我们通过取出vector中最大元素的下标,也就是index的方法,将One-Hot编 码的vector转换为单个的数字。为了和Python中的关键字class区分开,我们 使用cs来命名,表示单个数字的标签类别。我们将测试数据集标签都转换为单 个数字,然后取出前五个标签,可以看到它们组成的数组是7,2,10,4],也就是说
这个 MNIST 数据集是以 O瀁e-H瀂瀆瀇 编码方式进行加载的,这意味着标签从一 个单独的数字转换成了一个 瀉ec瀇瀂瀅,而 瀉ec瀇瀂瀅 的长度等于所有可能类别的数量。 本次教程中一共有 0 到 9 十个数字,所以 瀉ec瀇瀂瀅 的长度就是 10。每个 瀉ec瀇瀂瀅 中 只有一个代表第几个类别的元素是 1,其他的元素都是 0。例如,测试数据集前 五个图片标签中,第一行第七个坐标对应的数字是 1,其他都是 0,这也就意味 着第一个标签对应的图片就是 7。 为了比较和性能测试,我们还是需要把标签的类别表示为单独的数字。因此, 我们通过取出 瀉ec瀇瀂瀅 中最大元素的下标,也就是 i瀁de瀋 的方法,将 O瀁e-H瀂瀇 编 码的 瀉ec瀇瀂瀅 转换为单个的数字。为了和 P瀌瀇h瀂瀁 中的关键字 c濿a瀆瀆 区分开,我们 使用 c濿瀆 来命名,表示单个数字的标签类别。我们将测试数据集标签都转换为单 个数字,然后取出前五个标签,可以看到它们组成的数组是[7,2,1,0,4],也就是说
第一个图片的标签的类别是7,也就对应的是数字7,这和我们之前看到的vector 中第7个坐标对应的元素是1,而其他元素都是0是相符合的。 因为我们使用的MNIST书剧集中的图片,它的长度是28个像素,宽度也是 28个像素,所以我们现在需要定义几个数据维度的变量,以便我们在之后的代 码中能够重复使用这些数据维度。 首先,我们定义一个MNIST的图片,在每个维度上的长度是28个像素;其 次,我们再定义一个将图片存储在一维空间上的长度,即28×28这么长的一个 长度;然后,我们需要定义一个用来reshape图片的tuple;最后,我们需要定 义数字类别的数量,因为0到9一共有10个类别,所以数字类别的数量就是10。 数据维度T 工n【71:产加15T图片在每个度上都是2B个像景 i1m时gize-28 卓将雷片存在一维空间上的长度 img_size_flat img_size img_sizo ◆数字类别的数量,0到9一共10个类别 numc1asa88■10 下面定义一个画图的函数,这个画图函数主要是在3×3的网格上画出9张图 片,并且在图片下方标注图片所对应的正确类别和我们通过模型预测的类别,这 个函数主要是帮助大家能够可视化的理解整个工作的流程。 画图的函数 在3x3网格上画出9个图片并且在图片下方标注正碎的类别和预测的类别的函数 #创理一个包含3x3个子图的图 fig,axes plt.subplots(3,3) fig.subplots_adjust(hspace=0.3,vspace=0.3) ax.inshow(images[i].reshape(img_shape),cmap='binary') ·展示正种的类别和预测的类别 if cla_pred is None: xlabel "True:(0)".format(cls_true[i]) ax.set_xlabel(xlabel) ·将图中的鹅斯去掉 ax.set_xticka([]) ax.set_yticks(lJ) 下面我们将取出一些样本数据来看看我们这个数据集中所对应的一些手写
第一个图片的标签的类别是 7,也就对应的是数字 7,这和我们之前看到的 瀉ec瀇瀂瀅 中第 7 个坐标对应的元素是 1,而其他元素都是 0 是相符合的。 因为我们使用的 MNIST 书剧集中的图片,它的长度是 28 个像素,宽度也是 28 个像素,所以我们现在需要定义几个数据维度的变量,以便我们在之后的代 码中能够重复使用这些数据维度。 首先,我们定义一个 MNIST 的图片,在每个维度上的长度是 28 个像素;其 次,我们再定义一个将图片存储在一维空间上的长度,即 28×28 这么长的一个 长度;然后,我们需要定义一个用来 瀅e瀆ha瀃e 图片的 瀇瀈瀃濿e;最后,我们需要定 义数字类别的数量,因为 0 到 9 一共有 10 个类别,所以数字类别的数量就是 10。 下面定义一个画图的函数,这个画图函数主要是在 3×3 的网格上画出 9 张图 片,并且在图片下方标注图片所对应的正确类别和我们通过模型预测的类别,这 个函数主要是帮助大家能够可视化的理解整个工作的流程。 下面我们将取出一些样本数据来看看我们这个数据集中所对应的一些手写
字体以及它们对应的标签,然后再看看这些数据对不对。首先,我们从测试数据 集中取出前9张图片,然后再从测试数据集中取出前9个标签,将它们通过我们 刚才定义的画图函数进行绘制。然后,可以看到9张手写字体的图片以及它们所 对应的标签。 画几个图片看看数据是不是对的 I【91:来从测试数据集中取出前9个图片 images data.test.images(0:9] 从源试登据第中取出前个标签 cls_true data.test.cls[0:9] 严他用城雨致棕丽片阳短等面出度 plot_images(images-image8,cl8_true-cla_true) 因为我们需要通过操作符号变量来描述交互的操作单元,因此我们需要定义 一些操作符号变量。在第一个代码框中的X不是一个特定的值,而是一个占位符 (placeholder)。这些占位符在TensorFlow运行计算时需要对应的输入值。X也被 称作张量,也就是Tensor,,它可以表示为多维度的vector或者矩阵。因为我们 希望能够输入任意数量的MNIST图像,每一张图片都要转成28×28维的向量, 所以我们使用二维的浮点数张量来表示这些图。这个张量的数据类型被设置为 float32,形状是[None,28×28],这里的None表示此张量的第一个维度可以是 任意长度。然后,我们使用占位符变量表示图片对应的标签,这个占位符变量的 形状是None,第二位是l0,表示该变量可以存储任意数量的标签,并且每个标 签都是一个长度为10的vector。最后,我们定义一个保存标签对应数字的占位 符变量。为了方便比较,我们可以把标签转为单个数字,所以下面定义的这个变 量存储的就是这些数字。同样,这里的Noe表示这个变量是一个一维任意长度 的vector
字体以及它们对应的标签,然后再看看这些数据对不对。首先,我们从测试数据 集中取出前 9 张图片,然后再从测试数据集中取出前 9 个标签,将它们通过我们 刚才定义的画图函数进行绘制。然后,可以看到 9 张手写字体的图片以及它们所 对应的标签。 因为我们需要通过操作符号变量来描述交互的操作单元,因此我们需要定义 一些操作符号变量。在第一个代码框中的 X 不是一个特定的值,而是一个占位符 (瀃濿aceh瀂濿de瀅)。这些占位符在 Te瀁瀆瀂瀅F濿瀂瀊 运行计算时需要对应的输入值。X 也被 称作张量,也就是 Te瀁瀆瀂瀅,它可以表示为多维度的 瀉ec瀇瀂瀅 或者矩阵。因为我们 希望能够输入任意数量的 MNIST 图像,每一张图片都要转成 28×28 维的向量, 所以我们使用二维的浮点数张量来表示这些图。这个张量的数据类型被设置为 f濿瀂a瀇_32,形状是[N瀂瀁e, 28×28],这里的 N瀂瀁e 表示此张量的第一个维度可以是 任意长度。然后,我们使用占位符变量表示图片对应的标签,这个占位符变量的 形状是 N瀂瀁e,第二位是 10,表示该变量可以存储任意数量的标签,并且每个标 签都是一个长度为 10 的 瀉ec瀇瀂瀅。最后,我们定义一个保存标签对应数字的占位 符变量。为了方便比较,我们可以把标签转为单个数字,所以下面定义的这个变 量存储的就是这些数字。同样,这里的 N瀂瀁e 表示这个变量是一个一维任意长度 的 瀉ec瀇瀂瀅
占位符Placeholder)变量 我们通过操作符号变量来描迷交互的提作单元,x不是一个特定的值,而是一个占位荷placehoider,我们在TensorFlowi运行计算时裙入这个值。x就被称作张量 tensor),x可以表示为多维度的vector成者矩阵。我们希望缩够编入任您数量的M 图像,年一引 2B维的向量 我们用2维的泸 点数张量来表示这些 图,该张量的数据类型极设置为E1cat32,这个张量的形状是【N0ne,28x28]。(这里的one表示此张量的第一个维度可以是任何长度的, In [10]:x=tf.placeholder(tf.float32,[None,img_size_flat]) 然后我们使用占位符变量表示图片对应的标益,这个占位符受量的形状是Ioe,um_classes],这表示该变量可以存储任意数星的标签,并且每个标益都是 个长度为num_classest也就是10的vecto In [11]:y_true tf.placeholder(tf.float32,[None,num_classes]) 最后我们定义一个保存标签对应的数字的占位符变量,我们之前提到过为了方便比较我们把标签都转换为单个数字,所以下面定义的这个变量祝是存储这些数 字。[Woae】表示这个变量是一个一-维任意长座的vect0r In [12]:y_true_cls -tf.placeholder(tf.int64,[Nome]) 我们的模型除了前面的占位符变量之外,还需要一些权重值和偏置量,这些 当作另外的输入。我们可以使用占位符来表示它们,但是TensorFlow有一个更 好的方法表示,就是用Variable.。一个Variable代表一个可修改的张量,存放在 TensorFlow用于交互操作的图中,它们可以用于计算输入值,也可以在计算中被 修改。各种机器学习应用一般都会有模型参数,这些模型参数都可以用Variable 来表示,我们赋予Variable不同的初值来创建不同的Variable。在这里,我们使 用全为0的张量来初始化权重值weights和偏置量biases。.因为我们要学习 weights和biases的值,所以它们的初值可以随意设置。在这里,我们需要注意 到的是weights的形状是28×28和10,因为我们想用28×28位的图片向量乘以 它得到一个10维的向量,这个10维的向量每一个维度都对应不同的数字的类 别。然后,把biases的形状设置为一个1维的长度为10的向量,这样我们可以 直接把它加到输出上面。 In [13]:weights tf.Variable(tf.zeros([ing_size_flat,num_classes])) biases tf.Variable(tf.zeros([num_classes])) 下面我们将正式进入简单的线性模型的建立。首先,我们使用的这个简单的 线性模型就是把占位符变量X保存的图片vector和变量weights相乘,然后再 加上biases变量。从第一个代码框我们可以看到这个计算,因为我们的预测值得 到的结果可能很大或者很小,所以很难去分析这些预测值,所以我们希望能够归
我们的模型除了前面的占位符变量之外,还需要一些权重值和偏置量,这些 当作另外的输入。我们可以使用占位符来表示它们,但是 Te瀁瀆瀂瀅F濿瀂瀊 有一个更 好的方法表示,就是用 Va瀅iab濿e。一个 Va瀅iab濿e 代表一个可修改的张量,存放在 Te瀁瀆瀂瀅F濿瀂瀊 用于交互操作的图中,它们可以用于计算输入值,也可以在计算中被 修改。各种机器学习应用一般都会有模型参数,这些模型参数都可以用 Va瀅iab濿e 来表示,我们赋予 Va瀅iab濿e 不同的初值来创建不同的 Va瀅iab濿e。在这里,我们使 用全为 0 的张量来初始化权重值 瀊eigh瀇瀆 和偏置量 bia瀆e瀆。因为我们要学习 瀊eigh瀇瀆 和 bia瀆e瀆 的值,所以它们的初值可以随意设置。在这里,我们需要注意 到的是 瀊eigh瀇瀆 的形状是 28×28 和 10,因为我们想用 28×28 位的图片向量乘以 它得到一个 10 维的向量,这个 10 维的向量每一个维度都对应不同的数字的类 别。然后,把 bia瀆e瀆 的形状设置为一个 1 维的长度为 10 的向量,这样我们可以 直接把它加到输出上面。 下面我们将正式进入简单的线性模型的建立。首先,我们使用的这个简单的 线性模型就是把占位符变量 X 保存的图片 瀉ec瀇瀂瀅 和变量 瀊eigh瀇瀆 相乘,然后再 加上 bia瀆e瀆 变量。从第一个代码框我们可以看到这个计算,因为我们的预测值得 到的结果可能很大或者很小,所以很难去分析这些预测值,所以我们希望能够归
一化这些预测值,使得logits结果矩阵的每一行加起来等于1并且每个元素都限 制在[O,1]之间,这样,我们就可以分析这些预测值。所以我们使用TensorFlow里 面提供的softmax这个函数,然后把得到的预测结果保存在y_pred这个变量里 面。为了将预测值表示为单个数字,我们会使用TensorFlow的argmax这个函 数。这个函数把输入的矩阵中每一行最大值的坐标取出,因为我们每一行中最大 值的坐标对应这个图片所代表的数字的类别,所以也就获得了预测的标签值。 这个简单的双学模型就是把占位符变量x保存的图片vectorf和安量weighta相乘,然后再加上biae变量, 这样计算的结果是一个形状为[num images,num classes]的矩阵,因为x的形状是[nun images,ing size f1at]并且weighta的形状 是[1ng1zef1at,num_c1anae】,所以这两个变量的乘积是一个拥有Ina1nag0n,num_cla8e】形状的炬阵,再把b1a器e vector加到矩阵中的年 行, In [14]:logits -tf.matmul(x,weights)+biases 但是因为预测值可能很小或者很大,所以很流去分析这些预测值,因此我门希望能够归一化这些预调值。使得1gt矩华的每一行加起米等于1并且每个元素却限 制在0和1之间,这就是s0max径数的作用,得到的佑果存在y preds变量里面。 为了将测值表示为单个数字,我们使用1.argma函致,把ypre钜阵中每一行的最大值的坐标取出,也就获得了预测的标签值。 In [151:y_pred -tf.nn.softmax(logits) y_pred_cls tf.argnax(y_pred,1) 现在我们获得的logits这个变量就是一个有输入图片数量行和数字类别数量 列的一个矩阵,这个矩阵中第ⅰ行第]列的数据表示的是模型估计出第二张输入 图片的标签是第j个类别的概率,也就是说第二张图片上的手写数字是j的概率。 为了能够使得我们建立的模型更加准确地识别输入的图片,我们必须要调整 weights权重值和biases偏置量。 在机器学习中,我们通常定义一个指标来表示一个模型的好坏,这个指标通 常被称为成本或损失,我们需要尽量最小化这个指标。一个非常常见的成本函数 就是交叉熵。交叉熵产生于信息论里面的信息压缩编码技术,但是到后来演变成 为从博弈论到机器学习等其他领域里的重要技术手段。TensorFlow提供了一个 计算交叉熵的内部函数,直接将logits变量输入进去,并且把保存图片对应的正 确标签的ytue变量输入进去,它就可以对于每一个图片计算出它的交叉熵。 In [16]:cross_entropy-tf.nn.softmax_cross_entropy_with_logits(logits-logits, labels=y true)
一化这些预测值,使得 濿瀂gi瀇瀆 结果矩阵的每一行加起来等于 1 并且每个元素都限 制在[0,1]之间,这样,我们就可以分析这些预测值。所以我们使用 Te瀁瀆瀂瀅F濿瀂瀊 里 面提供的 瀆瀂f瀇瀀a瀋 这个函数,然后把得到的预测结果保存在 瀌_瀃瀅ed 这个变量里 面。为了将预测值表示为单个数字,我们会使用 Te瀁瀆瀂瀅F濿瀂瀊 的 a瀅g瀀a瀋 这个函 数。这个函数把输入的矩阵中每一行最大值的坐标取出,因为我们每一行中最大 值的坐标对应这个图片所代表的数字的类别,所以也就获得了预测的标签值。 现在我们获得的 濿瀂gi瀇瀆 这个变量就是一个有输入图片数量行和数字类别数量 列的一个矩阵,这个矩阵中第 i 行第 J 列的数据表示的是模型估计出第二张输入 图片的标签是第j个类别的概率,也就是说第二张图片上的手写数字是j的概率。 为了能够使得我们建立的模型更加准确地识别输入的图片,我们必须要调整 瀊eigh瀇瀆 权重值和 bia瀆e瀆 偏置量。 在机器学习中,我们通常定义一个指标来表示一个模型的好坏,这个指标通 常被称为成本或损失,我们需要尽量最小化这个指标。一个非常常见的成本函数 就是交叉熵。交叉熵产生于信息论里面的信息压缩编码技术,但是到后来演变成 为从博弈论到机器学习等其他领域里的重要技术手段。Te瀁瀆瀂瀅F濿瀂瀊 提供了一个 计算交叉熵的内部函数,直接将 濿瀂gi瀇瀆 变量输入进去,并且把保存图片对应的正 确标签的 瀌_瀇瀅瀈e 变量输入进去,它就可以对于每一个图片计算出它的交叉熵
现在,我们已经对于每个图片分类进行了交叉熵的计算,可以得到我们的模 型对于每张图片的预测表现,但是对于所有数据点的预测表现比单一数据点的表 现能更好地描述模型的性能,所以我们将所有图片的预测表现取平均值来作为我 们整个模型的预测表现。 In [17]:cost tf.reduce_mean(cross_entropy) 现在,我们已经可以表示出模型的一个成本,为了能够最小化这个成本,我 们需要建立一个优化函数。本次教程中使用的是一个基本的梯度下降算法,以0.5 的学习速率最小化这个交叉熵成本。需要注意的是,我们定义的优化函数在这里 并没有执行,事实上,所有之前定义的语句都没有执行,我们只是把它们添加到 TensorFlow的工作图当中,在之后的语句中我们会让所有语句开始执行。 In [18]:optimizer tf.train.GradientDescentoptimizer(learning_rate-0.5).minimize(coat) 接下来,我们需要对模型的性能进行评估。首先,我们需要找出那些预测正 确的标签,我们使用TensorFlow的equal函数来检测我们的预测是否与真实标 签匹配。输入的y_pred_cls代表的是对于任意输入图片预测到的标签值,而 y_true._cls代表图片对应的正确标签。这里获得的correct_prediction是一组bool 值,为了确定正确预测项的比例,我们可以把b0ol值转化为浮点数,然后再取 平均值,也就是使用第20行这个代码框。 性能评估 首先让我们找出那些预测正确的标签。y_pred.cs代表对于任一输入图片预测到的标签值,而y心_cs代表图片对应正裤的标盗,我们可以用.qua来检测我们 的预测是否真实标签匹配索引位置一样表示匹和。 In [191:correct_prediction tf.equal(y_pred_cl8,y_true_cla) comect_prediction是一组布尔值。为了确定正确预测项的此例,我们可以把布尔值转换成浮点,然后取平均值。例如,ue,False,TUe,True]会变成1,0,1, ,取平均值后得到0.75. In [201:accuracy tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) 我们可以举个例子,当correction_prediction这组bool值是[true,false,true, tue],经过我们的转换就会得到[1,0,1,1]这个数组,然后再取平均值,之后就是 0.75,也就是表示我们正确预测项的比例是0.75
现在,我们已经对于每个图片分类进行了交叉熵的计算,可以得到我们的模 型对于每张图片的预测表现,但是对于所有数据点的预测表现比单一数据点的表 现能更好地描述模型的性能,所以我们将所有图片的预测表现取平均值来作为我 们整个模型的预测表现。 现在,我们已经可以表示出模型的一个成本,为了能够最小化这个成本,我 们需要建立一个优化函数。本次教程中使用的是一个基本的梯度下降算法,以 0.5 的学习速率最小化这个交叉熵成本。需要注意的是,我们定义的优化函数在这里 并没有执行,事实上,所有之前定义的语句都没有执行,我们只是把它们添加到 Te瀁瀆瀂瀅F濿瀂瀊 的工作图当中,在之后的语句中我们会让所有语句开始执行。 接下来,我们需要对模型的性能进行评估。首先,我们需要找出那些预测正 确的标签,我们使用 Te瀁瀆瀂瀅F濿瀂瀊 的 e瀄瀈a濿 函数来检测我们的预测是否与真实标 签匹配。输入的 瀌_瀃瀅ed_c濿瀆 代表的是对于任意输入图片预测到的标签值,而 瀌_瀇瀅瀈e_c濿瀆 代表图片对应的正确标签。这里获得的 c瀂瀅瀅ec瀇_瀃瀅edic瀇i瀂瀁 是一组 b瀂瀂濿 值,为了确定正确预测项的比例,我们可以把 b瀂瀂濿 值转化为浮点数,然后再取 平均值,也就是使用第 20 行这个代码框。 我们可以举个例子,当 c瀂瀅瀅ec瀇i瀂瀁_瀃瀅edic瀇i瀂瀁 这组 b瀂瀂濿 值是[瀇瀅瀈e, fa濿瀆e, 瀇瀅瀈e, 瀇瀅瀈e],经过我们的转换就会得到[1,0,1,1]这个数组,然后再取平均值,之后就是 0.75,也就是表示我们正确预测项的比例是 0.75
到目前为止,我们已经把TensorFlow的工作图创建完成。下面,我们需要创 建一个Session来执行这个图。创建完Session之后,其中我们定义的weights和 biases这些变量需要在优化它们之前被初始化。 创建TensorFlow session 当TensorFlow工作图创建完减,我们需提创建一个session来执行这个图, In [21]:session tf.Session() 初始化变量 变量we1ght=和b1ae每需要在我们优化他们之前被初始化. In [22]:session.run(tf.global_variables_initializer()) 下面我们会定义一个执行优化迭代的函数,因为训练集中一共有5万张图片, 在理想情况下,我们希望使用所有的数据来进行每一步的训练,因为使用所有数 据集可以带来更好的训练结果。但是,这显然有很大的计算开销,因此,我们使 用其中的一小部分的随机数据来进行训练,这又被称作随机训练。在这里,更确 切地说是一个随机梯度下降训练,所以每一次训练我们可以使用不同的数据子集。 这样做既可以减少计算开销,又可以最大化学习到的数据集的总体特性。我们将 采取的是随机抓取训练数据中的一百个批处理数据点,用这些数据点作为参数替 换之前的占位符来进行训练。 执行优化迭代的函数 州塔集中一共有5000餐图片,在甲机情识下.,段们弟望用理们所右的药好来讲行每一指的信因为这馆给程面好的体结果,相已燃这需要阀大的计领开 销,因此我们使用一小部分的机数超来进行训练, 这又被称为植机训练(stochastic training)·在这里更确切的说是徒机梯度下降训练。所似,每一次训我们 可以使用不司的故据子集,这样做可以减少计算开镇,又可以最大化地学习到数据集的总体特性。 In【23]:batch_size100 在酒环的每个步骤中,我们都会陆机抓取训练数据中的100个批处理数据点,然后我们用这些数据点作为参数替换之前的占位符来进行训悠, In [24]:def optimize(num iterations): 如保存的示应的正益数据 x_batch,y_true_batch-data.train.next_batch(batch_eize) 卡将批处理据款入字莞1ict)中,字英中k@y的名字要与之前定义的占位符变量对拉 ,使用这些批处理取据作为诚陈欧据。然后运行优化函数 卡en8orF2ow会把:eedd1 ct erai1n中的变量赏值给对应的占位符变量,然后诺行优化裙数 session.run(optimizer,feed_dict-feed_dict_train) 上面就是一个执行优化迭代的函数。其中,我们首先获取一百个训练样本作 为批处理数据,然后将这些批处理数据放入一个字典中,字典中Ky的名字要与
到目前为止,我们已经把 Te瀁瀆瀂瀅F濿瀂瀊 的工作图创建完成。下面,我们需要创 建一个 Se瀆瀆i瀂瀁 来执行这个图。创建完 Se瀆瀆i瀂瀁 之后,其中我们定义的 瀊eigh瀇瀆 和 bia瀆e瀆 这些变量需要在优化它们之前被初始化。 下面我们会定义一个执行优化迭代的函数,因为训练集中一共有5万张图片, 在理想情况下,我们希望使用所有的数据来进行每一步的训练,因为使用所有数 据集可以带来更好的训练结果。但是,这显然有很大的计算开销,因此,我们使 用其中的一小部分的随机数据来进行训练,这又被称作随机训练。在这里,更确 切地说是一个随机梯度下降训练,所以每一次训练我们可以使用不同的数据子集。 这样做既可以减少计算开销,又可以最大化学习到的数据集的总体特性。我们将 采取的是随机抓取训练数据中的一百个批处理数据点,用这些数据点作为参数替 换之前的占位符来进行训练。 上面就是一个执行优化迭代的函数。其中,我们首先获取一百个训练样本作 为批处理数据,然后将这些批处理数据放入一个字典中,字典中 Ke瀌 的名字要与
之前定义的占位符变量相对应,然后使用这些批处理数据作为训练数据,运行优 化函数,然后再不断的进行模型的优化。 下面我们将定义一个展示模型性能的函数。首先,我们将测试数据放入到字 典中。和之前提到的训练字典一样,字典中Ky的名字要与之前定义的占位符变 量相对应。然后,我们定义了一个打印测试数据集预测准确性的函数。为了能够 直观地看到一些我们未被识别的图片,我们定义了一个展示测试数据集中被错误 识别的图片的函数。之后,我们会再定义一个画出模型权重值的函数。画出模型 权重值的函数一共会画出10张图片,每一张图片代表模型识别的一个数字的权 重值。 展示性能的函数 首先将测试数据放入到字典中和之前提到的练字典一样,字典中k的名字要与之前定义的占位符变量对应 In 125]:feed_dict_test -(x:data.test.images, tete) 打印测试数据集预测准确性的函数 In 126]:dot print_accuracy(): 使用ren8 orFlowi计算accuraoy acc session.run(accuracy,feed_dict-feed_dict_test) 展示测试数据集中被错误识别的图片的函数 每个试图片是否被正识刻的如o©1an值列表 摩和每个更片对应的原测顶列 correct,cla_pred session.run([correct_prediction,y_pred_cls], feed_dict-feed_dict_test) ) 鼻获得测试战起更中未坡正神记别的图片 images data.test.images[incorrect] ·获职这些图片的的质值 cla_pred cls_pred[incorrect] 单获丽这生图片对应的正障贡情 cls true data.test.cls[incorrect] ·画出雨九个图片 plot_images(images-images[0:9]
之前定义的占位符变量相对应,然后使用这些批处理数据作为训练数据,运行优 化函数,然后再不断的进行模型的优化。 下面我们将定义一个展示模型性能的函数。首先,我们将测试数据放入到字 典中。和之前提到的训练字典一样,字典中 Ke瀌 的名字要与之前定义的占位符变 量相对应。然后,我们定义了一个打印测试数据集预测准确性的函数。为了能够 直观地看到一些我们未被识别的图片,我们定义了一个展示测试数据集中被错误 识别的图片的函数。之后,我们会再定义一个画出模型权重值的函数。画出模型 权重值的函数一共会画出 10 张图片,每一张图片代表模型识别的一个数字的权 重值
面出楼华权重值的金故,一共西出10个图片,每个图片代表模型识别的一个数字, In [281:def plot weights(): 从r@na6rF1ow变量中获得权重值 w-seasion.run(weights) 卡获得所有机重值中最小和最大的值,这两个值用来改变图片上领色的密度,从面使得图片直坡可以进行比较 0a即nxw} F建立一个包含3x4个子图的图形,最后两个子图没有被使用,因为一共只有10个数字 fig,axes plt.subplot8(3,4) fig.subplotn_adjust(hspace-0.3,wspace-0.3) to) f1c10: 票取得鹅1个数字的机重值并且改变这个张量的形状,注意的形状是1nga1gef1ātx10 image -w[:,i].reshape(img_shape) el("Weightsi (0)".format(i)) 两图 ax.inshow(image,vmin-w min,vnax-w nax,cmap='neismic') 将被线从每个子图中除 下面,我们将正式运行我们的代码,然后检查整个模型优化前后的性能。首 先,我们在未进行任何优化迭代时,打印一下测试数据的准确性,发现只有9.8%, 这是因为模型只进行了初始化,但是没有进行优化,所以模型对于图片的预测值 都是0,这也就意味着10次预测只有一次是正确的,这和展示的错误例子相符 合。我们可以看到预测错误的这些图片,其预测值因为初始化为0,所以它的预 测值都是0。 测试据集的准调性只有9.8,这是因为模型只进行了初始化很是没有优化, 所以模型对于图片的预调值都是0, 这意着10次预测有1次是正确的,这和展示的 例子相特。 In [291:print_accuracy() Accuracy on test-set:9.8 In [30]:plot example errors) 2 4.Pre .Pre ue 9,Pred: rue:5.Pred True Pred o 然后,我们调用优化函数来完成一次优化迭代,我们可以发现模型的准确性 从9.8%提升到了37%。这里需要注意的是这里的37%,每次运行结果不一定都等 于这个数字,因为每次随机选取的图片样本可能不同,所以导致了我们优化之后 的准确性不同。下面会展示一些错误预测的图片
下面,我们将正式运行我们的代码,然后检查整个模型优化前后的性能。首 先,我们在未进行任何优化迭代时,打印一下测试数据的准确性,发现只有 9.8%, 这是因为模型只进行了初始化,但是没有进行优化,所以模型对于图片的预测值 都是 0,这也就意味着 10 次预测只有一次是正确的,这和展示的错误例子相符 合。我们可以看到预测错误的这些图片,其预测值因为初始化为 0,所以它的预 测值都是 0。 然后,我们调用优化函数来完成一次优化迭代,我们可以发现模型的准确性 从 9.8%提升到了 37%。这里需要注意的是这里的 37%,每次运行结果不一定都等 于这个数字,因为每次随机选取的图片样本可能不同,所以导致了我们优化之后 的准确性不同。下面会展示一些错误预测的图片