採用 Keras 和 TPU 的捲積類神經網路

1. 總覽

在本實驗室中,您將瞭解如何將卷積層組合成可辨識花朵的神經網路模型。此時,您將自行從頭開始建構模型,並運用 TPU 的強大功能在幾秒內訓練模型,並調整其設計。

本研究室包含有關卷積類神經網路的必要理論說明,也是開發人員學習深度學習的好起點。

本實驗室是「在 TPU 上使用 Keras」系列的第三部分。您可以按照下列順序或獨立執行這些操作。

ca8cc21f6838eccc.png

課程內容

  • 使用 Keras 序列模型建構卷積圖片分類器。
  • 如何在 TPU 上訓練 Keras 模型
  • 如要使用最佳卷積層微調模型。

意見回饋

如果您在這個程式碼研究室中發現不尋常的狀況,請告訴我們。您可以透過 GitHub 問題提供意見 [feedback link]。

2. Google Colaboratory 快速入門

這個實驗室使用 Google Collaboratory,您不需要進行任何設定。Colaboratory 是用於教育用途的線上筆記平台。提供免費 CPU、GPU 和 TPU 訓練。

688858c21e3beff2.png

您可以開啟這個範例筆記本,並執行幾個儲存格,熟悉 Colaboratory 的使用方式。

c3df49e90e5a654f.png Welcome to Colab.ipynb

選取 TPU 後端

8832c6208c99687d.png

在 Colab 選單中,依序選取「執行階段」>「變更執行階段類型」,然後選取 TPU。在本程式碼研究室中,您將使用強大的 TPU (Tensor Processing Unit),以便進行硬體加速訓練。系統會在第一次執行時自動連線至執行階段,您也可以使用右上角的「連線」按鈕。

執行筆記本

76d05caa8b4db6da.png

按一下儲存格並使用 Shift + Enter 鍵,即可逐一執行儲存格。您也可以依序點選「Runtime」>「Run all」執行整個筆記本

Table of contents

429f106990037ec4.png

所有筆記本都有目錄。您可以使用左側的黑色箭頭開啟報表。

隱藏的儲存格

edc3dba45d26f12a.png

部分儲存格只會顯示標題。這是 Colab 專屬的筆記本功能。您可以按兩下這些程式碼,以查看裡面的程式碼,但不太有趣。通常是支援或視覺化功能。您仍需要執行這些儲存格,才能定義其中的函式。

驗證

cdd4b41413100543.png

Colab 有機會存取您的私人 Google Cloud Storage 值區,但您必須使用已授權的帳戶進行驗證。上述程式碼片段會觸發驗證程序。

3. [INFO] 什麼是 Tensor Processing Unit (TPU)?

摘要

f88cf6facfc70166.png

在 Keras 中使用 TPU 訓練模型的程式碼 (如果沒有 TPU,則會改用 GPU 或 CPU):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

今天我們將使用 TPU 以互動式速度 (每個訓練執行作業只需幾分鐘) 建構及最佳化花朵分類器。

688858c21e3beff2.png

選用 TPU 的理由

現代的 GPU 是以可程式化的「核心」為基礎,這個架構非常靈活有彈性,可處理 3D 轉譯、深度學習、實體模擬等各種工作。另一方面,TPU 會將傳統向量處理器與專用矩陣乘積單元配對,並在需要大量矩陣乘積的任務 (例如神經網路) 中表現出色。

8eb3e718b8e2ed08.png

插圖:密集的類神經網路層以矩陣乘法運算為矩陣,會一次透過類神經網路處理一批八張圖像,請透過一行 x 資料欄的乘法驗證,確認這確實是圖片中所有像素值的加權總和。卷積層也可以以矩陣相乘表示,但會比較複雜 (這裡有說明,請參閱第 1 節)。

硬體

MXU 和 VPU

TPU v2 核心由矩陣乘法單元 (MXU) 和向量處理單元 (VPU) 組成,前者負責執行矩陣乘法,後者則負責執行所有其他任務,例如啟用和軟性最大值等。VPU 會處理 float32 和 int32 運算。另一方面,MXU 會以混合精度 16-32 位元浮點格式運作。

7d68944718f76b18.png

