7.1. 什麼是神經網路

神經網路(neural network)是一種行為由範例學習而來,而非由人工撰寫程式碼的演算法。同一套網路架構,若餵入一百萬張人臉影像,便會學會偵測人臉;同一套架構,若餵入一百萬張手部影像,便會學會偵測手部;同一套架構,若餵入涵蓋多種物件類別的已標記資料集,便會一次學會偵測所有這些類別。不同目標之間只有權重會改變,而這些權重是由一個離線的訓練流程產生的,該流程會比對網路的預測與已標記範例,並持續調整權重直到兩者相符。

7.1.1. 運作機制

神經網路是一疊層(layer)的堆疊。每一層都會將前一層的輸出乘上一個權重(weights)矩陣,加上一個偏置向量,再對結果套用一個非線性函式。某一層的輸出便是下一層的輸入。一張擷取到的影像從堆疊頂端進入,向下流經數十到數百層,最後從底部以一個張量的形式出現,其元素描述了影像中的內容。

每一層的權重究竟什麼,取決於網路是用什麼資料訓練出來的。視覺網路中的某個早期層權重矩陣可能會對一小段水平邊緣產生反應;稍深一點的層可能會對轉角產生反應;更深的層可能會對圓形的眼睛形狀產生反應;最深的層則可能會對整張臉的排列產生反應。這些都不是人工撰寫出來的。訓練流程在數百萬個已標記範例上反覆迭代,沿著損失函式將權重往下推,於是邊緣、再到轉角、再到眼睛、再到臉部的這套層級結構便從資料中自然浮現。

由九個帶標籤的方塊垂直堆疊而成,代表一個小型分類網路的各層。最上方的方塊標示為「Input image」,張量形狀為 (192, 192, 3)。一個箭頭向下指向一個「Conv + ReLU」方塊,形狀為 (96, 96, 32)。另一個箭頭指向第二個「Conv + ReLU」方塊,形狀為 (48, 48, 64)。接著是一個「MaxPool」方塊,形狀為 (24, 24, 64)。再來是兩個「Conv + ReLU」方塊,形狀分別為 (12, 12, 128) 與 (6, 6, 256)。一個「Global average pool」方塊形狀為 (256,)。一個「Fully connected」方塊形狀為 (1000,)。最下方的方塊標示為「Class scores」,形狀為 (1000,)。張量流向由上而下。

一個以層堆疊形式呈現的小型分類網路。輸入張量以擷取影像的形狀從頂端進入,向下流經各層,每一層都會轉換張量的維度。底部的輸出張量每個類別對應一個元素。偵測與關鍵點網路採用相同的層堆疊形式;只有輸出張量的解讀方式不同。

網路的架構(architecture)——也就是各層如何排列、由哪些運算連接它們——決定了網路能夠做什麼。權重則是網路已經學到的東西。相機在這當中所負責的,是載入訓練所產生的權重檔,並執行訓練器所執行的同一套運算,只不過套用在擷取到的影格上,而非訓練資料集上。

7.1.2. 輸入什麼、輸出什麼

網路的兩端都是張量(tensors)——多維的數字陣列,正是 numpy 章節剛剛介紹過的那種物件。視覺網路的輸入張量是把擷取到的影像重新排列成網路所預期的版面:通常是一個 (B, H, W, C) 的 4 元組形狀,其中 B 是批次維度(在相機上一律為 1,因為一次只處理一個影格),HW 是網路預期的像素高度與寬度,而 C 是通道數(RGB 網路為 3,灰階則為 1)。

輸出張量取決於網路的用途:

  • 分類(classification)網路會產生一個一維的信心分數張量,每個類別對應一個分數。分數最大的索引即為預測出的類別。大多數相機隨附的、由 MobileNet 衍生而來的人物偵測器就屬於這種形式:兩個分數,一個對應「person」,一個對應「not person」。

  • 偵測(detection)網路會產生一個二維張量,其元素描述了一串邊界框以及類別機率。YOLOv8 就屬於這種形式:一個 (84, N) 張量,其中 84 列裡有 4 列是邊界框迴歸值,另外 80 列是各類別的機率,並在 N 個錨點位置上重複。

  • 關鍵點(keypoint)網路會產生一個張量,其元素是具名地標的像素位置。MediaPipe 臉部地標模型就屬於這種形式:每張偵測到的臉有 468 個關鍵點。

  • 分割(segmentation)網路會產生一個二維張量,其元素是每個像素的類別標籤——維度與輸入相同,每個位置上都有一個類別索引。

  • 迴歸(regression)網路會產生單一數字或一個簡短的數字向量——例如深度估計值、角度或溫度。

每一種形式在相機上都有自己的後處理器(post-processor),負責將原始的輸出張量轉換回應用程式其餘部分所使用的結果形式——邊界框、關鍵點清單、類別標籤、數值估計。後處理器是應用端的程式碼,了解網路的輸出版面;網路本身只是產生張量的那套運算。

7.1.3. 為什麼這在相機上行得通

有兩項運算上的技巧讓這在微控制器等級的零件上變得可行。第一項是量化(quantization)。訓練是在 32 位元浮點運算中進行的;而對大多數網路而言,推論可以在 8 位元整數運算中執行,幾乎沒有任何精準度損失。8 位元權重所佔的儲存空間只有原本的四分之一,執行速度也比 32 位元浮點數快上數倍。相機所隨附的每一個模型都已經在離線時量化完成。

第二項是硬體加速(hardware acceleration)。微控制器的 CPU 一次只能逐條指令地慢慢處理的那套運算,神經網路加速器可以一次執行數百個運算。較新的相機(AE3 與 N6)搭載了一個專用的神經處理單元NPU)——一個位於 SoC 上的張量加速器——它能把一個原本在 CPU 上要跑一秒鐘的模型,變成只需數十毫秒就能執行完畢。推論引擎章節將說明相機在這當中所負責的部分長什麼樣子。

7.1.4. 本章涵蓋的內容

訓練不是相機的工作。一個訓練好的模型會以 .tflite 檔的形式抵達相機;相機載入它、讓每個擷取到的影格通過它,並把產生出來的張量解碼成應用程式可以據以採取行動的結果。接下來的所有內容都是關於這每一個步驟:

  • 載入並檢視一個模型;

  • 模型檔案所在的快閃記憶體分割區;

  • 一次推論呼叫的四個階段;

  • 實際執行運算的引擎;

  • 以及把輸出張量轉換回邊界框、關鍵點或類別清單的後處理器。

影像章節中的偵測器,每一個都針對某個特定目標而設計。本章其餘部分所涵蓋的偵測器,則是改由資料訓練而來,並以同一套引擎執行指令碼所載入的任何模型。隨之而來的工作流程改變——以針對特定目標的權重檔取代針對特定目標的演算法——正是接下來要詳細闡述的重點。