Keras'taki BatchNormalization işlevini nereden çağırabilirim?


168

Keras'ta BatchNormalization işlevini kullanmak istersem, yalnızca başlangıçta bir kez çağırmam gerekir mi?

Bunun için bu belgeleri okudum: http://keras.io/layers/normalization/

Nereye dediğimi anlamıyorum. Kodumu kullanmaya çalışıyorum aşağıdadır:

model = Sequential()
keras.layers.normalization.BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None)
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform'))
model.add(Activation('softmax'))

sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)

Ben kod toplu iş normalleştirme de dahil olmak üzere ikinci satır ile çalıştırmak ve ikinci satır olmadan kodu çalıştırmak eğer ben benzer çıktılar almak çünkü soruyorum. Bu yüzden ya fonksiyonu doğru yere çağırmıyorum ya da sanırım bu o kadar büyük bir fark yaratmıyor.

Yanıtlar:


225

Bu soruyu biraz daha ayrıntılı olarak cevaplamak için ve Pavel'in dediği gibi, Toplu Normalizasyon sadece başka bir katman, böylece istediğiniz ağ mimarisini oluşturmak için bunu kullanabilirsiniz.

Genel kullanım durumu ağınızdaki doğrusal ve doğrusal olmayan katmanlar arasında BN kullanmaktır, çünkü aktivasyon fonksiyonunuzun girişini normalleştirir, böylece aktivasyon fonksiyonunun (Sigmoid gibi) doğrusal bölümünde ortalanırsınız. Burada küçük bir tartışma var

Yukarıdaki durumda, bu şöyle görünebilir:


# import BatchNormalization
from keras.layers.normalization import BatchNormalization

# instantiate model
model = Sequential()

# we can think of this chunk as the input layer
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('tanh'))
model.add(Dropout(0.5))

# we can think of this chunk as the hidden layer    
model.add(Dense(64, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('tanh'))
model.add(Dropout(0.5))

# we can think of this chunk as the output layer
model.add(Dense(2, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('softmax'))

# setting up the optimization of our weights 
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)

# running the fitting
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)

Umarım bu biraz daha netleşir.


25
Görünüşe göre toplu normalizasyon aktivasyon fonksiyonundan sonra pratikte daha iyi çalışır
Claudiu

10
Merhaba @Claudiu, bu FYI üzerinde genişlemeyi düşünür müsün? Yukarıdaki cevapla doğrudan çelişiyor gibi görünüyor.
Ben Ogorek

7
@benogorek: emin bir şey, temelde ben tamamen burada toplu norm relu sonra daha iyi performans yerleştirme sonuçları dayalı . FWIW Denediğim ağda şu ya da bu şekilde uygularken başarılı
Claudiu

32
İlginç. Sadece takip etmek için, bu özette okumaya devam ederseniz, en iyi modellerinin [GoogLeNet128_BN_lim0606] aslında ReLU'dan ÖNCE BN katmanına sahip olduğunu söylüyor. Bu nedenle, Etkinleştirme sonrası BN, yalıtılmış bir durumda, tüm model oluşturulduğunda, en iyi şekilde gerçekleştirilmeden doğruluğu artırabilir. Etkinleştirme sonrasında BN yerleştirmenin doğruluk oranını artırabileceği muhtemeldir, ancak muhtemelen probleme bağlı olabilir.
Lucas Ramazan

7
@ CarlThome türü. Örneğin ReginaldIII'ın bu reddit yorumuna bakın . Şunu belirtiyorlar: "BN, bir evrişimden çıkan özelliklerin dağılımını normalleştiriyor, bu özelliklerin bazıları negatif olabilir [ve] ReLU gibi bir doğrusal olmama tarafından kesilebilir. Etkinleştirmeden önce normalize ederseniz, bu negatif değerleri etkinleştirmeden hemen sonra normalleştirme, bir sonraki evrişim katmanına geçmeyen özelliklerle istatistiksel olarak önyargısız olarak pozitif özellikleri normalleştirecektir. "
mab

60

Bu konu yanıltıcı. Lucas Ramadan'ın cevabı hakkında yorum yapmaya çalıştı, ama henüz doğru ayrıcalıklara sahip değilim, bu yüzden bunu buraya koyacağım.