混合精度浮點和 bfloat16

MXU 會使用 bfloat16 輸入和 float32 輸出來計算矩陣相乘運算。中階累計作業是以 float32 精度計算。

19c5fc432840c714.png

類神經網路訓練通常足以應付低浮點精確度所產生的雜訊。在某些情況下,雜訊甚至有助於最佳化工具收斂。16 位元浮點精確度通常用於加快運算速度,但 float16 和 float32 格式範圍差異極大。將精確度從 float32 降為 float16,通常會產生過流和反向溢位。現有解決方案存在,但通常需要額外工作才能讓 float16 運作。

這就是 Google 在 TPU 中導入 bfloat16 格式的原因。bfloat16 是截斷的 float32,與 float32 完全相同的指數位元和範圍都一樣。這超出了 TPU 計算矩陣乘法的精度和 bfloat16 輸入內容,但使用 float32 輸出,通常都不需要變更程式碼,就能享有低精確度的效能提升。

Systolic array

MXU 會使用所謂的「脈動陣列」架構,在硬體中實作矩陣乘法,在這種架構中,資料元素會流經一組硬體運算單元。(在醫學中,「收縮期」是指心臟收縮和血液流動,這裡指的是資料流量)。

矩陣乘法的基本元素是介於一個矩陣的線條與另一個矩陣的欄之間的點積 (請參閱本節上方的插圖)。對於矩陣相乘 Y=X*W,結果的一個元素會是:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

在 GPU 上,其中一個會將這個內積分裝成 GPU 的「核心」,然後在盡可能平行執行大量「核心」上執行該積點,嘗試同時計算產生的矩陣的每個值。如果產生的矩陣為 128x128,就需要 128x128=16K 個「核心」,但這通常是不可能的。最大的 GPU 約有 4,000 個核心。另一方面,TPU 在 MXU 中運算單元使用的硬體最低只有 bfloat16 x bfloat16 => float32 乘數加總,除此之外不用其他。這些都太小,TPU 可以在 128x128 MXU 中實作 16K 的容器,並一次處理這個矩陣乘法。

f1b283fc45966717.gif

插圖:MXU 脈動陣列。運算元素為乘積。其中一個矩陣的值會載入至陣列 (紅點)。其他矩陣的值流經陣列 (灰點)。垂直線會向上傳遞值。水平線會傳播部分和。請使用者自行驗證,當資料流經陣列時,您會從右側取得矩陣相乘的結果。

此外,雖然內積是以 MXU 計算中度積,但在相鄰的運算單元之間,中繼總和其實只會流動。不需要儲存及擷取至/自記憶體,甚至是登錄檔案。最終結果是 TPU 脈動陣列架構在計算矩陣乘法時,具有顯著密度和效能優勢;此外,在計算矩陣乘法時,TPU 的速度優勢也不可忽略。

Cloud TPU

在 Google Cloud Platform 上要求一個「Cloud TPU v2」時,您會取得一個含有 PCI 連接 TPU 板的虛擬機器 (VM)。TPU 板有四個雙核心 TPU 晶片。每個 TPU 核心都有一個 VPU (向量處理器) 和 128x128 MXU (MatriX 乘數)。接著,這個「Cloud TPU」通常會透過網路連線至提出要求的 VM。完整的圖片如下所示:

dfce5522ed644ece.png

插圖:VM 搭配網路連結的「Cloud TPU」加速器。「Cloud TPU」本身是由 VM 和 PCI 連接的 TPU 主機板組成,後者含有四個雙核心 TPU 晶片。

TPU Pod

在 Google 資料中心中,TPU 會連線至高效能運算 (HPC) 互連網路,讓 TPU 看起來像是一部超大型加速器。Google 會呼叫 Pod,且最多可包含 512 個 TPU v2 核心或 2048 個 TPU v3 核心。

2ec1e0d341e7fc34.jpeg

插圖:TPU v3 Pod。透過 HPC 互連網路連結的 TPU 板和機架。

在訓練期間,系統會使用全減算演算法在 TPU 核心之間交換梯度 (這裡有全減算的詳細說明)。受訓練的模型可利用大型批量進行訓練,以充分運用硬體。

d97b9cc5d40fdb1d.gif

