訂閱
糾錯(cuò)
加入自媒體

如何用Python從頭開始構(gòu)建VGG Net?

介紹

VGG-Network 是 K. Simonyan 和 A. Zisserman 在論文“Very Deep Convolutional Networks for Large-Scale Image Recognition”[1] 中提出的卷積神經(jīng)網(wǎng)絡(luò)模型。該架構(gòu)在 ImageNet 中實(shí)現(xiàn)了 92.7% 的 top-5 測(cè)試準(zhǔn)確率,該網(wǎng)絡(luò)擁有超過(guò) 1400 萬(wàn)張屬于 1000 個(gè)類別的圖像。它是深度學(xué)習(xí)領(lǐng)域著名的架構(gòu)之一。將第1層和第2層的大內(nèi)核大小的過(guò)濾器分別替換為11和5,顯示了對(duì) AlexNet 架構(gòu)的改進(jìn),多個(gè)3×3內(nèi)核大小的過(guò)濾器相繼出現(xiàn)。它接受了數(shù)周的訓(xùn)練,并使用了 NVIDIA Titan Black GPU。

VGG16 架構(gòu)卷積神經(jīng)網(wǎng)絡(luò)的輸入是一個(gè)固定大小的 224 × 224 RGB 圖像。它所做的唯一預(yù)處理是從每個(gè)像素中減去在訓(xùn)練數(shù)據(jù)集上計(jì)算的平均 RGB 值。然后圖像通過(guò)一堆卷積 (Conv.) 層運(yùn)行,其中的過(guò)濾器的感受野非常小,為 3 × 3,這是捕捉左/右、上/下概念的最小尺寸,和中心部分。在其中一種配置中,它還利用了1 × 1卷積濾波器,可以觀察到輸入通道的線性變換之后是非線性的。卷積步幅固定為1像素; 卷積層輸入的空間填充使卷積后的空間分辨率保持不變,即3 × 3個(gè)卷積層的填充為1像素。然后空間池化由五個(gè)最大池化層執(zhí)行,其中 16 個(gè)最大池層跟在一些 Conv 層之后,但不是所有的 Conv  層。這個(gè)最大池化是在一個(gè) 2 × 2 像素的窗口上執(zhí)行的,步長(zhǎng)為 2。

資料來(lái)源:neurohive.io

該架構(gòu)包含一堆卷積層,這些層在不同的架構(gòu)中具有不同的深度,然后是三個(gè)全連接 (FC) 層:前兩個(gè) FC 各有 4096 個(gè)通道,第三個(gè) FC 執(zhí)行 1000 路分類,因此包含 1000 個(gè)通道,每個(gè)類一個(gè)通道。最后一層是 soft-max 層。全連接層的配置在所有網(wǎng)絡(luò)中都是相似的。所有隱藏層都配備了整流 (ReLU) 非線性。此外,這里的一個(gè)網(wǎng)絡(luò)包含局部響應(yīng)歸一化 (LRN),這種歸一化不會(huì)提高訓(xùn)練數(shù)據(jù)集的性能,但使用它會(huì)導(dǎo)致內(nèi)存消耗和計(jì)算時(shí)間增加。架構(gòu)總結(jié):模型的輸入是固定大小的 224×224224×224 RGB 圖像預(yù)處理是從每個(gè)像素中減去訓(xùn)練集 RGB 值的平均值卷積層 17– 步幅固定為 1 像素– 3×33×3 的填充為 1 像素空間池化層– 按照慣例,這一層不計(jì)入網(wǎng)絡(luò)的深度– 空間池化是使用最大池化層完成的– 窗口大小為 2×22×2– 步幅固定為 2– Convnets 使用了 5 個(gè)最大池化層全連接層:第一:4096 (ReLU)第二:4096(ReLU)第三:1000(Softmax)架構(gòu)配置下圖包含 VGG 網(wǎng)絡(luò)的卷積神經(jīng)網(wǎng)絡(luò)配置以下:VGG-11VGG-11 (LRN)VGG-13VGG-16 (Conv1)VGG-16VGG-19

來(lái)源:“用于大規(guī)模圖像識(shí)別的深度卷積網(wǎng)絡(luò)”

上面提到的卷積神經(jīng)網(wǎng)絡(luò)配置每列一個(gè)。在下文中,網(wǎng)絡(luò)以其名稱 (A-E) 表示。所有配置都遵循傳統(tǒng)設(shè)計(jì),僅在深度上有所不同:從網(wǎng)絡(luò)A中的11個(gè)權(quán)重層(8個(gè)轉(zhuǎn)換和3個(gè)FC層)到網(wǎng)絡(luò)E中的19個(gè)權(quán)重層(16個(gè)轉(zhuǎn)換和3個(gè)FC層)。每個(gè)卷積層的寬度很小,通道數(shù)很小,從第一層的64開始,然后在每個(gè)最大池化層之后繼續(xù)增加2倍,直到達(dá)到512。每個(gè)配置的參數(shù)數(shù)量如下所述。雖然它有很大的深度,但網(wǎng)絡(luò)中的權(quán)值的數(shù)目并不大于較淺的網(wǎng)絡(luò)中的權(quán)值的數(shù)目,而該網(wǎng)絡(luò)具有較大的卷積層寬度和感受野

來(lái)源:“用于大規(guī)模圖像識(shí)別的非常深的卷積網(wǎng)絡(luò)”

