零基礎學習人工智慧—Python—Pytorch學習(八)

kiba518發表於2024-08-23

前言

本文介紹卷積神經網路的上半部分。
其實,學習還是需要老師的,因為我自己寫文章的時候,就會想當然,比如下面的滑動視窗,我就會想當然的認為所有人都能理解,而實際上,我們在學習的過程中之所以卡頓的點多,就是因為學習資源中想當然的地方太多了。

概念

卷積神經網路,簡稱CNN, 即Convolutional Neural Network的縮寫。

濾波器/卷積核(Filter/Kernels)

卷積核是一個小矩陣(通常是3x3、5x5等),它在輸入影像上滑動(即移動),並與影像的區域性區域進行矩陣乘法(點積)操作。結果是一個單值,這個值代表了該區域性區域的某種特徵。
點積就是內積,就是np.dot函式,內積是個值,就是兩個矩陣對應項相乘,在相加
例如。a=[2,3] 和 b=[4,5],它們的點積是a⋅b=(2×4)+(3×5)=8+15=23
點積的意義是a⋅b=∥a∥∥b∥cosθ,意思是說,點積等於a向量的模乘以b向量的模乘以ab的夾角θ的cos的值
向量的模就是向量的長度,v=[3,4],因為勾股定理,c²=a²+b²,所以∥v∥=c=根號下a²+b²=根號下9+16=根號下25=5
例。rgb圖,是3通道,卷積核會在3個通道上都進行卷積操作,最後形成一個特徵圖。

卷積核的尺寸

如果尺寸是 5×5,那麼滑動視窗的大小也是 5×5。
image

特徵圖(Feature Map)

當一個卷積核(或濾波器)滑動在輸入影像上時,它會在每一個位置計算卷積核與輸入影像區域的點積,結果是一個標量。透過滑動整個影像,得到一組標量值,這些值構成了一個新的二維矩陣,這個矩陣就是特徵圖。
在CNN中,使用越多的卷積核,意味著提取的特徵圖越多,因此卷積核越大就可以得到的越豐富的特徵。
更多的卷積核意味著更多的計算和記憶體消耗。因此,在選擇卷積核數量時,也要考慮硬體資源的限制。

最大池化層(Max Pooling Layer)

是卷積神經網路(CNN)中常用的下采樣(或降取樣)技術。它用於減小特徵圖的尺寸,從而減少計算量,並有助於控制模型的複雜度(防止過擬合)。
最大池化操作使用一個固定大小的視窗(通常是2x2或3x3),在特徵圖上滑動。
在視窗覆蓋的區域內,最大池化層會選擇該區域的最大值作為輸出。
步幅決定了池化視窗在特徵圖上滑動的步長。步幅為2意味著視窗每次移動2個畫素。
每次池化操作生成的特徵圖尺寸會比輸入特徵圖小。池化操作會減少特徵圖的寬度和高度,但保持深度(通道數)不變。
例,4x4 的輸入特徵圖如下

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

使用 2x2 的最大池化視窗和步幅為 2,池化過程如下:
池化視窗覆蓋 1 2 5 6,最大值為 6
池化視窗覆蓋 3 4 7 8,最大值為 8
池化視窗覆蓋 9 10 13 14,最大值為 14
池化視窗覆蓋 11 12 15 16,最大值為 16
得到的輸出特徵圖為:

6 8
14 16

結合程式碼理解

結合下面的程式碼理解上面的概念。

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
# device config
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# hyper parameters
batch_size = 4
learning_rate = 0.001
num_epochs = 0

# dataset has PILImage images of range [0, 1].# We transform them to Tensors of normalized range [-1, 1]
# transforms.ToTensor():將PIL影像或numpy陣列轉換為PyTorch張量,並將值範圍從[0,1]變為[0,255]。
# transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)):對影像進行歸一化處理,將影像的畫素值調整到[-1,1]範圍。
transform = transforms.Compose(
    [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])


train_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=True, download=True, transform=transform)

test_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=False, download=True, transform=transform)

train_loader = torch.utils. data.DataLoader(
    dataset=train_dataset, batch_size=batch_size, shuffle=True)

test_loader = torch.utils.data.DataLoader(
    dataset=test_dataset, batch_size=batch_size, shuffle=False)


print('每份100個,被分成多了份', len(train_loader))

def imshow(img):
    img = img / 2 + 0.5  # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()


# get some random training images
dataiter = iter(train_loader)
images, labels = dataiter.__next__()
# show images
imshow(torchvision.utils.make_grid(images))

# nn.Conv2d 是 PyTorch 用於定義二維卷積層的類
# 三個引數分別為 in_channels、out_channels 和 kernel_size
# in_channels (輸入通道數):
# 值=3 這是輸入影像的通道數。對於彩色影像,通常有3個通道(對應於RGB),因此這裡的值為3。如果輸入的是灰度影像,通常只有1個通道。
# 對於彩色影像(RGB),輸入影像有3個通道。卷積核對每個通道獨立進行操作,然後將這些結果相加,得到輸出特徵圖。
# 輸出特徵圖的數量由卷積核的數量決定。如果你有多個卷積核,它們會捕捉輸入影像中的不同特徵,每個卷積核生成一個特徵圖
# out_channels (輸出通道數):
# 值=6 這是卷積層輸出的通道數,也稱為卷積核的數量。這個引數決定了卷積操作後生成多少個不同的特徵圖。在本例中,卷積層會生成6個特徵圖,也就是說會有6個不同的卷積核應用於輸入影像。
# kernel_size (卷積核大小):
# 值=5 這是卷積核的尺寸,表示卷積核的寬度和高度。這裡使用的是 5x5 的卷積核。這意味著每個卷積核會檢視輸入影像的 5x5 畫素區域,並透過滑動視窗方式在整個影像上進行卷積操作。
# conv1:第一個卷積層,將輸入的3通道影像(RGB)透過一個5x5的卷積核,生成6個輸出通道。這裡,卷積層使用 6 個卷積核,每個卷積核會生成一個特徵圖。因此,該卷積層的輸出是 6 個特徵圖,特徵圖的深度(通道數)為 6。
conv1 = nn.Conv2d(3, 6, 5)
# pool:最大池化層,將特徵圖的尺寸縮小一半。
# 第一個引數 (2): 池化視窗的大小。這表示池化操作將應用於一個 2x2 的視窗上。池化視窗決定了在特徵圖上進行池化操作的區域大小。 
# 第二個引數 (2): 池化的步幅(stride)。步幅決定了池化視窗在特徵圖上滑動的步長。步幅為 2 意味著池化視窗每次移動 2 個畫素。
pool = nn.MaxPool2d(2, 2)
# conv2:第二個卷積層,將6個通道的輸入特徵圖透過一個5x5的卷積核,生成16個輸出通道。
conv2 = nn.Conv2d(6, 16, 5)
print(images.shape)


x = conv1(images)
# print(x.shape)
x = pool(x)
# print(x.shape)
x = conv2(x)
# print(x.shape)
x = pool(x)  # print(x.shape)

傳送門:
零基礎學習人工智慧—Python—Pytorch學習—全集


注:此文章為原創,任何形式的轉載都請聯絡作者獲得授權並註明出處!



若您覺得這篇文章還不錯,請點選下方的【推薦】,非常感謝!

https://www.cnblogs.com/kiba/p/18375380

相關文章