Tensorflow'un tf.nn.max_pool'unda 'SAME' ve 'VALID' dolgusu arasındaki fark nedir?


309

'AYNI' ve 'GEÇERLİ' dolgu arasındaki fark nedir tf.nn.max_poolait tensorflow?

Bence 'VALID', maksimum havuz yaptığımızda kenarların dışında sıfır dolgu olmayacağı anlamına geliyor.

Derin öğrenme için evrişim aritmetiği rehberine göre , havuz operatöründe dolgu olmayacağını, yani sadece 'VALID' kullanacağını söylüyor tensorflow. Ancak, maksimum havuzun 'AYNI' dolgusu tensorflownedir?


3
Kontrol tensorflow.org/api_guides/python/... detaylar için, bu tf yapmış nasıl.
GabrielChu


4
Dolgu ve adımların nasıl çalıştığını anlamak için bu şaşırtıcı giflere göz atın. Bağlantı
Deepak

1
@GabrielChu bağlantınız öldü ve artık genel bir bakışa yönlendiriliyor.
matt

Tensorflow 2.0'a yükseldikçe, şeylerin yerini Keras alacak ve sanırım havuz bilgilerini Keras belgelerinde bulabileceğinize inanıyorum. @matt
GabrielChu

Yanıtlar:


163

Açıklığa kavuşturmak için bir örnek vereceğim:

  • x: şekil [2, 3], 1 kanal giriş görüntüsü
  • valid_pad: 2x2 çekirdeğe sahip maksimum havuz, 2. adım ve VALID dolgu.
  • same_pad: 2x2 çekirdeğe sahip maksimum havuz, 2. adım ve AYNI dolgu (bu klasik yol)

Çıktı şekilleri:

  • valid_pad: burada, dolgu yok, böylece çıkış şekli [1, 1]
  • same_pad: burada, görüntüyü [2, 4] şekline yerleştiriyoruz ( -infve sonra maksimum havuz uygulayarak), böylece çıkış şekli [1, 2]

x = tf.constant([[1., 2., 3.],
                 [4., 5., 6.]])

x = tf.reshape(x, [1, 2, 3, 1])  # give a shape accepted by tf.nn.max_pool

valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

valid_pad.get_shape() == [1, 1, 1, 1]  # valid_pad is [5.]
same_pad.get_shape() == [1, 1, 2, 1]   # same_pad is  [5., 6.]


603

Eğer ascii sanat isterseniz:

  • "VALID" = dolgu olmadan:

       inputs:         1  2  3  4  5  6  7  8  9  10 11 (12 13)
                      |________________|                dropped
                                     |_________________|
  • "SAME" = sıfır dolgu ile:

                   pad|                                      |pad
       inputs:      0 |1  2  3  4  5  6  7  8  9  10 11 12 13|0  0
                   |________________|
                                  |_________________|
                                                 |________________|

Bu örnekte:

  • Giriş genişliği = 13
  • Filtre genişliği = 6
  • Adım = 5

Notlar:

  • "VALID" yalnızca en sağdaki sütunları (veya en alt satırları) düşürür.
  • "SAME" eşit olarak sola ve sağa doldurmaya çalışır, ancak eklenecek sütun miktarı garip ise, bu örnekte olduğu gibi sağa ekstra sütun ekler (aynı mantık dikey olarak uygulanır: fazladan bir satır olabilir altındaki sıfırlar).

Düzenle :

Adı hakkında:

  • İle "SAME"1 olarak adım kullanırsanız dolgusu, katmanın çıkışları olacaktır aynı onun girdi olarak mekansal boyutları.
  • "VALID"Dolgu ile "tamamlanmış" dolum girişi yoktur. Katman yalnızca geçerli giriş verileri kullanır .

"AYNI" demek, görüntü genişliği filtre genişliğinin katı değilse veya görüntü yüksekliği filtre yüksekliğinin katı değilse, filtre boyutunun değişmesi gerekmediğinden emin olmak için sıfır dolgu kullanın anlamına gelir mi? "? Gibi, genişlik sorun ise "filtre genişliği katına kadar sıfır ile yastık"?
İstatistiklerSorceress

