Chapter 4 Hello_world 範例程式 - 訓練

本章節對應到 TinyML TensorFLow Lite 機器學習中文版 的第四章

Hello world 示範程式跟一般的 AI 機器學習/深度學習的應用一樣, 分成“訓練 (training)” 跟 “推論 (inference)” 兩段, 參考 AI 大神 NVidia 關於訓練與推論的文章(英文版) .

簡單而言:

訓練就是‘學習’; 推論就是‘考試’

’訓練’需要大量的電腦資源 (CPU/GPU/NPU/memory) 、資料(data) 以及長時間的訓練, 就跟我們人類學習需要大量閱讀與長期的記憶, 而考試(推論)則需要我們的馬上反應; ’推論’是基於訓練出來的模型(如同我們大腦的記憶), 來推論出新資料的可能答案。因為訓練需要大量電腦資源, 我們無法使用開發板有限的 MCU 能力來做訓練, 而是需要電腦 (PC, Mac 甚至更快速的雲端伺服器, 如 google 的 colab) 來做訓練 (本章 §4 的內容), 再將訓練出來的模型轉換成開發板可以接受的檔案格式, 傳到開發板上來做推論,也就是下一章 §5 的內容.

4.1 在 Google colab 上建立及訓練 hello_world 的模型

github 的 Train a Simple TensorFlow Lite for Microcontrollers model 會同時看到 “在 Google colab 上執行” 及 “github 原始碼” 的圖示如下, 我們點選 “在 Google colab 上執行,” 就會在 browser 上新開一個畫面, 執行 colab 上的 training 程式.

colabandgithub colabandgithub

4.2 colab 執行 training 程式前的準備工作

機器學習需要大量的運算, 尤其是浮點運算, 所以 NVidia 的 GPU 比 intel 的 CPU 更適合做機器學習的訓練工作, 可以縮短大量的訓練時間. Google 的 colab 提供了 3 種 runtime type 的選擇, 到選單 ‘Runtime’ 下的 “Change runtime type” 選擇 GPU. (如果選擇 None, 就會使用 CPU, 選擇 TPU, 會使用 Google 特殊設計的機器學習加速晶片, 截至目前為止, GPU 還是機器學習訓練速度最快的選項. 只是, 本次訓練的模型不大, 不管選擇哪一種, 時間都差異不大)

4.3 colab 執行 train hello_world model.ipynb 程式

到選單 “Runtime” 選擇 “Run all,” 整個執行過程需時 5 分鐘之內. (同學們可以試試看不同的 runtime type 所需的時間各是多少)

4.3.1 訓練過程中, 學習如何修正及改善模型, 並將模型轉換成 TFLM 接受的格式

這訓練模型 train hello worldmode.ipynb 令我佩服的是, 利用實例來說明機器學習模式設計可能的問題, 模型太小只能有線性的表現, 而且用圖形來顯示此結果, 進一步擴充模型(增加一層神經網路)後得到更佳結果, 值得讀者細細研讀本書TinyML TensorFLow Lite 機器學習中文版的第 4 章, 列於 §附錄 C 當作進一步研究的主題.

最終訓練結果會顯示在最後一行, 帶出 2 個參數,

  • g_model_len : 是型態為整數(int), 內容是模型參數的個數, 在這個模型裡面, 有 2,488 個參數
  • g_model[] : 是型態為’字元’(char)的’串列’ (list), 內容就是模型的全部參數 (parameters);
    • 每一個參數佔用一個 byte, 也就是 8 個 bits. bit(s) 跟 byte(s) 是電腦處理器及記憶體的基本單位, 其中 1 byte = 8 bits. 在電腦常用的名詞裡, byte 還是比 bit 常用, 不過, 為了避免混淆, 常用的表達方式是用 ‘B’ 來表示 byte, 用 ‘b’ 來表示 bit. 例如現今電腦的操作系統已經進化到 64 位元(bits), 意思是 CPU 一次就可以處理 64 位元的資料, 而記憶體比較常用 128GB (bytes) 方式表達.
    • 如第一個的內容 0x1c, 0x 指的是以 16 進位(相對於人類使用的 10進位) 的方式表達, 在 16 進位的表達方式, 我們用英文字元 a - f 來表達 10 - 15 的數字.
    10 進位 16 進位 0x開頭 8 進位 0o開頭
    0 0x0 0o0
    1 0x1 0o1
    2 0x2 0o2
    3 0x3 0o3
    4 0x4 0o4
    5 0x5 0o5
    6 0x6 0o6
    7 0x7 0o7
    8 0x8 0o10
    9 0x9 0o11
    10 0xa 0o12
    11 0xb 0o13
    12 0xc 0o14
    13 0xd 0o15
    14 0xe 0o16
    15 0xf 0o17
    16 0x10 0o20
    17 0x11 0o21
    18 0x12 0o22
    19 0x13 0o23
    20 0x14 0o24
    21 0x15 0o25
    22 0x16 0o26
    23 0x17 0o27
    24 0x18 0o30
    25 0x19 0o31
    26 0x1a 0o32
    27 0x1b 0o33
    28 0x1c 0o34
    29 0x1d 0o35
    30 0x1e 0o36
    31 0x1f 0o37
    32 0x20 0o40

也就是說, 這個模型會佔用開發板上面記憶體(ROM)的 2,488 位元組(bytes), g_model_len 說明這個模型的參數個數, 模型的參數內容則儲存在 g_model[].

# Print the C source file
!cat {MODEL_TFLITE_MICRO}

unsigned char g_model[] = {
  0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x14, 0x00, 0x20, 0x00,
  0x1c, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
  0x98, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00,
  ...
  0x0c, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x09
};
unsigned int g_model_len = 2488;