圖解:在 Google TPU 的 2-D 環面網狀 HPC 網路使用 all-red 演算法,在訓練期間同步處理梯度。

軟體

大型批量訓練

TPU 的理想批次大小為每個 TPU 核心 128 個資料項目,但硬體已能顯示每個 TPU 核心 8 個資料項目有良好的使用率。請記住,一個 Cloud TPU 有 8 個核心。

在本程式碼研究室中,我們將使用 Keras API。在 Keras 中,您指定的批次是整個 TPU 的全域批次大小。批次將自動分割為 8 個,並在 TPU 的 8 核心上執行。

da534407825f01e3.png

如需其他效能提示,請參閱 TPU 效能指南。如果是非常大型的批量,某些模型可能需要特別留意,詳情請參閱 LARSOptimizer

後製:XLA

TensorFlow 程式會定義運算圖形。TPU 不會直接執行 Python 程式碼,而是執行 TensorFlow 程式所定義的運算圖表。實際上,稱為 XLA (加速線性代數編譯器) 的編譯器會將運算節點的 TensorFlow 圖形轉換為 TPU 機器碼。這個編譯器也會對程式碼和記憶體配置執行許多進階最佳化。系統會在工作傳送至 TPU 時自動編譯。您不需要在建構鏈結中明確加入 XLA。

edce61112cd57972.png

插圖:如要在 TPU 上執行,Tensorflow 程式定義的運算圖形會先轉譯為 XLA (加速線性代數編譯器) 表示法,再由 XLA 編譯成 TPU 機器碼。

在 Keras 中使用 TPU

自 TensorFlow 2.1 起,Keras API 就支援 TPU。Keras 支援 TPU 和 TPU Pod。以下是適用於 TPU、GPU 和 CPU 的範例:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

在這個程式碼片段中:

  • TPUClusterResolver().connect() 會在網路上尋找 TPU。在大多數 Google Cloud 系統 (AI 平台工作、Colaboratory、Kubeflow、透過「ctpu up」公用程式建立的深度學習 VM) 上,無需參數即可運作。這些系統會透過 TPU_NAME 環境變數得知 TPU 的位置。如果您手動建立 TPU,請在使用 TPU 的 VM 上設定 TPU_NAME 環境變數,或是以明確的參數呼叫 TPUClusterResolverTPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy 是實作分佈的部分,以及「all-reduce」梯度同步演算法的部分。
  • 系統是透過範圍套用策略。模型必須在策略 scope() 內定義。
  • tpu_model.fit 函式預期輸入用於 TPU 訓練的 tf.data.Dataset 物件。

常見的 TPU 移植工作

  • 在 TensorFlow 模型中載入資料的方法很多,但如果是 TPU,則必須使用 tf.data.Dataset API。
  • TPU 速度非常快,在 TPU 上執行時,擷取資料通常會成為瓶頸。TPU 效能指南中提供的工具可用來偵測資料瓶頸和其他效能提示。
  • 系統會將 int8 或 int16 號碼視為 int32。TPU 不提供小於 32 位元的整數硬體運作。
  • 不支援部分 Tensorflow 作業。請參閱這份清單。好消息是,這項限制只適用於訓練程式碼,也就是透過模型的正向和反向傳遞。您仍可在資料輸入管道中使用所有 TensorFlow 作業,因為 TensorFlow 將在 CPU 上執行。
  • TPU 不支援 tf.py_func

4. [INFO] 類神經網路分類器 101

概述

如果您已熟悉下一段文字中所有以 粗體顯示的詞彙,可以直接進行下一個練習。如果您剛開始學習深度學習,歡迎繼續閱讀。

如果是以多層圖層建構的模型,Keras 便提供 Sequential API。舉例來說,使用三個稠密層的圖片分類器,可在 Keras 中編寫如下:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

密集類神經網路

這是將圖片分類最簡單的類神經網路。它由分層排列的「神經元」組成。第一層會處理輸入資料,並將輸出內容提供給其他層。之所以稱為「密集」,是因為每個神經元都會連結至前一層的所有神經元。

c21bae6dade487bc.png

您可以將圖片全部的 RGB 值壓平成長向量,並將其做為輸入內容,提供給此類網路使用。這不是圖片辨識的最佳技術,但我們稍後會加以改進。