2
Kendi yan sorumu cevaplıyorum: HAYIR, sıfır doldurma noktası değil. Girişle çalışmak için filtre boyutunu (sıfır dolgu dahil) seçersiniz, ancak filtre boyutundan sonra sıfır dolgusunu seçmezsiniz.
StatsSorceress

@StatsSorceress yanıtını anlamıyorum. Bana öyle geliyor ki, tüm girdilerin bir filtre tarafından kapsanması için yeterli sıfır (mümkün olduğunca simetrik bir şekilde) ekliyorsunuz, değil mi?
guillefix

2
Büyük cevap, sadece eklemek için: Tensör değerlerinin negatif olması durumunda, max_pooling için dolgu ile -inf.
Tones29

Ya ksize = 2, stride = 2 ve SAME dolgusu olduğunda giriş genişliği çift bir sayı ise? ... o zaman sıfır dolgulu doğru olmamalı mı? .... Darkflow kod repo'ya baktığımda bunu söylüyorum , maxameing görüntü genişliği 416 piksel genişlikten 208 piksele düşürüldükten sonra, maxpool için SAME pad, stride = 2, ksize = 2 kullanıyorlar. Bunu açıklığa kavuşturan var mı?
K.vindi

161

Tüm stride1 (havuzu daha kıvrım daha tipik) olup, aşağıdaki ayrım düşünebiliriz:

  • "SAME": çıktı boyutu giriş boyutuyla aynı . Bu, filtre penceresinin giriş haritasının dışına kaymasını gerektirir, bu nedenle ped ihtiyacı vardır.
  • "VALID": Filtre penceresi giriş haritasının içinde geçerli konumda kalır , bu nedenle çıktı boyutu küçülür filter_size - 1. Dolgu meydana gelmez.

65
Sonunda yardımcı oldu. Bu noktaya kadar, ortaya çıktı SAMEve VALIDde denilebilir foovebar
omatai

7
Bence "çıktı boyutu giriş boyutu aynı " sadece adım uzunluğu 1 olduğunda doğrudur.
omsrisagar

92

TensorFlow Kıvrım , örneğin arasındaki fark ile ilgili genel bir bakış sağlar SAMEve VALID:

  • İçin SAMEdolgu, çıkış yükseklik ve genişlik olarak hesaplanır:

    out_height = ceil(float(in_height) / float(strides[1]))
    out_width  = ceil(float(in_width) / float(strides[2]))

Ve

  • İçin VALIDdolgu, çıkış yükseklik ve genişlik olarak hesaplanır:

    out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
    out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))

46

Dolgu, giriş verilerinin boyutunu arttırma işlemidir. 1 boyutlu veri durumunda, diziyi sabit bir şekilde ekler / başına eklersiniz, 2-dim'de bu sabitlerle çevreleyen matris. N-dim'de n-dim hiper küpünüzü sabitle çevrelersiniz. Çoğu durumda bu sabit sıfırdır ve sıfır dolgusu olarak adlandırılır.

p=12-d tensöre uygulanan sıfır dolgulu bir örnek : resim açıklamasını buraya girin


Çekirdeğiniz için rasgele dolgu kullanabilirsiniz, ancak dolgu değerlerinden bazıları diğerlerinden daha sık kullanılır:

  • VALID dolgu . En kolay durum, hiç dolgu olmadığı anlamına gelir. Sadece verilerinizi olduğu gibi bırakın.
  • AYNI dolgu bazen YARIM dolgu olarak da adlandırılır . SAME olarak adlandırılır, çünkü adım = 1 olan bir evrişim için (veya havuzlama için) girdiyle aynı boyutta çıktı üretmelidir. YARIM olarak adlandırılır, çünkü bir boyutta çekirdek içink resim açıklamasını buraya girin
  • TAM dolgu , sadece yastıklı elemanlar üzerinde kıvrılma ile sonuçlanmayan maksimum dolgudur. Boyutlu bir çekirdek için kbu dolgu eşittir k - 1.

TF'de keyfi dolgu kullanmak için şunları kullanabilirsiniz: tf.pad()


32

Hızlı Açıklama

