以下是最近看 "精通機器學習 (第二版)" 這本書第 14 章 CNN 的筆記 :
- 為何人腦對於語音與圖片能如此輕鬆辨識? 答案是人類的知覺是在意識範圍之外發生的, 發生的地點是在大腦專門處理視覺, 聽覺或其他知覺的模組裡面. 當知覺意識到達我們的意識時, 它就已經具備高層次的特徵了. 你無法解釋你是如何認出那是一隻可愛的小狗.
- 捲積神經網路 CNN 源自對人類大腦皮質的研究. CNN 不止能應用在視覺感知, 也能用在語音辨識與自然語言處理.
- 1981 年諾貝爾生醫獎得主 David Hobel 與 Torsten Wiesel 在 1958 年開始對貓與猴子視覺皮層進行一系列實驗研究, 發現視覺皮層的許多神經元都有一個小型的局部感受區, 它們只會對視野內的有限區域做出反應. 這些神經元的感受區可能會重疊, 將它們合在一起就形成了整個視野. 此外他們還發現有些神經元只對水平線的圖像有反應, 有些只對不同方向的線條有反應. 而且有些神經元的感受區較大, 會對複雜的圖像做出反應. 他們從這些觀察得出一個看法 : 高層的神經元會使用相鄰的低層神經元的輸出. 這些研究成果催生了 1980 年代出現的新認知機 (neocognitron), 而這就是後來捲積神經網路 CNN 的濫觴.
- Yann LeCun 等人在 1998 年發表的 LeNet-5 論文介紹了捲積層與池化層這兩個新元件, 這是機器學習很重要的里程碑.
- 捲積 (convolution) 是將一個函數轉移到另一個函數的逐點乘法積分運算, 它與傅立葉變換以及拉普拉斯變換有很深的關係. CNN 的捲積層使用的其實只是跟捲積很類似交叉相關 (cross-correlation) 運算.
- 為何不使用全連接的深度神經網路 (即 MLP 多層感知機) 來做圖像識別呢? 這對於 MNIST 之類的小圖片沒有問題, 但是對於大圖像卻因為需要大量參數而束手無策. 例如 100x100 的圖片有 1 萬個像素, 若第一層有 1000 個神經元, 則光是第一層就有 1000 萬個連接了. CNN 使用部分連接的階層以及權重共享 (即使用相同的捲積核) 來解決此問題.
- CNN 最重要的部分就是捲積層, 第一個捲積層的神經元不會連接輸入圖像的每一個像素, 只會連接它們的感受區範圍內的像素. 同樣地, 第二個捲積層的各神經元也只連接第一層的一個小矩形內的神經元. 這種結構使網路的第一個隱藏層專注於低階的小特徵, 而在下一個隱藏層將它們組合成較大的高階特徵, 此與現實世界中人腦辨識圖像的階層式結構非常類似, 這就是為何 CNN 用於圖像辨識如此成功的原因.
- 多層感知器是由一長串神經元組成的階層, 但輸入圖像必須展平為 1D 才能傳入神經網路, 這樣就喪失了許多空間特徵. 但在 CNN 中, 各階層都是用 2D 表示的, 因此使神經元更容易與 2D 的輸入配對.
- 神經元的權重可以用大小與感受區一樣的小圖示來表示, 稱為過濾器 (filter) 或捲積核 (convolution kernel). 讓所有神經元都使用同一種過濾器會輸出一張特徵圖 (feature map), 此特徵圖會凸顯圖像中最能觸發過濾器的區域. 過濾器不需要人工去定義 (但數量必須由我們決定), 在訓練過程中捲積層會自動學習對眼前的任務最實用的過濾器, 而捲積層上面的階層則會學習如何將它們組成更複雜的圖樣.
- 只有第一個捲積層適合使用像 5x5 這麼大的捲積核 (步幅可用 2), 這樣可以降低圖像的空間維度, 但又不會損失太多資訊. 其他捲積層不要使用太大的捲積核, 使用 5x5 捲積核還不如用兩層 3x3 疊起來.
- 每張特徵圖中的所有神經元都使用同一組參數 (即同一組權重與偏權值), 這樣可大幅降低模型得參數數量. 但不同張特徵圖使用不同組的參數, 捲積層會對其輸入套用多個可訓練的過濾器, 以便在輸入中到處偵測不同的特徵. CNN 與 DNN 的不同在於, 當 CNN 在一個地方學會辨識一個圖樣後就可在任何其他位置辨識它; 而 DNN 只能在它學會辨識的那個固定位置進行辨識.
- 輸入圖像是由多個子階層 (sublayer) 組成, 每個顏色通道 (color channel) 為一個子階層, 一般使用 R, G, B 三原色各一個通道, 而灰階圖像則只有一個通道. 拍攝額外光頻譜的圖片 (例如衛星照片) 可能含有更多顏色通道, 例如紅外線等.
- 在 TensorFlow 中每張輸入圖像的形狀 (shape) 都使用 [高, 寬, 通道] 的 3D 張量來表示, 而小批次訓練資料則使用 [小批次大小, 高, 寬, 通道] 的 4D 張量來表示. 捲積層的權重張量形狀為 4D 的 [fh, fw, fn', fn], 偏差項則是 1D 的 [fn].
- CNN 有一個問題是捲積層需要使用大量的 RAM (尤其是訓練期間), 因為在倒傳遞時需要使用順向傳遞時算出來的所有中間值, 雖然比起全連接層的恐怖數量來說, CNN 需要進行的浮點運算已經少了非常多, 但其計算量仍然要占用大量的記憶體, 特別是在訓練期間, 在順向傳遞過程中算出來的東西都必須保留下來給逆向傳遞時使用. 如果因為 RAM 不足導致訓練時系統崩潰, 可以嘗試下列方法 :
(1). 將小批次的大小降低
(2). 透過增大步幅 (stride) 來降低維數
(3). 移除部分階層
(4). 將 32-bit 浮點數改成 16-bit 浮點數
(5). 將 CNN 分散到多台電腦執行 - CNN 第二個元素池化層 (pooling layer) 主要的目的就是抽取輸入圖像的子樣本, 藉由縮小圖像來減低計算負擔與記憶體耗用量, 同時參數數量也降低了, 從而減少過擬 (over fitting) 的風險. 池化層的每個神經元都接到上一層有限數量的神經元輸出, 其結構與運作與捲積層類似, 同樣有一個小型的矩形感受區, 你必須決定它的大小, 步幅, 與填補方式. 但是池化層的神經元沒有權重 (池化核只是一個無狀態的滑動窗口), 它的工作只是使用 max(挑最大值) 或 mean(計算平均值) 等聚合函數來彙集感受區內的輸入. 採用 max 池化還有一個好處, 對於小幅度的平移對於輸出結果具有不變性 (invariance), 亦即池化核上下左右移動幾個像素對輸出結果影響不大, 但 max 池化的缺點是破壞性很強, 因為對於 2D 輸入而言它的輸出是輸入大小面積的 1/4.
- max 池化的表現比 mean 池化通常要好, 因為 max 池化只保留了最強的特徵, 而捨棄所有沒有意義的特徵, 讓下一層有更明確的信號可以處理, 而且其平移不變性勝過 mean 池化, 所需的計算也比較少.
- 過濾器的數量離 CNN 輸出層越近就要越多, 因為低階特徵的數量通常很少, 但將它們組成高階特徵的方法有很多種. 我們通常會在經過每一個池化層後將過濾器的數量加倍, 因為池化層會將各個空間維度除以 2, 故可放心將下一層的特徵圖數量加倍, 不必擔心參數數量, 記憶體使用量, 與計算負擔會爆炸.
- CNN 的後端是全連接網路, 由兩個隱藏稠密層與一個稠密輸出層組成, 要注意的是須將其輸入壓平, 因為稠密網路接收的是各個實例的 1D 特徵陣列. 另外為了降低過擬還要加入兩個 50% 卸除率的 Dropout 層.
- 除了典型的 CNN 架構外, 歷年來 ILSVRC ImageNet 挑戰賽參賽贏家也提出了非常多的 CNN 變體結構, 將前五位錯誤率 (top-five error rate) 在六年內從 26% 降到 2.3%. 其中 2015 年冠軍得主 Kaiming He 等人提出的 Residual Network (ResNet) 較為特殊, 它使用具有跳接 (skip connection) 或短路連接 (shortcut connection) 結構的 152 層的 CNN 網路, 透過跳接連結, 傳給某階層的信號同時也會被加到高幾層的輸出, 即使有好幾層還沒開始學習, 信號仍能輕鬆跨過整個網路開始向前邁進, 使得訓練速度獲得大幅提升. 由於跳接是把輸入 x 同時也加到網路的輸出, 使得訓練神經網路的目標從模擬目標函數 h(x) 變成模擬目標函數與輸入的差 h(x)-x, 故這種學習被稱為殘差學習 (residual learning). ILSVRC 2017 挑戰賽冠軍架構 SENet 擴展了 GoggLeNet 的 inception 網路與 ResNet 網路, 加入一個稱為 SE block 的小型神經網路, 取得前五位錯誤率 2.25% 的驚人成就.
- YOLO (You Only Look Once) 是 Josph Redmon 於 2015 年提出的一種非常快速與準確之物體偵測神經網路結構, 目前已升級至第三版 YOLOv3, 其速度快到可以即時處理視訊, 參見 Redmon 的展示網頁. YOLO 會為每個格子輸出 5 個外框, 每個外框都有一個 objectiveness 分數與 20 個類別機率, 所以每個格子共有 45 個數字 : 5 個外框, 每個有 4 個座標, 加上 5 個 objectiveness 分數與 20 個類別機率.
- 除了常用的 2D 捲積層 keras.layers.Conv2D 外, TensorFlow 還提供了其他的捲積層 :
(1). keras.layers.Conv1D : 給時間序列或文字輸入用的 1D 捲積層
(2). keras.layers.Conv3D : 給 3D 圖像輸入 (例如 PET 掃描圖片) 用的捲積層
(3). dilation_rate : 任何捲積層超參數 dilation_rate 設為 2 以上者
(4). tf.nn.depthwise_conv2d : 建立深向 (depthwise) 捲積層用
"精通機器學習 (第二版)" 這本書的程式碼範例可在 GitHub 下載 :
下面是閱讀 "TensorFlow 自然語言處理" 第 5 章 "CNN 捲積神經網路|句子分類" 的摘要筆記 :
- CNN 神經網路主要由卷積層, 池化層, 全連接層構成, CNN 與單純的全連結神經網路不同, 它的卷積層具有更少的參數, 故不用擔心記憶體溢出問題, 它在圖片分類, 物體偵測, 語音辨識, 與句子分類等方面已達到最先進的表現.
- 卷積層會用一個權重矩陣 (又稱為過濾器 filter) 滑過整個輸入矩陣, 透過卷積運算生成輸出結果. 卷積層與下一個舉積層之間可能會穿插池化層用來降低輸入的維度, 同時可讓 CNN 具有影像平移不變性, 且能迫使 CNN 在訊息比較少的情況下學習.
- CNN 網路後端通常會串接全連接層, 且全連接層的權重占了 CNN 參數的很大部分, 這是因為卷積層的參數很少的關係. 有用全連接層的 CNN 比沒有使用全連接層的模型表現好很多, 原因是卷積層尺寸較小, 學習到的多半是局部的特徵, 而全連結層則可提供關於這些局部特徵如何連結在一起的整體概念.
- CNN 的結構設計在學習階段可保留輸入的空間訊息, 對二維資料來說在卷積與池化層仍保有二維特徵, 只有在後面串接全連接層時才會因為展平而被破壞.
- 卷積層若採用較大的步幅就可以降低輸入的維度, 其效果與池化層類似, 所以有時也會用較大的步幅來進行卷積操作以取代 CNN 中的池化層以降低計算複雜度. 但較大的步幅會產生強烈的降維效果, 為了解決此問題, 會採用填充的方法, 將零填充到輸入的邊界, 這樣輸出的大小就會與輸入一樣.
- 池化操作之所以被導入 CNN 主要是要用來降低中間輸出的大小 (降維), 並且使 CNN 具有平移不便特性. 池化的作法比不使用填充的卷積所造成的降維效果還要受歡迎, 因為我們可以決定在何處加入池化層來降維, 而不是被迫看著出現降維. 在未使用填充情況下的被迫降維會使 CNN 模型可擁有的層數受到極大限制.
- 卷積層會學習圖片中的空間特徵, 較前面的卷積層學會較低層級的特徵, 例如圖片中不同方向的連線; 而比較後面的卷積層則會學習較高層級的特徵, 例如圖片中的形狀 (三角形, 圓形等), 或物體中教大的區塊 (狗臉, 尾巴, 車頭等). 中間的池化層會讓這些學習到的特徵具有平移不變性, 就算特徵出現的位置偏移, CNN 還是可以識別出該特徵. 最後全連結層會把 CNN 學習到的高階特徵組合起來, 以生成具有整體性的表達方式.
沒有留言 :
張貼留言