Де я називаю функцію BatchNormalization в Керасі?


167

Якщо я хочу використовувати функцію BatchNormalization в Keras, то чи потрібно мені викликати її один раз лише на початку?

Я читав цю документацію на неї: http://keras.io/layers/normalization/

Я не бачу, куди мені це потрібно дзвонити. Нижче наведено мій код, який намагається використовувати його:

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)

Я запитую, тому що якщо я запускаю код з другого рядка, включаючи пакетну нормалізацію, і якщо я запускаю код без другого рядка, я отримую аналогічні результати. Тож або я не називаю функцію в потрібному місці, або, мабуть, це не має великої різниці.

Відповіді:


225

Просто, щоб відповісти на це питання трохи детальніше, і як сказав Павло, Batch Normalization - це лише ще один шар, тому ви можете використовувати його як такий для створення потрібної мережевої архітектури.

Загальним випадком використання є використання BN між лінійним та нелінійним шарами у вашій мережі, оскільки це нормалізує вхід до вашої функції активації, так що ви зосереджені в лінійному розділі функції активації (наприклад, Sigmoid). Там невелика дискусія про це тут

У вашому випадку вище це може виглядати так:


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

Сподіваюсь, це трохи прояснює речі.


25
FYI, очевидно, нормалізація партії працює краще на практиці після функції активації
Клавдіу

10
Привіт, @Claudiu, ви б не хотіли розширити цей FYI? Схоже, це прямо суперечить відповіді вище.
Бен Огорек

7
@benogorek: впевнений , що, в основному я грунтувався виключно на результатах тут , де помістити пакетну норму після того , як Relu виконується краще. FWIW У мене не було успіху застосувати його так чи інакше в одній мережі, яку я пробував
Клавдіу

32
Цікаво. Щоб продовжити, якщо ви продовжуєте читати далі у цьому резюме, там сказано, що в їхній кращій моделі [GoogLeNet128_BN_lim0606] насправді є BN-шар ДО ПЕРЕД РОЛУ. Отже, хоча BN після активації може підвищити точність в ізольованому випадку, коли вся модель побудована, перш ніж виконати найкраще. Ймовірно, можливо, що розміщення BN після активації може підвищити точність, але, ймовірно, залежить від проблеми.
Лукас Рамадан

7
@ CarlThomé вид. Наприклад, дивіться цей коментар до редагування ReginaldIII. Вони заявляють: "BN нормалізує розподіл функцій, що виходять із згортки, деякі [з] цих особливостей можуть бути негативними [і] усіченими нелінійністю, як ReLU. Якщо ви нормалізуєтесь перед активацією, ви включаєте ці негативні значення в нормалізація безпосередньо перед тим, як викреслити їх з простору функцій. BN після активації нормалізує позитивні ознаки, не статистично обробляючи їх характеристиками, які не пробиваються до наступного згорткового шару ".
маб

60

Ця нитка вводить в оману. Спробував коментувати відповідь Лукаса Рамадана, але я ще не маю правильних привілеїв, тому я просто викладу це тут.

Пакетна нормалізація працює найкраще після функції активації, і ось тут або ось чому: вона була розроблена для запобігання внутрішнього коваріатного зсуву. Внутрішній коваріатний зсув відбувається при розподілі активаційшару значно зміщується протягом тренування. Пакетна нормалізація використовується так, що розподіл входів (і ці входи буквально є результатом функції активації) на певний рівень не змінюється з часом через оновлення параметрів кожної партії (або, принаймні, дозволяє їй змінюватися вигідним чином). Він використовує пакетну статистику для нормалізації, а потім використовує параметри нормалізації партії (гамма та бета-версія в оригінальному документі) ", щоб переконатися, що перетворення, вставлене в мережу, може представляти трансформацію ідентичності" (цитата з оригінального паперу). Але справа в тому, що ми намагаємося нормалізувати входи до шару, тому він повинен завжди переходити безпосередньо перед наступним шаром у мережі. Чи ні це "


27
Я щойно побачив у класі deepplearning.ai, що Ендрю Нг каже, що в спільноті Deep Learning про це дискутують. Він вважає за краще застосовувати пакетну нормалізацію перед нелінійністю.
shahensha

3
@kRazzyR я мав в виду , що професор Ендрю Нг говорили про цю тему в своїх глибоких класах навчання на deeplearning.ai Він сказав , що громада діляться на правильному шляху робити речі , і що він вважав за краще застосовувати пакетну нормалізацію перед нанесенням нелінійності.
shahensha

3
@jmancuso, BN застосовується перед активацією. З самого паперу рівняння є g(BN(Wx + b)), де gфункція активації.
yashgarg1232

43

Цей потік має значну дискусію щодо того, чи слід застосовувати BN перед нелінійністю поточного шару або до активації попереднього шару.