VALID: Herhangi bir dolgu uygulamayın, yani tüm boyutların geçerli olduğunu varsayın böylece giriş görüntüsü belirttiğiniz filtre ve adımla tamamen kaplanır.

SAME: Girdi görüntüsünün filtre ile tam olarak kaplanması ve belirttiğiniz adımda girmesi için girişe dolgu (gerekirse) uygulayın. Adım 1 için bu, çıktı resim boyutunun aynı olmasını sağlayacaktır girişle olmasını sağlar.

notlar

  • Bu, aynı zamanda hem havuz katmanları hem de maksimum havuz katmanları için geçerlidir
  • Görüntünün bir kısmını düşürürseniz işler "geçersiz" hale gelmediği için "geçerli" terimi yanlış bir isimdir. Bazen bunu bile isteyebilirsiniz. Bu muhtemelen çağrılmış olmalıNO_PADDING yerine .
  • "Aynı" terimi de yanlış adlandırmadır çünkü çıktı boyutu giriş boyutuyla aynı olduğunda yalnızca adım 1 için anlamlıdır. Adım 2 için, örneğin çıktı boyutları yarı olacaktır. Bunun AUTO_PADDINGyerine büyük olasılıkla çağrılmış olmalıydı .
  • In SAMEhem sol ve sağda (yani otomatik ped modu), Tensorflow eşit yayılmış dolgu çalışacaktır.
  • In VALIDfiltre ve adım tam kapak giriş görüntüsünü yapmazsa (yani hiçbir doldurma modunda), Tensorflow sağ ve / veya alt hücrelerini düşecek.

19

Bu cevabı resmi tensorflow dokümanlarından alıntılıyorum https://www.tensorflow.org/api_guides/python/nn#Convolution 'SAME' dolgusu için çıktı yüksekliği ve genişliği şu şekilde hesaplanır:

out_height = ceil(float(in_height) / float(strides[1]))
out_width  = ceil(float(in_width) / float(strides[2]))

ve üst ve soldaki dolgu şu şekilde hesaplanır:

pad_along_height = max((out_height - 1) * strides[1] +
                    filter_height - in_height, 0)
pad_along_width = max((out_width - 1) * strides[2] +
                   filter_width - in_width, 0)
pad_top = pad_along_height // 2
pad_bottom = pad_along_height - pad_top
pad_left = pad_along_width // 2
pad_right = pad_along_width - pad_left

'VALID' dolgusu için çıkış yüksekliği ve genişliği şu şekilde hesaplanır:

out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width  = ceil(float(in_width - filter_width + 1) / float(strides[2]))

ve dolgu değerleri her zaman sıfırdır.


1
Açıkçası bu sadece geçerli ve eksiksiz bir cevap, 1'in adımlarıyla sınırlı değil. Ve tüm gereken belgelerden bir alıntı. +1
P-Gn

1
Bu yanıtı bulmak için çok yararlı, özellikle de işaret ettiğiniz bağlantı artık çalışmıyor ve Google'ın bu bilgileri tf web sitesinden sildiği anlaşılıyor!
Daniel

12

Üç dolgu seçeneği vardır: geçerli (dolgu yok), aynı (veya yarım), dolu. Açıklamaları (Theano'da) burada bulabilirsiniz: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

  • Geçerli veya dolgu yok:

Geçerli dolgu, sıfır dolgu içermez, bu nedenle yapay olarak oluşturulan sıfırları içermeyen yalnızca geçerli girdiyi kapsar. Eğer adım s = 1 ise, çıkış uzunluğu k (k = 1) için (giriş uzunluğu) - (k-1)) olur.

  • Aynı veya yarım dolgu:

Aynı dolgu, s = 1 olduğunda çıktıların boyutunu girişlerinkiyle aynı yapar. S = 1 ise, doldurulmuş sıfır sayısı (k-1) 'dir.

  • Tam dolgu:

Dolu dolgu, çekirdeğin tüm girdilerin üzerinden geçtiği anlamına gelir, bu nedenle uçlarda çekirdek yalnızca bir girişi ve sıfırları karşılayabilir. Eğer s = 1 ise, doldurulmuş sıfır sayısı 2'dir (k-1). Eğer s = 1 ise çıkış uzunluğu ((giriş uzunluğu) + (k-1)) şeklindedir.

