Apa perbedaan antara padding 'SAMA' dan 'VALID' di tf.nn.max_pool of tensorflow?

309

Apa perbedaan antara 'SAMA' dan padding 'VALID' di tf.nn.max_pooldari tensorflow?

Menurut pendapat saya, 'VALID' berarti tidak akan ada bantalan nol di luar tepi ketika kita melakukan max pool.

Menurut A guide to convolution arithmetic untuk pembelajaran mendalam , dikatakan bahwa tidak akan ada padding pada operator pool, yaitu cukup gunakan 'VALID' dari tensorflow. Tapi apa yang dimaksud dengan 'SAMPAIAN' max pool tensorflow?

karl_TUM
sumber
3
Periksa tensorflow.org/api_guides/python/… untuk detailnya, beginilah cara melakukannya.
GabrielChu
3
Inilah jawaban yang cukup terperinci dengan visualisasi .
rbinnun
4
Lihatlah gif menakjubkan ini untuk memahami cara kerja padding dan stride. Tautan
Deepak
1
@GabrielChu tautan Anda tampaknya telah mati dan sekarang menjadi arahan umum.
matt
Saat Tensorflow meningkatkan ke 2.0, segalanya akan digantikan oleh Keras dan saya yakin Anda dapat menemukan informasi pengumpulan dalam dokumentasi Keras. @matt
GabrielChu

Jawaban:

163

Saya akan memberikan contoh untuk membuatnya lebih jelas:

  • x: masukan gambar bentuk [2, 3], 1 saluran
  • valid_pad: max pool dengan kernel 2x2, stride 2 dan VALID padding.
  • same_pad: max pool dengan kernel 2x2, stride 2 dan SAMA padding (ini adalah cara klasik untuk pergi)

Bentuk output adalah:

  • valid_pad: di sini, tidak ada bantalan sehingga bentuk output adalah [1, 1]
  • same_pad: di sini, kami menempelkan gambar ke bentuk [2, 4] (dengan -infdan kemudian menerapkan max pool), jadi bentuk keluaran adalah [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.]

Olivier Moindrot
sumber
603

Jika Anda suka ascii art:

  • "VALID" = tanpa bantalan:

       inputs:         1  2  3  4  5  6  7  8  9  10 11 (12 13)
                      |________________|                dropped
                                     |_________________|
  • "SAME" = dengan nol bantalan:

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

Dalam contoh ini:

  • Lebar input = 13
  • Lebar filter = 6
  • Langkah = 5

Catatan:

  • "VALID" hanya pernah menjatuhkan kolom paling kanan (atau baris paling bawah).
  • "SAME" mencoba untuk pad secara merata kiri dan kanan, tetapi jika jumlah kolom yang akan ditambahkan adalah aneh, itu akan menambahkan kolom tambahan ke kanan, seperti halnya dalam contoh ini (logika yang sama berlaku secara vertikal: mungkin ada baris tambahan dari nol di bagian bawah).

Edit :

Tentang namanya:

  • Dengan "SAME"padding, jika Anda menggunakan langkah 1, output layer akan memiliki dimensi spasial yang sama dengan inputnya.
  • Dengan "VALID"padding, tidak ada input padding "buatan". Lapisan hanya menggunakan data input yang valid .
