TensorFlow版本的HelloWord

下面是TensorFlow官网提供的一个入门代码,对于一个机器学习的新手来说,好难呀,所以下面就只能一行一行的来理解了。

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

model.compile(
  optimizer='adam',
  loss='sparse_categorical_crossentropy',
  metrics=['accuracy'],
)

model.fit(
  x_train,
  y_train,
  epochs=5,
)

model.evaluate(x_test, y_test)

首先是导入tensorflow库,正常操作,不用解释。

import tensorflow as tf

下面这个要分几段理解:

  • tf.keras:TensorFlow对KerasAPI规范的实现,使用它以设置TensorFlow程序,那么问题来了,啥是KerasAPI呢?KerasAPI是一个用于构建和训练模型的高阶API,包含对TensorFlow特定功能的顶级支持。
  • datasets:是DatasetsAPI的实现与支持,使用DatasetsAPI可扩展为大型数据集或多设备训练。那么问题又来了,啥是DatasetsAPI呢?DatasetsAPI实现了从内存或者硬盘文件中加载数据组成数据集,同时对数据集进行一系列变换操作,最终将数据集提供给其他API使用的一系列功能。
  • mnist:是MNIST数据集,来自美国国家标准与技术研究所,由来自250个不同人手写的数字构成,其中50%是高中学生,50%来自人口普查局的工作人员。也是同样比例的手写数字数据。

合在一起的意思就是说,我们要下载MNIST数据集的图像数据了。

mnist = tf.keras.datasets.mnist

上面代码下载的东西本身并没有使用标准的图片格式储存,要用下面代码中的load_data方法,也就是tf.keras自带的MNIST数据集加载方法去手动解压。

图片数据将被解压成2维的tensor:[image index, pixel index] 其中每一项表示某一图片中特定像素的强度值, 范围从 [0, 255] 到 [-0.5, 0.5]。 "image index"代表数据集中图片的编号, 从0到数据集的上限值。"pixel index"代表该图片中像素点得个数, 从0到图片的像素上限值。

也就是说,load_data方法把MNIST数据集划分训练集和测试集来使用。x_train是训练集图片,y_train是训练集标签,x_test是训练集图片,y_test是训练集标签。

再形象一下,就是下面这张图片咯,每一张图片都有28X28的像素,用一个数字数组来表示每一张图片,把数组展开成一个向量,长度等于28X28=784。因此,MNIST数据集的图片就是在784维向量空间里面的点,相当复杂,784维呢。

1503285601200049.png
(x_train, y_train),(x_test, y_test) = mnist.load_data()

回顾一下上面说的几个点:

  • x_train是训练集图片,x_test是训练集图片。
  • MNIST数据集的图片就是在784维向量空间里面的点。
  • 1个点就是1个像素单位,像素值的范围是 [0, 255] 。

所以,下面代码的意思就很清楚了,将图像的RGB数值,除于255归一到(0,1)之间的小数。也就是归一化,把数据变成(0,1)或者(1,1)之间的小数,主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,机器处理起来可以更加便捷快速。

还有一个网上说的不明觉厉的理由:把有量纲表达式变成无量纲表达式,便于不同单位或量级的指标能够进行比较和加权。归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为纯量。

x_train, x_test = x_train / 255.0, x_test / 255.0

上面有说到,tf.keras是TensorFlow对KerasAPI 规范的实现,所以,tf.keras可以运行任何与Keras兼容的代码。下面代码中,就用到了Keras代码。

model是Keras中主要的数据结构,这个数据结构定义了一个完整的图,你可以向已经存在的图中加入任何的网络结构。在Keras中,通过组合层来构建模型,模型通常是由层构成的图。最常见的模型类型是层的堆叠(tf.keras.Sequential)模型。

Keras文档里是tf.keras.Sequential,TensorFlow文档里是tf.keras.models.Sequential,没什么差别,怎么写都可以,效果一个样。下面代码会构建一个简单的全连接网络,即多层感知器,或者叫序贯(Sequential)模型。

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

上面代码里面还有4个函数,分别在下面解释一下是啥意思。

tf.keras.layers.Flatten(input_shape=(28, 28)),

tf.layers.Flatten函数,在保留axis(axis 0)的同时平移输入张量。轴(axis)用来为超过一维的数组定义的属性,二维数据拥有两个轴,第0轴沿着行的垂直往下,表示沿着每一列或行标签/索引值向下执行方法;第1轴沿着列的方向水平延伸,表示沿着每一行或者列标签横向执行对应的方法。下面有一张比较形象的图片来解释:

1252882-20181130160009588-1393126436.png

再回顾下,上面有说到,每一张图片都有28X28的像素,使用代码的意思也出来了,就是将图像的格式从2d阵列(28x28像素)转换为28x28=784像素的1d阵列。根本目的是展平图像数据,用通俗的话来说,这就是真正的降维攻击呀。

下一行代码使用构造函数参数实例化全连接(tf.keras.layers.Dense)层,Dense层是密​​集连接或完全连接的神经层。在像素被展平后,网络由两层tf.keras.layers.Dense序列组成。

