ฉันจะเรียกใช้ฟังก์ชัน BatchNormalization ใน Keras ได้ที่ไหน


168

ถ้าฉันต้องการใช้ฟังก์ชั่น 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

เพียงเพื่อตอบคำถามนี้ในรายละเอียดเพิ่มเติมเล็กน้อยตามที่ Pavel กล่าว Batch Normalization เป็นอีกชั้นหนึ่งดังนั้นคุณจึงสามารถใช้มันเพื่อสร้างสถาปัตยกรรมเครือข่ายที่คุณต้องการ

กรณีการใช้งานทั่วไปคือการใช้ BN ระหว่างเลเยอร์เชิงเส้นและไม่เป็นเชิงเส้นในเครือข่ายของคุณเพราะมันทำให้อินพุตเข้าสู่ฟังก์ชั่นการเปิดใช้งานของคุณเป็นแบบปกติดังนั้นคุณจึงอยู่กึ่งกลางในส่วนเชิงเส้นของ มีการสนทนาเล็ก ๆ ของที่นี่

ในกรณีของคุณด้านบนอาจมีลักษณะดังนี้:


# 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 เห็นได้ชัดว่าการทำให้กลับสู่สภาพปกติเป็นชุดทำงานได้ดีขึ้นในทางปฏิบัติหลังจากฟังก์ชั่นการเปิดใช้งาน
Claudiu

10
สวัสดี @Claudiu คุณจะขยายความใน FYI นี้หรือไม่? ดูเหมือนจะขัดแย้งโดยตรงกับคำตอบข้างต้น
Ben Ogorek

7
@benogorek: แน่นอนว่าโดยพื้นฐานแล้วฉันอ้างอิงจากผลลัพธ์ทั้งหมดที่นี่ซึ่งวางชุดบรรทัดฐานหลังจาก relu ทำงานได้ดีขึ้น FWIW ฉันไม่เคยประสบความสำเร็จในการนำมันไปใช้ไม่ทางใดก็ทางหนึ่งในเน็ตที่ฉันได้ลอง
Claudiu

32
น่าสนใจ เพียงแค่ติดตามหากคุณยังคงอ่านต่อในบทสรุปนั้นมันบอกว่ารุ่นที่ดีที่สุดของพวกเขา [GoogLeNet128_BN_lim0606] มีเลเยอร์ BN ก่อนที่จะ ReLU ดังนั้นในขณะที่ BN หลังจากการเปิดใช้งานอาจปรับปรุงความแม่นยำในกรณีที่แยกได้เมื่อสร้างแบบจำลองทั้งหมดก่อนที่จะทำได้ดีที่สุด อาจเป็นไปได้ว่าการวาง BN หลังการเปิดใช้งานสามารถปรับปรุงความแม่นยำ แต่อาจขึ้นกับปัญหา
Lucas Ramadan

7
@ CarlThoméชนิดของ ดูความคิดเห็นreddit นี้โดย ReginaldIII เช่น พวกเขากล่าวว่า: "BN กำลังทำให้การกระจายของคุณลักษณะเป็นไปอย่างปกติการแปลงลักษณะบางอย่างของ [ของ] เหล่านี้อาจเป็นค่าลบ [และ] ถูกตัดทอนโดยไม่เป็นเชิงเส้นเหมือน ReLU ถ้าคุณทำให้เป็นมาตรฐานก่อนเปิดใช้งาน การทำให้เป็นมาตรฐานในทันทีก่อนที่จะทำการคัดออกจากพื้นที่ฟีเจอร์ BN หลังจากการเปิดใช้งานจะทำให้คุณสมบัติในเชิงบวกเป็นปกติโดยไม่มีการให้น้ำหนักด้วยสถิติที่มีคุณสมบัติที่ไม่ทำให้ผ่านไปยังเลเยอร์ต่อไป "
mab

60

เธรดนี้ทำให้เข้าใจผิด พยายามแสดงความคิดเห็นเกี่ยวกับคำตอบของ Lucas Ramadan แต่ฉันยังไม่มีสิทธิ์ที่ถูกต้องดังนั้นฉันจะใส่ที่นี่