MiniQuark
sumber
Apakah adil untuk mengatakan "SAMA" berarti "menggunakan zero-padding untuk memastikan ukuran filter tidak harus berubah jika lebar gambar bukan kelipatan dari lebar filter atau tinggi gambar bukan kelipatan dari tinggi filter "? Seperti pada, "pad dengan nol hingga kelipatan lebar filter" jika lebar masalahnya?
StatsSorceress
2
Menjawab pertanyaan saya sendiri: TIDAK, itu bukan inti dari bantalan nol. Anda memilih ukuran filter untuk bekerja dengan input (termasuk bantalan nol), tetapi Anda tidak memilih bantalan nol setelah ukuran filter.
StatsSorceress
Saya tidak mengerti jawaban Anda sendiri @StatsSorceress. Menurut saya, Anda menambahkan angka nol yang cukup (dengan cara sesimetris mungkin) sehingga semua input dilindungi oleh beberapa filter, apakah saya benar?
perbaikan guille
2
Jawaban yang bagus, cukup dengan menambahkan: Jika nilai tensor bisa negatif, padding dengan max_pooling ada bersama -inf.
Nada 29
Bagaimana jika lebar input adalah bilangan genap ketika ksize = 2, stride = 2 dan dengan padding SAMA? ... maka tidak boleh nol-empuk kan? .... Saya mengatakan ini ketika saya melihat repo kode darkflow , mereka menggunakan pad SAMA, melangkah = 2, ksize = 2 untuk maxpool .... setelah lebar gambar maxpooling dikurangi menjadi 208 piksel dari lebar 416 piksel. Adakah yang bisa menjelaskan hal ini?
K.vindi
161

Kapan stride1 (lebih tipikal dengan konvolusi daripada pooling), kita dapat memikirkan perbedaan berikut:

  • "SAME": ukuran output sama dengan ukuran input. Ini membutuhkan jendela filter untuk menyelinap keluar input peta, maka perlu pad.
  • "VALID": Jendela filter tetap pada posisi yang valid di dalam peta input, sehingga ukuran output menyusut filter_size - 1. Tidak ada bantalan terjadi.
YvesgereY
sumber
65
Ini akhirnya membantu. Sampai pada titik ini, tampak bahwa SAMEdan VALIDmungkin juga telah dipanggil foodanbar
omatai
7
Saya pikir "ukuran output sama dengan ukuran input" benar hanya ketika panjang langkahnya adalah 1.
omsrisagar
92

The TensorFlow Konvolusi contoh memberikan gambaran tentang perbedaan antara SAMEdan VALID:

  • Untuk SAMEpadding, tinggi dan lebar output dihitung sebagai:

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

Dan

  • Untuk VALIDpadding, tinggi dan lebar output dihitung sebagai:

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

Padding adalah operasi untuk menambah ukuran data input. Dalam hal data 1-dimensi Anda hanya menambahkan / menambahkan array dengan konstanta, dalam 2-dim Anda mengelilingi matriks dengan konstanta ini. Dalam n-redup Anda mengelilingi hypercube n-redup dengan konstanta. Dalam sebagian besar kasus, konstanta ini adalah nol dan disebut zero-padding.

Berikut adalah contoh zero-padding dengan p=1diterapkan pada tensor 2-d: masukkan deskripsi gambar di sini


Anda dapat menggunakan padding sewenang-wenang untuk kernel Anda tetapi beberapa nilai padding digunakan lebih sering daripada yang lain:

  • Padding VALID . Kasing termudah, berarti tidak ada bantalan sama sekali. Biarkan saja data Anda sama seperti sebelumnya.
  • Padding SAMA terkadang disebut SETENGAH padding . Disebut SAMA karena untuk konvolusi dengan langkah = 1, (atau untuk penyatuan) ia harus menghasilkan output dengan ukuran yang sama dengan input. Disebut HALF karena untuk ukuran kernelk masukkan deskripsi gambar di sini
  • Padding LENGKAP adalah padding maksimum yang tidak menghasilkan lilitan atas elemen hanya empuk. Untuk ukuran kernel k, padding ini sama dengan k - 1.

Untuk menggunakan padding sewenang-wenang dalam TF, Anda dapat menggunakan tf.pad()

Salvador Dali
sumber
32

Penjelasan Cepat

VALID: Jangan gunakan bantalan apa pun, mis., Asumsikan bahwa semua dimensi valid sehingga gambar input sepenuhnya tercakup oleh filter dan langkah yang Anda tentukan.

SAME: Terapkan padding ke input (jika perlu) sehingga gambar input sepenuhnya tertutup oleh filter dan langkah yang Anda tentukan. Untuk langkah 1, ini akan memastikan bahwa ukuran gambar output sama dengan input.

