iT邦幫忙

2025 iThome 鐵人賽

DAY 15
0
AI & Data

從0開始:傳統圖像處理到深度學習模型系列 第 15

Day 15 - 卷積神經網路(三) GoogLeNet 與 ResNet

  • 分享至 

  • xImage
  •  

雖然昨天我們知道 VGGNet 在一定程度上有著網路越深、效果越好的特性,但是當研究人員把網路堆疊約 20 層以上時,模型的準確率反而開始下降。這不是過擬合所導致,因為在訓練集上同樣有這個問題,被稱為網路退化

GoogLeNet

我們知道 VGGNet 是 ILSVRC 2014 的亞軍,但真正的冠軍其實是 GoogLeNet。GoogLeNet 不是一味地加深網路,反而是大幅增加網路的寬度,也強化了對多尺度特徵的適應能力。

設計者思考了一個核心問題:在卷積層中,到底該選擇多大尺寸的卷積核?5×5 的卷積核能看到更大的感受域,3×3 的更關注細節,而 1×1 的則能進行通道整合。既然難以抉擇,怎麼不把它們全都用上?

這思想稱為 Inception,它就像網路中的網路,並行執行四個分支操作

  1. 一個 1×1 卷積

  2. 一個 1×1 卷積,後面再接一個 3×3 卷積

  3. 一個 1×1 卷積,後面再接一個 5×5 卷積

  4. 一個 3×3 最大池化,後面再接一個 1×1 卷積

最後,將這四個分支的輸出特徵圖,在通道維度上進行拼接,形成一個更厚的、融合了多尺度資訊的特徵圖。

1×1 卷積的用途

在計算量較大的 3×3 和 5×5 卷積之前,以及在池化之後,都跟了一個 1×1 的卷積。這個 1×1 卷積在這裡用於降維。它可以像一個瓶頸一樣,先將輸入特徵圖的通道數大幅減少,然後再進行昂貴的卷積運算,最後再用 1×1 卷積恢復通道數。這使得 Inception 模組在獲得強大性能的同時,計算量和參數數量甚至比 VGGNet 還要少得多。

GoogLeNet 就是透過堆疊多個這樣的 Inception 模組,構建出了一個 22 層深的網路並獲得冠軍。

ResNet

2015 年由何愷明等人提出的 ResNet (Residual Network) 是在深度上取得了突破,ResNet 團隊直面了「網路退化」這個問題。

他們提出了一個假設:

  • 如果我們有一個淺層的網路,我們在其之上再增加一些新的層,那麼這個更深的模型的表現,最差也應該和那個淺層網路一樣好。因為,我們可以讓那些新增的層什麼都不做,僅進行恆等映射 (identity mapping),即直接將輸入複製到輸出。

  • 但當時的神經網路,要讓多個非線性層去擬合一個恆等映射,卻非常困難,ResNet 的思想就因此而誕生。

與其讓網路直接學習目標映射 H(x),不如讓它去學習一個殘差 (residual)

https://ithelp.ithome.com.tw/upload/images/20250825/201781005WrdD4m134.png

這樣,原始的目標映射就變成了

https://ithelp.ithome.com.tw/upload/images/20250825/20178100AYdd0meYZr.png

這個 + x 的操作,在網路結構中,就是一條從輸入直接跳過中間層、連接到輸出的捷徑連接 (shortcut connection),它同時也帶來了兩個好處

  1. 解決網路退化:如果中間的 F(x) 層學習到了最有用的特徵,它就正常輸出;如果中間層發現自己是多餘的,它只需要將自己的權重學習成0,那麼整個殘差塊就變成了 H(x) = 0 + x,即一個恆等映射。這使得網路可以輕易地跳過無用的層,從而讓訓練極深的網路成為可能。

  2. 緩解梯度消失:在反向傳播時,梯度不僅可以沿著權重層 F(x) 傳播,還可以暢通無阻地通過這條 + x 的捷徑直接傳播回淺層網路,極大地緩解了梯度消失問題。

用 PyTorch 載入預訓練的 ResNet-50

import torch
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image
import requests
import json
from io import BytesIO

# --- 1. 比較 VGG-16 和 ResNet-50 的參數數量 ---
vgg16 = models.vgg16(pretrained=False) # pretrained=False 只載入結構,不載入權重
resnet50 = models.resnet50(pretrained=False)

vgg16_params = sum(p.numel() for p in vgg16.parameters() if p.requires_grad)
resnet50_params = sum(p.numel() for p in resnet50.parameters() if p.requires_grad)

print(f"VGG-16 (16層) 的可訓練參數數量: {vgg16_params / 1_000_000:.2f} M")
print(f"ResNet-50 (50層) 的可訓練參數數量: {resnet50_params / 1_000_000:.2f} M")
print("ResNet-50 比 VGG-16 深得多,但參數反而比較少")

# --- 2. 載入預訓練的 ResNet-50 模型進行預測 ---
print("\n正在下載並載入預訓練的 ResNet-50 模型...")
resnet50_pretrained = models.resnet50(pretrained=True)
resnet50_pretrained.eval() # 設為評估模式
print("模型載入完成!")

# --- 3. 準備輸入圖片與預處理 (與昨天相同) ---
preprocess = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

image_url = "https://images.pexels.com/photos/33287/dog-viszla-close.jpg" # Vizsla
response = requests.get(image_url)
img_pil = Image.open(BytesIO(response.content))
batch_t = torch.unsqueeze(preprocess(img_pil), 0)

# --- 4. 進行預測 ---
with torch.no_grad():
    output = resnet50_pretrained(batch_t)

# --- 5. 解讀輸出結果 ---
# 下載 ImageNet 的類別標籤
LABELS_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json'
response = requests.get(LABELS_URL)
class_idx = json.loads(response.text)
# 將 { 'class_id': ['class_code', 'class_name'] } 轉換為 { 'class_id': 'class_name' }
imagenet_labels = {int(k): v[1] for k, v in class_idx.items()}

probabilities = torch.nn.functional.softmax(output[0], dim=0)
top5_prob, top5_catid = torch.topk(probabilities, 5)

print("\n--- 預測結果 Top 5 ---")
for i in range(top5_prob.size(0)):
    class_name = imagenet_labels[top5_catid[i].item()]
    probability = top5_prob[i].item()
    print(f"第 {i+1} 名: {class_name:<20} | 機率: {probability:.4f}")

# 顯示圖片
import matplotlib.pyplot as plt
plt.imshow(img_pil)
plt.title("Test Image")
plt.axis('off')
plt.show()

結果
https://ithelp.ithome.com.tw/upload/images/20250825/20178100zkjXQhpVL0.png

--- 預測結果 Top 5 ---
第 1 名: vizsla               | 機率: 0.9981
第 2 名: Weimaraner           | 機率: 0.0012
第 3 名: Rhodesian_ridgeback  | 機率: 0.0004
第 4 名: Chesapeake_Bay_retriever | 機率: 0.0002
第 5 名: redbone              | 機率: 0.0001

上一篇
Day 14 – 卷積神經網路(二) AlexNet 與 VGG
下一篇
Day 16 - 卷積神經網路(四)Grad-CAM
系列文
從0開始:傳統圖像處理到深度學習模型23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言