如何用Python從頭開始構建VGG Net?
介紹
VGG-Network 是 K. Simonyan 和 A. Zisserman 在論文“Very Deep Convolutional Networks for Large-Scale Image Recognition”[1] 中提出的卷積神經(jīng)網(wǎng)絡模型。該架構在 ImageNet 中實現(xiàn)了 92.7% 的 top-5 測試準確率,該網(wǎng)絡擁有超過 1400 萬張屬于 1000 個類別的圖像。它是深度學習領域著名的架構之一。將第1層和第2層的大內(nèi)核大小的過濾器分別替換為11和5,顯示了對 AlexNet 架構的改進,多個3×3內(nèi)核大小的過濾器相繼出現(xiàn)。它接受了數(shù)周的訓練,并使用了 NVIDIA Titan Black GPU。
VGG16 架構卷積神經(jīng)網(wǎng)絡的輸入是一個固定大小的 224 × 224 RGB 圖像。它所做的唯一預處理是從每個像素中減去在訓練數(shù)據(jù)集上計算的平均 RGB 值。然后圖像通過一堆卷積 (Conv.) 層運行,其中的過濾器的感受野非常小,為 3 × 3,這是捕捉左/右、上/下概念的最小尺寸,和中心部分。在其中一種配置中,它還利用了1 × 1卷積濾波器,可以觀察到輸入通道的線性變換之后是非線性的。卷積步幅固定為1像素; 卷積層輸入的空間填充使卷積后的空間分辨率保持不變,即3 × 3個卷積層的填充為1像素。然后空間池化由五個最大池化層執(zhí)行,其中 16 個最大池層跟在一些 Conv 層之后,但不是所有的 Conv 層。這個最大池化是在一個 2 × 2 像素的窗口上執(zhí)行的,步長為 2。
資料來源:neurohive.io
該架構包含一堆卷積層,這些層在不同的架構中具有不同的深度,然后是三個全連接 (FC) 層:前兩個 FC 各有 4096 個通道,第三個 FC 執(zhí)行 1000 路分類,因此包含 1000 個通道,每個類一個通道。最后一層是 soft-max 層。全連接層的配置在所有網(wǎng)絡中都是相似的。所有隱藏層都配備了整流 (ReLU) 非線性。此外,這里的一個網(wǎng)絡包含局部響應歸一化 (LRN),這種歸一化不會提高訓練數(shù)據(jù)集的性能,但使用它會導致內(nèi)存消耗和計算時間增加。架構總結:模型的輸入是固定大小的 224×224224×224 RGB 圖像預處理是從每個像素中減去訓練集 RGB 值的平均值卷積層 17– 步幅固定為 1 像素– 3×33×3 的填充為 1 像素空間池化層– 按照慣例,這一層不計入網(wǎng)絡的深度– 空間池化是使用最大池化層完成的– 窗口大小為 2×22×2– 步幅固定為 2– Convnets 使用了 5 個最大池化層全連接層:第一:4096 (ReLU)第二:4096(ReLU)第三:1000(Softmax)架構配置下圖包含 VGG 網(wǎng)絡的卷積神經(jīng)網(wǎng)絡配置以下:VGG-11VGG-11 (LRN)VGG-13VGG-16 (Conv1)VGG-16VGG-19
來源:“用于大規(guī)模圖像識別的深度卷積網(wǎng)絡”
上面提到的卷積神經(jīng)網(wǎng)絡配置每列一個。在下文中,網(wǎng)絡以其名稱 (A-E) 表示。所有配置都遵循傳統(tǒng)設計,僅在深度上有所不同:從網(wǎng)絡A中的11個權重層(8個轉換和3個FC層)到網(wǎng)絡E中的19個權重層(16個轉換和3個FC層)。每個卷積層的寬度很小,通道數(shù)很小,從第一層的64開始,然后在每個最大池化層之后繼續(xù)增加2倍,直到達到512。每個配置的參數(shù)數(shù)量如下所述。雖然它有很大的深度,但網(wǎng)絡中的權值的數(shù)目并不大于較淺的網(wǎng)絡中的權值的數(shù)目,而該網(wǎng)絡具有較大的卷積層寬度和感受野
來源:“用于大規(guī)模圖像識別的非常深的卷積網(wǎng)絡”
訓練損失函數(shù)是多項邏輯回歸學習算法是基于動量反向傳播的小批量隨機梯度下降 (SGD)批量大小為 256動量是 0.9正則化L2 權重衰減(懲罰乘數(shù)為 0.0005)前兩個全連接層的 Dropout 設置為 0.5學習率初始:0.01當驗證集精度停止提高時,它會降低到 10。盡管與 Alexnet 相比,它具有更多的參數(shù)和深度,但由于 CNN 的損失函數(shù)收斂所需的時期更少小卷積核和大深度的更多正則化。某些層的預初始化。訓練圖像大小S 是同位素重縮放圖像的最小邊設置S的兩種方法Fix S,稱為單尺度訓練這里 S = 256 和 S = 384Vary S,稱為多尺度訓練S 來自 [Smin, Smax] 其中 Smin = 256, Smax = 512– 然后 224×224224×224圖像是從每次 SGD 迭代重新縮放的圖像中隨機裁剪的。
主要特征VGG16 共有 16 層,具有一定的權重。僅使用卷積和池化層。始終使用 3 x 3 內(nèi)核進行卷積。202×2 大小的最大池。1.38 億個參數(shù)。在ImageNet 數(shù)據(jù)上訓練。它的準確率為 92.7%。另一個版本是 VGG 19,共有 19 個帶權重的層。這是一個非常好的深度學習架構,用于對任何特定任務進行基準測試。VGG 的預訓練網(wǎng)絡是開源的,因此它可以開箱即用地用于各種類型的應用程序。讓我們實現(xiàn) VGG 網(wǎng)絡首先讓我們?yōu)?VGG 網(wǎng)絡的每個版本創(chuàng)建過濾器映射。參考上面的配置圖片了解過濾器的數(shù)量。即為鍵名為 VGG11、VGG13、VGG16、VGG19 的版本創(chuàng)建一個字典,并分別根據(jù)每個版本中的過濾器數(shù)量創(chuàng)建一個列表。這里列表中的“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)建一個全局變量來說明架構的版本。然后創(chuàng)建一個名為 VGG_net 的類,輸入為 in_channels 和 num_classes,它接受輸入,如圖像通道數(shù)和輸出類數(shù)。初始化 Sequential 層,即在序列中,Linear layer->ReLU->Dropout。然后創(chuàng)建一個名為 create_conv_layers 的函數(shù),它將 VGGnet 架構配置作為輸入,即我們上面為不同版本創(chuàng)建的列表。當它遇到上面列表中的字母“M”時,它執(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)
完成后,編寫一個小的測試代碼來檢查我們的實現(xiàn)是否運行良好。在下面的測試代碼中,給出的類數(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)
輸出應該是這樣的:
如果你想查看網(wǎng)絡架構,你可以取消對上述代碼中的*print(model)*語句的注釋。也可以通過更改變量 VGGType 中的 VGG 版本來嘗試使用不同的版本。
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
推薦專題
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結構工程師 廣東省/深圳市