Catatan

  • Ini berlaku untuk lapisan konv serta lapisan kumpulan maks dengan cara yang sama
  • Istilah "valid" sedikit keliru karena hal-hal tidak menjadi "tidak valid" jika Anda melepaskan bagian dari gambar. Terkadang Anda mungkin menginginkan itu. Ini seharusnya disebut NO_PADDINGsebagai gantinya.
  • Istilah "sama" juga keliru karena hanya masuk akal untuk langkah 1 ketika dimensi output sama dengan dimensi input. Untuk langkah 2, dimensi output akan menjadi setengah, misalnya. Ini seharusnya disebut AUTO_PADDINGsebagai gantinya.
  • Dalam SAME(yaitu mode pad-otomatis), Tensorflow akan mencoba untuk menyebar padding secara merata di kiri dan kanan.
  • Dalam VALID(yaitu tanpa mode padding), Tensorflow akan turun sel kanan dan / atau bawah jika filter dan langkah Anda tidak penuh gambar input penutup.
Shital Shah
sumber
19

Saya mengutip jawaban ini dari dokumen resmi tensorflow https://www.tensorflow.org/api_guides/python/nn#Convolution Untuk lapisan 'SAMA', tinggi dan lebar keluaran dihitung sebagai:

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

dan padding di bagian atas dan kiri dihitung sebagai:

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

Untuk lapisan 'VALID', tinggi dan lebar keluaran dihitung sebagai:

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

dan nilai padding selalu nol.

Vaibhav Dixit
sumber
1
Terus terang ini adalah satu-satunya jawaban yang valid dan lengkap, tidak terbatas pada langkah 1. Dan yang diperlukan hanyalah kutipan dari dokumen. +1
P-Gn
1
Sangat berguna untuk mendapatkan jawaban ini, khususnya karena tautan yang Anda tuju tidak berfungsi lagi dan tampaknya Google menghapus informasi itu dari situs web tf!
Daniel
12

Ada tiga pilihan padding: valid (tanpa padding), sama (atau setengah), penuh. Anda dapat menemukan penjelasan (dalam Theano) di sini: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

  • Berlaku atau tidak ada bantalan:

Padding yang valid tidak melibatkan padding nol, sehingga hanya mencakup input yang valid, tidak termasuk nol yang dihasilkan secara buatan. Panjang output adalah ((panjang input) - (k-1)) untuk ukuran kernel k jika langkah s = 1.

  • Padding yang sama atau setengah:

Padding yang sama membuat ukuran output sama dengan input ketika s = 1. Jika s = 1, jumlah nol yang diisi adalah (k-1).

  • Padding penuh:

Padding penuh berarti bahwa kernel menjalankan seluruh input, sehingga pada akhirnya, kernel dapat memenuhi satu-satunya input dan nol lainnya. Jumlah nol yang diisi adalah 2 (k-1) jika s = 1. Panjang output adalah ((panjang input) + (k-1)) jika s = 1.

Oleh karena itu, jumlah bantalan: (valid) <= (sama) <= (penuh)

Mengubah dunia
sumber
8

Padding on / off. Tentukan ukuran efektif input Anda.

VALID:Tidak ada bantalan. Konvolusi dll. Ops hanya dilakukan di lokasi yang "valid", yaitu tidak terlalu dekat dengan batas tensor Anda.
Dengan kernel 3x3 dan gambar 10x10, Anda akan melakukan konvolusi pada area 8x8 di dalam batas.

SAME:Padding disediakan. Setiap kali operasi Anda mereferensikan suatu lingkungan (tidak peduli seberapa besar), nilai nol diberikan ketika lingkungan tersebut melampaui luar tensor asli untuk memungkinkan operasi itu bekerja juga pada nilai batas.
Dengan kernel 3x3 dan gambar 10x10, Anda akan melakukan konvolusi pada area 10x10 penuh.

Laine Mikael
sumber
8

VALID padding: ini dengan zero padding. Semoga tidak ada kebingungan.

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)

Padding SAMA : Ini agak sulit untuk dipahami di tempat pertama karena kita harus mempertimbangkan dua kondisi secara terpisah sebagaimana disebutkan dalam dokumen resmi .

