Bir CNN'de, her yeni filtrenin her giriş kanalı için farklı ağırlıkları var mı, yoksa giriş kanalları arasında kullanılan her filtrenin aynı ağırlıkları mı?


28

Anladığım kadarıyla, evrişimsel bir sinir ağının evrişim katının dört boyutu vardır: giriş_ kanalları, filtre_ yüksekliği, filtre_ genişliği, sayı_of_ filtreleri. Ayrıca, her yeni filtrenin giriş_ kanallarının (veya önceki katmandaki özellik / aktivasyon haritalarının) TÜMÜ üzerine yoğunlaştığını anlıyorum.

NASIL, CS231'den gelen grafik, her bir filtrenin kanallar arasında kullanılmasından ziyade TEK KANAL'a uygulandığını gösterir (kırmızı). Bu, EACH kanalı için ayrı bir filtre olduğunu gösteriyor gibi görünüyor (bu durumda bir giriş görüntüsünün üç renkli kanalı olduklarını farz ediyorum, ancak aynı tüm giriş kanalları için de geçerli olacaktır).

Bu kafa karıştırıcıdır - her giriş kanalı için farklı bir benzersiz filtre var mı?

görüntü tanımını buraya girin

Kaynak: http://cs231n.github.io/convolutional-networks/

Yukarıdaki resim, O'reilly'nin “Derin Öğrenmenin Temelleri” nden bir alıntıya aykırı görünüyor :

"... filtreler yalnızca tek bir özellik haritasında çalışmazlar. Belirli bir katmanda oluşturulan özellik haritalarının tümünde çalışırlar ... Sonuç olarak, özellik haritaları birimler üzerinde çalışabilmelidir, sadece alanlar değil "

... Ayrıca, aşağıdaki görüntülerin bir AYNI filtrenin sadece üç giriş kanalının (yukarıdaki CS231 grafiğinde gösterilenin aksine) tersine çevrildiğini gösterdiğini gösterdiğini anladım.

görüntü tanımını buraya girin

görüntü tanımını buraya girin


Yanıtlar:


13

Bir evrişimsel sinir ağında, her giriş kanalı için benzersiz bir filtre var mı, yoksa tüm giriş kanalları arasında kullanılan yeni filtreler mi var?

Eski. Aslında, her giriş kanalı / çıkış kanalı kombinasyonu için tanımlanmış ayrı bir çekirdek vardır .

Tipik olarak bir CNN mimarisi için, number_of_filtersparametreniz tarafından tanımlandığı gibi tek bir filtrede , giriş kanalı başına bir 2B çekirdek vardır. Her input_channels * number_of_filtersbiri bir evrişim çekirdeğini tanımlayan ağırlıklar vardır . Bu nedenle, her filtre için giriş kanalı başına bir ağırlık seti gösteren diyagramlar doğrudur. İlk diyagram ayrıca, bu çekirdeklerin uygulanmasının sonuçlarının, onları toplayarak ve her bir çıkış kanalı için önyargı ekleyerek birleştirildiğini açıkça göstermektedir.

Bu , giriş ile aynı derinliğe sahip olan her çıkış kanalı için bir 3B evrişim kullanmak olarak da görülebilir. İkinci diyagramınızın gösterdiği şey de budur ve ayrıca birçok kütüphanenin dahili olarak ne yapacağını gösterir. Matematiksel olarak bu aynı sonuçtur (derinliklerin tam olarak eşleşmesi şartıyla), ancak tabaka tipi tipik olarak "Conv2D" veya benzeri olarak etiketlenir. Benzer şekilde, giriş türünüz voksel veya video gibi doğal olarak 3B ise, o zaman bir "Conv3D" katmanı kullanabilirsiniz, ancak dahili olarak bir 4D evrişimi olarak da uygulanabilir.


Bu açıklama için teşekkürler. Her filtrenin aslında farklı ağırlıklarainput_channels sahip versiyonları varmış gibi geliyor . Bu anlayışı onaylayan bir "resmi" kaynağınız var mı?
Ryan Chase

