1. 程式人生 > >TensorFlow 學習(六)時尚(衣服、鞋、包等) Fashion MNIST識別

TensorFlow 學習(六)時尚(衣服、鞋、包等) Fashion MNIST識別

使用 jupyter notebook 筆記,匯入需要的包

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

import numpy as np

import numpy as np
import matplotlib.pyplot as plt
import gzip
import os
import matplotlib

使用Fashion MNIST資料集,其中包含10個類別的70000個灰度影象。如圖所示,這些圖片顯示的是每件衣服的低解析度(28×28畫素)

Fashion MNIST的目標是作為經典MNIST資料的替換——通常被用作計算機視覺機器學習程式的“Hello, World”。MNIST資料集包含手寫數字(0,1,2等)的影象,格式與我們將在這裡使用的衣服相同

使用了時尚MNIST的多樣性,因為它是一個比常規MNIST稍微更具挑戰性的問題。這兩個資料集都相對較小,用於驗證演算法是否按預期工作。它們是測試和除錯程式碼的好起點

我們將使用6萬張圖片來訓練網路和1萬張圖片來評估網路對圖片的分類有多精確。

準備好資料集

因為資料集需要科學上網才能下載,所以可以先下載下來地址:Fashion MNIST資料集
主要下載下面四個壓縮檔案和中文字型,  'train-labels-idx1-ubyte.gz',  'train-images-idx3-ubyte.gz',  't10k-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz' 和中文字型 'SimHei-windows.ttf '。

# 下載中文支援字型。後面畫圖需要
zhfont = matplotlib.font_manager.FontProperties(fname='./fashion_mnist_data/SimHei-windows.ttf')


# 解析解壓得到四個訓練的資料
def read_data():
    files = [
      'train-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz',
      't10k-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz'
    ]
    # 我在當前的目錄下建立資料夾,裡面放入上面的四個壓縮檔案
    current = './fashion_mnist_data'
    paths = []
    for i in range(len(files)):
         paths.append('./fashion_mnist_data/'+ files[i])
    
    with gzip.open(paths[0], 'rb') as lbpath:
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[1], 'rb') as imgpath:
        x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)

    with gzip.open(paths[2], 'rb') as lbpath:
        y_test = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[3], 'rb') as imgpath:
        x_test = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)
        
    return (x_train, y_train), (x_test, y_test)

讀取資料

# 分別得到訓練資料集和測試資料集
(train_images, train_labels), (test_images, test_labels) = read_data()

這些影象是28x28的NumPy陣列,畫素值在0到255之間。標籤是一個整數陣列,範圍從0到9。這些與形象所代表的服裝類別相對應                        

標籤 所代表的意思
0 短袖圓領T恤
1 褲子
2 套衫
3 連衣裙
4 外套
5 涼鞋
6 襯衫
7 運動鞋
8
9 短靴

每個影象對映到一個標籤。由於類名不包含在資料集中,因此將它們儲存在這裡,方便後面繪製圖像時使用

class_names = ['短袖圓領T恤', '褲子', '套衫', '連衣裙', '外套',
              '涼鞋', '襯衫', '運動鞋','包', '短靴']

在訓練之前,必須對資料進行預處理。如果檢視訓練集中的第一張影象,可以看到畫素值在0到255之間,可以嘗試畫出來

# 建立一個新圖形
plt.figure()

# 顯示一張圖片在二維的資料上 train_images[0] 第一張圖
plt.imshow(train_images[0])

# 在圖中新增顏色條
plt.colorbar()

# 是否顯示網格線條,True: 顯示,False: 不顯示
plt.grid(False)

在jupyter notebook 執行得出結果鞋子:

但是在給神經網路模型提供資料之前,我們需要將這些值縮放到0到1的範圍。為此,將影象元件的資料型別從整數轉換為浮點數,併除以255。這才是預處理影象的函式

# 訓練影象縮放255,在0 和 1 的範圍
train_images = train_images / 255.0

# 測試影象縮放
test_images = test_images / 255.0

顯示來自訓練集的前25個影象,並在每個影象下面顯示類名。驗證資料的格式是否正確,我們準備構建和訓練網路。

# 儲存畫布的圖形,寬度為 10 , 長度為10
plt.figure(figsize=(10,10))

# 顯示訓練集的 25 張影象
for i in range(25):
    # 建立分佈 5 * 5 個圖形
    plt.subplot(5, 5, i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    # 顯示照片,以cm 為單位。
    plt.imshow(train_images[i], cmap=plt.cm.binary)

    # 此處就引用到上面的中文字型,顯示指定中文,對應下方的圖片意思,以證明是否正確
    plt.xlabel(class_names[train_labels[i]], fontproperties = zhfont)

執行結果:

建立模型

當畫素處理後,神經網路由兩個 tf.keras.layer 序列組成。緻密層。它們是緊密相連的,或者說完全相連的神經層。第一個緻密層有128個節點(或神經元)。第二個(也是最後一個)層是10個節點的 softmax 層——它返回一個10個概率分數的陣列,其和為1。每個節點包含一個分數,表示當前影象屬於這10個類之一的概率。

# 建立模型
def build_model():
    # 線性疊加
    model = tf.keras.models.Sequential()
    # 改變平緩輸入 
    model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
    # 第一層緊密連線128神經元
    model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))
    # 第二層分10 個類別
    model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))
    return model

編譯模型

