.. _sec_pooling:
Ortaklama
=========
Çoğu zaman, imgeleri işledikçe, gizli temsillerimizin konumsal
çözünürlüğünü yavaş yavaş azaltmak istiyoruz, böylece ağda ne kadar
yükseğe çıkarsak, her gizli düğümün hassas olduğu alım alanı (girdide) o
kadar büyük olur.
Genellikle esas görevimiz bize imge hakkında küresel bir soru
sormaktadır, örn. *bir kedi içeriyor mu?* Bu nedenle tipik olarak son
katmanımızın birimleri tüm girdiye karşı hassas olmalıdır. Bilgiyi
kademeli olarak toplayarak, daha kaba eşlemeler üreterek, en sonunda
küresel bir gösterimi öğrenme amacını gerçekleştiriyoruz ve bunu
yaparken evrişimli ara katmanlardaki işlemlerin tüm avantajlarını
tutuyoruz.
Dahası, kenarlar gibi (:numref:`sec_conv_layer` içinde tartışıldığına
benzer) alt seviye öznitelikleri tespit ederken, genellikle
temsillerimizin yer değiştirmelerden etkilenmez olmasını isteriz.
Örneğin, siyah beyaz arasında keskin gösterimli bir ``X`` imgesini alıp
tüm imgeyi bir pikselle sağa kaydırırsak, yani
``Z[i, j] = X[i, j + 1]``, yeni imgenin çıktısı çok farklı olabilir.
Kenar bir piksel ile kaydırılmış olacaktır. Gerçekte, nesneler neredeyse
hiç bir zaman aynı yerde olmaz. Aslında, bir tripod ve sabit bir
nesneyle bile, deklanşörün hareketi nedeniyle kameranın titreşimi her
şeyi bir piksel kaydırabilir (üst düzey kameralar bu sorunu gidermek
için özel özelliklerle donatılmıştır).
Bu bölümde, evrişimli katmanların konuma duyarlılığını azaltmak ve
gösterimleri uzaysal örnek seyreltmek gibi ikili amaçlara hizmet eden
*ortaklama katmanları* tanıtılmaktadır.
Maksimum Ortaklama ve Ortalama Ortaklama
----------------------------------------
*Ortaklama* işlemcileri, evrişimli katmanlar gibi, sabit şekilli
pencerenin (bazen *ortaklama penceresi* olarak da bilinir) geçtiği her
konum için tek bir çıktı hesaplayarak, uzun adımına göre girdideki tüm
bölgelere kaydırılan sabit şekilli bir pencereden oluşur. Bununla
birlikte, evrişimli katmandaki girdi ve çekirdeklerin çapraz korelasyon
hesaplamasının aksine, ortaklama katmanı hiçbir parametre içermez
(*çekirdek* yoktur). Bunun yerine, ortaklama uygulayıcıları gerekircidir
(determinist) ve genellikle ortaklama penceresindeki öğelerin maksimum
veya ortalama değerini hesaplar. Bu işlemler sırasıyla *maksimum
ortaklama* (*kısaca ortaklama*) ve *ortalama ortaklama* olarak
adlandırılır.
Her iki durumda da, çapraz korelasyon uygulayıcısında olduğu gibi,
ortaklama penceresinin girdi tensörünün sol üstünden başlayarak girdi
tensörünün soldan sağa ve yukarıdan aşağıya doğru kayması olarak
düşünebiliriz. Ortaklama penceresinin vurduğu her konumda, maksimum veya
ortalama ortaklamanın kullanılmasına bağlı olarak, pencerede girdi alt
tensörünün maksimum veya ortalama değerini hesaplar.
.. _fig_pooling:
.. figure:: ../img/pooling.svg
:math:`2 \times 2` şeklinde bir ortaklama penceresi ile maksimum
ortaklama. Gölgeli kısımlar, ilk çıktı elemanı ve çıktı hesaplaması
için kullanılan girdi tensör elemanlarıdır:
:math:`\max(0, 1, 3, 4)=4`.
:numref:`fig_pooling` içindeki çıktı tensör 2'lik yüksekliğe ve 2'lik
genişliğe sahiptir. Dört öğe, her ortaklama penceresindeki maksimum
değerden türetilir:
.. math::
\max(0, 1, 3, 4)=4,\\
\max(1, 2, 4, 5)=5,\\
\max(3, 4, 6, 7)=7,\\
\max(4, 5, 7, 8)=8.\\
Ortaklama penceresi şeklindeki :math:`p \times q` ortaklama katmanına
:math:`p \times q` ortaklama katmanı denir. Ortaklama işlemi
:math:`p \times q` ortaklama olarak adlandırılır.
Bu bölümün başında belirtilen nesne kenarı algılama örneğine dönelim.
Şimdi :math:`2\times 2` maksimum ortaklama için girdi olarak evrişimli
tabakanın çıktısını kullanacağız. Evrişimli katman girdisini ``X`` ve
ortaklama katmanı çıktısını ``Y`` olarak düzenleyelim. ``X[i, j]`` ve
``X[i, j + 1]`` veya ``X[i, j + 1]`` ve ``X[i, j + 2]`` değerleri farklı
olsa da olmasa da, ortaklama katmanı her zaman ``Y[i, j] = 1`` çıktısını
verir. Yani, :math:`2\times 2` maksimum ortaklama katmanını kullanarak,
evrişimli katman tarafından tanınan desenin yükseklik veya genişlik
olarak birden fazla eleman yine de hareket edip etmediğini tespit
edebiliriz.
Aşağıdaki kodda, ``pool2d`` işlevinde ortaklama katmanının ileri
yaymasını uyguluyoruz. Bu işlev :numref:`sec_conv_layer` içindeki
``corr2d`` işlevine benzer. Ancak, burada çekirdeğimiz yok, çıktıyı
girdideki her bölgenin maksimumu veya ortalaması olarak hesaplıyoruz.
.. 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 pool2d(X, pool_size, mode='max'):
p_h, p_w = pool_size
Y = np.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
if mode == 'max':
Y[i, j] = X[i: i + p_h, j: j + p_w].max()
elif mode == 'avg':
Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
return Y
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import torch
from torch import nn
from d2l import torch as d2l
def pool2d(X, pool_size, mode='max'):
p_h, p_w = pool_size
Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
if mode == 'max':
Y[i, j] = X[i: i + p_h, j: j + p_w].max()
elif mode == 'avg':
Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
return Y
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import tensorflow as tf
def pool2d(X, pool_size, mode='max'):
p_h, p_w = pool_size
Y = tf.Variable(tf.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w +1)))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
if mode == 'max':
Y[i, j].assign(tf.reduce_max(X[i: i + p_h, j: j + p_w]))
elif mode =='avg':
Y[i, j].assign(tf.reduce_mean(X[i: i + p_h, j: j + p_w]))
return Y
.. raw:: html
.. raw:: html
İki boyutlu maksimum ortaklama tabakasının çıktısını doğrulamak için
:numref:`fig_pooling` içinde girdi tensörü ``X``'i inşa ediyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.array([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
pool2d(X, (2, 2))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[4., 5.],
[7., 8.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
pool2d(X, (2, 2))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[4., 5.],
[7., 8.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.constant([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
pool2d(X, (2, 2))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Ayrıca, ortalama ortaklama katmanıyla da deney yapalım.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d(X, (2, 2), 'avg')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[2., 3.],
[5., 6.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d(X, (2, 2), 'avg')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[2., 3.],
[5., 6.]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d(X, (2, 2), 'avg')
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Dolgu ve Uzun Adım
------------------
Evrişimli katmanlarda olduğu gibi, ortaklama katmanları da çıktının
şeklini değiştirebilir. Ayrıca daha önce olduğu gibi, girdiyi
dolgulayarak ve uzun adımı ayarlayarak istenen çıktı şeklini elde etmek
için işlemi değiştirebiliriz. Derin öğrenme çerçevesinden yerleşik iki
boyutlu maksimum ortaklama katmanı aracılığıyla ortaklama katmanlarında
dolgu ve uzun adımların kullanımını gösterebiliriz. İlk olarak dört
boyutlu şekle sahip bir ``X`` girdi tensörü inşa ediyoruz, burada
örneklerin sayısı (iş boyutu) ve kanalların sayısının her ikisi de
1'dir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.arange(16, dtype=np.float32).reshape((1, 1, 4, 4))
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.arange(16, dtype=torch.float32).reshape((1, 1, 4, 4))
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]]]])
.. raw:: html
.. raw:: html
Dikkat edilecek bir husus tensorflow'un *kanallar son sıra* (son eksen)
girdileri tercih ettiği ve ona göre optimize edildiğidir.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.reshape(tf.range(16, dtype=tf.float32), (1, 4, 4, 1))
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Varsayılan olarak, çerçevenin yerleşik sınıfındaki örnekteki uzun adım
ve ortaklama penceresi aynı şekle sahiptir. Aşağıda, ``(3, 3)``
şeklindeki bir ortaklama penceresi kullanıyoruz, bu nedenle varsayılan
olarak ``(3, 3)``'lük bir adım şekli alıyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2D(3)
# Ortaklama katmanında model parametresi olmadığı için parametre
# ilkleme fonksiyonunu çağırmamız gerekmez
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[10.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2d(3)
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[10.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3])
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Uzun adım ve dolgu manuel olarak belirtilebilir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2D(3, padding=1, strides=2)
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[ 5., 7.],
[13., 15.]]]])
Tabii ki, keyfi bir dikdörtgen ortaklama penceresi belirleyebilir ve
sırasıyla yükseklik ve genişlik için dolguyu ve uzun adımı
belirtebiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2D((2, 3), padding=(0, 1), strides=(2, 3))
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[ 5., 7.],
[13., 15.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[ 5., 7.],
[13., 15.]]]])
Tabii ki, keyfi bir dikdörtgen ortaklama penceresi belirleyebilir ve
sırasıyla yükseklik ve genişlik için dolguyu ve uzun adımı
belirtebiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2d((2, 3), stride=(2, 3), padding=(0, 1))
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[ 5., 7.],
[13., 15.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
paddings = tf.constant([[0, 0], [1,0], [1,0], [0,0]])
X_padded = tf.pad(X, paddings, "CONSTANT")
pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3], padding='valid',
strides=2)
pool2d(X_padded)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Tabii ki, keyfi bir dikdörtgen ortaklama penceresi belirleyebilir ve
sırasıyla yükseklik ve genişlik için dolguyu ve uzun adımı
belirtebiliriz.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
paddings = tf.constant([[0, 0], [0, 0], [1, 1], [0, 0]])
X_padded = tf.pad(X, paddings, "CONSTANT")
pool2d = tf.keras.layers.MaxPool2D(pool_size=[2, 3], padding='valid',
strides=(2, 3))
pool2d(X_padded)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Çoklu Kanal
-----------
Çok kanallı girdi verilerini işlerken, ortaklama katmanı, girdileri bir
evrişimli katmanda olduğu gibi kanallar üzerinden toplamak yerine her
girdi kanalını ayrı ayrı ortaklar. Bu, ortaklama katmanının çıktı
kanallarının sayısının girdi kanalı sayısıyla aynı olduğu anlamına
gelir. Aşağıda, 2 kanallı bir girdi oluşturmak için kanal boyutundaki
``X`` ve ``X + 1`` tensörleri birleştiriyoruz.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = np.concatenate((X, X + 1), 1)
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]],
[[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.],
[13., 14., 15., 16.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = torch.cat((X, X + 1), 1)
X
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]],
[[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.],
[13., 14., 15., 16.]]]])
.. raw:: html
.. raw:: html
Bunun, kanallar son sıra sözdizimi nedeniyle TensorFlow için son boyut
boyunca bir birleştirme gerektireceğini unutmayın.
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
X = tf.concat([X, X + 1], 3) # Concatenate along `dim=3` due to channels-last syntax
.. raw:: html
.. raw:: html
Gördüğümüz gibi, çıktı kanallarının sayısı ortaklamadan sonra hala
2'dir.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2D(3, padding=1, strides=2)
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
array([[[[ 5., 7.],
[13., 15.]],
[[ 6., 8.],
[14., 16.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
pool2d(X)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
tensor([[[[ 5., 7.],
[13., 15.]],
[[ 6., 8.],
[14., 16.]]]])
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
paddings = tf.constant([[0, 0], [1,0], [1,0], [0,0]])
X_padded = tf.pad(X, paddings, "CONSTANT")
pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3], padding='valid',
strides=2)
pool2d(X_padded)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
Tensorflow ortaklama çıktısının ilk bakışta farklı göründüğünü, ancak
sayısal olarak aynı sonuçların MXNet ve PyTorch'teki gibi temsil
edildiğini unutmayın. Fark, boyutlulukta yatmaktadır ve çıktıyı dikey
olarak okumak, diğer uygulamalarla aynı çıktıyı verir.
.. raw:: html
.. raw:: html
Özet
----
- Ortaklama penceresinde girdi öğelerini alarak, maksimum ortaklama
işlemi çıktı olarak maksimum değeri atar ve ortalama ortaklama işlemi
ortalama değeri çıktı olarak atar.
- Bir ortaklama tabakasının en önemli avantajlarından biri, evrişimli
tabakanın konumuna aşırı duyarlılığını hafifletmektir.
- Ortaklama katmanı için dolgu ve uzun adım belirtebiliriz.
- Uzamsal boyutları (örn. genişlik ve yükseklik) azaltmak için 1'den
büyük bir uzun adımla birlikte maksimum ortaklama kullanılabilir.
- Ortaklama katmanının çıktı kanalı sayısı, girdi kanallarının
sayısıyla aynıdır.
Alıştırmalar
------------
1. Bir evrişim tabakasının özel bir durumu olarak ortalama ortaklama
uygulayabilir misiniz? Eğer öyleyse, yapınız.
2. Bir evrişim tabakasının özel bir durumu olarak maksimum ortaklama
uygulayabilir misiniz? Eğer öyleyse, yapınız.
3. Ortaklama katmanının hesaplama maliyeti nedir? Ortaklama katmanına
girdi boyutunun :math:`c\times h\times w` olduğunu, ortaklama
penceresinin :math:`p_h\times p_w` bir şekle sahip,
:math:`(p_h, p_w)` dolgulu ve :math:`(s_h, s_w)` uzun adımlı olduğunu
varsayalım.
4. Neden maksimum ortaklama ile ortalama ortaklamanın farklı çalışmasını
beklersiniz?
5. Ayrı bir minimum ortaklama katmanına ihtiyacımız var mıdır? Onu başka
bir işlemle değiştirebilir misiniz?
6. Ortalama ve maksimum ortaklama arasında düşünebileceğiniz başka bir
işlem var mıdır (İpucu: Softmaks'i anımsayın)? Neden o kadar popüler
olmayacaktır?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html