# Lesson 8. 卷積神經網絡 (CNN) 課程筆記

**URL:** https://vip.studycamp.tw/t/lesson-8-%E5%8D%B7%E7%A9%8D%E7%A5%9E%E7%B6%93%E7%B6%B2%E7%B5%A1-cnn-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7965
**Category:** fast.ai
**Tags:** ai-輔助撰寫筆記
**Created:** [2025年三月28日 02:48 UTC](https://vip.studycamp.tw/t/lesson-8-%E5%8D%B7%E7%A9%8D%E7%A5%9E%E7%B6%93%E7%B6%B2%E7%B5%A1-cnn-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7965 "2025-03-28T02:48:32Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![sky](https://vip.studycamp.tw/user_avatar/vip.studycamp.tw/sky/32/8098_2.png) [@sky](https://vip.studycamp.tw/u/sky)
#### Post date: [2025年三月28日 02:48 UTC](https://vip.studycamp.tw/t/lesson-8-%E5%8D%B7%E7%A9%8D%E7%A5%9E%E7%B6%93%E7%B6%B2%E7%B5%A1-cnn-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7965/1 "2025-03-28T02:48:32Z")

</div>

這是以 Claude 輔助撰寫筆記的第二次嘗試（上次是 隨機森林 Random Forest & 表格模型，兩個版本都失敗，結果是 Claude 充份發揮了它的想像力），表現好一些。之後會在時間許可時，逐步修改加入我想放的資料。

我心目中理想的 Claude 輔助撰寫筆記是這樣： **Claude 扮演大部分打字和整理的工作，我則接手修飾** （因為 GAI 大多 ~~廢話~~ 贅詞很多） **和撰寫真正的感想** ，而不是我之前形容的，心得分享變成了課程英翻中。

例如 mini-batch 的真實意義：

 ![13_convolutions mini-batch](https://vip.studycamp.tw/uploads/default/original/2X/e/e891c7b2afd052b916ce2f8298786791c912cb7b.jpeg)

* * *

這堂課的前面，Jeremy 老師還在補充前一個主題，後面則在抒發心得（因為是第一階段的最後一堂課），所以真正講述的內容不多。

主要就講解 CNN 的概念，並以一個試算表補充。所以筆記會以書上的資料（第13章）為主。

**CNN 的概念，推薦李弘毅老師的講解，淺顯易懂** ，連結（包含 [**影片**](https://www.youtube.com/watch?v=OP5HcXJg2Aw)和 [**議義**](https://speech.ee.ntu.edu.tw/~hylee/ml/ml2021-course-data/cnn_v4.pdf)）放在參考資料中。

> **Convolution（卷積） = con-（一起） + volv-（滾動、捲曲）+ -tion（名詞化）**
> 
> 字面意思： **「一起滾動或捲起來的過程」** ，即「盤繞、纏繞」的概念。
> 
> 一種數學運算，合併兩個函數、產生一個新的函數，表達其相互影響。

 ![att_00069](https://vip.studycamp.tw/uploads/default/original/2X/4/413ba77235e171bc5a6d1f6252e4cc9f9b5c52a0.png)

## ▌卷積的基本概念

### 特徵工程簡介

在機器學習領域， **特徵工程** （Feature engineering）是指將原始數據轉換為更適合模型的形式。對於圖像來說，特徵可以是視覺上的獨特屬性，如邊緣、紋理或形狀等。

> **術語解釋** ：特徵工程指創建輸入數據的新轉換，使其更易於建模。
> 
> **將原始資料轉換成更能表達與任務相關模式的形式** 。
> 
> 例如本範例中的直線、橫線、斜線所組合而成的數字 0~9。
> 
> 或是信用卡盜刷中的日期格式。以特徵工程將時間戳轉換為以下特徵：距離上次交易間隔時間（頻率突然提高）、刷卡時間是否為正常交易時段（半夜兩三點）。

以數字識別為例：

- 數字「7」的特徵：頂部的水平邊緣和從右上到左下的對角線邊緣
- 數字「3」的特徵：不同方向的對角線和水平邊緣

如果我們能夠提取圖像中邊緣出現的位置信息，並用這些信息作為特徵，而不是原始像素值，可能會得到更好的結果。這正是 **卷積** （Convolution）所做的工作。

### 卷積基礎

卷積是一種基本的數學運算，僅需乘法和加法，就能實現圖像特徵提取。卷積需要一個 **卷積核** （kernel），也稱為濾波器，通常是一個小矩陣（如3×3）。

卷積操作示例：

1. 將卷積核應用於圖像的一個小區域（比如3×3的塊）
2. 對應元素相乘
3. 將乘積相加得到一個輸出值

 ![卷積基本操作](https://vip.studycamp.tw/uploads/default/original/2X/7/7092ac5db74d8869273ee71be709990a2bfeda2a.png)

### 邊緣檢測實例

讓我們通過程式碼實例了解卷積如何檢測邊緣：

```python
# 頂部邊緣檢測卷積核
top_edge = tensor([[-1,-1,-1],
                   [0, 0, 0],
                   [1, 1, 1]]).float()

```

這個卷積核設計用於檢測水平邊緣，特別是從暗到亮的過渡（從上到下）。當應用於有暗色上方區域和亮色下方區域的圖像時，會產生較強的正值響應。

應用於圖像時，計算過程如下：

```python
# 在圖像的小區域應用卷積核
im3_t[0:3,0:3] * top_edge
# 計算結果總和
(im3_t[0:3,0:3] * top_edge).sum()

```

卷積核的數學原理：若使用上述頂部邊緣卷積核，對於像素值為 a1~a9 的3×3區域（按左上到右下排序），卷積結果為：

```auto
結果 = -a1 - a2 - a3 + a7 + a8 + a9

```

這意味著：

- 當上方區域（a1,a2,a3）暗（值小）且下方區域（a7,a8,a9）亮（值大）時，結果為較大的正值
- 當上方區域亮且下方區域暗時，結果為較大的負值
- 當上下區域亮度相似時，結果接近零

通過這種方式，卷積核有效地檢測出從暗到亮的水平邊緣。

## ▌卷積數學原理

### 卷積映射

將卷積核應用於整個圖像需要在每個可能的位置進行計算。對於一個h×w的圖像和一個k×k的卷積核（不考慮填充），輸出將是(h-k+1)×(w-k+1)大小的特徵圖。

下面的程式碼演示了如何實現這一過程：

```python
# 定義一個應用卷積核的函數
def apply_kernel(row, col, kernel):
    return (im3_t[row-1:row+2,col-1:col+2] * kernel).sum()

# 在整個坐標網格上應用卷積核
rng = range(1,27)
top_edge3 = tensor([[apply_kernel(i,j,top_edge) for j in rng] for i in rng])

```

我們可以創建不同類型的卷積核來檢測不同特徵：

- 水平邊緣檢測器（檢測從暗到亮或從亮到暗的水平過渡）
- 垂直邊緣檢測器（例如：`left_edge = tensor([[-1,0,1],[-1,0,1],[-1,0,1]])` 檢測從左到右的暗到亮過渡）
- 對角線邊緣檢測器

通過這些不同的卷積核，我們可以提取圖像中的各種特徵，這些特徵對於識別和分類任務非常有用。

![13_convolutions 原始](https://vip.studycamp.tw/uploads/default/original/2X/4/4035b436b33aebbfb88e30617657b6cc57fe4f57.png)  
 ![13_convolutions 橫線](https://vip.studycamp.tw/uploads/default/original/2X/e/ec4b5c23ffbeb01db471bf9c7960f878fb58be4c.png)  
 ![13_convolutions 直線](https://vip.studycamp.tw/uploads/default/original/2X/a/a79e69b548a05aff6a2e7abcd5146a7ef47f0da7.png)

## ▌PyTorch中的卷積

PyTorch提供了高效的卷積實現：`F.conv2d`，其主要參數包括：

- `input`: 形狀為 `(minibatch, in_channels, iH, iW)` 的輸入張量
- `weight`: 形狀為 `(out_channels, in_channels, kH, kW)` 的濾波器

PyTorch的卷積具有幾個強大特性：

1. 可以同時對批次中的多張圖像應用卷積
2. 可以同時應用多個卷積核
3. 可以利用GPU並行處理，大幅提升速度

示例：

```python
# 創建多個邊緣檢測卷積核
edge_kernels = torch.stack([left_edge, top_edge, diag1_edge, diag2_edge])
# 調整形狀以符合PyTorch期望的輸入（增加輸入通道維度）
edge_kernels = edge_kernels.unsqueeze(1)
# 應用卷積
batch_features = F.conv2d(xb, edge_kernels)

```

在這個例子中，我們將四種不同的邊緣檢測器應用於輸入圖像，每種檢測器會產生自己的特徵圖。PyTorch的實現允許我們一次性執行所有這些操作，大大提高了效率。

## ▌步幅與填充

### 填充（Padding）

當應用卷積操作時，輸出特徵圖的大小會小於原始圖像。為了保持輸出大小與輸入相同，我們可以在圖像周圍添加額外的像素，稱為 **填充** （通常是填充零）。

 ![13_convolutions padding](https://vip.studycamp.tw/uploads/default/original/2X/f/f4062827073f2887dc122847ca779f6d5e38d081.png)

對於大小為 `ks × ks` 的卷積核（`ks` 為奇數），需要 `ks//2` 的填充才能保持輸出大小與輸入相同。例如，3×3的卷積核需要1個像素的填充，5×5的卷積核需要2個像素的填充。

### 步幅（Stride）

步幅定義了卷積核在圖像上移動的像素數。默認步幅為1，但我們也可以使用更大的步幅：

- 步幅1：每次移動1個像素，輸出特徵圖與輸入大小相近（取決於填充）
- 步幅2：每次移動2個像素，輸出特徵圖的寬高約為輸入的一半
- 更大步幅可以進一步減小輸出特徵圖的大小

 ![13_convolutions Strides](https://vip.studycamp.tw/uploads/default/original/2X/f/f8c1adbfe6bd85dc8bcfa12124ffaa3e6210a48c.png)

使用填充為1和步幅為2的情況下，h×w大小的圖像將產生大約(h+1)//2 × (w+1)//2大小的輸出。一般公式為：`(n + 2*pad - ks)//stride + 1`，其中`n`是輸入維度，`pad`是填充大小，`ks`是卷積核大小，`stride`是步幅。

這些參數的選擇對網絡架構設計至關重要：

- 步幅1的卷積通常用於保持特徵圖大小不變，同時處理特徵
- 步幅2的卷積用於下採樣，減小特徵圖大小並增加感受野

## ▌卷積方程理解

卷積可以從多個視角理解：

1. **直觀理解** ：將卷積核逐一應用於圖像的每個位置，計算加權和

2. **矩陣運算視角** ：卷積可以表示為特殊的矩陣乘法，其中：

 ![att_00035](https://vip.studycamp.tw/uploads/default/original/2X/b/b25e31ec26a5e616bf14d7773242a51e92fd4a97.png)

 ![att_00036](https://vip.studycamp.tw/uploads/default/original/2X/3/38400dca70dfe2efe9207be4527e126224ef2aca.png)

 ![att_00038](https://vip.studycamp.tw/uploads/default/original/2X/2/276be36c905b77f55fb279c588d0bc26123cecd5.png)

這種權重共享和稀疏連接的特性使卷積網絡參數更少，但仍能表示複雜的視覺特徵。卷積層的這些約束實際上是一種有效的歸納偏置（inductive bias），特別適合處理具有空間結構的數據，如圖像。

## ▌構建第一個CNN

我們不必手動設計卷積核，而是可以通過 **隨機梯度下降** （SGD）學習它們的值。使用卷積層替代或配合常規線性層，我們創建了 **卷積神經網絡** （CNN）。

### 基本CNN架構

從簡單的線性網絡開始：

```python
simple_net = nn.Sequential(
    nn.Linear(28*28,30),
    nn.ReLU(),
    nn.Linear(30,1)
)

```

轉換為卷積架構：

```python
# 定義卷積模塊
def conv(ni, nf, ks=3, act=True):
    res = nn.Conv2d(ni, nf, stride=2, kernel_size=ks, padding=ks//2)
    if act: res = nn.Sequential(res, nn.ReLU())
    return res

# 構建簡單CNN
simple_cnn = sequential(
    conv(1 ,4), #14x14
    conv(4 ,8), #7x7
    conv(8 ,16), #4x4
    conv(16,32), #2x2
    conv(32,2, act=False), #1x1
    Flatten(),
)

```

與線性層不同，卷積層不需要指定輸入大小，因為卷積自動應用於每個像素。步幅為2的卷積會將特徵圖大小減半，通常我們會同時增加通道數以保持網絡容量。

這裡的關鍵設計原則是：

- 使用步幅2的卷積減小特徵圖大小
- 隨著特徵圖尺寸減小，增加通道數（特徵數）
- 最後使用`Flatten()`將最終的特徵圖轉換為向量，用於分類

### 網絡訓練

```python
learn = Learner(dls, simple_cnn, loss_func=F.cross_entropy, metrics=accuracy)
learn.fit_one_cycle(2, 0.01)

```

透過訓練，網絡會自動學習有用的特徵卷積核，這些特徵對於識別任務是最有用的。這比手動設計特徵提取器更有效，因為網絡可以根據數據自適應地學習最相關的特徵。

## ▌感受野

**感受野** 是指影響一個層中特定位置輸出的輸入區域。深層網絡的感受野會隨著層數增加而擴大，特別是使用步幅大於1的卷積時。

例如，對於兩個連續的步幅為2的卷積層：

- 第一層的每個輸出受到原始圖像中3×3區域的影響
- 第二層的每個輸出受到原始圖像中7×7區域的影響

 ![att_00068](https://vip.studycamp.tw/uploads/default/original/2X/7/76418a61f2f378ba9c4ad2b50cc6c858958a5e7b.png)

 ![att_00069](https://vip.studycamp.tw/uploads/default/original/2X/4/413ba77235e171bc5a6d1f6252e4cc9f9b5c52a0.png)

這可以通過跟踪計算路徑來理解：第二層的一個單元依賴於第一層的3×3區域，而第一層的每個單元又依賴於原始圖像的3×3區域，綜合起來就是7×7的感受野。

隨著網絡深度增加，感受野擴大，網絡可以學習更複雜的特徵。這就是為什麼深層網絡中通常會增加通道數的原因之一 — 處理更大感受野的複雜特徵需要更多的參數。

## ▌彩色圖像處理

彩色圖像是一個三維張量，第一個維度包含顏色通道（紅、綠、藍）：

```python
im = image2tensor(Image.open(image_bear()))
im.shape # torch.Size([3, 1000, 846])

```

對於彩色圖像的卷積，卷積核需要匹配輸入通道數：

- 對於RGB圖像，第一層的卷積核形狀為[輸出通道數, 3, 核高, 核寬]
- 每個輸入通道都有自己的濾波器

 ![RGB卷積](https://vip.studycamp.tw/uploads/default/original/2X/2/2632adedd97f32b7df9bcf578f1fb7f02bb1833c.png)

卷積運算會在所有通道上進行，然後將結果加總，產生一個數值，即特徵圖中單個位置的激活值。數學上表示為：

```auto
輸出(i,j) = 偏置 + 
             ∑(輸入通道c) 
               ∑(核高h) 
                 ∑(核寬w) 
                   卷積核(c,h,w) * 輸入(c, i+h, j+w)

```

在PyTorch中，卷積權重的維度順序是：[輸出通道, 輸入通道, 核高, 核寬]。例如，對於第一層處理RGB圖像的16個卷積核，權重形狀為[16, 3, 3, 3]。

處理彩色圖像時不需要特別的機制，只需確保第一層有正確數量的輸入通道（RGB為3）。

## ▌提升訓練穩定性

在訓練深度網絡時，我們常常面臨不穩定性問題。以下是一些改進策略：

### 1. 增加批次大小

較大的批次提供更準確的梯度，但會減少每個周期的更新次數：

```python
dls = get_dls(512) # 增加批次大小至512

```

優點：

- 梯度更穩定，減少隨機性
- 可以使用更高的學習率

缺點：

- 每個周期的更新次數減少
- 可能會在某些情況下泛化性能略差
- 需要更多的GPU記憶體

### 2. 1cycle訓練

Leslie Smith提出的1cycle訓練方法包括：

- 從低學習率開始，逐漸增加到高學習率（預熱階段）
- 然後再逐漸降低回低學習率（退火階段）

這種方法允許我們使用更高的最大學習率，帶來兩個主要好處：

- 更快的訓練速度（超收斂現象）
- 更好的泛化性能（避免陷入尖銳的局部最小值）

在fastai中使用1cycle訓練：

```python
learn.fit_one_cycle(epochs, lr)

```

動量（momentum）也會循環變化，與學習率方向相反：高學習率時使用較低動量，退火階段使用較高動量。這種策略進一步增強了訓練的穩定性。

原理上，高學習率有助於跳出尖銳的局部最小值，而最終的低學習率階段則幫助模型精確收斂到一個良好的最小值。

## ▌批次正規化

**批次正規化** （Batch Normalization）是解決訓練不穩定和激活接近零問題的有效方法。Sergey Ioffe和Christian Szegedy在2015年提出，可以：

- 加速深度網絡訓練
- 使用更高的學習率
- 對初始化不那麼敏感
- 改善模型泛化能力

### 工作原理

批次正規化通過計算層激活的平均值和標準差，並用這些統計量來正規化激活。對於輸入 x，批次正規化的基本公式為：

```auto
y = γ * (x - μ)/σ + β

```

其中：

- μ 是批次的平均值
- σ 是批次的標準差
- γ 和 β 是可學習的縮放和偏移參數

> α (Alpha)  
> β (Beta)  
> γ (Gamma)  
> δ (Delta)
> 
> Batch Normalization 對每一層的 **輸入** 進行標準化，使其近似均值為 0、標準差為 1，然後通過可學習的參數 γ 和 β 進行縮放和偏移，減少內部協變量偏移(internal covariate shift)，提高學習速度與穩定性。
> 
> 主要差異：
> 
> 1. **位置** ：批次正規化通常應用於層的 **輸入** ，而不是輸出（雖然從數學上講，它可以被視為前一層的輸出處理）
> 2. **完整過程** ：批次正規化不僅進行標準化，還有後續的縮放和偏移步驟：
> 
> - 首先標準化：(x - μ)/σ
> - 然後縮放和偏移：γ \* (標準化結果) + β
> - 其中 γ 和 β 是可學習的參數
> 
> 1. **目的** ：批次正規化的主要目的是減少「內部協變量偏移」，即深度網絡中每層輸入分佈的變化
> 
> 這個過程使網絡能夠使用更高的學習率、不那麼依賴精確的初始化，並且在訓練過程中保持更穩定的激活分佈。  
> 這些可學習參數使網絡能夠恢復原始的表達能力，同時保持正規化的優勢。

```python
# 在卷積函數中加入批次正規化
def conv(ni, nf, ks=3, act=True):
    layers = [nn.Conv2d(ni, nf, stride=2, kernel_size=ks, padding=ks//2)]
    if act: layers.append(nn.ReLU())
    layers.append(nn.BatchNorm2d(nf))
    return nn.Sequential(*layers)

```

批次正規化的行為在訓練和驗證階段不同：

- 訓練時：使用當前批次的統計量來正規化
- 驗證時：使用訓練期間計算的統計量的運行平均值

### 泛化效果

含有批次正規化層的模型往往泛化性能更好，主要原因是：

1. 批次正規化為訓練過程增加了隨機性（每個批次的統計量略有不同）
2. 模型必須學會對這些變化保持穩健
3. 這種隨機性有類似正則化的效果，有助於減少過擬合

批次正規化顯著改善了訓練穩定性，使我們能夠使用更高的學習率並獲得更好的準確率。在大多數現代卷積網絡中，批次正規化（或其變體）都是標準組件。

## ▌總結與實踐建議

1. **卷積基礎**

2. **CNN架構設計**

3. **訓練技巧**

4. **實用指南**

通過這些技術和理解，我們可以構建高效、穩定的卷積神經網絡，用於各種計算機視覺任務。CNN已成為現代計算機視覺的基石，從簡單的分類任務到複雜的目標檢測和語義分割，都離不開卷積的基本原理。

* * *

## ▌參考資料

### 推薦影片

> 李弘毅老師的 CNN 課程。2021年錄製，至今依然是我看過最棒的影片。
> 
> 老師影片中使用的 **[簡報檔](https://speech.ee.ntu.edu.tw/~hylee/ml/ml2021-course-data/cnn_v4.pdf)**。

[![](https://img.youtube.com/vi/OP5HcXJg2Aw/maxresdefault.jpg "【機器學習2021】卷積神經網路 (Convolutional Neural Networks, CNN)") ](https://www.youtube.com/watch?v=OP5HcXJg2Aw)

> 3Blue1Brown 關於 Neural networks 的系列影片。3Blue1Brown 是我看過視覺化教學最棒的 YouTuber，這系列也不例外。他的強項是以影像表現數學概念，在微積分和線性代數的表現特別突出。這系列影片我的收穫依然很多，但可能程度未到，還是有些地方不太理解。
> 
> 系列影片有 8 部，並非同時期錄製。CNN主題我推薦至少看前兩部，有空的話再加兩部，會了解的更透徹。

**權重（weight）告訴我們下一層的神經元所關注的圖樣。**

**偏置（bias）則告訴我們加權總和要超過什麼程度才是有意義的。**

 ![Stochastic Gradient Descent（隨機梯度下降） 16.36.55](https://vip.studycamp.tw/uploads/default/original/2X/d/d79248761788f2cba1fc7e6445b5ffd52f3f3779.png)

 ![13_convolutions 特徵](https://vip.studycamp.tw/uploads/default/original/2X/e/e9a7ba5d83106803533806f874965d8739657dce.jpeg)

![](https://img.youtube.com/vi/aircAruvnKk/maxresdefault.jpg)https://www.youtube.com/embed/aircAruvnKk?feature=oembed&wmode=opaque&list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi

### 術語對照表

| 英文 | 繁體中文 |
| --- | --- |
| Convolution | 卷積 |
| Kernel/Filter | 卷積核/濾波器 |
| Feature | 特徵 |
| Feature engineering | 特徵工程 |
| Edge detector | 邊緣檢測器 |
| Padding | 填充 |
| Stride | 步幅 |
| Channel | 通道 |
| Activation map/Feature map | 激活圖/特徵圖 |
| Receptive field | 感受野 |
| Batch normalization | 批次正規化 |
| 1cycle training | 1cycle訓練 |
| Learning rate | 學習率 |
| Momentum | 動量 |
| Weight sharing | 權重共享 |
| Inductive bias | 歸納偏置 |
| Spatial structure | 空間結構 |

### 常見問題解答

1. **問：為什麼使用卷積而不是全連接層處理圖像？**  
答：卷積利用權重共享和局部連接，大大減少參數數量，更適合處理圖像的空間結構。對於28×28的圖像，全連接層需要784個輸入參數，而3×3卷積核只需要9個參數。

2. **問：如何選擇卷積核大小？**  
答：通常使用3×3或5×5，較小的核速度更快，較大的核可以捕獲更大範圍的特徵。第一層常用較大的卷積核（5×5），以捕獲更多原始信息。

3. **問：為什麼在步幅2的卷積後增加通道數？**  
答：步幅2將特徵圖面積減少4倍，增加通道數可以維持網絡容量和表達能力。此外，更深的層需要表示更複雜的特徵，因此需要更多的通道。

4. **問：批次正規化和層正規化有什麼區別？**  
答：批次正規化在批次維度上正規化，層正規化在特徵維度上正規化。批次正規化在小批次時效果可能下降，而層正規化不受批次大小影響。

5. **問：如何避免訓練過程中的不穩定性？**  
答：使用批次正規化、適當的學習率調度（如1cycle）、監控層激活分布，避免權重初始化不當。確保網絡中沒有大量接近零的激活，這會導致梯度問題。

### 習題解答

書中所有的 40 個問題，一樣請 Claude 代為解惑： **[Lesson 8. 卷積神經網絡（CNN）習題解答](https://vip.studycamp.tw/t/lesson-8-%E5%8D%B7%E7%A9%8D%E7%A5%9E%E7%B6%93%E7%B6%B2%E7%B5%A1%EF%BC%88cnn%EF%BC%89%E7%BF%92%E9%A1%8C%E8%A7%A3%E7%AD%94/7961)** 。