第一个Dense层有512个节点或神经元,该层实现了outputs = activation(inputs * kernel + bias),中activation是作为activation参数传递的激活函数,是由层创建的权重矩阵(非None时)。kernel是由层创建的权重矩阵,并且bias是由层创建的偏差向量(use_bias为True时)。

小结一下就是,一个有512列的全连接层,tf.nn.relu函数是计算校正线性的。

tf.keras.layers.Dense(512, activation=tf.nn.relu),

tf.layers.Dropout函数,将退出率(Dropout)应用于输入。Dropout包括在每次更新期间随机将输入单位的分数rate设置为0,这有助于防止过度拟合(overfitting)。保留的单位按比例1/(1-rate)进行缩放,以便在训练时间和推理时间内它们的总和不变。

就是设置一下需要断开的神经元的比例,防止过度拟合,过度拟合的定义是:为了得到一致假设而使假设变得过度严格称为过拟合。实际目的是为了让模型更包容一些。

tf.keras.layers.Dropout(0.2),

tf.nn.softmax函数,计算softmax激活。在数学,尤其是概率论和相关领域中,Softmax函数,或称归一化指数函数,是逻辑函数的一种推广。

下面的代码是第二个,也是最后一层是10个节点的softmax层,会返回10个概率分数的数组,其总和为1,每个节点包含指示当前图像属于10个类之一的概率的分数。就是一个有10列的全连接层。

tf.keras.layers.Dense(10, activation=tf.nn.softmax)

现在回顾一下这个模型,首先,将每一个图像的格式从2d阵列降维到1d阵列,再把每一个1d阵列存入到一个784(28x28)行N列的2d阵列中,把数据从原来784维降成2维。

再创建两个全连接(tf.keras.layers.Dense)层,一个是通过校正线性计算的有512个节点或神经元的全连接层,一个是通过归一化指数(tf.nn.softmax)函数计算的10个节点的全连接层。

最后在两个全连接(tf.keras.layers.Dense)层之间通过退出率(Dropout)函数来防止过度拟合。这个过程就像下面的图片展示的那样:

softmax-layer-generic.png

构建好模型后,我们就可以通过调用compile方法配置该模型的学习流程。这个方法有下面几个参数:

  • optimizer参数:优化器,此对象会指定训练过程,从tf.train模块向其传递优化器实例。
  • loss参数:损失函数交叉熵,要在优化期间最小化的函数。损失函数由名称或通过从tf.keras.losses模块传递可调用对象来指定。
  • metrics参数:评价指标列表,用于监控训练。它们是tf.keras.metrics模块中的字符串名称或可调用对象。
model.compile(
  optimizer='adam',
  loss='sparse_categorical_crossentropy',
  metrics=['accuracy'],
)

因为小型数据集,我们使用内存中的NumPy数组训练和评估模型,即使用fit方法使模型与训练数据拟合。开始训练迭代5轮。

其中x_train是输入数据,y_train是标签元组。epochs参数,以周期为单位进行训练,一个周期是对整个输入数据的一次迭代,以较小的批次完成迭代。

model.fit(
  x_train,
  y_train,
  epochs=5,
)

tf.keras.Model.evaluate可以使用NumPy数据,用来评估所提供数据的推理模式损失和指标。我们输入x_testy_test两个测试集对训练后的模型进行测试。

model.evaluate(x_test, y_test)

最后我们就可以执行代码了,执行完成以后,控制台的输出就是下面的这些内容:

Epoch 1/5
60000/60000 [==============================] - 8s 131us/sample - loss: 0.2183 - acc: 0.9355
Epoch 2/5
60000/60000 [==============================] - 7s 119us/sample - loss: 0.0961 - acc: 0.9704
Epoch 3/5
60000/60000 [==============================] - 6s 102us/sample - loss: 0.0691 - acc: 0.9784
Epoch 4/5
60000/60000 [==============================] - 6s 97us/sample - loss: 0.0530 - acc: 0.9826
Epoch 5/5
60000/60000 [==============================] - 6s 97us/sample - loss: 0.0432 - acc: 0.9862
10000/10000 [==============================] - 0s 36us/sample - loss: 0.0801 - acc: 0.9766

# 时期 1/5
# 60000/60000 [==============================] - 6秒 104微秒/抽样 - 损失: 0.2170 - 准确率: 0.9354
# 时期 2/5
# 60000/60000 [==============================] - 6秒 104微秒/抽样 - 损失: 0.0959 - 准确率: 0.9701
# 时期 3/5
# 60000/60000 [==============================] - 7秒 121微秒/抽样 - 损失: 0.0668 - 准确率: 0.9790
# 时期 4/5
# 60000/60000 [==============================] - 7秒 121微秒/抽样 - 损失: 0.0527 - 准确率: 0.9830
# 时期 5/5
# 60000/60000 [==============================] - 7秒 110微秒/抽样 - 损失: 0.0424 - 准确率: 0.9860
# 10000/10000 [==============================] - 0秒 40微秒/抽样 - 损失: 0.0718 - 准确率: 0.9798

你可能感兴趣的:(TensorFlow版本的HelloWord)