@RyanChase: Evet doğru. Sadece Andrew Ng’un CNN’ler
Neil Slater

Bu kaynağın ( cs231n.github.io/convolutional-networks ) kaynağında , filtrelerin (ağırlıklar veya çekirdek) hacimler olduğunu (yani 3 boyutlu) ve aynı 3 boyutunun girdilerden birine sahip olduğunu belirtmek isterim. hacmi. Ayrıca, bu kaynakta (en azından) şimdi belirtildiği gibi, filtrenin giriş hacmine daha iyi uygulanmasını görselleştirmek için hacimler 3. boyut boyunca dilimlenmiştir. Genel olarak, "her giriş kanalı / çıkış kanalı birleşimi için tanımlanmış ayrı bir çekirdek olduğunu" sanmıyorum. doğru.
nbro

Filtrelerin (veya çekirdeklerin) öğrenilmesi gereken ağırlıklar olduğuna dikkat edin (yani sabit değiller, ancak aslında CNN'in parametreleridir). Sonunda, 3. boyut boyunca aynı oldukları (yani filtrenin dilimleri) olabilir.
nbro

@ nbro: Evet , çekirdek derinliği kanal sayısıyla aynı olacak şekilde tek bir 3B evrişim olarak birden fazla 2B dilime 2B evrişim uygulayabilirsiniz . Matematiksel olarak bu benim tanımla aynı. Ayrıca, paylaşılan ağırlıklara sahip (çoğu sıfır olan) kesilmiş, tam bağlantılı bir ileri besleme ağı olarak da görüntüleyebilirsiniz. Bu cevap 2D filtrelerin görünümünün ne olduğuna odaklanır, çünkü OP 2D filtrelerin nasıl düzenlendiğini soruyor. Aslında daha büyük bir 3D çekirdeğe düzenlenebilirler, ancak yine de 3B evrimin eşdeğer olduğu "hile" kullanılarak 2B çekirdek olarak uygulanırlar.
Neil Slater

12

Sorunuzda kullandığınız aşağıdaki resim, neler olduğunu tam olarak açıklamaktadır. 3D filtrenin her bir öğesinin (gri küp) farklı bir değerden ( 3x3x3=27değerler) oluştuğunu unutmayın . Böylece, üç farklı 2B boyuttaki filtre , 3x3bu 3B boyuttaki filtreyi oluşturmak için birleştirilebilir 3x3x3.

convnet2D

3x3x3Resim RGB öbek çarpılır elementwise bir yan 3D filtre (gri olarak gösterilmiştir). Bu durumda, filtrenin 3x3x3=27ağırlıkları vardır. Bu ağırlıklar bilge ile çarpıldığında ve sonra toplandığında, bir değer verir.


Yani, her giriş kanalı için ayrı bir filtre var mı?

EVET , görüntüdeki giriş kanalı sayısı kadar 2B filtre vardır . Ancak , birden fazla kanala sahip giriş matrisleri için yalnızca bir 3B filtre olduğunu düşünürseniz yardımcı olur (yukarıdaki resimde gösterildiği gibi).


Öyleyse neden buna 2D evrişimi denir (filtre 3D ise ve giriş matrisi 3D ise)?

Bu 2B evrişimdir, çünkü filtrenin basamakları sadece yükseklik ve genişlik boyutları boyuncadır ( derinlik DEĞİLDİR ) ve bu nedenle bu evrişim tarafından üretilen çıktı aynı zamanda 2B bir matristir. Filtrenin hareket yönü sayısı, evrişimin boyutlarını belirler.

Not: Anlayışınızı , birden fazla 2B filtre yerine (her katman için bir tane) tek bir 3B filtreyi görselleştirerek oluşturursanız, Resnet, InceptionV3 vb. Gibi gelişmiş CNN mimarilerini anlamak için kolay bir zamanınız olur.


bu iyi bir açıklama, fakat daha spesifik olarak anlamaya çalıştığım soru, her giriş kanalında çalışan filtrelerin aynı ağırlıkların kopyaları mı yoksa tamamen farklı ağırlıklar mı olduğu. Bu aslında görüntüde gösterilmemiştir ve aslında bana bu görüntü, her kanala aynı ağırlıkların uygulandığını gösterir (aynı renkten beri) ... Per @neil slater'in cevabı, her ses Filtrenin aslında farklı ağırlıklara input_channelssahip versiyonları vardır . Bu aynı zamanda sizin anlayışınız ise, bunu doğrulayan bir "resmi" kaynak var mı?
Ryan Chase

Evet, gerçekten de, bu benim anlayışım. Benim için, bu gri küpün 27 farklı ağırlık değerinden oluştuğunu düşünmeye çalıştığımda açıktı . Bu, her giriş katmanına uygulanan aynı 2B filtreden ziyade 3 farklı 2B filtre olduğu anlamına gelir.
Mohsin Bukhari

Bunu doğrulamak için herhangi bir resmi kaynak bulamadım. Bununla birlikte, kafamı bu aynı konseptin etrafına sarmaya çalışırken, Tensorflow'ta boş bir girdi ve ağırlık filtresi oluşturdum ve çıktıyı gözlemledim. Bundan memnun oldum. Herhangi bir resmi açıklama bulursam . Cevabımı yukarıda düzenleyeceğim.
Mohsin Bukhari

Tensorflow yolunu izlerseniz. Sahte CNN katmanınıza bir giriş örneği gösterdikten sonra ağırlık filtrenizi yazdırabilirsiniz.
Mohsin Bukhari

@Moshsin Bukhari Kesinlikle TensorFlow içindeki filtreleri keşfetmeye çalışacağım. Filtrelerde bulunanları keşfetme konusunda kodunuzu paylaşmaya istekli misiniz? Örneğin, filtre değerlerini ağdaki her adımda yazdırabiliyor musunuz?
Ryan Chase,

3

Konvolüsyonun sırasıyla girdi ve çıktı kanalları ve ağırlıkları bakımından nasıl çalıştığını daha iyi açıklamak için yukarıda verilen cevapları somut bir örnekle takip ediyorum:

Örnek aşağıdaki gibi olsun (1 ile evrişimli katman):

  • giriş tensörü 9x9x5, yani 5 giriş kanalı, yani input_channels=5
  • filtre / çekirdek boyutu 4x4 ve adım 1
  • çıkış tensörü 6x6x56, yani 56 çıkış kanalı, yani output_channels=56
  • doldurma tipi 'VALID' (yani doldurma yok)

Bunu not ediyoruz:

  • giriş 5 kanala sahip olduğundan, filtre boyutu 4x4x5 olur, yani 4x4 boyutunda 5 ayrı, benzersiz 2B filtre vardır (yani her biri 16 ağırlığa sahiptir); 9x9x5 boyutundaki girişin üzerinde kıvrılmak için filtre 3B olur ve 4x4x5 boyutunda olmalıdır
  • Bu nedenle: Her giriş kanalı için, her biri 16 farklı ağırlığa sahip ayrı bir 2B filtre vardır. Başka bir deyişle, 2B filtrelerin sayısı giriş kanallarının sayısıyla eşleşiyor
  • 56 çıkış kanalı bulunduğundan, 4x4x5 boyutunda 56 3 boyutlu filtre W0, W1, ..., W55 olmalıdır (bkz. CS231 grafiğinde, 2 çıkış için 2 3 boyutlu filtre W0, W1 vardır. 5 boyutunun 3. boyutunun 5 giriş kanalının bağlantısını temsil ettiği kanallar (CS231 grafiğinde her bir 3B filtresinin W0, W1, 3 giriş kanalıyla eşleşen 3. boyut 3'e sahip olduğu)
  • bu nedenle: 3B filtrelerin sayısı, çıkış kanallarının sayısına eşittir

Böylece evrişimli tabaka şunları içerir:

56 4x4x5 ebadında 3-boyutlu filtreler (= her biri 80 farklı ağırlık), her biri 5 girdi 3 ile aynı değerde olan 56 çıkış kanalını hesaba katar. Toplamda var

number_of_filters=input_channel*output_channels=5*56=280

4x4 boyutunda 2D filtreler (toplamda 280x16 farklı ağırlık).


0

2B'de sadece kısıtlamalar var. Niye ya?

Tamamen bağlı bir katman düşünün.

Çok büyük olurdu, her bir nöron belki 1000x1000x3 giriş nöronlarına bağlanacaktı. Ancak, yakın pikselin işlenmesinin bir anlam ifade ettiğini biliyoruz, bu yüzden kendimizi küçük bir 2D-mahallesiyle sınırlandırıyoruz, böylece her bir nöron 2B'deki sadece 3x3 yakınındaki nöronlara bağlı. Kanallar hakkında böyle bir şey bilmiyoruz, bu yüzden tüm kanallara bağlanıyoruz.

Yine de, çok fazla ağırlık olacaktı. Ancak, çeviri değişmezliği nedeniyle, bir alanda iyi çalışan bir filtre farklı bir alanda çok faydalıdır. Bu yüzden 2D'de aynı ağırlık grubunu kullanıyoruz. Yine, kanallar arasında böyle bir çeviri değişmezliği yoktur, dolayısıyla burada böyle bir kısıtlama yoktur.


0

Http://cs231n.github.io/convolutional-networks/ adresindeki "Yerel Bağlantı" bölümüne bakın ve 7-18.

Filtrenin "Alıcı Alan" hiperparametresi, derinlik önceki tabakanın derinliği ile sabitlendiğinden, sadece yükseklik ve genişlik ile tanımlanır.

"Derinlik ekseni boyunca bağlantı derecesinin her zaman giriş hacminin DERİNLİĞİ'ne eşit olduğunu" -veya- etkinleştirme haritasının DERİNLİĞİ (daha sonraki katmanlarda).

Sezgisel olarak, bu görüntü kanalları verilerinin düzlemsel değil serpiştirilmiş olmasından kaynaklanmaktadır. Bu şekilde, filtre uygulamak basitçe sütun vektörleri çarpımı ile elde edilebilir.

Convolutional Network'ün tüm filtre parametrelerini (derinlik boyutu dahil) öğrendiğini ve bunların toplam "h w input_layer_depth + 1 (bias)" olduklarını unutmayın.


0

Yüksek lisans tezimin 2.2.1 bölümünü cevap olarak öneriyorum . Kalan cevaplara eklemek için:

Keras, ne olduğunu anlamak için arkadaşın:

from keras.models import Sequential
from keras.layers import Conv2D

model = Sequential()
model.add(Conv2D(32, input_shape=(28, 28, 3),
          kernel_size=(5, 5),
          padding='same',
          use_bias=False))
model.add(Conv2D(17, (3, 3), padding='same', use_bias=False))
model.add(Conv2D(13, (3, 3), padding='same', use_bias=False))
model.add(Conv2D(7, (3, 3), padding='same', use_bias=False))
model.compile(loss='categorical_crossentropy', optimizer='adam')

print(model.summary())

verir

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 28, 28, 32)        2400      
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 28, 28, 17)        4896      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 28, 28, 13)        1989      
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 28, 28, 7)         819       
=================================================================
Total params: 10,104

