.. _sec_nin:
Ağ İçinde Ağ (Network in Network - NiN)
=======================================
LeNet, AlexNet ve VGG ortak bir tasarım deseni paylaşır: Öznitelikleri
bir dizi evrişim ve ortaklama katmanları aracılığıyla *mekansal* yapıdan
faydalanarak çıkar ve daha sonra tam bağlı katmanlar aracılığıyla
temsilleri sonradan işle. AlexNet ve VGG tarafından LeNet üzerindeki
iyileştirmeler, esas olarak bu sonraki ağların bu iki modülü nasıl
genişlettiği ve derinleştirdiği konusunda yatmaktadır. Alternatif
olarak, tam bağlı katmanları süreç içinde daha önce kullanmayı hayal
edebiliriz. Bununla birlikte, yoğun katmanların dikkatsiz kullanımı,
temsilin mekansal yapısını tamamen görmezden gelebilir; *ağ içindeki ağ*
(*NiN*) blokları burada bir alternatif sunuyor. Çok basit bir anlayışa
dayalı olarak önerildiler: Her piksel için kanallarda ayrı ayrı bir MLP
kullanmak :cite:`Lin.Chen.Yan.2013`.
NiN Blokları
------------
Evrişimli katmanların girdi ve çıktılarının, örneğe, kanala, yüksekliğe
ve genişliğe karşılık gelen eksenlere sahip dört boyutlu tensörlerden
oluştuğunu hatırlayın. Ayrıca, tam bağlı katmanların girdi ve
çıktılarının tipik olarak örneğe ve özniteliğe karşılık gelen iki
boyutlu tensörler olduğunu hatırlayın. NiN'in arkasındaki fikir, her
piksel konumuna (her yükseklik ve genişlik için) tam bağlı bir katman
uygulamaktır. Ağırlıkları her mekansal konum boyunca bağlarsak, bunu bir
:math:`1\times 1` evrişimli katman (:numref:`sec_channels` içinde
açıklandığı gibi) veya her piksel konumunda bağımsız olarak hareket eden
tam bağlı bir katman olarak düşünebiliriz. Bunu görmenin bir başka yolu
da mekansal boyuttaki her elemanın (yükseklik ve genişlik) bir örneğe
eşdeğer ve bir kanalın bir özniteliğe eşdeğer olduğunu düşünmektir.
:numref:`fig_nin`, VGG ve NiN arasındaki ana yapısal farklılıkları ve
bloklarını göstermektedir. NiN bloğu, bir evrişimli katmandan ve
ardından ReLU etkinleştirmeleri ile piksel başına tam bağlı katmanlar
olarak hareket eden iki :math:`1\times 1` evrişimli katmandan oluşur.
İlk katmanın evrişim penceresi şekli genellikle kullanıcı tarafından
ayarlanır. Sonraki pencere şekilleri :math:`1 \times 1`'e sabitlenir.
.. _fig_nin:
.. figure:: ../img/nin.svg
:width: 600px
VGG and NiN mimarilerinin ve bloklarının karşılaştırılması
.. raw:: html
.. raw:: html
.. 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 nin_block(num_channels, kernel_size, strides, padding):
blk = nn.Sequential()
blk.add(nn.Conv2D(num_channels, kernel_size, strides, padding,
activation='relu'),
nn.Conv2D(num_channels, kernel_size=1, activation='relu'),
nn.Conv2D(num_channels, kernel_size=1, activation='relu'))
return blk
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import torch
from torch import nn
from d2l import torch as d2l
def nin_block(in_channels, out_channels, kernel_size, strides, padding):
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),
nn.ReLU(),
nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import tensorflow as tf
from d2l import tensorflow as d2l
def nin_block(num_channels, kernel_size, strides, padding):
return tf.keras.models.Sequential([
tf.keras.layers.Conv2D(num_channels, kernel_size, strides=strides,
padding=padding, activation='relu'),
tf.keras.layers.Conv2D(num_channels, kernel_size=1,
activation='relu'),
tf.keras.layers.Conv2D(num_channels, kernel_size=1,
activation='relu')])
.. raw:: html
.. raw:: html
NiN Modeli
----------
Orijinal NiN ağı, AlexNet'ten kısa bir süre sonra önerildi ve açıkçası
ondan biraz ilham almıştır. NiN, :math:`11\times 11`, :math:`5\times 5`
ve :math:`3\times 3` pencere şekilleri ile evrişimli katmanlar kullanır
ve karşılık gelen çıktı kanalı sayıları AlexNet'teki ile aynıdır. Her
NiN bloğunu, 2'lik bir adım ve :math:`3\times 3`'lük bir pencere şekli
ile bir maksimum ortaklama katmanı izler.
NiN ve AlexNet arasındaki önemli bir fark, NiN'in tam bağlı katmanlardan
kaçınmasıdır. Bunun yerine NiN, etiket sınıflarının sayısına eşit sayıda
çıktı kanalı içeren bir NiN bloğu kullanır ve onun ardından gelen
*global* ortalama ortaklama katmanı ile bir logit vektörü oluşturur.
NiN'in tasarımının bir avantajı, gerekli model parametrelerinin sayısını
önemli ölçüde azaltmasıdır. Bununla birlikte, pratikte, bu tasarım bazen
artan model eğitim süresi gerektirir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = nn.Sequential()
net.add(nin_block(96, kernel_size=11, strides=4, padding=0),
nn.MaxPool2D(pool_size=3, strides=2),
nin_block(256, kernel_size=5, strides=1, padding=2),
nn.MaxPool2D(pool_size=3, strides=2),
nin_block(384, kernel_size=3, strides=1, padding=1),
nn.MaxPool2D(pool_size=3, strides=2),
nn.Dropout(0.5),
# 10 etiket sınıfı var
nin_block(10, kernel_size=3, strides=1, padding=1),
# Global ortalama ortaklama katmanı, pencere şeklini girdinin
# yüksekliğine ve genişliğine otomatik olarak ayarlar
nn.GlobalAvgPool2D(),
# Dört boyutlu çıktıyı (toplu iş boyutu, 10)
# şeklinde iki boyutlu çıktıya dönüştür
nn.Flatten())
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
net = nn.Sequential(
nin_block(1, 96, kernel_size=11, strides=4, padding=0),
nn.MaxPool2d(3, stride=2),
nin_block(96, 256, kernel_size=5, strides=1, padding=2),
nn.MaxPool2d(3, stride=2),
nin_block(256, 384, kernel_size=3, strides=1, padding=1),
nn.MaxPool2d(3, stride=2),
nn.Dropout(0.5),
# 10 etiket sınıfı var
nin_block(384, 10, kernel_size=3, strides=1, padding=1),
nn.AdaptiveAvgPool2d((1, 1)),
# Dört boyutlu çıktıyı (toplu iş boyutu, 10)
# şeklinde iki boyutlu çıktıya dönüştür
nn.Flatten())
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def net():
return tf.keras.models.Sequential([
nin_block(96, kernel_size=11, strides=4, padding='valid'),
tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
nin_block(256, kernel_size=5, strides=1, padding='same'),
tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
nin_block(384, kernel_size=3, strides=1, padding='same'),
tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
tf.keras.layers.Dropout(0.5),
# 10 etiket sınıfı var
nin_block(10, kernel_size=3, strides=1, padding='same'),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Reshape((1, 1, 10)),
# Dört boyutlu çıktıyı (toplu iş boyutu, 10)
# şeklinde iki boyutlu çıktıya dönüştür
tf.keras.layers.Flatten(),
])
.. raw:: html
.. raw:: html
Her bloğun çıktı şeklini görmek için bir veri örneği oluşturuyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.random.uniform(size=(1, 1, 224, 224))
net.initialize()
for layer in net:
X = layer(X)
print(layer.name, 'cikti sekli:\t', X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
sequential1 cikti sekli: (1, 96, 54, 54)
pool0 cikti sekli: (1, 96, 26, 26)
sequential2 cikti sekli: (1, 256, 26, 26)
pool1 cikti sekli: (1, 256, 12, 12)
sequential3 cikti sekli: (1, 384, 12, 12)
pool2 cikti sekli: (1, 384, 5, 5)
dropout0 cikti sekli: (1, 384, 5, 5)
sequential4 cikti sekli: (1, 10, 5, 5)
pool3 cikti sekli: (1, 10, 1, 1)
flatten0 cikti sekli: (1, 10)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.rand(size=(1, 1, 224, 224))
for layer in net:
X = layer(X)
print(layer.__class__.__name__,'cikti sekli:\t', X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Sequential cikti sekli: torch.Size([1, 96, 54, 54])
MaxPool2d cikti sekli: torch.Size([1, 96, 26, 26])
Sequential cikti sekli: torch.Size([1, 256, 26, 26])
MaxPool2d cikti sekli: torch.Size([1, 256, 12, 12])
Sequential cikti sekli: torch.Size([1, 384, 12, 12])
MaxPool2d cikti sekli: torch.Size([1, 384, 5, 5])
Dropout cikti sekli: torch.Size([1, 384, 5, 5])
Sequential cikti sekli: torch.Size([1, 10, 5, 5])
AdaptiveAvgPool2d cikti sekli: torch.Size([1, 10, 1, 1])
Flatten cikti sekli: torch.Size([1, 10])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.random.uniform((1, 224, 224, 1))
for layer in net().layers:
X = layer(X)
print(layer.__class__.__name__,'cikti sekli:\t', X.shape)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Sequential cikti sekli: (1, 54, 54, 96)
MaxPooling2D cikti sekli: (1, 26, 26, 96)
Sequential cikti sekli: (1, 26, 26, 256)
MaxPooling2D cikti sekli: (1, 12, 12, 256)
Sequential cikti sekli: (1, 12, 12, 384)
MaxPooling2D cikti sekli: (1, 5, 5, 384)
Dropout cikti sekli: (1, 5, 5, 384)
Sequential cikti sekli: (1, 5, 5, 10)
GlobalAveragePooling2D cikti sekli: (1, 10)
Reshape cikti sekli: (1, 1, 1, 10)
Flatten cikti sekli: (1, 10)
.. raw:: html
.. raw:: html
Eğitim
------
Daha önce olduğu gibi modeli eğitmek için Fashion-MNIST'i kullanıyoruz.
NiN'in eğitimi AlexNet ve VGG'ninkine benzerdir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.1, 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.998, train acc 0.650, test acc 0.653
2930.3 examples/sec on gpu(0)
.. figure:: output_nin_8ad4f3_39_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.1, 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.364, train acc 0.864, test acc 0.845
3180.3 examples/sec on cuda:0
.. figure:: output_nin_8ad4f3_42_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
lr, num_epochs, batch_size = 0.1, 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.349, train acc 0.872, test acc 0.880
3663.5 examples/sec on /GPU:0
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. figure:: output_nin_8ad4f3_45_2.svg
.. raw:: html
.. raw:: html
Özet
----
- NiN, evrişimli bir tabaka ve birden fazla :math:`1\times 1` evrişimli
katmanlardan oluşan bloklar kullanır. Bu, piksel başına daha fazla
doğrusal olmayan işleve izin vermek için evrişimli yığın içinde
kullanılabilir.
- NiN, tam bağlı katmanları kaldırır ve onları kanal sayısını istenen
çıktı sayısına indirdikten sonra (örneğin, Fashion-MNIST için 10)
küresel ortalama ortaklama ile yer değiştirir (yani, tüm konumlar
üzerinden toplar).
- Tam bağlı katmanların çıkarılması aşırı öğrenmeyi azaltır. NiN önemli
ölçüde daha az parametreye sahiptir.
- NiN tasarımı, müteakip birçok CNN tasarımını etkiledi.
Alıştırmalar
------------
1. Sınıflandırma doğruluğunu artırmak için hiper parametreleri
ayarlayın.
2. NiN bloğunda neden iki :math:`1\times 1` evrişimli katman var?
Bunlardan birini çıkarın, deneysel olguları gözlemleyin ve
çözümleyin.
3. NiN için kaynak kullanımını hesaplayın.
1. Parametrelerin sayısı nedir?
2. Hesaplama miktarı nedir?
3. Eğitim sırasında ihtiyaç duyulan bellek miktarı nedir?
4. Tahmin sırasında gereken bellek miktarı nedir?
4. :math:`384 \times 5 \times 5` gösterimini bir adımda
:math:`10 \times 5 \times 5` gösterimine indirgeme ile ilgili olası
sorunlar nelerdir?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html