# 編譯模型
model = build_model()
model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
  • optimizer:   模型如何更新基於它看到的資料和它的損失函式。tf.train.AdamOptimizer(), 使用Adam梯度下降優化方法,降低損失。
  • loss : 用來測量模型在訓練過程中的精確度。最小化這個函式來“引導”模型向正確的方向。‘sparse_categorical_crossentropy’ : 稀疏多分類交叉熵損失。
  • metrics: 用於監視培訓和測試步驟。使用了 'accuracy',精確分類的影象的比例。

API介面描述

compile(self,

        optimizer,

        loss=None,

        metrics=None,
 
        loss_weights=None,

        sample_weight_mode=None,

        weighted_metrics=None,

        target_tensors=None,

        distribute=None,

        **kwargs):

作用:配置引數,主要用於訓練的模型

引數描述:

  • optimizer: optimizer的名稱字串,或者optimizer的類。
  • loss: 損失目標函式的名稱字串,或者目標函式
  • metrics: 模型評估的指標列表,在評估訓練和測試模型。一般 metrics = ['accuracy']
  • loss_weights: 標量的列表或字典,係數(Python 浮點數)衡量不同模型的損失權重。
  • sample_weight_mode: 樣品權重模式
  • weighted_metrics: 訓練和測試模型期間,將根據樣本權重或類權重進行評估和加權的指標列表
  • target_tensors: keras為模型的目標值建立佔位符,在訓練期間,fed目標資料。
  • distribute: 我們想要用來分發模型訓練(DistributionStrategy例項類)
  • **kwargs: 這些引數轉遞給會話 'tf.Session.run'

訓練模型

# 訓練模型
model.fit(train_images, train_labels, epochs=5)

6000份訓練集分 5 批次,依次訓練。影象目標值:train_images,  標籤:train_labels

執行結果:下面損失和精度指標顯示。該模型對訓練資料的準確率約為0.89 (89%)

該API介面引數描述

引數

fit (self,

    x=None,

    y=None,

    batch_size=None,

    epochs=1,

    verbose=1,

    callbacks=None,

    validation_split=0.,

    validation_data=None,

    shuffle=True,

    class_weight=None,

    sample_weight=None,

    initial_epoch=0,

    steps_per_epoch=None,

    validation_steps=None,

    max_queue_size=10,

    workers=1,

    use_multiprocessing=False,

    **kwargs):

作用:指定數量次數迭代(資料集依次迭代)訓練模型
主要介紹下面部分引數:

  • x: 輸入資料,特徵
  • y: 目標資料,標籤
  • batch_size: 每次梯度更新的樣本數量大小
  • epochs: 訓練模型的次數
  • verbose: 冗長的模式, 0,1,或者 2; 0表示無,1表示進度顯示, 2表示每次一行
  • callbacks: 'keras.callbacks.Callback'的類,訓練模型時的回撥函式列表

 

評估模型

比較測試集與訓練集這兩個的情況,是否會出現過擬合或者欠擬合的情況

# 評估模型(主要是測試資料集)
test_loss, test_acc = model.evaluate(test_images, test_labels)

print('測試損失:%f 測試準確率: %f' % (test_loss, test_acc))

執行結果:

可以從上面訓練模型中的訓練資料集的損失為 0.2967, 準確率約為 89%。

這裡的測試資料集的損失為 0.3536, 準確率約為 87%

可以看出,測試資料集的準確率略低於訓練資料集的準確率。

它們之間的差距就是過度擬合的一個例子。過度擬合是指機器學習模型在新資料上的表現不如在訓練資料上的表現。

API介面描述:

evaluate( self,

         x=None,

         y=None,

         batch_size=None,

         verbose=1,

         sample_weight=None,

         steps=None,

         max_queue_size=10,

         workers=1,

         use_multiprocessing=False):

作用:返回模型下的測試資料集的損失值和準確率,評估模型
主要介紹下面部分引數:

  • x: 測試特徵資料集
  • y: 測試標籤資料集
  • batch_size:  每次梯度更新的樣本數量大小
  • verbose: 冗長的模式, 0,1,或者 2; 0表示無,1表示進度顯示, 2表示每次一行
  • sample_weight: 測試樣本權重的numpy陣列
  • steps: 步長總數

 

使用模型做預測

predictions = model.predict(test_images)
# 提取20個數據集,進行預測判斷是否正確
for i in range(25):
    pre = class_names[np.argmax(predictions[i])]
    tar = class_names[test_labels[i]]
    print("預測:%s   實際:%s" % (pre, tar))

執行結果:可以看出25個數據中,有三個預測出現錯誤了。較少的出錯概率

也可以畫圖出來

# 儲存畫布的圖形,寬度為 10 , 長度為10
plt.figure(figsize=(10,10))

# 預測 25 張影象是否準確,不準確為紅色。準確為藍色
for i in range(25):
    # 建立分佈 5 * 5 個圖形
    plt.subplot(5, 5, i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    # 顯示照片,以cm 為單位。
    plt.imshow(test_images[i], cmap=plt.cm.binary)
    
    # 預測的圖片是否正確,黑色底表示預測正確,紅色底表示預測失敗
    predicted_label = np.argmax(predictions[i])
    true_label = test_labels[i]
    if predicted_label == true_label:
        color = 'black'
    else:
        color = 'red'
    plt.xlabel("{} ({})".format(class_names[predicted_label],
                                class_names[true_label]),
                                color=color,
                                fontproperties = zhfont)
plt.show()

執行結果:黑色底表示預測正確,紅色底表示預測失敗