Seçeneklerinizi formüle etmeye çalışın. Başka bir şey olursa, parametreler için bu ne anlama gelir?

2400=32(355)

Bu yaklaşım aynı zamanda sadece evrişimli katmanlarla değil, diğer katman türleriyle de yardımcı olur.

Lütfen başka sayısız parametreye sahip olabilecek farklı çözümleri uygulamakta serbestsiniz.


0

Sadece iki ayrıntıyı açıkça belirtmek için:

N-N-3x3N-2N-

N-2N-3x3x

Kendinizi bu konuda ikna etmenin en kolay yolu, diğer senaryolarda neler olduğunu hayal etmek ve hesaplamanın bozulmaya başladığını görmektir - yani sonuçları bir araya getirip yeniden birleştirmezseniz, farklı çıktılar aslında hiçbir şey yapmaz - bunlar birleştirilmiş ağırlıklar ile tek bir çıktı ile aynı etkiye sahip olur.


0

Konvolüsyonların nasıl hesaplandığını anlamaya çalışan herkes için, Pytorch'ta yararlı bir kod pasajı:

batch_size = 1
height = 3 
width = 3
conv1_in_channels = 2
conv1_out_channels = 2
conv2_out_channels = 2
kernel_size = 2
# (N, C_in, H, W) is shape of all tensors. (batch_size, channels, height, width)
input = torch.Tensor(np.arange(0, batch_size*height*width*in_channels).reshape(batch_size, in_channels, height, width))
conv1 = nn.Conv2d(in_channels, conv1_out_channels, kernel_size, bias=False) # no bias to make calculations easier
# set the weights of the convolutions to make the convolutions easier to follow
nn.init.constant_(conv1.weight[0][0], 0.25)
nn.init.constant_(conv1.weight[0][1], 0.5)
nn.init.constant_(conv1.weight[1][0], 1) 
nn.init.constant_(conv1.weight[1][1], 2) 
out1 = conv1(input) # compute the convolution

