Tôi gọi hàm BatchN normalization trong Keras ở đâu?


167

Nếu tôi muốn sử dụng chức năng BatchN normalization trong Keras, thì tôi có cần gọi nó một lần duy nhất khi bắt đầu không?

Tôi đọc tài liệu này cho nó: http://keras.io/layers/n normalization /

Tôi không thấy nơi tôi phải gọi nó. Dưới đây là mã của tôi đang cố gắng sử dụng nó:

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)

Tôi hỏi bởi vì nếu tôi chạy mã với dòng thứ hai bao gồm chuẩn hóa hàng loạt và nếu tôi chạy mã mà không có dòng thứ hai, tôi sẽ nhận được kết quả tương tự. Vì vậy, hoặc tôi không gọi hàm đúng chỗ, hoặc tôi đoán nó không tạo ra nhiều sự khác biệt.

Câu trả lời:


225

Chỉ cần trả lời câu hỏi này chi tiết hơn một chút, và như Pavel đã nói, Batch Normalization chỉ là một lớp khác, vì vậy bạn có thể sử dụng nó như vậy để tạo kiến ​​trúc mạng mong muốn của mình.

Trường hợp sử dụng chung là sử dụng BN giữa các lớp tuyến tính và phi tuyến tính trong mạng của bạn, vì nó bình thường hóa đầu vào cho chức năng kích hoạt của bạn, để bạn tập trung vào phần tuyến tính của chức năng kích hoạt (như Sigmoid). Có một cuộc thảo luận nhỏ về nó ở đây

Trong trường hợp của bạn ở trên, điều này có thể trông giống như:


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

Hy vọng điều này làm rõ mọi thứ hơn một chút.


25
FYI rõ ràng bình thường hóa hàng loạt hoạt động tốt hơn trong thực tế sau chức năng kích hoạt
Claudiu

10
Xin chào @Claudiu, bạn có phiền mở rộng về FYI này không? Nó xuất hiện mâu thuẫn trực tiếp với câu trả lời ở trên.
Ben Ogorek

7
@benogorek: chắc chắn, về cơ bản, tôi hoàn toàn dựa vào kết quả ở đây , nơi đặt định mức lô sau khi relu hoạt động tốt hơn. FWIW Tôi đã không thành công khi áp dụng nó theo cách này hay cách khác trên mạng mà tôi đã thử
Claudiu

32
Hấp dẫn. Chỉ cần theo dõi, nếu bạn tiếp tục đọc trong bản tóm tắt đó, nó nói rằng mô hình tốt nhất của họ [GoogLeNet128_BN_lim0606] thực sự có lớp BN TRƯỚC ReLU. Vì vậy, trong khi BN sau khi kích hoạt có thể cải thiện độ chính xác trong trường hợp bị cô lập, khi toàn bộ mô hình được xây dựng, trước khi hoạt động tốt nhất. Có khả năng việc đặt BN sau khi kích hoạt có thể cải thiện độ chính xác, nhưng có khả năng phụ thuộc vào vấn đề.
Lucas Ramadan

7
@ CarlThomé loại. Xem bình luận reddit này của ReginaldIII chẳng hạn. Họ tuyên bố: "BN đang bình thường hóa việc phân phối các tính năng ra khỏi tích chập, một số [của] các tính năng này có thể bị âm [và] bị cắt bởi một phi tuyến tính như ReLU. Nếu bạn bình thường hóa trước khi kích hoạt, bạn sẽ đưa các giá trị âm này vào chuẩn hóa ngay lập tức trước khi loại bỏ chúng khỏi không gian tính năng. BN sau khi kích hoạt sẽ bình thường hóa các tính năng tích cực mà không làm sai lệch thống kê chúng với các tính năng không chuyển sang lớp chập tiếp theo. "
mab

60

Chủ đề này là sai lệch. Đã thử nhận xét về câu trả lời của Lucas Ramadan, nhưng tôi chưa có đặc quyền đúng, vì vậy tôi sẽ chỉ đưa nó ở đây.