Bu nedenle, dolgu sayısı: (geçerli) <= (aynı) <= (tam)


8

Dolgu açık / kapalı. Girişinizin etkin boyutunu belirler.

VALID:Dolgu yok. Konvolüsyon vb. Ops, yalnızca "geçerli" olan yerlerde, yani tensörünüzün sınırlarına çok yakın olmayan yerlerde gerçekleştirilir.
3x3 çekirdeği ve 10x10 görüntüsü ile, sınırların içindeki 8x8 alanda evrişim yapıyorsunuz.

SAME:Dolgu sağlanır. Operasyonunuz bir mahalleye ne zaman başvurursa (ne kadar büyük olursa olsun), o mahalle orijinal tensörün dışına uzandığında sıfırlanır ve bu işlemin sınır değerleri üzerinde de çalışmasına izin verir.
3x3 çekirdeği ve 10x10 görüntüsü ile, tam 10x10 alanda evrişim gerçekleştiriyor olacaksınız.


8

VALID dolgu: bu sıfır dolgu ile. Umarım karışıklık olmaz.

x = tf.constant([[1., 2., 3.], [4., 5., 6.],[ 7., 8., 9.], [ 7., 8., 9.]])
x = tf.reshape(x, [1, 4, 3, 1])
valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
print (valid_pad.get_shape()) # output-->(1, 2, 1, 1)

AYNI dolgu: Bu, ilk etapta anlaşılması biraz zordur çünkü resmi dokümanlarda belirtildiği gibi iki koşulu ayrı ayrı ele almamız gerekir .

Girdi olarak çıktı olarak , dolgu olarak , adım olarak ve çekirdek boyutunu olarak alalım (sadece tek bir boyut dikkate alınır)

Durum 01 ::

Durum 02 ::

dolgu için alınabilecek minimum değer hesaplanır. Değeri bilindiğinden, değeri bu formül kullanılarak bulunabilir .

Bu örneği inceleyelim:

x = tf.constant([[1., 2., 3.], [4., 5., 6.],[ 7., 8., 9.], [ 7., 8., 9.]])
x = tf.reshape(x, [1, 4, 3, 1])
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
print (same_pad.get_shape()) # --> output (1, 2, 2, 1)

Burada x'in boyutu (3,4) 'tür. Sonra yatay yön alınırsa (3):

Dikey yön alınırsa (4):

Umarım bu TFO'nun aslında SAD dolgusunun nasıl çalıştığını anlamaya yardımcı olacaktır .


7

Buradaki açıklamaya ve Tristan'ın cevabını takip ederek, genellikle bu hızlı işlevleri akıl sağlığı kontrolleri için kullanıyorum.

# a function to help us stay clean
def getPaddings(pad_along_height,pad_along_width):
    # if even.. easy..
    if pad_along_height%2 == 0:
        pad_top = pad_along_height / 2
        pad_bottom = pad_top
    # if odd
    else:
        pad_top = np.floor( pad_along_height / 2 )
        pad_bottom = np.floor( pad_along_height / 2 ) +1
    # check if width padding is odd or even
    # if even.. easy..
    if pad_along_width%2 == 0:
        pad_left = pad_along_width / 2
        pad_right= pad_left
    # if odd
    else:
        pad_left = np.floor( pad_along_width / 2 )
        pad_right = np.floor( pad_along_width / 2 ) +1
        #
    return pad_top,pad_bottom,pad_left,pad_right

