一、激活函數(Activation Functions)¶
爲什麼需要激活函數?
神經網絡的基本單元是神經元,每個神經元的輸出是輸入的加權和(線性變換)。如果沒有激活函數,無論堆疊多少層神經元,輸出始終是輸入的線性組合,無法擬合複雜的非線性關係(比如圖像中的邊緣、紋理等)。激活函數的作用就是引入非線性變換,讓網絡具備“學習複雜模式”的能力。
1. 常見激活函數及PyTorch實現¶
(1)ReLU(Rectified Linear Unit)¶
- 公式:
y = max(0, x) - 當輸入
x > 0時,輸出等於輸入;當x ≤ 0時,輸出爲0。 - 特點:計算簡單,解決了傳統Sigmoid/Tanh的梯度消失問題,訓練速度快,是目前最常用的激活函數。
- PyTorch實現:
import torch
import torch.nn as nn
# 創建ReLU激活函數實例
relu = nn.ReLU()
# 測試:輸入一個張量
x = torch.tensor([-1.0, 0.0, 1.5, -0.3])
y = relu(x)
print("ReLU輸出:", y) # 輸出:tensor([0.0000, 0.0000, 1.5000, 0.0000])
(2)Sigmoid函數¶
- 公式:
y = 1 / (1 + exp(-x)) - 輸出範圍在
(0, 1)之間,常用於二分類問題的輸出層(將結果轉爲概率)。 - 特點:輸出是概率值,但當
x很大或很小時,梯度趨近於0,容易出現梯度消失,深層網絡訓練困難。 - PyTorch實現:
sigmoid = nn.Sigmoid()
x = torch.tensor([-2.0, 0.0, 2.0])
y = sigmoid(x)
print("Sigmoid輸出:", y) # 輸出:tensor([0.1192, 0.5000, 0.8808])
(3)Tanh函數¶
- 公式:
y = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) - 輸出範圍在
(-1, 1)之間,均值爲0,理論上比Sigmoid更易訓練。 - 特點:仍存在梯度消失問題,應用場景較少,主要用於RNN等序列模型的隱藏層。
- PyTorch實現:
tanh = nn.Tanh()
x = torch.tensor([-1.0, 0.0, 1.0])
y = tanh(x)
print("Tanh輸出:", y) # 輸出:tensor([-0.7616, 0.0000, 0.7616])
二、卷積層(Convolutional Layers)¶
卷積層是什麼?
卷積層是CNN(卷積神經網絡)的核心,通過滑動一個“濾鏡”(卷積核)在輸入數據上,提取局部特徵(如邊緣、紋理)。例如,用不同的卷積核可以識別圖像中的“邊緣”“條紋”等模式。
1. 卷積操作的基本概念¶
- 輸入:假設輸入是一張灰度圖像(單通道,二維矩陣),形狀爲
(H, W)。 - 卷積核(Filter/Kernel):一個小矩陣(如
3x3),用於特徵提取。 - 步長(Stride):卷積核每次滑動的像素數(默認1)。
- 填充(Padding):在輸入邊緣添加0,控制輸出尺寸(避免特徵丟失)。
簡單示例:
輸入:3x3矩陣(像素值)
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
卷積核:2x2矩陣
[[a, b],
[c, d]]
輸出計算:每個位置是卷積核覆蓋區域的像素乘積之和
- 左上角:1*a + 2*b + 4*c + 5*d
- 右上角:2*a + 3*b + 5*c + 6*d
- 左下角:4*a + 5*b + 7*c + 8*d
- 右下角:5*a + 6*b + 8*c + 9*d
2. PyTorch中的卷積層(nn.Conv2d)¶
在PyTorch中,卷積層通過nn.Conv2d實現,用於處理二維圖像數據(如RGB圖像)。輸入形狀爲(batch_size, in_channels, height, width),其中:
- batch_size:批量樣本數(如一次處理16張圖像);
- in_channels:輸入通道數(RGB圖像爲3,灰度圖爲1);
- height/width:圖像高度和寬度。
關鍵參數:
- in_channels:輸入通道數;
- out_channels:輸出通道數(卷積核數量,決定特徵圖複雜度);
- kernel_size:卷積核大小(如3表示3x3);
- stride:步長(默認1);
- padding:填充(默認0)。
輸出形狀計算:
輸出高度/寬度 = (輸入高度/寬度 + 2*padding - kernel_size) // stride + 1
代碼示例:
假設輸入是一張RGB圖像(batch=1,通道數=3,尺寸=28x28),用3x3卷積核,輸出16個通道:
# 1. 導入庫
import torch
import torch.nn as nn
# 2. 創建輸入張量(batch=1, 通道=3, 高=28, 寬=28)
x = torch.randn(1, 3, 28, 28) # 隨機生成數據
# 3. 定義卷積層
conv = nn.Conv2d(
in_channels=3, # 輸入3個通道(RGB)
out_channels=16, # 輸出16個通道(16個卷積核)
kernel_size=3, # 3x3卷積核
stride=1, # 步長1
padding=1 # 填充1,保持輸出尺寸不變
)
# 4. 前向傳播(應用卷積)
y = conv(x)
# 5. 打印輸入和輸出形狀
print("輸入形狀:", x.shape) # 輸出:torch.Size([1, 3, 28, 28])
print("輸出形狀:", y.shape) # 輸出:torch.Size([1, 16, 28, 28])
3. 卷積層 + 激活函數實戰¶
通常卷積層後接激活函數(如ReLU),形成“卷積→激活”的基本單元:
# 創建卷積層+ReLU
conv_relu = nn.Sequential(
nn.Conv2d(3, 16, 3, 1, 1), # 卷積層
nn.ReLU() # 激活函數
)
y = conv_relu(x)
print("卷積+ReLU輸出:", y.shape) # 仍爲torch.Size([1, 16, 28, 28])
總結:激活函數讓神經網絡引入非線性,卷積層通過滑動窗口提取圖像特徵。兩者結合是CNN模型的核心結構,後續可進一步學習池化層(如MaxPooling)和全連接層,構建完整的圖像識別模型。
小練習:嘗試修改卷積核大小(如kernel_size=5)或步長(stride=2),觀察輸出形狀變化,理解各參數對特徵提取的影響。