2016-01-11 13 views
57

Jeśli chcę używać funkcji BatchNormalization w Keras, czy muszę wywołać ją tylko raz na początku?Gdzie mogę wywołać funkcję BatchNormalization w Keras?

czytam tę dokumentację do niego: http://keras.io/layers/normalization/

nie widzę gdzie mam to nazwać. Poniżej jest mój kod próbuje go używać:

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) 

Pytam bo jeśli uruchomić kod z drugiej linii w tym normalizacja partii i jeśli uruchomić kod bez drugiej linii mam podobne wyjść. Więc albo nie nazywam funkcji we właściwym miejscu, albo chyba nie robi to wielkiej różnicy.

Odpowiedz

83

Wystarczy odpowiedzieć na to pytanie w Nieco więcej szczegółów, a jak powiedział Pavel, Normalizacja wsadowa jest po prostu kolejną warstwą, więc można jej użyć jako takiej do stworzenia pożądanej architektury sieci.

Ogólnym zastosowaniem jest użycie BN pomiędzy warstwami liniowymi i nieliniowymi w sieci, ponieważ normalizuje on wejście do funkcji aktywacji, dzięki czemu jesteś wyśrodkowany w liniowej części funkcji aktywacji (np. jako Sigmoid). Jest mała dyskusja z nim here

W twoim przypadku powyżej, może to wyglądać tak:


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

Nadzieja to wyjaśnia sprawę nieco więcej.

+6

FYI pozornie normalizacja wsadu działa lepiej w praktyce po funkcji aktywacji – Claudiu

+3

Hi @ Claudiu, czy mógłbyś rozszerzyć ten FYI? ? Wydaje się, że jest to wprost sprzeczne z powyższą odpowiedzią: –

+4

@benogorek: na pewno opieram się całkowicie na wynikach [tutaj] (https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm .md) gdzie lepiej było umieścić normę wsadu po relu FWIW Nie odniosłem sukcesu stosując ją w taki czy inny sposób w sieci, którą wypróbowałem – Claudiu

2

To jest inny rodzaj warstwy, więc należy dodać ją jako warstwę w odpowiednim miejscu modelu

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

Zobacz przykład tutaj: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py

+0

Po dodaniu BatchNormalization, val_acc przestał zwiększać każdą epokę. Val_acc pozostał w stagnacji na tym samym numerze po każdej epoce po dodaniu BatchNormalization. Myślałem, że Normalizacja wsadowa ma zwiększyć wartość val_acc. Skąd mam wiedzieć, czy działa poprawnie? Czy wiesz, co mogło to spowodować? – pr338

+0

Niestety link nie jest już ważny :( – user2324712

+0

Istnieją kopie tego przykładu w widłach Keras (np. Https://github.com/WenchenLi/kaggle/blob/master/otto/keras/kaggle_otto_nn.py), ale ja nie wiem, dlaczego został usunięty z pierwotnego repozytorium Keras, a jeśli kod jest zgodny z najnowszymi wersjami Keras –

15

Już prawie stało się tendencją do posiadania Conv2D, po którym następuje ReLu, a następnie warstwa BatchNormalization. Więc wymyśliłem małą funkcję, aby zadzwonić do wszystkich na raz. Sprawia, że ​​definicja modelu wygląda o wiele czystsza i łatwiejsza do odczytania.

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))) 
+3

może popchnąć to do keras? –

12

Keras teraz obsługuje opcję bias=False, więc możemy zaoszczędzić trochę obliczeń pisząc jak

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

lub

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

hows 'model.add (BatchNormalization())' różni się od 'model.add (BatchNormalization (oś = bn_axis)) ' –

14

Ten wątek jest mylące. Próbowałem skomentować odpowiedź Lucasa Ramadana, ale nie mam jeszcze odpowiednich uprawnień, więc powiem to tutaj.

Normalizacja wsadu działa najlepiej po włączeniu funkcji, a here lub here powoduje, że: został opracowany, aby zapobiec wewnętrznemu przesunięciu współzmiennemu. Wewnętrzne przesunięcie covariate występuje, gdy rozkład aktywacji warstwy zmienia się znacząco podczas treningu.Normalizacja wsadowa jest wykorzystywana w taki sposób, że dystrybucja danych wejściowych (i tych danych jest dosłownie wynikiem funkcji aktywującej) do określonej warstwy nie zmienia się w czasie z powodu aktualizacji parametrów z każdej partii (lub przynajmniej umożliwia jej zmianę w korzystny sposób). Wykorzystuje statystyki wsadowe do normalizacji, a następnie wykorzystuje parametry normalizacji wsadowej (gamma i beta w oryginalnym dokumencie) ", aby upewnić się, że transformacja wprowadzona do sieci może reprezentować przekształcenie tożsamości" (cytat z oryginalnego dokumentu). Chodzi o to, że staramy się znormalizować dane wejściowe do warstwy, więc zawsze powinno to nastąpić bezpośrednio przed następną warstwą w sieci. To, czy jest po funkcji aktywacji, zależy od architektury, o której mowa.

+6

Właśnie widziałem w klasie deeplearning.ai że Andrew Ng mówi, że jest debata na ten temat w społeczność Deep Learning. Preferuje normalizację partii przed nieliniowością. – shahensha

+1

Czy mógłbyś dodać więcej informacji @shahensha –

13

Wątek ten ma sporą debatę o tym, czy należy zastosować BN przed nieliniowością bieżącej warstwy lub aktywacjami poprzedniej warstwy.

Chociaż nie ma poprawnej odpowiedzi, autorzy normalizacji partii mówią, że Należy ją zastosować bezpośrednio przed nieliniowością bieżącej warstwy. Powodem (cytat z oryginalnego papieru) -

„Dodajmy BN przekształcić bezpośrednio przed nieliniowości przez normalizację x = Wu + b Mogliśmy również znormalizowane Wejścia zawartych w warstwie U, ale ponieważ u jest prawdopodobne. Wynik innej nieliniowości, kształt jej rozkładu prawdopodobnie zmieni się podczas treningu i ograniczenie jego pierwszych i drugich momentów nie wyeliminuje przesunięcia covariate . Przeciwnie, Wu + b jest bardziej prawdopodobne, aby mieć symetrię rozkład nierozdzielny, czyli "więcej Gaussa" (Hyv¨arinen & Oja, 2000), normalizowanie go prawdopodobnie do produkuje aktywacje o stabilnym rozkładzie. "

+0

Z mojego własnego doświadczenia nie robi to wielkiej różnicy, ale wszystkie inne są równe, zawsze widziałem, że BN działa trochę lepiej, gdy normalizacja partii jest stosowana przed nieliniowością (przed funkcją aktywacji). –

Powiązane problemy