Di mana saya memanggil fungsi BatchNormalisasi di Keras?

167

Jika saya ingin menggunakan fungsi BatchNormalization di Keras, maka apakah saya perlu memanggilnya sekali saja di awal?

Saya membaca dokumentasi ini untuknya: http://keras.io/layers/normalization/

Saya tidak tahu di mana saya seharusnya menyebutnya. Di bawah ini adalah kode saya yang mencoba menggunakannya:

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)

Saya bertanya karena jika saya menjalankan kode dengan baris kedua termasuk normalisasi batch dan jika saya menjalankan kode tanpa baris kedua saya mendapatkan output yang sama. Jadi saya tidak memanggil fungsi di tempat yang tepat, atau saya kira itu tidak membuat banyak perbedaan.

pr338
sumber

Jawaban:

225

Hanya untuk menjawab pertanyaan ini dengan sedikit lebih detail, dan seperti yang dikatakan Pavel, Normalisasi Batch hanyalah lapisan lain, sehingga Anda dapat menggunakannya untuk membuat arsitektur jaringan yang Anda inginkan.

Kasus penggunaan umum adalah menggunakan BN antara lapisan linier dan non-linear di jaringan Anda, karena itu menormalkan input ke fungsi aktivasi Anda, sehingga Anda berpusat di bagian linier dari fungsi aktivasi (seperti Sigmoid). Ada diskusi kecil di sini

Dalam kasus Anda di atas, ini mungkin terlihat seperti:


# 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)

Semoga ini menjelaskan lebih banyak hal.

Lucas Ramadan
sumber
25
FYI ternyata normalisasi bets berfungsi lebih baik dalam praktik setelah fungsi aktivasi
Claudiu
10
Hai @Cudiudiu, maukah Anda memperluas FYI ini? Tampaknya bertentangan langsung dengan jawaban di atas.
Ben Ogorek
7
@ Benogorek: tentu saja, pada dasarnya saya mendasarkannya sepenuhnya pada hasil di sini di mana menempatkan norma batch setelah relu berkinerja lebih baik. FWIW Saya belum berhasil menerapkannya dengan satu cara atau yang lain di internet yang saya coba
Claudiu
32
Menarik. Sebagai tindak lanjut, jika Anda terus membaca di ringkasan itu, dikatakan bahwa model terbaik mereka [GoogLeNet128_BN_lim0606] sebenarnya memiliki layer BN SEBELUM ReLU. Jadi sementara BN setelah Aktivasi dapat meningkatkan akurasi dalam kasus yang terisolasi, ketika seluruh model dibangun, sebelum dilakukan yang terbaik. Mungkin saja menempatkan BN setelah Aktivasi dapat meningkatkan akurasi, tetapi kemungkinan besar tergantung masalah.
Lucas Ramadan
7
@ CarlThomé agak. Lihat komentar reddit ini oleh ReginaldIII misalnya. Mereka menyatakan: "BN menormalkan distribusi fitur yang keluar dari konvolusi, beberapa fitur ini mungkin negatif [dan] terpotong oleh non-linearitas seperti ReLU. Jika Anda menormalkan sebelum aktivasi Anda termasuk nilai-nilai negatif dalam normalisasi segera sebelum mengambilnya dari ruang fitur. BN setelah aktivasi akan menormalkan fitur positif tanpa secara statistik membiaskan mereka dengan fitur yang tidak berhasil sampai ke lapisan konvolusional berikutnya. "
mab
60

Utas ini menyesatkan. Sudah mencoba mengomentari jawaban Lucas Ramadan, tapi saya belum memiliki hak yang tepat, jadi saya hanya akan menempatkan ini di sini.