ฟื้นฟูแบทช์การทำงานที่ดีที่สุดหลังจากการเปิดใช้งานฟังก์ชั่นและที่นี่หรือที่นี่คือเหตุผลที่มันถูกพัฒนาขึ้นเพื่อป้องกันไม่ให้เกิดการเปลี่ยนแปลงตัวแปรร่วมภายใน การเปลี่ยนแปลงของตัวแปรร่วมภายในเกิดขึ้นเมื่อมีการกระจายการเปิดใช้งานของเลเยอร์กะอย่างมีนัยสำคัญตลอดการฝึกอบรม การปรับสภาพแบบแบทช์ถูกใช้เพื่อให้การกระจายตัวของอินพุต (และอินพุตเหล่านี้เป็นผลจากฟังก์ชันการเปิดใช้งาน) ไปยังเลเยอร์ที่ระบุไม่เปลี่ยนแปลงตลอดเวลาเนื่องจากการอัปเดตพารามิเตอร์จากแต่ละแบทช์ (หรืออย่างน้อยช่วยให้สามารถเปลี่ยนได้ ในทางที่ได้เปรียบ) จะใช้สถิติชุดการทำ normalizing แล้วใช้พารามิเตอร์ชุดการทำให้เป็นมาตรฐาน (แกมม่าและเบต้าในกระดาษต้นฉบับ) "เพื่อให้แน่ใจว่าการแปลงที่ใส่ในเครือข่ายสามารถแสดงการแปลงเอกลักษณ์" (อ้างจากกระดาษต้นฉบับ) แต่ประเด็นคือเรากำลังพยายามทำให้อินพุตปกติเป็นเลเยอร์ดังนั้นมันควรจะไปข้างหน้าเลเยอร์ถัดไปในเครือข่ายเสมอ หรือไม่นั้น


27
ฉันเพิ่งเห็นในชั้น deeplearning.ai ที่ Andrew Ng บอกว่ามีการถกเถียงกันเรื่องนี้ในชุมชน Deep Learning เขาชอบใช้การทำให้เป็นกลุ่มแบบแบตช์ก่อนที่จะไม่เป็นเชิงเส้น
shahensha

3
@ kRazzyR ฉันหมายความว่าศาสตราจารย์แอนดรูว์อึ้งพูดคุยเกี่ยวกับหัวข้อนี้ในชั้นเรียนการเรียนรู้ลึกของเขาในdeeplearning.ai เขาบอกว่าชุมชนถูกแบ่งออกเป็นวิธีที่ถูกต้องในการทำสิ่งต่าง ๆ และเขาต้องการใช้การทำให้เป็นมาตรฐาน
shahensha

3
@jmancuso ใช้ BN ก่อนเปิดใช้งาน จากกระดาษที่ตัวเองเป็นสมการg(BN(Wx + b))ที่gเป็นฟังก์ชั่นการเปิดใช้งาน
yashgarg1232

43

เธรดนี้มีการถกเถียงอย่างมากเกี่ยวกับว่า BN ควรจะใช้ก่อนที่จะไม่เป็นเชิงเส้นของเลเยอร์ปัจจุบันหรือกับการเปิดใช้งานของเลเยอร์ก่อนหน้า

แม้ว่าจะไม่มีคำตอบที่ถูกต้อง แต่ผู้เขียนของการทำให้เป็นมาตรฐานชุดบอกว่า มันควรจะนำไปใช้ทันทีก่อนที่จะไม่เชิงเส้นของชั้นปัจจุบัน เหตุผล (ยกมาจากกระดาษต้นฉบับ) -

"เราเพิ่มการแปลง BN ทันทีก่อนความไม่เชิงเส้นโดยการทำให้มาตรฐานเป็น x = Wu + b เราสามารถทำให้ชั้นอินพุทเป็นมาตรฐานได้เช่นกัน แต่เนื่องจากคุณน่าจะเป็นเอาท์พุทของความไม่เชิงเส้นอื่น การฝึกอบรมและการบังคับช่วงเวลาแรกและช่วงที่สองจะไม่ลดการเปลี่ยนแปลงของ covariate ในทางกลับกัน Wu + b มีแนวโน้มที่จะมีการแจกแจงแบบสมมาตรและไม่กระจัดกระจายนั่นคือ "เกาส์มากขึ้น" (Hyv¨arinen & Oja, 2000) การทำให้เป็นปกติจะทำให้เกิดการเปิดใช้งานด้วยการกระจายที่เสถียร


3
ในประสบการณ์ส่วนตัวของฉันเองมันไม่ได้สร้างความแตกต่างอย่างใหญ่หลวง แต่สิ่งอื่น ๆ ที่เท่าเทียมกันฉันเคยเห็น BN ทำงานได้ดีขึ้นเล็กน้อยเมื่อใช้การทำแบทช์ให้เป็นมาตรฐานก่อนที่จะไม่เป็นเชิงเส้น
แบรดเฮสส์

31