神經元、啟用、RELU

「神經元」會計算所有輸入值的加權總和,並加入稱為「偏差」的值,然後透過稱為「活化函數」的函式提供結果。一開始不知道權重和偏誤。模型會以隨機方式初始化,並透過大量的已知資料訓練類神經網路,藉此「學習」。

644f4213a4ee70e5.png

最常見的活化函式是 RELU,代表「線性整流函數」。如上圖所示,這是非常簡單的函式。

啟用 Softmax

我們將花朵分類為 5 個類別 (玫瑰、鬱金香、蒲公英、雛菊、向日葵),因此上方的網路以 5 個神經元層結束。而中間層中的神經元是透過傳統版 RELU 活化函式啟用。但在上一層中,我們想要計算 0 到 1 之間的數字,代表這朵花成為玫瑰、鬱金香等的可能性。我們會使用名為「softmax」的啟用函式。

在向量上套用軟性最大值,方法是取每個元素的指數,然後將向量標準化,通常使用 L1 範數 (絕對值的總和),讓值加總為 1,並可解讀為機率。

ef0d98c0952c262d.png d51252f75894479e.gif

交叉熵損失

神經網路已根據輸入圖片產生預測結果,我們需要評估這些結果的準確度,也就是網路的預測結果與正確答案之間的距離,通常稱為「標籤」。請注意,我們已為資料集中的所有圖片加上正確的標籤。

任何距離都適用,但對於分類問題而言,所謂的「交叉熵距離」最有效。我們會稱此錯誤或「損失」函式:

7bdf8753d20617fb.png

梯度下降法

「訓練」神經網路其實是指使用訓練圖片和標籤調整權重和偏誤,以便盡量減少交叉熵損失函式。運作方式如下:

交叉熵是指權重、偏誤、訓練圖片像素及其已知類別的功能。

如果我們計算交叉熵相對於所有權重和偏誤的偏微分,就會取得「梯度」,這是針對特定圖片、標籤和權重和偏誤的現值計算而得。請注意,我們可能有數百萬個權重和偏差,因此計算梯度聽起來很麻煩。幸好,Tensorflow 幫我們辦到。漸層的數學特性是指向「上方」。由於我們要前往十字區的低點,所以方向是相反的。我們會更新部分漸層的權重和偏誤。接著,我們會在訓練迴圈中使用下一批訓練圖片和標籤,重複執行相同的動作。希望這會收斂到交叉熵最小的位置,但沒有任何保證這個最小值是唯一的。

gradient descent2.png

小批次和動量

您可以只針對單一示例圖片計算漸層,並立即更新權重和偏差,但如果針對一批 (例如 128 張) 圖片執行此操作,所得的漸層將更能代表不同示例圖片的限制,因此可能會更快收斂至解決方案。迷你批次的大小是可調整的參數,

這項技巧有時也稱為「隨機梯度下降」,還有另一個更顯著的優勢:使用批次處理也意味著使用較大的矩陣,而這類技術通常更容易對 GPU 和 TPU 進行最佳化。

然而,收斂法還是有點混亂,即使漸層向量全為零,甚至會停止。這代表我們已經找到最低限度了?不一定。漸層元件可以是最小值或最大值。如果某個漸層向量有數百萬個元素,但全都是零,則每個零對應最小,且都不對應到最大點的機率極小。而且在許多維度的空間中很常見,我們不想停下來。

52e824fe4716c4a0.png

插圖:馬鞍縫。漸層為 0,但並非在所有方向的最小值。(圖片來源:Wikimedia:由 Nicoguaro 創作,CC BY 3.0)

解決方法是為最佳化演算法增加成長動能,讓演算法不必停下腳步,順利滑行。

詞彙

批次迷你批次:訓練作業一律會在批次訓練資料和標籤上執行。這有助於演算法收斂。「批次」維度通常是資料張量的第一個維度。舉例來說,形狀為 [100, 192, 192, 3] 的張量包含 100 張 192x192 像素的圖片,每個像素有三個值 (RGB)。

交叉熵損失:分類器經常使用的特殊損失函式。

密集層:神經元層,其中每個神經元都會連結至前一層的所有神經元。

