ResNet18 結構分析

一、概述

ResNet(殘差神經網絡)於 2015 年提出,是 ImageNet 圖像分類任務上的冠軍。其核心思想是通過引入跨層連接(shortcut connection)解決了深層神經網絡訓練過程中梯度消失和梯度爆炸的問題。ResNet18 是 ResNet 的一個較小版本,共有 18 層,包括 16 層卷積神經網絡層和 2 層全連接層。

二、ResNet18 細節

1.卷積層

ResNet18 的卷積層共包含16層,在 3×3 的卷積核後,採用 ReLU 激活函數,步長為1,不使用池化層。其中,前7層卷積沒有跨層連接,8-16 層使用了跨層連接。具體來說,8-16 層中每隔一個殘差塊就有一條跨層連接,用於將上一層特徵圖與下一層殘差塊的輸出相加。

2.殘差塊

ResNet18 的每個殘差塊包含 2-3 個卷積層,每個卷積層都跟隨着 Batch Normalization 層和 ReLU 激活函數。具體來說,第一個卷積層的卷積核大小為 3 × 3,第二個卷積層的卷積核大小也為 3 × 3。如果跨層連接存在,還需要添加一層 1 × 1 的卷積層用於調整維度。

3.全連接層

ResNet18 的最後兩層全連接層都含有 512 個神經元,倒數第二層使用 ReLU 激活函數,而最後一層使用 Softmax 函數產生對類的預測輸出。

三、代碼示例

1.定義 ResNet18 結構

import torch.nn as nn

class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, in_planes, planes, stride=1):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion*planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion*planes)
            )

    def forward(self, x):
        out = nn.functional.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = nn.functional.relu(out)
        return out

class ResNet18(nn.Module):
    def __init__(self, num_classes=10):
        super(ResNet18, self).__init__()
        self.in_planes = 64

        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(64, 2, stride=1)
        self.layer2 = self._make_layer(128, 2, stride=2)
        self.layer3 = self._make_layer(256, 2, stride=2)
        self.layer4 = self._make_layer(512, 2, stride=2)
        self.linear = nn.Linear(512*BasicBlock.expansion, num_classes)

    def _make_layer(self, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(BasicBlock(self.in_planes, planes, stride))
            self.in_planes = planes * BasicBlock.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = nn.functional.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = nn.functional.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

2.實例化 ResNet18 模型

resnet18 = ResNet18()

3.模型訓練

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(resnet18.parameters())

for epoch in range(num_epochs):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()
        outputs = resnet18(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        if i % 2000 == 1999:    
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

原創文章,作者:QWYJ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/135397.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
QWYJ的頭像QWYJ
上一篇 2024-10-04 00:12
下一篇 2024-10-04 00:12

相關推薦

  • Vue TS工程結構用法介紹

    在本篇文章中,我們將從多個方面對Vue TS工程結構進行詳細的闡述,涵蓋文件結構、路由配置、組件間通訊、狀態管理等內容,並給出對應的代碼示例。 一、文件結構 一個好的文件結構可以極…

    編程 2025-04-29
  • Python程序的三種基本控制結構

    控制結構是編程語言中非常重要的一部分,它們指導着程序如何在不同的情況下執行相應的指令。Python作為一種高級編程語言,也擁有三種基本的控制結構:順序結構、選擇結構和循環結構。 一…

    編程 2025-04-29
  • Lidar避障與AI結構光避障哪個更好?

    簡單回答:Lidar避障適用於需要高精度避障的場景,而AI結構光避障更適用於需要快速響應的場景。 一、Lidar避障 Lidar,即激光雷達,通過激光束掃描環境獲取點雲數據,從而實…

    編程 2025-04-27
  • Switch C:多選結構的利器

    在編寫程序時,我們經常需要根據某些條件執行不同的代碼,這時就需要使用選擇結構。在C語言中,有if語句、switch語句等多種選擇結構可供使用。其中,switch語句是一種非常強大的…

    編程 2025-04-25
  • Python分支結構的詳細闡述

    一、if語句的基本語法 if 條件: 代碼語句1 代碼語句2 …… if語句是Python分支結構中最基本也是最常用的結構,它的基本語法如上所示。if語句會先判斷條件是否成立,如果…

    編程 2025-04-24
  • 深入理解 Vue 目錄結構

    Vue 是一款由 Evan You 開發的流行 JavaScript 框架。Vue 具有響應式視圖和組件化的思想,讓開發者可以輕鬆構建交互式的 Web 應用。那麼在 Vue 開發中…

    編程 2025-04-24
  • JS遞歸遍歷樹結構詳解

    一、JS遞歸遍歷樹結構並修改 function traverse(node) { if(node == null) return; //遍歷結束 node.value++; // …

    編程 2025-04-24
  • 詳解數組結構

    一、數組的基本概念 數組是一種有序的數據結構,可以容納一組相同數據類型的元素。每個元素有一個唯一的索引(下標),可以通過下標來訪問數組的元素。數組一般分為一維和多維,也可以具有不同…

    編程 2025-04-23
  • 殘差結構:從原理到應用

    一、殘差結構的原理 殘差結構在深度學習中的應用越來越廣泛,其核心原理是將輸入特徵和參考特徵拼接在一起進行訓練,以增強模型的學習能力和泛化能力。 具體地,殘差結構引入了跨層連接,使得…

    編程 2025-04-23
  • LTE幀結構詳解

    一、幀結構簡介 LTE網絡中的幀結構是由多個子幀和時隙構成的。每個子幀由14個符號組成,符號的長度為0.5ms。每個符號中又包含7個資源塊,一個資源塊可以傳輸12個子載波。一個子幀…

    編程 2025-04-22

發表回復

登錄後才能評論