ตอนนี้ Keras สนับสนุน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'))

ชำนาญmodel.add(BatchNormalization())แตกต่างจากmodel.add(BatchNormalization(axis=bn_axis))
kRazzy R

@kRazzR ไม่แตกต่างกันหากคุณใช้tensorflowเป็นแบ็กเอนด์ มันเขียนไว้ที่นี่เพราะเขาคัดลอกสิ่งนี้จากkeras.applicationsโมดูลซึ่งbn_axisจะต้องมีการระบุเพื่อรองรับทั้งchannels_firstและchannels_lastรูปแบบ
ldavid

9
มีใครช่วยอธิบายเพิ่มเติมเกี่ยวกับคำถาม OP ได้ไหม (ฉันค่อนข้างเริ่มต้นกับ NNs ดังนั้นบางทีฉันอาจจะพลาดอะไรบางอย่าง)
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
อาจจะผลักดันให้ keras?
sachinruk

6

เป็นเลเยอร์อีกประเภทหนึ่งดังนั้นคุณควรเพิ่มเป็นเลเยอร์ในตำแหน่งที่เหมาะสมสำหรับโมเดลของคุณ

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

ดูตัวอย่างได้ที่นี่: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py


1
หลังจากที่ฉันเพิ่ม BatchNormalization, val_acc หยุดเพิ่มขึ้นทุกยุค val_acc อยู่นิ่งที่หมายเลขเดียวกันหลังจากทุกยุคหลังจากฉันเพิ่ม BatchNormalization ฉันคิดว่า Batch Normalization ควรจะเพิ่มค่า val_acc ฉันจะรู้ได้อย่างไรว่ามันทำงานอย่างถูกต้อง? คุณรู้หรือไม่ว่าอะไรทำให้เกิดสิ่งนี้
pr338

ขออภัยลิงก์ไม่สามารถใช้งานได้อีกต่อไป :(
2324712

มีสำเนาของตัวอย่างนั้นใน forks of Keras (เช่นgithub.com/WenchenLi/kaggle/blob/master/otto/keras/ ...... ) แต่ฉันไม่รู้ว่าทำไมมันถูกลบออกจาก repo Keras ดั้งเดิมและถ้า รหัสเข้ากันได้กับเวอร์ชั่นล่าสุดของ Keras
Pavel Surmenok

4

Batch Normalization ใช้ในการทำให้ปกติเลเยอร์อินพุทรวมถึงเลเยอร์ที่ซ่อนอยู่โดยการปรับค่าเฉลี่ยและการปรับขนาดของการเปิดใช้งาน ด้วยเหตุนี้การทำให้เป็นมาตรฐานด้วยเลเยอร์เพิ่มเติมในเครือข่ายนิวรัลลึกเครือข่ายสามารถใช้อัตราการเรียนรู้ที่สูงขึ้นโดยไม่หายไปหรือระเบิดการไล่ระดับสี นอกจากนี้การทำให้เป็นปกติของแบทช์ทำให้เครือข่ายเป็นปกติเช่นที่ง่ายต่อการพูดคุยทั่วไปและดังนั้นจึงไม่จำเป็นต้องใช้การออกกลางคันเพื่อลดการเกิด overfitting

หลังจากการคำนวณฟังก์ชั่นเชิงเส้นโดยใช้ say, Dense () หรือ Conv2D () ใน Keras เราใช้ BatchNormalization () ซึ่งคำนวณฟังก์ชันเชิงเส้นในเลเยอร์แล้วเราจะเพิ่มความไม่เป็นเชิงเส้นลงในเลเยอร์โดยใช้ 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)

การปรับบรรทัดคำสั่งแบบ Batch มีการนำไปใช้อย่างไร

สมมติว่าเรามีการป้อน [l-1] ไปยังเลเยอร์ l นอกจากนี้เรายังมีน้ำหนัก W [l] และหน่วยอคติ b [l] สำหรับชั้น l ปล่อยให้ [l] เป็นเวกเตอร์การเปิดใช้งานที่คำนวณได้ (เช่นหลังจากเพิ่มความไม่เป็นเชิงเส้น) สำหรับเลเยอร์ l และ z [l] เป็นเวกเตอร์ก่อนที่จะเพิ่มความไม่เป็นเชิงเส้น

  1. การใช้ [l-1] และ W [l] เราสามารถคำนวณ z [l] สำหรับเลเยอร์ l
  2. โดยทั่วไปในการเผยแพร่ฟีดไปข้างหน้าเราจะเพิ่ม bias unit ใน 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])
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.