Toplu normalleştirme en iyi şekilde etkinleştirme işlevinden sonra ve burada veya burada çalışır neden: dahili ortak değişken kaymasını önlemek için geliştirilmiştir. Dahili ortak değişken kayması, aktivasyonların dağılımıbir katmanın eğitim boyunca önemli ölçüde kayması. Toplu normalleştirme, girişlerin (ve bu girişlerin tam anlamıyla bir aktivasyon fonksiyonunun sonucu olduğu) belirli bir katmana dağıtılması, her bir partiden parametre güncellemeleri nedeniyle zamanla değişmemesi için kullanılır (veya en azından, değişmesine izin verir) avantajlı bir şekilde). Normalleştirmeyi yapmak için toplu iş istatistiklerini kullanır ve daha sonra toplu iş normalleştirme parametrelerini (orijinal kağıttaki gama ve beta) kullanır "" ağa eklenen dönüşümün kimlik dönüşümünü temsil edebildiğinden emin olmak için "(orijinal kağıttan alıntı). Ancak mesele şu ki, bir katmandaki girdileri normalleştirmeye çalışıyoruz, bu yüzden her zaman ağdaki bir sonraki katmandan hemen önce gitmelidir. Olsun ya da olmasın '


27
Deeplearning.ai sınıfında Andrew Ng'in Deep Learning topluluğunda bununla ilgili bir tartışma olduğunu söylediğini gördüm. Doğrusallıktan önce toplu normalizasyon uygulamayı tercih ediyor.
shahensha

3
@kRazzyR Profesör Andrew Ng'ın derin öğrenme sınıflarındaki derin öğrenme sınıflarında bu konuyu konuştuğunu kastediyorum . Topluluğun bir şeyler yapmanın doğru yoluna bölündüğünü ve doğrusal olmamadan önce toplu normalizasyon uygulamayı tercih ettiğini söyledi.
shahensha

3
@jmancuso, aktivasyondan önce BN uygulanır. Makalenin kendisinden denklem, etkinleştirme fonksiyonunun g(BN(Wx + b))nerede golduğu.
1919

43

Bu iş parçacığı, BN'nin geçerli katmanın doğrusal olmasından önce mi yoksa önceki katmanın aktivasyonlarına mı uygulanacağı konusunda önemli tartışmalara sahiptir.

Doğru cevap olmamasına rağmen, Toplu Normalizasyon yazarları , mevcut katmanın doğrusal olmasından hemen önce uygulanması gerektiğini söylüyorlar . Nedeni (orijinal kağıttan alıntı) -

"BN dönüşümünü doğrusal olmayanlıktan hemen önce x = Wu + b'yi normalleştirerek ekliyoruz. U katman girişlerini de normalleştirebilirdik, ancak u muhtemelen başka bir doğrusal olmayanlığın çıktısı olduğundan, dağılımının şekli muhtemelen antrenman yapmak ve birinci ve ikinci anlarını kısıtlamak, değişken değişimi ortadan kaldırmaz.Ancak, Wu + b'nin simetrik, seyrek olmayan bir dağılımı olması daha muhtemeldir, yani “daha ​​Gaussian” (Hyv¨arinen ve Oja, 2000) normalleştirmenin kararlı bir dağılımla aktivasyonlar üretmesi muhtemeldir. "


3
Kendi kişisel deneyimime göre, büyük bir fark yaratmıyor, ama her şey eşitken, toplu normalizasyon doğrusal olmayanlıktan önce (aktivasyon fonksiyonundan önce) uygulandığında BN'nin her zaman biraz daha iyi performans gösterdiğini gördüm.
Brad Hesse

31

Keras artık use_bias=Falseseçeneği destekliyor , bu yüzden aşağıdaki gibi yazarak bazı hesaplamaları kaydedebiliriz