features (特徵):類神經網路的輸入內容有時稱為「特徵」。要準確判斷資料集的哪些部分 (或零件組合) 並提供給類神經網路以獲得準確的預測結果,就稱為「特徵工程」。

標籤:在監督式分類問題中,「類別」或正確答案的另一個名稱

學習率:在訓練迴圈的每個疊代中更新權重和偏誤的梯度比例。

logits:套用活化函式前一層神經元層的輸出內容稱為「logits」。「Logistic 函式」亦取自「sigmoid 函式」,後者是最常使用的活化函數。「Logits 前方的 Neron outputs」會縮短為「logits」。

loss:比較神經網路輸出內容與正確答案的錯誤函式

神經元:計算輸入值的加權總和、加入偏差,並透過啟用函式提供結果。

one-hot 編碼:5 個類別中的第 3 個類別會編碼為 5 個元素的向量,除了第 3 個元素為 1 之外,其他元素皆為 0。

relu:線性整流函數。神經元經常使用的活化函數。

sigmoid:另一個曾經流行的啟用函式,在特殊情況下仍很實用。

softmax:這是一種特殊的啟用函式,可作用於向量,增加最大元件與所有其他元件之間的差異,並將向量標準化,使其總和為 1,以便解讀為機率向量。用於分類器的最後一個步驟。

張量:「張量」就像矩陣,但有任意維度數量。1 維張量是一種向量。2 維張量是矩陣。接著,就能使用有 3、4、5 或更多維度的張量。

5. [新資訊] 卷積類神經網路

概述

如果您知道下個段落中的所有以粗體顯示的字詞,則可進行下一個練習。如果您剛開始使用卷積類神經網路,請繼續閱讀下文。

convolutional.gif

插圖:篩選圖片,以及兩個由 4x4x3=48 可學習權重組成的兩個連續濾鏡。

以下是簡易卷積類神經網路在 Keras 中的模樣:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

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

688858c21e3beff2.png

卷積類神經網路入門

在卷積網路層中,一個「神經元」只會針對圖片的小區域,進行正上方像素的加權總和。它會加入偏差,並透過活化函數提供總和,就像一般密集層中的神經元一樣。接著,系統會為整張圖片,以相同的權重重複執行這項作業。請記住,在稠密層中,每個神經元都有各自的權重。在這個例子中,單一「補丁」權重會在圖片的兩個方向滑動 (稱為「卷積」)。輸出內容的值與圖片中的像素數量一樣多 (但邊緣需要一些邊框間距)。本身是篩選作業,使用 4x4x3=48 權重的篩選器。

不過,48 個權重是不夠的。為了增加更多的自由度,我們以一組新的權重重複同一項作業。這會產生一組新的濾鏡輸出內容。現在我們稱之為類比的「管道」,也就是輸入圖片中的 R、G、B 管道。

Screen Shot 2016-07-29 at 16.02.37.png

透過新增維度,即可將兩組或多組權重加總為一個張量。這就是卷積層的權重張量的一般形狀。由於輸入和輸出管道的數量是參數,因此我們可以開始堆疊和連結卷積層。

d1b557707bcd1cb9.png

插圖:卷積類神經網路會將資料「立方」轉換為其他資料「立方」。

有步幅的卷積運算、最大池化

透過以 2 或 3 為步幅執行卷積運算,我們也可以在水平維度中縮小產生的資料立方體。有兩種常見方式:

  • 網格卷積:相同滑步濾鏡,但步長大於 1
  • 最大集區:套用 MAX 運算的滑動窗口 (通常在 2x2 修補程式中,每 2 像素重複一次)

2b2d4263bb8470b.gif

插圖:將運算視窗滑動 3 像素,可產生較少輸出值。步進卷積或最大值池化 (在 2x2 視窗上以步進 2 滑動至最大值) 是縮小水平維度中資料立方體的方法。

C卷積分類器

最後,我們會透過將最後一個資料立方體扁平化,並透過密集的 softmax 啟用層提供資料,附加分類頭。卷積分類器通常如下所示:

4a61aaffb6cba3d1.png