Chuẩn hóa hàng loạt hoạt động tốt nhất sau chức năng kích hoạt, và đây hoặc đây là lý do: nó được phát triển để ngăn sự thay đổi đồng biến nội bộ. Sự thay đổi đồng biến nội bộ xảy ra khi phân phối các kích hoạtcủa một lớp thay đổi đáng kể trong suốt đào tạo. Chuẩn hóa hàng loạt được sử dụng để phân phối các đầu vào (và các đầu vào này theo nghĩa đen là kết quả của chức năng kích hoạt) cho một lớp cụ thể không thay đổi theo thời gian do cập nhật tham số từ mỗi lô (hoặc ít nhất, cho phép nó thay đổi một cách thuận lợi). Nó sử dụng số liệu thống kê hàng loạt để thực hiện chuẩn hóa, và sau đó sử dụng các tham số chuẩn hóa hàng loạt (gamma và beta trong bài báo gốc) "để đảm bảo rằng phép chuyển đổi được chèn trong mạng có thể biểu thị biến đổi nhận dạng" (trích dẫn từ bài báo gốc). Nhưng vấn đề là chúng ta đang cố gắng bình thường hóa các đầu vào thành một lớp, vì vậy nó phải luôn đi ngay trước lớp tiếp theo trong mạng. Có hay không điều đó '


27
Tôi chỉ thấy trong lớp deeplearning.ai mà Andrew Ng nói rằng có một cuộc tranh luận về vấn đề này trong cộng đồng Deep Learning. Ông thích áp dụng chuẩn hóa hàng loạt trước khi phi tuyến tính.
shahensha

3
@kRazzyR Ý tôi là giáo sư Andrew Ng đã nói về chủ đề này trong các lớp học sâu của anh ấy về deeplearning.ai Ông nói rằng cộng đồng được chia theo cách làm việc đúng đắn và ông thích áp dụng bình thường hóa hàng loạt trước khi áp dụng phi tuyến tính.
shahensha

3
@jmancuso, BN được áp dụng trước khi kích hoạt. Từ chính bài báo, phương trình là g(BN(Wx + b)), đâu glà hàm kích hoạt.
yashgarg1232

43

Chủ đề này có một số tranh luận đáng kể về việc BN nên được áp dụng trước khi phi tuyến tính của lớp hiện tại hoặc kích hoạt của lớp trước.

Mặc dù không có câu trả lời chính xác, các tác giả của Batch bình thường hóa nói rằng nó nên được áp dụng ngay trước sự phi tuyến tính của lớp hiện tại. Lý do (trích từ giấy gốc) -

"Chúng tôi thêm biến đổi BN ngay trước độ phi tuyến, bằng cách chuẩn hóa x = Wu + b. Chúng tôi cũng có thể bình thường hóa các đầu vào lớp u, nhưng vì u có thể là đầu ra của một phi tuyến khác, hình dạng phân phối của nó có thể thay đổi trong suốt đào tạo và hạn chế khoảnh khắc thứ nhất và thứ hai của nó sẽ không loại bỏ sự thay đổi đồng biến. Ngược lại, Wu + b có nhiều khả năng phân phối đối xứng, không thưa thớt, đó là Gaussian đấm (Hyv¨arinen & Oja, 2000). ; bình thường hóa nó có khả năng tạo ra kích hoạt với phân phối ổn định. "


3
Theo kinh nghiệm cá nhân của tôi, nó không tạo ra sự khác biệt lớn, nhưng tất cả những thứ khác đều bằng nhau, tôi luôn thấy BN hoạt động tốt hơn một chút khi áp dụng chuẩn hóa hàng loạt trước khi phi tuyến tính (trước chức năng kích hoạt).
Brad Hesse

31

Keras hiện hỗ trợ use_bias=Falsetùy chọn, vì vậy chúng tôi có thể lưu một số tính toán bằng cách viết như

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

hoặc là

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

bí quyết model.add(BatchNormalization())khác nhau từmodel.add(BatchNormalization(axis=bn_axis))
kRazzy R

@kRazzR nó không khác nếu bạn đang sử dụng tensorflowlàm phụ trợ. Nó được viết ở đây bởi vì anh ta đã sao chép nó từ keras.applicationsmô-đun, nơi bn_axiscần được chỉ định để hỗ trợ cả định dạng channels_firstchannels_lastđịnh dạng.
ldavid

