.. _sec_vgg:
Blokları Kullanan Ağlar (VGG)
=============================
AlexNet derin CNN'lerin iyi sonuçlar elde edebileceğine dair deneysel
kanıtlar sunarken, yeni ağlar tasarlamada sonraki araştırmacılara
rehberlik etmek için genel bir şablon sağlamadı. Aşağıdaki bölümlerde,
derin ağları tasarlamak için yaygın olarak kullanılan çeşitli sezgisel
kavramları tanıtacağız.
Bu alandaki ilerleme, mühendislerin transistörleri yerleştirilmede
mantıksal elemanlardan mantık bloklarına geçtiği yonga tasarımına
benzemektedir. Benzer şekilde, sinir ağı mimarilerinin tasarımı,
araştırmacıların bireysel nöron tabanlı düşünmekten tam katmanlara ve
şimdi de katmanların kalıplarını tekrarlayan bloklara geçerek daha soyut
bir hale gelmişti.
Blokları kullanma fikri ilk olarak Oxford Üniversitesi'ndeki `Görsel
Geometri Grubu `__'nun (Visual
Geometry Group - VGG), kendi adını taşıyan *VGG* ağında ortaya
çıkmıştır. Bu tekrarlanan yapıları, döngüler ve alt programlar
kullanarak herhangi bir modern derin öğrenme çerçevesi ile kodda
uygulamak kolaydır.
.. _subsec_vgg-blocks:
VGG Blokları
------------
Klasik CNN'lerin temel yapı taşı aşağıdakilerin bir dizisidir: (i)
Çözünürlüğü korumak için dolgulu bir evrişimli katman, (ii) ReLU gibi
bir doğrusal olmayan işlev, (iii) Maksimum ortaklama katmanı gibi bir
ortaklama katmanı. Bir VGG bloğu, uzamsal örnek seyreltme için bir
maksimum ortaklama katmanı izleyen bir evrişimli katman dizisinden
oluşur. Orijinal VGG makalesinde :cite:`Simonyan.Zisserman.2014`,
yazarlar :math:`3\times3` çekirdeklerle evrişim (yüksekliği ve genişliği
aynı tutarak) ve 2 birim uzun adımlı :math:`2 \times 2` maksimum
ortaklama (her bloktan sonra çözünürlüğü yarıya indirerek) kullandılar.
Aşağıdaki kodda, bir VGG bloğu uygulamak için ``vgg_block`` adlı bir
işlev tanımlıyoruz.
.. raw:: html
.. raw:: html
İşlev, evrişimli katmanların sayısı ``num_convs``'a ve çıktı
kanallarının sayısı ``num_channels``'a karşılık gelen iki argüman alır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
from d2l import mxnet as d2l
from mxnet import np, npx
from mxnet.gluon import nn
npx.set_np()
def vgg_block(num_convs, num_channels):
blk = nn.Sequential()
for _ in range(num_convs):
blk.add(nn.Conv2D(num_channels, kernel_size=3,
padding=1, activation='relu'))
blk.add(nn.MaxPool2D(pool_size=2, strides=2))
return blk
.. raw:: html
.. raw:: html
İşlev, ``num_convs`` evrişim katmanlarının sayısına, ``in_channels``
girdi kanallarının sayısına ve ``out_channels`` çıktı kanallarının
sayısına karşılık gelen üç argüman alır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import torch
from torch import nn
from d2l import torch as d2l
def vgg_block(num_convs, in_channels, out_channels):
layers = []
for _ in range(num_convs):
layers.append(nn.Conv2d(in_channels, out_channels,
kernel_size=3, padding=1))
layers.append(nn.ReLU())
in_channels = out_channels
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
return nn.Sequential(*layers)
.. raw:: html
.. raw:: html
İşlev, evrişimli katmanların sayısı ``num_convs``'a ve çıktı
kanallarının sayısı ``num_channels``'a karşılık gelen iki argüman alır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import tensorflow as tf
from d2l import tensorflow as d2l
def vgg_block(num_convs, num_channels):
blk = tf.keras.models.Sequential()
for _ in range(num_convs):
blk.add(tf.keras.layers.Conv2D(num_channels,kernel_size=3,
padding='same',activation='relu'))
blk.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
return blk
.. raw:: html
.. raw:: html
VGG Ağı
-------
AlexNet ve LeNet gibi, VGG ağı iki kısma bölünebilir: Birincisi
çoğunlukla evrişim ve ortaklama katmanlarından ve ikincisi tam bağlı
katmanlardan oluşur. Bu :numref:`fig_vgg` içinde tasvir edilmiştir.
.. _fig_vgg:
.. figure:: ../img/vgg.svg
:width: 400px
AlexNet'ten yapı bloklarından tasarlanmış VGG'ye
Ağın evrişimli kısmı, :numref:`fig_vgg` içindeki gösterilen
(``vgg_block`` işlevinde de tanımlanmıştır) birkaç VGG bloğunu arka
arkaya bağlar. Aşağıdaki ``conv_arch`` değişken, her biri iki değer
içeren bir çokuzlu (blok başına bir) listesinden oluşur: Evrişimli
katmanların sayısı ve çıktı kanallarının sayısı, ki tam olarak
``vgg_block`` işlevini çağırmak için gerekli argümanlardır. VGG ağının
tam bağlı kısmı AlexNet'te kapsananla aynıdır.
Orijinal VGG ağında, ilk ikisinin her birinin bir evrişimli tabakaya
sahip olduğu ve sonraki üçünün her birinin iki evrişimli katman içerdiği
5 evrişimli blok vardı. İlk blokta 64 çıktı kanalı vardır ve sonraki her
blok, bu sayı 512'ye ulaşıncaya kadar çıktı kanalı sayısını iki katına
çıkarır. Bu ağ 8 evrişimli katman ve 3 tam bağlı katman kullandığından,
genellikle VGG-11 olarak adlandırılır.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
Aşağıdaki kodda VGG-11'i uygulanıyor. Bu, ``conv_arch`` üzerinde bir
-for- döngüsü yürütme gibi basit bir konudur.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def vgg(conv_arch):
net = nn.Sequential()
# Evrişimli kısım
for (num_convs, num_channels) in conv_arch:
net.add(vgg_block(num_convs, num_channels))
# Tam bağlı kısım
net.add(nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
nn.Dense(10))
return net
net = vgg(conv_arch)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def vgg(conv_arch):
conv_blks = []
in_channels = 1
# Evrişimli kısım
for (num_convs, out_channels) in conv_arch:
conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blks, nn.Flatten(),
# Tam bağlı kısım
nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(4096, 10))
net = vgg(conv_arch)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def vgg(conv_arch):
net = tf.keras.models.Sequential()
# Evrişimli kısım
for (num_convs, num_channels) in conv_arch:
net.add(vgg_block(num_convs, num_channels))
# Tam bağlı kısım
net.add(tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(4096, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(4096, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(10)]))
return net
net = vgg(conv_arch)
.. raw:: html
.. raw:: html
Daha sonra, her katmanın çıktı şeklini gözlemlemek için 224'lik
yüksekliğe ve genişliğe sahip tek kanallı bir veri örneği oluşturacağız.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net.initialize()
X = np.random.uniform(size=(1, 1, 224, 224))
for blk in net:
X = blk(X)
print(blk.name, 'output shape:\t', X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
sequential1 output shape: (1, 64, 112, 112)
sequential2 output shape: (1, 128, 56, 56)
sequential3 output shape: (1, 256, 28, 28)
sequential4 output shape: (1, 512, 14, 14)
sequential5 output shape: (1, 512, 7, 7)
dense0 output shape: (1, 4096)
dropout0 output shape: (1, 4096)
dense1 output shape: (1, 4096)
dropout1 output shape: (1, 4096)
dense2 output shape: (1, 10)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.randn(size=(1, 1, 224, 224))
for blk in net:
X = blk(X)
print(blk.__class__.__name__,'output shape:\t',X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Sequential output shape: torch.Size([1, 64, 112, 112])
Sequential output shape: torch.Size([1, 128, 56, 56])
Sequential output shape: torch.Size([1, 256, 28, 28])
Sequential output shape: torch.Size([1, 512, 14, 14])
Sequential output shape: torch.Size([1, 512, 7, 7])
Flatten output shape: torch.Size([1, 25088])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 10])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.random.uniform((1, 224, 224, 1))
for blk in net.layers:
X = blk(X)
print(blk.__class__.__name__,'output shape:\t', X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Sequential output shape: (1, 112, 112, 64)
Sequential output shape: (1, 56, 56, 128)
Sequential output shape: (1, 28, 28, 256)
Sequential output shape: (1, 14, 14, 512)
Sequential output shape: (1, 7, 7, 512)
Sequential output shape: (1, 10)
.. raw:: html
.. raw:: html
Gördüğünüz gibi, her blokta yüksekliği ve genişliği yarıya indiriyoruz,
nihayet ağın tam bağlı kısmı tarafından işleme için temsilleri
düzleştirmeden önce 7'lik bir yüksekliğe ve genişliğe ulaşıyoruz.
Eğitim
------
VGG-11 AlexNet'ten hesaplamalı olarak daha ağır olduğundan, daha az
sayıda kanala sahip bir ağ oluşturuyoruz. Bu, Fashion-MNIST üzerinde
eğitim için fazlasıyla yeterlidir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
# Recall that this has to be a function that will be passed to
# `d2l.train_ch6()` so that model building/compiling need to be within
# `strategy.scope()` in order to utilize the CPU/GPU devices that we have
net = lambda: vgg(small_conv_arch)
.. raw:: html
.. raw:: html
Biraz daha büyük bir öğrenme hızı kullanmanın haricinde, model eğitim
süreci :numref:`sec_alexnet` içindeki AlexNet'e benzerdir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss 0.174, train acc 0.936, test acc 0.927
1802.4 examples/sec on gpu(0)
.. figure:: output_vgg_4a7574_56_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss 0.172, train acc 0.936, test acc 0.919
2570.7 examples/sec on cuda:0
.. figure:: output_vgg_4a7574_59_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss 0.177, train acc 0.935, test acc 0.913
2963.4 examples/sec on /GPU:0
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. figure:: output_vgg_4a7574_62_2.svg
.. raw:: html
.. raw:: html
Özet
----
- VGG-11 yeniden kullanılabilir evrişimli bloklar kullanarak bir ağ
oluşturur. Farklı VGG modelleri, her bloktaki evrişimli katman ve
çıktı kanallarının sayısındaki farklılıklarla tanımlanabilir.
- Blokların kullanımı, ağ tanımının çok sıkıştırılmış temsillerine yol
açar. Karmaşık ağların verimli tasarımını sağlar.
- Simonyan ve Ziserman, VGG makalelerinde çeşitli mimarilerle deneyler
yaptılar. Özellikle, derin ve dar evrişimlerin (yani
:math:`3 \times 3`) birkaç katmanının daha az sayıda geniş evrişimli
katmandan daha etkili olduğunu buldular.
Alıştırmalar
------------
1. Katmanların boyutlarını yazdırırken 11 yerine sadece 8 sonuç gördük.
Kalan 3 katman bilgisi nereye gitti?
2. AlexNet ile karşılaştırıldığında, VGG hesaplama açısından çok daha
yavaştır ve ayrıca daha fazla GPU belleğine ihtiyaç duyar. Bunun
nedenlerini analiz edin.
3. Fashion-MNIST içindeki imgelerin yüksekliğini ve genişliğini 224'ten
96'ya değiştirmeyi deneyin. Bunun deneyler üzerinde ne etkisi olur?
4. VGG-16 veya VGG-19 gibi diğer yaygın modelleri oluşturmak için VGG
makalesindeki :cite:`Simonyan.Zisserman.2014` Tablo 1'e bakın.
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html