【Google 机器学习笔记】十、TensorFlow 2.1 实战(二)基本图像分类(MNIST)

【Google 机器学习笔记】

十、TensorFlow 2.1 实战(二)基本图像分类

  为节省时间,降低学习成本,本节实战的图片分类对象 tf.keras 中内置的 MNIST 数据集。


  首先回顾机器学习编程的几个基本步骤
    1. 数据
      ① 获取数据
      ② 处理数据
      ③ 拆分数据
      ④ 检查数据
    2. 模型
      ① 构建模型
      ② 检查模型
      ③ 训练模型
      ④ 进行预测
  现根据以上步骤进行实战训练


数据
获取数据
# 首先先导入 TF
import tensorflow as tf
# TF 的高级 API —— Keras
from tensorflow import keras
from tensorflow.keras import layers
# 用到的第三方包
import numpy as np
import matplotlib.pyplot as plt
# TensorFlow 中为方便机器学习,内置了很多数据集在 tf.keras.datasets 中,
# 而且已经将数据处理并拆分好了。具体使用方法可前往官网查看 API 文档
# 获取数据
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()
处理数据

  处理数据前,我们先认识一下这份数据集。先看看 train_images 的情况,

train_images.shape
(60000, 28, 28)

  这里说明 train_images 中包含 60000 张图片,每张图片都是 28*28 像素。
  再看看 train_labels 的情况,

train_labels.shape
(60000,)

  共 60000 个标签,一一对应 train_images 中的图片。
  你也可以通过 train_lables 看看 train_labels 中的内容,结果应该是:

array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)

  对于 test_images、test_labels,你也可以通过类似的方法了解这份数据。

test_images.shape
(10000, 28, 28)
test_labels.shape
(10000,)

  OK,我们已经基本知道这个数据集的结构了,但是对于 train_images 中的图片的情况还不是很了解,这时我们可以使用 Numpy 中的 plt 来查看这些图片。

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.xlabel(train_labels[0])
plt.show()

【Google 机器学习笔记】十、TensorFlow 2.1 实战(二)基本图像分类(MNIST)_第1张图片
  这是 train_images 中的第一张图片,数字 5 (第一眼我没看出来这是 5 …),颜色范围 0~255,是一个离散值。
  之前讲到,如果数据是一个离散值,一般将其缩放至 [-1,1],这样可以加快模型训练速度。这里我们采用线性缩放的方式将其缩放至 [0,1]。

train_images = train_images / 255.0
test_images = test_images / 255.0

  至此数据处理完毕

拆分数据

  此步骤在 “获取数据” 已完成,略过。

检查数据

  为了确保数据的正确性,我们需要在将它放进模型训练之前检查这份数据的正确性。

plt.figure(figsize=(5,5))
# 检查数据集的前 25 份数据
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(train_labels[i])
plt.show()

【Google 机器学习笔记】十、TensorFlow 2.1 实战(二)基本图像分类(MNIST)_第2张图片
  大部分图片还是看的出来它的数字的(除了那个5是真的飘…),接下来我们构建模型。


模型
构建模型

  由于数据是一张张图像,可以构建卷积神经网络训练模型,但用于 MNIST 大材小用了。因此在这里构建机器学习的常规模型。