9
Ai đó có thể vui lòng giải thích làm thế nào điều này liên quan đến câu hỏi OP? (Tôi là người mới bắt đầu làm NN nên có lẽ tôi bỏ lỡ điều gì đó.)
Pepacz

30

Nó gần như trở thành một xu hướng hiện nay để có một Conv2Dtheo sau là một ReLutiếp theo là một BatchNormalizationlớp. Vì vậy, tôi đã tạo ra một chức năng nhỏ để gọi tất cả chúng cùng một lúc. Làm cho định nghĩa mô hình trông gọn gàng hơn và dễ đọc hơn.

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
có thể đẩy cái này đến máy ảnh?
sachinruk

6

Đây là một loại lớp khác, vì vậy bạn nên thêm nó dưới dạng một lớp ở một vị trí thích hợp của mô hình của bạn

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

Xem ví dụ tại đây: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py


1
Sau khi tôi thêm BatchN normalization, val_acc ngừng tăng mỗi epoch. Val_acc bị trì trệ ở cùng một số sau mỗi kỷ nguyên sau khi tôi thêm BatchN normalization. Tôi nghĩ rằng Batch bình thường hóa được cho là để tăng val_acc. Làm thế nào để tôi biết nếu nó hoạt động đúng? Bạn có biết những gì có thể đã gây ra điều này?
pr338

Thật không may, liên kết không còn hợp lệ :(
user2324712

Có những bản sao của ví dụ đó trong dĩa của Keras (ví dụ: github.com/WenchenLi/kaggle/blob/master/otto/keras/ ,), nhưng tôi không biết tại sao nó lại bị xóa khỏi repo Keras ban đầu và nếu mã tương thích với các phiên bản Keras mới nhất.
Pavel Surmenok

4

Chuẩn hóa hàng loạt được sử dụng để chuẩn hóa lớp đầu vào cũng như các lớp ẩn bằng cách điều chỉnh giá trị trung bình và tỷ lệ kích hoạt. Do hiệu ứng chuẩn hóa này với lớp bổ sung trong các mạng nơ ron sâu, mạng có thể sử dụng tốc độ học tập cao hơn mà không biến mất hoặc làm nổ độ dốc. Hơn nữa, chuẩn hóa hàng loạt thường xuyên hóa mạng sao cho dễ khái quát hóa hơn và do đó không cần thiết phải sử dụng bỏ học để giảm thiểu tình trạng thừa.

Ngay sau khi tính toán hàm tuyến tính bằng cách sử dụng say, Dense () hoặc Conv2D () trong Keras, chúng tôi sử dụng BatchN normalization () để tính toán hàm tuyến tính trong một lớp và sau đó chúng tôi thêm phi tuyến tính vào lớp bằng cách sử dụng Kích hoạt ().

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)

Batch bình thường hóa được áp dụng như thế nào?

Giả sử chúng ta đã nhập [l-1] cho một lớp l. Ngoài ra, chúng tôi có trọng số W [l] và đơn vị thiên vị b [l] cho lớp l. Đặt [l] là vectơ kích hoạt được tính (nghĩa là sau khi thêm phi tuyến tính) cho lớp l và z [l] là vectơ trước khi thêm phi tuyến tính

  1. Sử dụng [l-1] và W [l] chúng ta có thể tính z [l] cho lớp l
  2. Thông thường trong quá trình truyền chuyển tiếp, chúng tôi sẽ thêm đơn vị thiên vị cho z [l] ở giai đoạn này như z [l] + b [l], nhưng trong Batch Chuẩn hóa, bước này không cần thêm b [l] tham số b [l] được sử dụng.
  3. Tính z [l] có nghĩa và trừ nó từ mỗi phần tử
  4. Phân chia (z [l] - trung bình) bằng độ lệch chuẩn. Gọi nó là Z_temp [l]
  5. Bây giờ hãy xác định các tham số mới và sẽ thay đổi tỷ lệ của lớp ẩn như sau:

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

Trong đoạn trích mã này, Dense () lấy [l-1], sử dụng W [l] và tính z [l]. Sau đó, BatchN normalization () ngay lập tức sẽ thực hiện các bước trên để cung cấp z_norm [l]. Và sau đó Kích hoạt ngay lập tức () sẽ tính toán tanh (z_norm [l]) để đưa ra [l] tức là

a[l] = tanh(z_norm[l])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.