conv2 = nn.Conv2d(conv1_out_channels, conv2_out_channels, kernel_size, bias=False)
nn.init.constant_(conv2.weight[0][0], 0.25)
nn.init.constant_(conv2.weight[0][1], 0.5)
nn.init.constant_(conv2.weight[1][0], 1) 
nn.init.constant_(conv2.weight[1][1], 2) 
out2 = conv2(out1) # compute the convolution

for tensor, name in zip([input, conv1.weight, out1, conv2.weight, out2], ['input', 'conv1', 'out1', 'conv2', 'out2']):
    print('{}: {}'.format(name, tensor))
    print('{} shape: {}'.format(name, tensor.shape))

Bunu çalıştırmak aşağıdaki çıktıyı verir:

input: tensor([[[[ 0.,  1.,  2.],
          [ 3.,  4.,  5.],
          [ 6.,  7.,  8.]],

         [[ 9., 10., 11.],
          [12., 13., 14.],
          [15., 16., 17.]]]])
input shape: torch.Size([1, 2, 3, 3])
conv1: Parameter containing:
tensor([[[[0.2500, 0.2500],
          [0.2500, 0.2500]],

         [[0.5000, 0.5000],
          [0.5000, 0.5000]]],


        [[[1.0000, 1.0000],
          [1.0000, 1.0000]],

         [[2.0000, 2.0000],
          [2.0000, 2.0000]]]], requires_grad=True)
conv1 shape: torch.Size([2, 2, 2, 2])
out1: tensor([[[[ 24.,  27.],
          [ 33.,  36.]],

         [[ 96., 108.],
          [132., 144.]]]], grad_fn=<MkldnnConvolutionBackward>)
out1 shape: torch.Size([1, 2, 2, 2])
conv2: Parameter containing:
tensor([[[[0.2500, 0.2500],
          [0.2500, 0.2500]],

         [[0.5000, 0.5000],
          [0.5000, 0.5000]]],


        [[[1.0000, 1.0000],
          [1.0000, 1.0000]],

         [[2.0000, 2.0000],
          [2.0000, 2.0000]]]], requires_grad=True)
conv2 shape: torch.Size([2, 2, 2, 2])
out2: tensor([[[[ 270.]],

         [[1080.]]]], grad_fn=<MkldnnConvolutionBackward>)
out2 shape: torch.Size([1, 2, 1, 1])

Konvolüsyonun her bir kanalının önceki tüm kanal çıktılarına göre nasıl toplandığına dikkat edin.

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.