# strides [image index, y, x, depth]
# padding 'SAME' or 'VALID'
# bottom and right sides always get the one additional padded pixel (if padding is odd)
def getOutputDim (inputWidth,inputHeight,filterWidth,filterHeight,strides,padding):
    if padding == 'SAME':
        out_height = np.ceil(float(inputHeight) / float(strides[1]))
        out_width  = np.ceil(float(inputWidth) / float(strides[2]))
        #
        pad_along_height = ((out_height - 1) * strides[1] + filterHeight - inputHeight)
        pad_along_width = ((out_width - 1) * strides[2] + filterWidth - inputWidth)
        #
        # now get padding
        pad_top,pad_bottom,pad_left,pad_right = getPaddings(pad_along_height,pad_along_width)
        #
        print 'output height', out_height
        print 'output width' , out_width
        print 'total pad along height' , pad_along_height
        print 'total pad along width' , pad_along_width
        print 'pad at top' , pad_top
        print 'pad at bottom' ,pad_bottom
        print 'pad at left' , pad_left
        print 'pad at right' ,pad_right

    elif padding == 'VALID':
        out_height = np.ceil(float(inputHeight - filterHeight + 1) / float(strides[1]))
        out_width  = np.ceil(float(inputWidth - filterWidth + 1) / float(strides[2]))
        #
        print 'output height', out_height
        print 'output width' , out_width
        print 'no padding'


# use like so
getOutputDim (80,80,4,4,[1,1,1,1],'SAME')

6

Özetle, 'geçerli' dolgu, dolgu olmadığı anlamına gelir. Katlamalı katmanın çıkış boyutu, giriş boyutuna ve çekirdek boyutuna bağlı olarak küçülür.

Aksine, 'aynı' dolgu, dolgu kullanmak anlamına gelir. Adım 1 olarak ayarlandığında, evrişim katmanının çıktı boyutu evrişim hesaplanırken giriş verilerinin etrafına belirli sayıda '0-kenar' ekleyerek giriş boyutu olarak kalır.

Umarım bu sezgisel açıklama yardımcı olur.


5

Genel formül

Burada, W ve H giriş genişliği ve yüksekliği, F filtre boyutları, P dolgu boyutu (yani, doldurulacak satır veya sütun sayısı)

AYNI dolgu için:

AYNI DOLGU

VALID dolgu için:

VALID dolgu


2

YvesgereY'nin harika cevabını tamamlayarak, bu görselleştirmeyi son derece yararlı buldum:

Dolgu görselleştirme

Dolgu ' geçerli ' ilk rakamdır. Filtre penceresi görüntünün içinde kalır.

Dolgu ' aynı ' üçüncü rakamdır. Çıktı aynı boyutta.


Bu makalede buldum .


0

Tensorflow 2.0 Uyumlu Yanıt : Yukarıda "Geçerli" ve "Aynı" Dolgu hakkında ayrıntılı açıklamalar verilmiştir.

Ancak, Tensorflow 2.x (>= 2.0)topluluğun yararına farklı Havuzlama İşlevleri ve ilgili Komutları belirleyeceğim .

1.x'deki fonksiyonlar :

tf.nn.max_pool

tf.keras.layers.MaxPool2D

Average Pooling => None in tf.nn, tf.keras.layers.AveragePooling2D

2.x içindeki fonksiyonlar :

tf.nn.max_pool2.x'de kullanılırsa tf.compat.v1.nn.max_pool_v2veya veya tf.compat.v2.nn.max_pool1.x'ten 2.x'e taşınırsa.

tf.keras.layers.MaxPool2D 2.x'de kullanılırsa ve

tf.compat.v1.keras.layers.MaxPool2Dveya tf.compat.v1.keras.layers.MaxPooling2Dveya tf.compat.v2.keras.layers.MaxPool2Dveya tf.compat.v2.keras.layers.MaxPooling2D, 1.x'ten 2.x'e taşınırsa.

Average Pooling => tf.nn.avg_pool2dveya tf.keras.layers.AveragePooling2DTF 2.x'de kullanılırsa ve

tf.compat.v1.nn.avg_pool_v2veya tf.compat.v2.nn.avg_poolveya tf.compat.v1.keras.layers.AveragePooling2Dveya tf.compat.v1.keras.layers.AvgPool2Dveya tf.compat.v2.keras.layers.AveragePooling2Dveya tf.compat.v2.keras.layers.AvgPool2D, 1.x'ten 2.x'e taşınırsa.

Tensorflow 1.x'ten 2.x'e Geçiş hakkında daha fazla bilgi için lütfen bu Geçiş Kılavuzu'na bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.