深度學習在影像處理領域的蓬勃發展,卷積神經網路(CNN)功不可沒。相較於傳統的全連線網路,CNN 更能有效地捕捉影像特徵,降低計算成本,並提升模型準確度。本文將從 CNN 的基礎元件開始,逐步探討其架構演進,並以 ResNet 為例,剖析其內部結構和技術原理。首先,卷積層利用濾波器提取影像特徵,池化層則降低特徵圖解析度,減少運算量。步幅和填充等超引數的調整,能有效控制特徵提取的精細程度。ReLU 啟用函式的引入,為模型增添非線性特性,提升表達能力。Dropout 技術則能有效防止過擬合,提升模型泛化能力。
卷積神經網路(Convolutional Neural Networks)
在第2章中,我們嘗試使用全連線神經網路(fully connected neural networks)進行實驗後,可能會注意到一些問題。如果嘗試增加更多層或大幅增加引數數量,很可能會導致GPU記憶體不足。此外,訓練到一定的準確率需要一段時間,即使如此,準確率也不太理想,尤其是考慮到深度學習的熱潮。為什麼會這樣呢?
理論上,全連線網路(或稱前饋網路)可以作為通用近似器(universal approximator),但理論並未說明需要多長時間才能訓練成所需的函式近似值。然而,我們可以做得更好,特別是在影像處理方面。在本章中,我們將學習卷積神經網路(CNNs),以及它們如何成為目前最準確的影像分類別器的基礎。我們將建立一個新的根據卷積的神經網路架構,用於我們的魚與貓的應用,並展示它比前一章的方法更快訓練且更準確。
我們的第一個卷積模型
這次,我們將先介紹最終的模型架構,然後討論所有新的部分。如同第2章所述,我們建立的訓練方法是獨立於模型的,因此您可以先測試這個模型,然後再回來看解釋。
class CNNNet(nn.Module):
def __init__(self, num_classes=2):
super(CNNNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
內容解密:
nn.Sequential()的使用:允許我們建立一系列層。在forward()方法中,輸入會依次透過陣列中的每個層。可以利用這一點將模型分解為更邏輯的排列。在這個網路中,我們有兩個主要的鏈:features區塊和classifier。Conv2d層:是一個2D卷積層。如果我們有一個灰階影像,它由一個陣列組成,x畫素寬和y畫素高,每個條目都有一個值,指示它是黑色還是白色或介於兩者之間。對於彩色影像,如RGB影像,輸入通道數為3。nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding):in_channels是該層接收的輸入通道數。在網路的開始,我們接收RGB影像作為輸入,因此輸入通道數為3。out_channels是輸出通道數,對應於我們的卷積層中的濾波器數量。kernel_size描述了濾波器的高度和寬度。可以是一個單一的純量,指定一個正方形濾波器(例如,在第一個卷積層中,我們設定了一個11×11的濾波器),或者可以使用一個元組(例如(3,5)表示一個3×5的濾波器)。stride指示當我們調整濾波器到新位置時,在輸入上移動多少步。
卷積運算
卷積層會有許多這樣的濾波器,它們的值由網路的訓練填充,並且該層中的所有濾波器分享相同的偏差值。
考慮一個小的4×4影像:
10 11 9 3
2 123 4 0
45 237 23 99
20 67 22 255
以及一個2×2的濾波器:
1 0
1 0
將濾波器拖過原始輸入,從左上角開始,第一個計算是:
(10 × 1) + (11 × 0) + (2 × 1) + (123 × 0) = 12
移動濾波器,進行下一次計算,假設步長為2,則得到輸出13。重複這個過程,直到遍歷整個輸入,最終得到一個特徵圖(feature map)。
圖表說明
此圖示展示了一個3×3的核心如何在4×4的張量上運作,產生一個2×2的輸出。
為什麼使用卷積神經網路?
- 卷積神經網路特別適合處理影像資料,因為它們能夠捕捉區域性模式和特徵。
- 相較於全連線網路,CNNs引數更少,需要的計算資源也更少,從而能夠更有效地訓練和執行。
卷積神經網路(CNN)基礎元件詳解
卷積神經網路(CNN)是一種專門為處理具有網格結構的資料(如影像)而設計的神經網路架構。本篇文章將探討CNN中的幾個關鍵元件,包括卷積層(Convolutional Layers)、池化層(Pooling Layers)以及丟棄層(Dropout Layers)。
卷積層(Conv2d)
卷積層是CNN的核心元件,主要用於提取輸入資料的特徵。卷積運算透過在輸入資料上滑動一個濾波器(filter),並計算濾波器與輸入資料之間的點積,從而生成特徵對映(feature map)。
步幅(Stride)與填充(Padding)
在進行卷積運算時,有兩個重要的超引數需要考慮:步幅(stride)和填充(padding)。步幅決定了濾波器在輸入資料上移動的步長,而填充則是在輸入資料周圍新增額外的畫素,以控制輸出特徵對映的大小。
例如,當步幅設為1時,濾波器每次移動一個畫素;而當填充設為1時,輸入資料周圍會新增一圈零畫素,以確保濾波器能夠完全覆寫輸入資料的邊緣區域。
# 以PyTorch為例,建立一個卷積層
import torch.nn as nn
conv_layer = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=1)
內容解密:
in_channels=1表示輸入資料的通道數為1(例如,灰階影像)。out_channels=1表示輸出的特徵對映數量為1。kernel_size=3表示濾波器的大小為3x3。stride=1表示濾波器每次移動一個畫素。padding=1表示在輸入資料周圍新增一圈零畫素。
池化層(Pooling Layers)
池化層的主要功能是降低特徵對映的解析度,從而減少網路中的引數數量並加速計算。最常見的池化方法是最大池化(Max Pooling),它會在每個區域中選取最大值作為輸出。
最大池化(MaxPool2d)
在我們的範例模型中,使用了最大池化層,核大小為3,步幅為2。下面是一個簡單的例子:
假設有一個5x5的輸入:
1 2 1 4 1
5 6 1 2 5
5 0 0 9 6
使用核大小為3x3、步幅為2的最大池化層,會得到兩個3x3的張量:
1 2 1 1 4 1
5 6 1 1 2 5
5 0 0 0 9 6
最大池化會從每個張量中選取最大值,從而得到輸出張量 [6, 9]。
# 以PyTorch為例,建立一個最大池化層
max_pool_layer = nn.MaxPool2d(kernel_size=3, stride=2)
內容解密:
kernel_size=3表示池化核的大小為3x3。stride=2表示池化核每次移動兩個畫素。
丟棄層(Dropout Layers)
丟棄層是一種正則化技術,透過在訓練過程中隨機丟棄某些神經元,以防止過擬合。在我們的範例模型中,丟棄層被初始化為0.5,表示有50%的神經元會被隨機丟棄。
# 以PyTorch為例,建立一個丟棄層
dropout_layer = nn.Dropout(p=0.5)
內容解密:
p=0.5表示有50%的神經元會被隨機丟棄。
CNN架構的歷史發展
雖然CNN模型已經存在了幾十年,但直到GPU變得普及後,深層CNN網路才變得實用。在過去的十年中,許多重要的CNN架構被提出,例如AlexNet,它在2012年的ImageNet競賽中取得了當時最好的成績,並推廣了最大池化和丟棄層的使用。
AlexNet
AlexNet是深度學習歷史上的一個重要里程碑。它引入了最大池化和丟棄層的概念,並證明瞭深層網路可以在GPU上高效訓練。雖然它現在已經不是最先進的架構,但它對深度學習的發展起到了重要作用。
卷積神經網路(CNN)架構的演進
卷積神經網路(CNN)在影像識別領域取得了巨大的成功,不同的架構不斷被提出以提高準確率和效率。本篇文章將介紹幾種具有代表性的CNN架構,包括AlexNet、Inception/GoogLeNet、VGG、ResNet等,並探討它們的特點和創新之處。
AlexNet架構
AlexNet是深度學習在影像識別領域的一個重要里程碑。它採用了多層卷積和池化層,並使用ReLU作為啟用函式。AlexNet的成功在於它展示了深度神經網路在影像識別任務上的強大能力。
程式碼範例:AlexNet模型定義
import torchvision.models as models
alexnet = models.alexnet(num_classes=2)
內容解密:
import torchvision.models as models:匯入PyTorch的torchvision.models模組,該模組提供了多種預訓練的模型。alexnet = models.alexnet(num_classes=2):呼叫models.alexnet函式建立一個AlexNet模型,並指定輸出類別數為2。
Inception/GoogLeNet架構
Inception/GoogLeNet是2014年ImageNet競賽的冠軍,它引入了Inception模組。Inception模組允許網路同時使用不同大小的卷積核,從而捕捉不同尺度的特徵。
Inception模組結構圖
此圖示展示了Inception模組的基本結構。
內容解密:
- Inception模組首先對輸入進行1x1卷積,以減少維度。
- 同時進行不同大小(3x3、5x5)的卷積運算,以捕捉不同尺度的特徵。
- 將所有卷積結果合併,作為下一層的輸入。
VGG架構
VGG是2014年ImageNet競賽的亞軍,它採用了一種簡單而有效的結構:多層卷積和池化層的堆積疊。VGG-16是其中一個著名的變體,它包含了16層可訓練的權重。
VGG-16結構圖
此圖示展示了VGG-16的基本結構。
內容解密:
- VGG-16採用多層卷積和池化層的堆積疊結構。
- 使用兩個大型的全連線層進行分類別。
ResNet架構
ResNet是2015年ImageNet競賽的冠軍,它引入了殘差連線(residual connection)的概念,解決了深層網路訓練中的梯度消失問題。
ResNet殘差塊結構圖
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title CNN 卷積神經網路模型架構解析
package "機器學習流程" {
package "資料處理" {
component [資料收集] as collect
component [資料清洗] as clean
component [特徵工程] as feature
}
package "模型訓練" {
component [模型選擇] as select
component [超參數調優] as tune
component [交叉驗證] as cv
}
package "評估部署" {
component [模型評估] as eval
component [模型部署] as deploy
component [監控維護] as monitor
}
}
collect --> clean : 原始資料
clean --> feature : 乾淨資料
feature --> select : 特徵向量
select --> tune : 基礎模型
tune --> cv : 最佳參數
cv --> eval : 訓練模型
eval --> deploy : 驗證模型
deploy --> monitor : 生產模型
note right of feature
特徵工程包含:
- 特徵選擇
- 特徵轉換
- 降維處理
end note
note right of eval
評估指標:
- 準確率/召回率
- F1 Score
- AUC-ROC
end note
@enduml
此圖示展示了ResNet殘差塊的基本結構。
內容解密:
- 殘差塊允許輸入直接跳過幾層連線至輸出。
- 這種結構有助於解決深層網路中的梯度消失問題。
使用預訓練模型
PyTorch提供了多種預訓練的CNN模型,可以直接用於影像識別任務。這些模型包括AlexNet、VGG、ResNet等。
程式碼範例:使用預訓練的ResNet模型
import torchvision.models as models
resnet = models.resnet18(pretrained=True)
內容解密:
models.resnet18(pretrained=True):呼叫models.resnet18函式建立一個預訓練的ResNet-18模型。
卷積神經網路架構解析:以ResNet為例
本段落將深入解析卷積神經網路(CNN)中的經典架構——ResNet的內部結構,並詳細闡述其關鍵元件的作用與技術原理。
ResNet模型結構剖析
首先,讓我們觀察ResNet模型的結構:
(conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(layer1): Sequential(
(0): BasicBlock(...)
(1): BasicBlock(...)
)
(layer2): Sequential(
(0): BasicBlock(...)
(1): BasicBlock(...)
)
...
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Linear(in_features=512, out_features=1000, bias=True)
內容解密:
- 初始卷積層:使用7x7的卷積核,步長為2,輸出64個特徵圖
- 批次標準化(BatchNorm2d):對每個小批次的輸出進行標準化處理,使其均值接近0,變異數為1
- ReLU啟用函式:引入非線性特性,提高模型的表達能力
- 最大池化(MaxPool2d):降低特徵圖的解析度,減少計算量
BatchNorm技術解析
BatchNorm是ResNet架構中的關鍵技術之一,其主要功能是:
- 自動調整網路中的資料分佈,避免梯度消失或爆炸
- 加速網路訓練過程
- 提高模型的穩定性
為何需要BatchNorm?
在深層網路中,由於多層之間的連續相乘,可能導致梯度問題。BatchNorm透過動態調整每層的輸出分佈,有效緩解了這一問題。
ResNet層級結構分析
ResNet採用模組化的設計思路,主要包含以下幾個層級:
- layer1-layer4:由多個BasicBlock組成,每個Block包含兩個卷積層和一個捷徑連線(shortcut connection)
- BasicBlock內部結構:
- 兩個3x3卷積層,中間夾雜ReLU啟用函式
- 使用BatchNorm進行標準化處理
- 捷徑連線實作殘差學習,有效解決梯度消失問題
內容解密:
- 殘差學習:透過捷徑連線,將輸入直接加到輸出上,實作殘差學習,改善梯度傳遞效率
- 卷積層設計:採用3x3的小型卷積核,既減少引數量,又能捕捉區域性特徵
模型選擇建議
在實際應用中,選擇適當的預訓練模型至關重要。建議:
- 列印模型結構:使用
print(model)檢視不同架構的層級結構和運算順序 - 根據任務需求選擇模型:考慮模型的複雜度和效能需求,選擇合適的ResNet版本(如ResNet-50或ResNet-152)