Хоча правильної відповіді немає, автори "Batch Normalization" кажуть, що її слід застосовувати безпосередньо перед нелінійністю поточного шару. Причина (цитується з оригіналу паперу) -

"Ми додаємо BN перетворення безпосередньо перед нелінійністю, нормалізуючи x = Wu + b. Ми могли б також нормалізувати вхідні шари u, але оскільки u, ймовірно, вихід іншої нелінійності, форма його розподілу, ймовірно, зміниться протягом тренування, а обмеження першого та другого моментів не призведе до усунення зрушення коваріату. На противагу цьому, Wu + b, швидше за все, має симетричний, нерідкий розподіл, тобто "більш гауссовий" (Hyv¨arinen & Oja, 2000) нормалізація, ймовірно, призведе до активації зі стабільним розподілом ".


3
В моєму особистому досвіді це не має великої різниці, але за інших рівних даних я завжди бачив, що BN працює трохи краще, коли нормалізація партії застосовується перед нелінійністю (перед функцією активації).
Бред Гессе

31

Тепер Керас підтримує цю use_bias=Falseопцію, тому ми можемо зберегти деякі обчислення, написавши подібні

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

або

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

hows model.add(BatchNormalization())відрізняється відmodel.add(BatchNormalization(axis=bn_axis))
kRazzy R

@kRazzR він не відрізняється, якщо ви використовуєте tensorflowяк бекенд. Тут написано, тому що він скопіював це з keras.applicationsмодуля, де bn_axisпотрібно вказати, щоб підтримувати channels_firstі channels_lastформати, і формати.
ldavid

9
Чи може хтось, будь-ласка, роз'яснити, як це стосується питання щодо ОП? (Я швидше початківець з НН, тому, можливо, щось пропускаю.)
Pepacz

30

Зараз майже стало трендом, Conv2Dа за ним ReLuслідує BatchNormalizationшар. Тому я створив невелику функцію, щоб зателефонувати всім їх відразу. Робить визначення моделі набагато чистішим та легшим для читання.

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
може, підштовхнути це до керам?
sachinruk

6

Це ще один тип шару, тому слід додати його як шар у відповідному місці вашої моделі

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

Дивіться приклад тут: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py


1
Після того, як я додав BatchNormalization, val_acc припинив збільшувати кожну епоху. Після того, як я додав BatchNormalization, val_acc залишався в одному і тому ж числі після кожної епохи. Я думав, що нормалізація партії повинна була збільшити val_acc. Як дізнатись, чи працює вона правильно? Чи знаєте ви, що це могло спричинити це?
pr338

на жаль, посилання більше не діє :(
user2324712

Є копії цього прикладу у виделках Keras (наприклад, github.com/WenchenLi/kaggle/blob/master/otto/keras/… ), але я не знаю, чому він був видалений з оригінального репорта Keras , і якщо код сумісний з останніми версіями Keras.
Павло Сурменок

4

Пакетна нормалізація використовується для нормалізації вхідного шару, а також прихованих шарів за допомогою регулювання середнього та масштабування активацій. Завдяки цьому нормалізуючому ефекту з додатковим шаром у глибоких нейронних мережах мережа може використовувати більш високу швидкість навчання без зникнення або вибуху градієнтів. Крім того, пакетна нормалізація регулює мережу таким чином, щоб її було легше узагальнити, і, таким чином, не потрібно використовувати випадання для пом'якшення перевитрати.

Одразу після обчислення лінійної функції за допомогою скажімо, щільної () або Conv2D () у Керасі, ми використовуємо BatchNormalization (), яка обчислює лінійну функцію в шарі, а потім додаємо нелінійність до шару за допомогою активації ().

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)

Як застосовується пакетна нормалізація?

Припустимо, ми ввели a [l-1] в шар l. Також маємо ваги W [l] та одиницю зміщення b [l] для шару l. Нехай [l] - обчислений вектор активації (тобто після додавання нелінійності) для шару l і ​​z [l] - вектор перед додаванням нелінійності

  1. Використовуючи [l-1] і W [l], ми можемо обчислити z [l] для шару l
  2. Зазвичай при розповсюдженні подачі вперед ми додамо одиницю зміщення до z [l] на цьому етапі, як це z [l] + b [l], але в Batch Normalization цей крок додавання b [l] не потрібен і ні b [l] використовується параметр.
  3. Обчислити z [l] означає і відняти його від кожного елемента
  4. Ділимо (z [l] - середнє значення), використовуючи стандартне відхилення. Назвіть це Z_temp [l]
  5. Тепер визначте нові параметри γ і β, які змінять масштаб прихованого шару наступним чином:

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

У цьому витязі з коду Dense () приймає a [l-1], використовує W [l] і обчислює z [l]. Тоді негайна BatchNormalization () виконає вищезазначені кроки, щоб дати z_norm [l]. І тоді негайна активація () обчислить tanh (z_norm [l]), щоб дати [l], тобто

a[l] = tanh(z_norm[l])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.