Saya melihat dokumen tensorflow tentang di tf.nn.conv2d
sini . Tetapi saya tidak dapat memahami apa yang dilakukannya atau apa yang ingin dicapai. Dikatakan di dokumen,
# 1: Meratakan filter ke matriks 2-D dengan bentuk
[filter_height * filter_width * in_channels, output_channels]
.
Sekarang apa fungsinya? Apakah itu perkalian bijak atau hanya perkalian matriks biasa? Saya juga tidak dapat memahami dua poin lainnya yang disebutkan dalam dokumen. Saya telah menuliskannya di bawah ini:
# 2: Mengekstrak patch citra dari tensor input untuk membentuk tensor virtual
[batch, out_height, out_width, filter_height * filter_width * in_channels]
.# 3: Untuk setiap tambalan, perbanyak kanan matriks filter dan vektor tambalan gambar.
Akan sangat membantu jika ada yang bisa memberikan contoh, sepotong kode (sangat membantu) mungkin dan menjelaskan apa yang terjadi di sana dan mengapa operasinya seperti ini.
Saya sudah mencoba mengkodekan sebagian kecil dan mencetak bentuk operasi. Tetap saja, saya tidak bisa mengerti.
Saya mencoba sesuatu seperti ini:
op = tf.shape(tf.nn.conv2d(tf.random_normal([1,10,10,10]),
tf.random_normal([2,10,10,10]),
strides=[1, 2, 2, 1], padding='SAME'))
with tf.Session() as sess:
result = sess.run(op)
print(result)
Saya memahami potongan-potongan jaringan saraf konvolusional. Saya mempelajarinya di sini . Tetapi implementasi pada tensorflow tidak seperti yang saya harapkan. Jadi itu menimbulkan pertanyaan.
EDIT : Jadi, saya menerapkan kode yang lebih sederhana. Tapi saya tidak tahu apa yang sedang terjadi. Maksud saya bagaimana hasilnya seperti ini. Akan sangat membantu jika ada yang bisa memberi tahu saya proses apa yang menghasilkan keluaran ini.
input = tf.Variable(tf.random_normal([1,2,2,1]))
filter = tf.Variable(tf.random_normal([1,1,1,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
print("input")
print(input.eval())
print("filter")
print(filter.eval())
print("result")
result = sess.run(op)
print(result)
keluaran
input
[[[[ 1.60314465]
[-0.55022103]]
[[ 0.00595062]
[-0.69889867]]]]
filter
[[[[-0.59594476]]]]
result
[[[[-0.95538563]
[ 0.32790133]]
[[-0.00354624]
[ 0.41650501]]]]
sumber
tf.nn.conv2d()
, jadi metode yang dimaksud tidak digunakan sama sekali ketika kita menggunakan TF dengan dukungan GPU, kecualiuse_cudnn_on_gpu=False
ditentukan secara eksplisit.Jawaban:
Konvolusi 2D dihitung dengan cara yang sama seperti cara menghitung konvolusi 1D : Anda menggeser kernel ke atas input, menghitung perkalian berdasarkan elemen, dan menjumlahkannya. Tetapi alih-alih kernel / input Anda menjadi sebuah array, inilah matriksnya.
Pada contoh paling dasar tidak ada padding dan stride = 1. Mari kita asumsikan
input
dankernel
adalah:Ketika Anda menggunakan kernel Anda, Anda akan menerima keluaran berikut:, yang dihitung dengan cara berikut:
Fungsi konv2 TF menghitung konvolusi dalam batch dan menggunakan format yang sedikit berbeda. Sebagai masukan, ini
[batch, in_height, in_width, in_channels]
untuk kernel[filter_height, filter_width, in_channels, out_channels]
. Jadi kami perlu menyediakan data dalam format yang benar:import tensorflow as tf k = tf.constant([ [1, 0, 1], [2, 1, 0], [0, 0, 1] ], dtype=tf.float32, name='k') i = tf.constant([ [4, 3, 1, 0], [2, 1, 0, 1], [1, 2, 4, 1], [3, 1, 0, 2] ], dtype=tf.float32, name='i') kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel') image = tf.reshape(i, [1, 4, 4, 1], name='image')
Setelah itu konvolusi dihitung dengan:
res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID")) # VALID means no padding with tf.Session() as sess: print sess.run(res)
Dan akan setara dengan yang kami hitung dengan tangan.
Untuk contoh padding / langkah, lihat di sini .
sumber
Ok saya rasa ini tentang cara termudah untuk menjelaskan semuanya.
Contoh Anda adalah 1 gambar, ukuran 2x2, dengan 1 saluran. Anda memiliki 1 filter, dengan ukuran 1x1, dan 1 saluran (ukuran tinggi x lebar x saluran x jumlah filter).
Untuk kasus sederhana ini, gambar saluran 2x2, 1 yang dihasilkan (ukuran 1x2x2x1, jumlah gambar x tinggi x lebar xx saluran) adalah hasil perkalian nilai filter dengan setiap piksel gambar.
Sekarang mari kita coba lebih banyak saluran:
input = tf.Variable(tf.random_normal([1,3,3,5])) filter = tf.Variable(tf.random_normal([1,1,5,1])) op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
Di sini gambar 3x3 dan filter 1x1 masing-masing memiliki 5 saluran. Citra yang dihasilkan akan berukuran 3x3 dengan 1 kanal (ukuran 1x3x3x1), dimana nilai tiap piksel adalah produk titik melintasi kanal filter dengan piksel yang sesuai pada citra masukan.
Sekarang dengan filter 3x3
input = tf.Variable(tf.random_normal([1,3,3,5])) filter = tf.Variable(tf.random_normal([3,3,5,1])) op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
Disini kita mendapatkan gambar 1x1, dengan 1 channel (ukuran 1x1x1x1). Nilainya adalah jumlah dari 9 produk titik 5 elemen. Tetapi Anda bisa menyebutnya sebagai perkalian titik 45 elemen.
Sekarang dengan gambar yang lebih besar
input = tf.Variable(tf.random_normal([1,5,5,5])) filter = tf.Variable(tf.random_normal([3,3,5,1])) op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
Outputnya berupa gambar 1 saluran 3x3 (ukuran 1x3x3x1). Masing-masing nilai ini adalah jumlah dari 9 produk titik 5 elemen.
Setiap keluaran dibuat dengan memusatkan filter pada salah satu dari 9 piksel tengah gambar masukan, sehingga tidak ada filter yang menonjol. The
x
s bawah mewakili pusat filter untuk setiap keluaran pixel.Sekarang dengan padding "SAMA":
input = tf.Variable(tf.random_normal([1,5,5,5])) filter = tf.Variable(tf.random_normal([3,3,5,1])) op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
Ini memberikan gambar keluaran 5x5 (ukuran 1x5x5x1). Ini dilakukan dengan memusatkan filter di setiap posisi pada gambar.
Salah satu produk titik 5 elemen yang filternya menonjol melewati tepi gambar akan mendapatkan nilai nol.
Jadi sudut-sudutnya hanyalah penjumlahan dari 4, hasil perkalian 5-elemen titik.
Sekarang dengan banyak filter.
input = tf.Variable(tf.random_normal([1,5,5,5])) filter = tf.Variable(tf.random_normal([3,3,5,7])) op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
Ini masih memberikan gambar keluaran 5x5, tetapi dengan 7 saluran (ukuran 1x5x5x7). Dimana setiap saluran diproduksi oleh salah satu filter di set.
Sekarang dengan langkah 2,2:
input = tf.Variable(tf.random_normal([1,5,5,5])) filter = tf.Variable(tf.random_normal([3,3,5,7])) op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
Sekarang hasilnya masih ada 7 channel, tapi hanya 3x3 (ukuran 1x3x3x7).
Ini karena alih-alih memusatkan filter di setiap titik pada gambar, filter dipusatkan di setiap titik lain pada gambar, mengambil langkah (langkah) lebar 2. Di
x
bawah ini mewakili pusat filter untuk setiap piksel keluaran, di gambar masukan.Dan tentu saja input dimensi pertama adalah jumlah gambar sehingga Anda dapat menerapkannya pada 10 gambar, misalnya:
input = tf.Variable(tf.random_normal([10,5,5,5])) filter = tf.Variable(tf.random_normal([3,3,5,7])) op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
Ini melakukan operasi yang sama, untuk setiap gambar secara terpisah, memberikan tumpukan 10 gambar sebagai hasilnya (ukuran 10x3x3x7)
sumber
Must have strides[0] = strides[3] = 1. For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1].
the 3x3 image and the 1x1 filter each have 5 channels
, saya menemukan hasilnya berbeda dari perkalian titik yang dihitung secara manual.Hanya untuk menambah jawaban lainnya, Anda harus memikirkan parameter di
filter = tf.Variable(tf.random_normal([3,3,5,7]))
sebagai '5' sesuai dengan jumlah saluran di setiap filter. Setiap filter adalah kubus 3d, dengan kedalaman 5. Kedalaman filter Anda harus sesuai dengan kedalaman gambar input Anda. Parameter terakhir, 7, harus dianggap sebagai jumlah filter dalam kelompok. Lupakan saja ini adalah 4D, dan sebagai gantinya bayangkan Anda memiliki satu set atau sekumpulan 7 filter. Apa yang Anda lakukan adalah membuat 7 kubus filter dengan dimensi (3,3,5).
Jauh lebih mudah untuk divisualisasikan dalam domain Fourier karena konvolusi menjadi perkalian yang bijaksana. Untuk gambar masukan dimensi (100.100,3) Anda dapat menulis ulang dimensi filter sebagai
filter = tf.Variable(tf.random_normal([100,100,3,7]))
Untuk mendapatkan salah satu dari 7 peta fitur keluaran, kita cukup melakukan perkalian titik-bijak dari kubus filter dengan kubus gambar, lalu kita menjumlahkan hasilnya di seluruh dimensi saluran / kedalaman (ini 3), menciut menjadi 2d (100.100) peta fitur. Lakukan ini dengan setiap kubus filter, dan Anda mendapatkan 7 peta fitur 2D.
sumber
Saya mencoba menerapkan konv2 (untuk studi saya). Nah, saya menulis bahwa:
def conv(ix, w): # filter shape: [filter_height, filter_width, in_channels, out_channels] # flatten filters filter_height = int(w.shape[0]) filter_width = int(w.shape[1]) in_channels = int(w.shape[2]) out_channels = int(w.shape[3]) ix_height = int(ix.shape[1]) ix_width = int(ix.shape[2]) ix_channels = int(ix.shape[3]) filter_shape = [filter_height, filter_width, in_channels, out_channels] flat_w = tf.reshape(w, [filter_height * filter_width * in_channels, out_channels]) patches = tf.extract_image_patches( ix, ksizes=[1, filter_height, filter_width, 1], strides=[1, 1, 1, 1], rates=[1, 1, 1, 1], padding='SAME' ) patches_reshaped = tf.reshape(patches, [-1, ix_height, ix_width, filter_height * filter_width * ix_channels]) feature_maps = [] for i in range(out_channels): feature_map = tf.reduce_sum(tf.multiply(flat_w[:, i], patches_reshaped), axis=3, keep_dims=True) feature_maps.append(feature_map) features = tf.concat(feature_maps, axis=3) return features
Semoga saya melakukannya dengan benar. Diperiksa di MNIST, memiliki hasil yang sangat dekat (tetapi penerapan ini lebih lambat). Saya harap ini membantu Anda.
sumber
Selain jawaban lain, operasi konv2d beroperasi di c ++ (cpu) atau cuda untuk mesin gpu yang perlu meratakan dan membentuk kembali data dengan cara tertentu dan menggunakan perkalian matriks gemmBLAS atau cuBLAS (cuda).
sumber
Ini melakukan konvulsi melalui gambar ketika Anda mencoba misalnya fungsi klasifikasi gambar yang memiliki semua parameter yang diperlukan untuk melakukan itu.
Bila pada dasarnya Anda dapat memilih dimensi filter. Langkah. Lapisan. Sebelum digunakan perlu undestant konsep konvolusi
sumber