訓(xùn)練損失函數(shù)是多項(xiàng)邏輯回歸學(xué)習(xí)算法是基于動(dòng)量反向傳播的小批量隨機(jī)梯度下降 (SGD)批量大小為 256動(dòng)量是 0.9正則化L2 權(quán)重衰減(懲罰乘數(shù)為 0.0005)前兩個(gè)全連接層的 Dropout 設(shè)置為 0.5學(xué)習(xí)率初始:0.01當(dāng)驗(yàn)證集精度停止提高時(shí),它會(huì)降低到 10。盡管與 Alexnet 相比,它具有更多的參數(shù)和深度,但由于 CNN 的損失函數(shù)收斂所需的時(shí)期更少小卷積核和大深度的更多正則化。某些層的預(yù)初始化。訓(xùn)練圖像大小S 是同位素重縮放圖像的最小邊設(shè)置S的兩種方法Fix S,稱為單尺度訓(xùn)練這里 S = 256 和 S = 384Vary S,稱為多尺度訓(xùn)練S 來(lái)自 [Smin, Smax] 其中 Smin = 256, Smax = 512– 然后 224×224224×224圖像是從每次 SGD 迭代重新縮放的圖像中隨機(jī)裁剪的。

主要特征VGG16 共有 16 層,具有一定的權(quán)重。僅使用卷積和池化層。始終使用 3 x 3 內(nèi)核進(jìn)行卷積。202×2 大小的最大池。1.38 億個(gè)參數(shù)。在ImageNet 數(shù)據(jù)上訓(xùn)練。它的準(zhǔn)確率為 92.7%。另一個(gè)版本是 VGG 19,共有 19 個(gè)帶權(quán)重的層。這是一個(gè)非常好的深度學(xué)習(xí)架構(gòu),用于對(duì)任何特定任務(wù)進(jìn)行基準(zhǔn)測(cè)試。VGG 的預(yù)訓(xùn)練網(wǎng)絡(luò)是開源的,因此它可以開箱即用地用于各種類型的應(yīng)用程序。讓我們實(shí)現(xiàn) VGG 網(wǎng)絡(luò)首先讓我們?yōu)?VGG 網(wǎng)絡(luò)的每個(gè)版本創(chuàng)建過(guò)濾器映射。參考上面的配置圖片了解過(guò)濾器的數(shù)量。即為鍵名為 VGG11、VGG13、VGG16、VGG19 的版本創(chuàng)建一個(gè)字典,并分別根據(jù)每個(gè)版本中的過(guò)濾器數(shù)量創(chuàng)建一個(gè)列表。這里列表中的“M”稱為 Maxpool 操作。import torch
import torch.nn as nn
VGG_types = {
"VGG11": [64, "M", 128, "M", 256, 256, "M", 512, 512, "M", 512, 512, "M"],
"VGG13": [64, 64, "M", 128, 128, "M", 256, 256, "M", 512, 512, "M", 512, 512, "M"],
"VGG16": [64,64,"M",128,128,"M",256,256,256,"M",512,512,512,"M",512,512,512,"M",],
"VGG19": [64,64,"M",128,128,"M",256,256,256,256,"M",512,512,512,512,
         "M",512,512,512,512,"M",],}
創(chuàng)建一個(gè)全局變量來(lái)說(shuō)明架構(gòu)的版本。然后創(chuàng)建一個(gè)名為 VGG_net 的類,輸入為 in_channels 和 num_classes,它接受輸入,如圖像通道數(shù)和輸出類數(shù)。初始化 Sequential 層,即在序列中,Linear layer->ReLU->Dropout。然后創(chuàng)建一個(gè)名為 create_conv_layers 的函數(shù),它將 VGGnet 架構(gòu)配置作為輸入,即我們上面為不同版本創(chuàng)建的列表。當(dāng)它遇到上面列表中的字母“M”時(shí),它執(zhí)行 MaxPool2d 操作。VGGType = "VGG16"
class VGGnet(nn.Module):
   def __init__(self, in_channels=3, num_classes=1000):
       super(VGGnet, self).__init__()
       self.in_channels = in_channels
       self.conv_layers = self.create_conv_layers(VGG_types[VGGType])
self.fcs = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, num_classes),
)
def forward(self, x):
x = self.conv_layers(x)
x = x.reshape(x.shape[0], -1)
x = self.fcs(x)
return x
def create_conv_layers(self, architecture):
layers = []
in_channels = self.in_channels
for x in architecture:
if type(x) == int:
out_channels = x
layers += [
nn.Conv2d(
in_channels=in_channels,
out_channels=out_channels,
kernel_size=(3, 3),
stride=(1, 1),
padding=(1, 1),
),
nn.BatchNorm2d(x),
nn.ReLU(),
]
in_channels = x
elif x == "M":
layers += [nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))]
return nn.Sequential(*layers)
完成后,編寫一個(gè)小的測(cè)試代碼來(lái)檢查我們的實(shí)現(xiàn)是否運(yùn)行良好。在下面的測(cè)試代碼中,給出的類數(shù)是 500。if __name__ == "__main__":
   device = "cuda" if torch.cuda.is_available() else "cpu"
   model = VGGnet(in_channels=3, num_classes=500).to(device)
   # print(model)
   x = torch.randn(1, 3, 224, 224).to(device)
   print(model(x).shape)
輸出應(yīng)該是這樣的:

如果你想查看網(wǎng)絡(luò)架構(gòu),你可以取消對(duì)上述代碼中的*print(model)*語(yǔ)句的注釋。也可以通過(guò)更改變量 VGGType 中的 VGG 版本來(lái)嘗試使用不同的版本。

image.png

聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問(wèn)題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過(guò)于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無(wú)評(píng)論

暫無(wú)評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)