model.add(Dense(64, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation('tanh'))

veya

model.add(Convolution2D(64, 3, 3, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation('relu'))

nasıl model.add(BatchNormalization())farklımodel.add(BatchNormalization(axis=bn_axis))
kRazzy R

@kRazzR tensorflow, arka uç olarak kullanmanız farklı değildir . O bu kopyalanan çünkü burada yazılanlardan keras.applicationsmodülü, bn_axisihtiyaçlar hem desteklemek amacıyla belirtilmesi channels_firstve channels_lastbiçimleri.
ldavid

9
Birisi bunun OP sorusuyla nasıl ilgili olduğunu açıklayabilir mi? (
NN'lere oldukça acemiyim,

30

Neredeyse artık etmiş bir eğilim haline geldi Conv2Dbir tarafından takip ReLubir takip BatchNormalizationkatmanın. Bu yüzden hepsini aynı anda çağırmak için küçük bir işlev oluşturdum. Model tanımının çok daha temiz ve okunmasını kolaylaştırır.

def Conv2DReluBatchNorm(n_filter, w_filter, h_filter, inputs):
    return BatchNormalization()(Activation(activation='relu')(Convolution2D(n_filter, w_filter, h_filter, border_mode='same')(inputs)))

7
belki bunu keras'a itmek?
sachinruk

6

Başka bir katman türüdür, bu nedenle modelinizin uygun bir yerine katman olarak eklemelisiniz

model.add(keras.layers.normalization.BatchNormalization())

Buradaki bir örneğe bakın: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py


1
BatchNormalization ekledikten sonra, val_acc her çağın artmasını durdurdu. BatchNormalization ekledikten sonra her çağdan sonra val_acc aynı sayıda durgun kaldı. Ben Toplu Normalizasyon val_acc artırmak gerekiyordu düşündüm. Düzgün çalışıp çalışmadığını nasıl bilebilirim? Buna neyin sebep olabileceğini biliyor musunuz?
pr338

ne yazık ki bağlantı artık geçerli değil :(
user2324712

Bu örneğin Keras çatallarında (örneğin github.com/WenchenLi/kaggle/blob/master/otto/keras/… ) kopyaları var , ancak orijinal Keras deposundan neden kaldırıldığını bilmiyorum ve kodu en son Keras sürümleriyle uyumludur.
Pavel Surmenok

4

Toplu Normalleştirme, giriş katmanının yanı sıra gizli katmanları da aktivasyonların ortalamasını ve ölçeklendirmesini ayarlayarak normalleştirmek için kullanılır. Derin sinir ağlarında ek katman ile bu normalleştirici etki nedeniyle, ağ degradeleri yok etmek veya patlatmaksızın daha yüksek öğrenme oranı kullanabilir. Ayrıca, parti normalizasyonu ağı genellemenin daha kolay olacağı şekilde düzenler ve bu nedenle fazla takmayı azaltmak için çıkarma kullanılmasına gerek yoktur.

Keras'ta say, Dense () veya Conv2D () kullanarak doğrusal işlevi hesapladıktan hemen sonra, bir katmandaki doğrusal işlevi hesaplayan BatchNormalization () kullanırız ve sonra Activation () kullanarak katmana doğrusal olmayanlığı ekleriz.

from keras.layers.normalization import BatchNormalization
model = Sequential()
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('softmax'))

sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True, 
validation_split=0.2, verbose = 2)

Toplu Normalleştirme nasıl uygulanır?

Farz edelim ki, l tabakasına bir [l-1] girdimiz var. Ayrıca l tabakası için ağırlık [W] ve ağırlık birimi b [l] var. L ve z [l] katmanı için hesaplanan aktivasyon vektörü (yani doğrusal olmayanlık eklendikten sonra) olsun [l] doğrusal olmayanlık eklemeden önce vektör olsun

  1. Bir [l-1] ve W [l] kullanarak, l tabakası için z [l] hesaplayabiliriz
  2. Genellikle ileri beslemeli yayılımda, bu aşamada z [l] + b [l] gibi z [l] 'ye önyargı birimi ekleyeceğiz, ancak Toplu Normalizasyonda b [l]' nin bu ekleme adımı gerekli değildir ve hayır b [l] parametresi kullanılır.
  3. Z [l] ortalamalarını hesapla ve her elemandan çıkar
  4. Standart sapmayı kullanarak bölün (z [l] - ortalama). Buna Z_temp [l] de
  5. Şimdi gizli katmanın ölçeğini aşağıdaki gibi değiştirecek yeni parametreler γ ve β tanımlayın:

    z_norm [l] = γ.Z_temp [l] + β

Bu kod alıntısında, Dense () a [l-1] alır, W [l] kullanır ve z [l] değerini hesaplar. Ardından hemen BatchNormalization () yöntemi, z_norm [l] değerini vermek için yukarıdaki adımları gerçekleştirir. Ve sonra hemen Etkinleştirme () tanh (z_norm [l]) değerini [l] yani

a[l] = tanh(z_norm[l])
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.