插圖:使用卷積和 Softmax 層的圖像分類器。使用 3x3 和 1x1 濾鏡。maxpool 圖層最多只能使用 2x2 個資料點的群組。分類主體是使用具有 softmax 啟用功能的密集層實作。

在 Keras 中

上述的卷積堆疊可使用 Keras 編寫,如下所示:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

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

6. 您的自訂 convnet

動手做

我們將從頭開始建構及訓練卷積類神經網路。使用 TPU 可讓我們快速進行疊代。請開啟下列筆記本,執行儲存格 (Shift-ENTER),然後按照指示操作,即可看到「已完成工作」標籤。

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

目標是超越遷移學習模型的 75% 準確度。這個模型的優點是,它已在包含數百萬張圖片的資料集上預先訓練,而我們這裡只有 3670 張圖片。你能不能至少達到這個水準?

其他資訊

有多少層?有多少層?

選擇圖層大小不只是科學而已,必須在參數過少與過多 (權重和偏誤) 之間取得平衡。如果權重太少,神經網路就無法呈現花朵形狀的複雜性。如果過多,就可能會出現「過度擬合」的情況,也就是專注於訓練圖片,而無法推廣。參數太多也會導致模型訓練速度變慢。在 Keras 中,model.summary() 函式會顯示模型的結構和參數數量:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

以下提供幾個訣竅:

  • 擁有多層是「深」類神經網路的優勢。以這個簡單的花朵辨識問題來說,5 到 10 層應該很合理。
  • 使用小型濾鏡。一般來說,3x3 濾鏡在任何地方都很實用。
  • 您也可以使用 1x1 篩選器,而且價格較低。它們並不會真正「過濾」任何內容,而是計算通道的線性組合。並交替使用。(詳情請參閱下一節的「1x1 卷積」一節)。
  • 針對這類分類問題,請經常使用最大池化層 (或步幅大於 1 的卷積) 進行降樣。您不關心花朵的位置,只在乎它是玫瑰或蒲公英,因此失去 x 和 y 資訊並不重要,篩選較小的區域會更省錢。
  • 篩選器的數量通常會與網路結尾處的類別數量相近 (原因請參閱下方的「全域平均匯集」技巧)。如果分類為數百個類別,請在連續圖層中逐步提高篩選器數量。若為含有 5 個類別的花卉資料集,只使用 5 個篩選器是不夠的。您可以在大多數圖層中使用相同的濾鏡數量,例如 32,並在接近結尾時減少。
  • 最終稠密層的成本是/昂貴。其權重可能比所有捲積層的總和還多。舉例來說,即使在最後的資料立方為 24x24x10 的資料點中,輸出的結果相當合理,100 個神經元稠密層還是會產生 24x24x10x100=576,000 權重 !!請保持謹慎,或嘗試使用全域平均集區 (請見下方)。

全球平均集區

您可以將傳入的資料「立方體」拆分為與類別數量相同的部分,然後計算平均值,並透過 softmax 活化函式將這些值輸入,而非在卷積神經網路結尾處使用密集層。這種建立分類標頭的方式不會產生權重。在 Keras 中,語法為 tf.keras.layers.GlobalAveragePooling2D().

93240029f59df7c2.png

解決方案

以下是解決方案筆記本。如果遇到問題,可以使用此功能。

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

涵蓋內容

  • 🤔 玩轉卷積層
  • 🤓? 試驗並嘗試以最大集區法、擊球數、全球平均集區攻擊...
  • 😀 在 TPU 上快速迭代實際模型

請花點時間在腦中過一遍這份檢查清單。

7. 恭喜!

您已成功建立第一個現代化卷積類神經網路,並將該網路訓練至 80% 以上的準確率。有了 TPU,您就能在幾分鐘內完成架構的疊代作業。請繼續前往下一個研究室,瞭解現代卷積架構:

TPU 實務

Cloud AI Platform 提供 TPU 和 GPU:

最後,我們非常喜歡使用者的意見。如果您在這個研究室中發現任何錯誤,或您認為需要改善,請告訴我們。您可以透過 GitHub 問題提供意見 [feedback link]。

HR.png

Martin Görner ID small.jpg
作者:Martin Görner
Twitter:@martin_gorner

tensorflow logo.jpg
www.tensorflow.org