Normalisasi batch berfungsi paling baik setelah fungsi aktivasi, dan sini atau di sini adalah alasannya: ia dikembangkan untuk mencegah pergeseran kovariat internal. Pergeseran kovariat internal terjadi ketika distribusi aktivasidari suatu lapisan bergeser secara signifikan selama pelatihan. Normalisasi batch digunakan sehingga distribusi input (dan input ini secara harfiah merupakan hasil dari fungsi aktivasi) ke lapisan tertentu tidak berubah dari waktu ke waktu karena pembaruan parameter dari setiap batch (atau setidaknya, memungkinkannya untuk berubah dengan cara yang menguntungkan). Ia menggunakan statistik batch untuk melakukan normalisasi, dan kemudian menggunakan parameter normalisasi batch (gamma dan beta di kertas asli) "untuk memastikan bahwa transformasi yang dimasukkan dalam jaringan dapat mewakili transformasi identitas" (kutipan dari kertas asli). Tetapi intinya adalah bahwa kita mencoba untuk menormalkan input ke suatu layer, jadi itu harus selalu pergi sebelum lapisan berikutnya dalam jaringan. Apakah itu atau tidak '

jmancuso
sumber
27
Saya baru saja melihat di kelas deeplearning. Di mana Andrew Ng mengatakan bahwa ada perdebatan mengenai hal ini di komunitas Deep Learning. Dia lebih suka menerapkan normalisasi batch sebelum non-linearitas.
shahensha
3
@kRazzyR Saya maksudkan bahwa Prof. Andrew Ng berbicara tentang topik ini di kelas pembelajarannya yang mendalam tentang deeplearning.ai dia mengatakan bahwa masyarakat dibagi pada cara yang benar dalam melakukan sesuatu dan bahwa dia lebih suka menerapkan normalisasi batch sebelum menerapkan non-linearitas.
shahensha
3
@jmancuso, BN diterapkan sebelum aktivasi. Dari makalah itu sendiri, persamaan adalah g(BN(Wx + b)), di mana gadalah fungsi aktivasi.
yashgarg1232
43

Utas ini memiliki beberapa perdebatan besar tentang apakah BN harus diterapkan sebelum non-linearitas lapisan saat ini atau untuk aktivasi lapisan sebelumnya.

Meskipun tidak ada jawaban yang benar, penulis Normalisasi Batch mengatakan bahwa itu harus diterapkan segera sebelum non-linearitas lapisan saat ini. Alasannya (dikutip dari kertas asli) -

"Kami menambahkan transformasi BN segera sebelum nonlinier, dengan menormalkan x = Wu + b. Kami juga dapat menormalkan input layer u, tetapi karena Anda kemungkinan merupakan output nonlinier lain, bentuk distribusinya cenderung berubah selama pelatihan, dan membatasi momen pertama dan kedua tidak akan menghilangkan pergeseran kovariat. Sebaliknya, Wu + b lebih cenderung memiliki distribusi simetris, non-jarang, yaitu "lebih Gaussian" (Hyv¨arinen & Oja, 2000) ; normalisasi kemungkinan menghasilkan aktivasi dengan distribusi yang stabil. "

pengguna12340
sumber
3
Dalam pengalaman pribadi saya, itu tidak membuat perbedaan besar, tetapi semuanya sama, saya selalu melihat BN berkinerja lebih baik ketika normalisasi batch diterapkan sebelum non-linearitas (sebelum fungsi aktivasi).
Brad Hesse
31

Keras sekarang mendukung use_bias=Falseopsi ini, sehingga kami dapat menyimpan beberapa perhitungan dengan menulis like

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

atau

model.add(Convolution2D(64, 3, 3, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation('relu'))
dontloo
sumber
bagaimana model.add(BatchNormalization())berbeda darimodel.add(BatchNormalization(axis=bn_axis))
kRazzy R
@ kRazzR tidak berbeda jika Anda menggunakan tensorflowbackend. Itu ditulis di sini karena dia menyalin ini dari keras.applicationsmodul, di mana bn_axisperlu ditentukan untuk mendukung format channels_firstdan keduanya channels_last.
ldavid
9
Bisakah seseorang menjelaskan bagaimana ini terkait dengan pertanyaan OP? (Saya agak pemula untuk NN jadi mungkin saya melewatkan sesuatu.)
Pepacz
30

Sekarang hampir menjadi tren untuk Conv2Ddiikuti oleh ReLudiikuti oleh sebuah BatchNormalizationlapisan. Jadi saya membuat fungsi kecil untuk memanggil mereka semua sekaligus. Membuat definisi model terlihat jauh lebih bersih dan lebih mudah dibaca.

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)))
stochastic_zeitgeist
sumber
7
mungkin mendorong ini ke keras?
sachinruk
6