model = keras.Sequential([
    # 使用 Flatten,将输入数据压平,格式化输入数据
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(128, activation='relu'),
    # 使用 Softmax 返回概率
    layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
检查模型
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________
训练模型
model.fit(train_images, train_labels, epochs=10)
Train on 60000 samples
Epoch 1/10
60000/60000 [==============================] - 10s 160us/sample - loss: 1.5669 - accuracy: 0.9123
Epoch 2/10
60000/60000 [==============================] - 9s 155us/sample - loss: 1.5152 - accuracy: 0.9509
Epoch 3/10
60000/60000 [==============================] - 9s 143us/sample - loss: 1.5021 - accuracy: 0.9625
Epoch 4/10
60000/60000 [==============================] - 9s 142us/sample - loss: 1.4940 - accuracy: 0.9701
Epoch 5/10
60000/60000 [==============================] - 9s 149us/sample - loss: 1.4888 - accuracy: 0.9747
Epoch 6/10
60000/60000 [==============================] - 8s 139us/sample - loss: 1.4848 - accuracy: 0.9784
Epoch 7/10
60000/60000 [==============================] - 9s 145us/sample - loss: 1.4821 - accuracy: 0.9806
Epoch 8/10
60000/60000 [==============================] - 8s 135us/sample - loss: 1.4802 - accuracy: 0.9826
Epoch 9/10
60000/60000 [==============================] - 9s 153us/sample - loss: 1.4782 - accuracy: 0.9845
Epoch 10/10
60000/60000 [==============================] - 9s 146us/sample - loss: 1.4769 - accuracy: 0.9857

  可以看到准确率达到98.57%,说明这个模型对训练集预测效果很好,接下来看看在测试集上的效果:
  TF 给我们内置了一个用于模型评估的方法 tf.keras.model.evaluate(),可以用来测试评估模型。

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
print('Test accuracy:', test_acc)
10000/10000 - 1s - loss: 1.4858 - accuracy: 0.9764
Test accuracy: 0.9764

  准确率 97.64%,有一点点过拟合,但总体还是很不错的。

进行预测

  由于已经没有验证集来给我们进行预测了,所以此处使用测试集来进行预测。

predictions = model.predict(test_images)
print('prediction:\n', predictions[0])
print('actually:\n', test_labels[0])
prediction:
 [1.5629017e-16 6.4852802e-27 1.2689112e-15 8.6887691e-11 2.4175891e-22
 2.0408761e-22 2.1866591e-31 1.0000000e+00 6.5104445e-18 1.2703980e-15]
actually:
 7

  正好下标为 6 的概率值等于 1 (实际上应该接近 1,这里应该是有精度损失)。
  也可以用如下方法可视化概率:

def plot_image(i, predictions_array, true_label, img):
  # 显示图片和柱状图的背景
  predictions_array, true_label, img = predictions_array, true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(predicted_label,
                                100*np.max(predictions_array),
                                true_label),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  # 显示柱状图的柱子
  predictions_array, true_label = predictions_array, true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')
num_rows = 20
num_cols = 5
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

【Google 机器学习笔记】十、TensorFlow 2.1 实战(二)基本图像分类(MNIST)_第3张图片
  如果预测正确,标签与柱状图都是蓝色;如果预测错误,标签变红,柱状图预测结果变红,真实结果用蓝色标示出来。



结语

  历时很久的【Google 机器学习笔记】终于完结了,想想从 1 月 12 日开始发布笔记到现在 2 月 28 日,用了将近一个多月的时间,这个学习速度实在令人惭愧。但不管如何,还是得感谢这一段时间没有停下脚步的自己,没有因为时间匆忙而放弃兴趣爱好的学习,也没有因为艰难险阻或着懒惰而停滞不前。
  写这篇笔记的初衷是为了解决草稿纸短缺的问题,但后来发现,电脑上写笔记其实比在纸上方便一些,这一点在复制粘贴上体现地淋漓尽致,当然,也有很多不方便的地方,比如排版问题,有时候需要处理很久,写公式的时候也比较不方便。总之各有春秋吧。
  另外,从这个专栏的访问量来看,访问量不高,侧面也突出了一些问题,我会在近期的博客中修补这些方面,尽最大努力提高自己的水平和扯皮手段。
  说回到机器学习,其实我只学了一点皮毛,还有神经网路、深度学习等很多知识点没有深入下去,继续学习还需要走很久的路,但是,当初学习机器学习主要是为了能看懂机器学习有关的文献和代码。因此,为了主要的学习任务,在机器学习的这条道路上只能先暂时走到这里,若日后有足够精力,再继续拾起这块“石头”吧。

END


上一篇:【Google 机器学习笔记】十、TensorFlow 2.1 实战(一)简单的线性回归预测

你可能感兴趣的:(Google,机器学习笔记,机器学习,tensorflow)