Havuzlama ve evrişimli operasyonlar, giriş tensörü boyunca bir "pencere" kaydırır. tf.nn.conv2d
Örnek olarak kullanmak : Eğer giriş tensörünün 4 boyutu varsa:, [batch, height, width, channels]
bu durumda evrişim height, width
boyutlar üzerinde 2B bir pencere üzerinde çalışır .
strides
boyutların her birinde pencerenin ne kadar kayacağını belirler. Tipik kullanım, ilk (toplu iş) ve son (derinlik) adımı 1'e ayarlar.
Çok somut bir örnek kullanalım: 32x32 gri tonlamalı bir giriş görüntüsü üzerinde 2 boyutlu bir evrişim çalıştırma. Gri tonlamalı diyorum çünkü o zaman giriş görüntüsünün derinliği = 1, bu da basit kalmasına yardımcı oluyor. Bu görüntü şöyle görünsün:
00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
Tek bir örnek üzerinde 2x2 evrişim penceresi çalıştıralım (parti boyutu = 1). Evrişime 8 çıkış kanalı derinliği vereceğiz.
Evrişimin girdisi vardır shape=[1, 32, 32, 1]
.
Eğer belirtirseniz strides=[1,1,1,1]
ile padding=SAME
, daha sonra filtrenin çıkış olacaktır [1, 32, 32, 8].
Filtre önce aşağıdakiler için bir çıktı oluşturacaktır:
F(00 01
10 11)
Ve sonra:
F(01 02
11 12)
ve bunun gibi. Ardından ikinci sıraya geçerek şunları hesaplar:
F(10, 11
20, 21)
sonra
F(11, 12
21, 22)
[1, 2, 2, 1] adımını belirtirseniz, örtüşen pencereler oluşmaz. Hesaplayacak:
F(00, 01
10, 11)
ve sonra
F(02, 03
12, 13)
Adım, havuzlama operatörleri için benzer şekilde çalışır.
Soru 2: Konvnetler için neden [1, x, y, 1] adımlar atılıyor?
İlki toplu iştir: Genellikle grubunuzdaki örnekleri atlamak istemezsiniz veya ilk etapta bunları dahil etmemelisiniz. :)
Son 1, evrişimin derinliğidir: Aynı nedenden dolayı genellikle girdileri atlamak istemezsiniz.
Bunu conv2d operatör, daha geneldir olabilir diğer boyutlarla birlikte pencere slayt helezonlar oluşturmak, ama bu convnets tipik bir kullanım değil. Tipik kullanım, onları mekansal olarak kullanmaktır.
Neden -1 -1'e yeniden şekillendirmek , "tam tensör için gereken boyuta uyacak şekilde gerektiği gibi ayarlayın" diyen bir yer tutucudur. Bu, kodun girdi parti boyutundan bağımsız olmasını sağlamanın bir yoludur, böylece ardışık düzeninizi değiştirebilir ve kodun her yerinde parti boyutunu ayarlamanız gerekmez.