Ini adalah jenis lapisan lain, jadi Anda harus menambahkannya sebagai lapisan di tempat yang sesuai dengan model Anda

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

Lihat contoh di sini: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py

Pavel Surmenok
sumber
1
Setelah saya menambahkan BatchNormalisasi, val_acc berhenti bertambah setiap zaman. Val_acc tetap stagnan di nomor yang sama setelah setiap zaman setelah saya menambahkan BatchNormalisasi. Saya pikir Normalisasi Batch seharusnya meningkatkan val_acc. Bagaimana saya tahu jika itu berfungsi dengan baik? Apakah Anda tahu apa yang menyebabkan ini?
pr338
sayangnya tautannya tidak lagi valid :(
user2324712
Ada salinan contoh itu di garpu Keras (misalnya github.com/WenchenLi/kaggle/blob/master/otto/keras/… ), tapi saya tidak tahu mengapa itu dihapus dari repo Keras asli, dan jika kode ini kompatibel dengan versi Keras terbaru.
Pavel Surmenok
4

Batch Normalisasi digunakan untuk menormalkan lapisan input serta lapisan tersembunyi dengan menyesuaikan rata-rata dan penskalaan aktivasi. Karena efek normalisasi ini dengan lapisan tambahan dalam jaringan saraf yang dalam, jaringan dapat menggunakan tingkat pembelajaran yang lebih tinggi tanpa menghilangkan atau meledakkan gradien. Selain itu, normalisasi batch mengatur jaringan sehingga lebih mudah untuk digeneralisasi, dan karenanya tidak perlu menggunakan dropout untuk mengurangi overfitting.

Tepat setelah menghitung fungsi linear menggunakan say, the Dense () atau Conv2D () di Keras, kami menggunakan BatchNormalization () yang menghitung fungsi linear dalam sebuah layer dan kemudian kami menambahkan non-linearitas ke layer menggunakan Activation ().

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)

Bagaimana Normalisasi Batch diterapkan?

Misalkan kita memiliki input [l-1] ke layer l. Kami juga memiliki bobot W [l] dan satuan bias b [l] untuk lapisan l. Biarkan [l] menjadi vektor aktivasi yang dihitung (yaitu setelah menambahkan non-linearitas) untuk layer l dan z [l] menjadi vektor sebelum menambahkan non-linearitas

  1. Menggunakan [l-1] dan W [l] kita dapat menghitung z [l] untuk layer l
  2. Biasanya dalam propagasi umpan maju kita akan menambahkan satuan bias ke z [l] pada tahap ini seperti z [l] + b [l] ini, tetapi dalam Normalisasi Batch, langkah penambahan b [l] ini tidak diperlukan dan tidak ada b [l] parameter digunakan.
  3. Hitung z [l] berarti dan kurangi dari setiap elemen
  4. Membagi (z [l] - rata-rata) menggunakan standar deviasi. Sebut saja Z_temp [l]
  5. Sekarang tentukan parameter baru γ dan β yang akan mengubah skala lapisan tersembunyi sebagai berikut:

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

Dalam kutipan kode ini, Dense () mengambil a [l-1], menggunakan W [l] dan menghitung z [l]. Maka BatchNormalization langsung () akan melakukan langkah-langkah di atas untuk memberikan z_norm [l]. Dan kemudian Aktivasi langsung () akan menghitung tanh (z_norm [l]) untuk memberikan [l] yaitu

a[l] = tanh(z_norm[l])
Aishwarya Radhakrishnan
sumber