Mari kita ambil input as , output as , padding as , stride as dan ukuran kernel as (hanya dimensi tunggal yang dipertimbangkan)

Kasus 01 ::

Kasus 02 ::

dihitung sedemikian rupa sehingga nilai minimum yang dapat diambil untuk pengisi. Karena nilai diketahui, nilai dapat ditemukan menggunakan rumus ini .

Mari kita kerjakan contoh ini:

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)

Di sini dimensi x adalah (3,4). Kemudian jika arah horizontal diambil (3):

Jika arah vertikal diambil (4):

Semoga ini bisa membantu untuk memahami bagaimana sebenarnya padding SAMA bekerja di TF.

GPrathap
sumber
7

Berdasarkan penjelasan di sini dan menindaklanjuti jawaban Tristan, saya biasanya menggunakan fungsi cepat ini untuk pemeriksaan kewarasan.

# 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')
ahmedhosny
sumber
6

Singkatnya, padding 'valid' berarti tidak ada padding. Ukuran output dari lapisan convolutional menyusut tergantung pada ukuran input & ukuran kernel.

Sebaliknya, padding 'sama' berarti menggunakan padding. Ketika langkahnya diatur sebagai 1, ukuran output dari lapisan convolutional dipertahankan sebagai ukuran input dengan menambahkan sejumlah 'batas 0' di sekitar data input saat menghitung konvolusi.

Semoga deskripsi intuitif ini membantu.

Frederick HONG
sumber
5

Formula Umum

Di sini, W dan H adalah lebar dan tinggi input, F adalah dimensi filter, P adalah ukuran padding (yaitu, jumlah baris atau kolom yang akan diisi)

Untuk padding SAMA:

Padding SAMA

Untuk bantalan VALID:

Padding VALID

Shivam Kushwaha
sumber
2

Melengkapi jawaban hebat YvesgereY, saya menemukan visualisasi ini sangat membantu:

Padding visualisasi

Padding ' valid ' adalah gambar pertama. Jendela filter tetap berada di dalam gambar.

Padding ' sama ' adalah angka ketiga. Outputnya berukuran sama.


Ditemukan di artikel ini .

zmx
sumber
0

Tensorflow 2.0 Kompatibel Jawaban : Penjelasan rinci telah diberikan di atas, tentang "Valid" dan "Sama" Padding.

Namun, saya akan menentukan Fungsi Pooling yang berbeda dan Perintah masing-masing Tensorflow 2.x (>= 2.0), untuk kepentingan masyarakat.

Fungsi dalam 1.x :

tf.nn.max_pool

tf.keras.layers.MaxPool2D

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

Fungsi dalam 2.x :

tf.nn.max_pooljika digunakan dalam 2.x dan tf.compat.v1.nn.max_pool_v2atau tf.compat.v2.nn.max_pool, jika bermigrasi dari 1.x ke 2.x.

tf.keras.layers.MaxPool2D jika digunakan dalam 2.x dan

tf.compat.v1.keras.layers.MaxPool2Datau tf.compat.v1.keras.layers.MaxPooling2Datau tf.compat.v2.keras.layers.MaxPool2Datau tf.compat.v2.keras.layers.MaxPooling2D, jika bermigrasi dari 1.x ke 2.x.

Average Pooling => tf.nn.avg_pool2datau tf.keras.layers.AveragePooling2Djika digunakan dalam TF 2.x dan

tf.compat.v1.nn.avg_pool_v2atau tf.compat.v2.nn.avg_poolatau tf.compat.v1.keras.layers.AveragePooling2Datau tf.compat.v1.keras.layers.AvgPool2Datau tf.compat.v2.keras.layers.AveragePooling2Datau tf.compat.v2.keras.layers.AvgPool2D, jika bermigrasi dari 1.x ke 2.x.

Untuk informasi lebih lanjut tentang Migrasi dari Tensorflow 1.x ke 2.x, silakan merujuk ke Panduan Migrasi ini .

Dukungan Tensorflow
sumber