मैं केरस में बैचनलाइज़ेशन फ़ंक्शन को कहां से कहूं?


167

अगर मैं केरस में बैचनेक्लाइज़ेशन फ़ंक्शन का उपयोग करना चाहता हूं, तो क्या मुझे इसे केवल शुरुआत में एक बार कॉल करने की आवश्यकता है?

मैंने इसके लिए यह दस्तावेज़ पढ़ा: 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

बस इस सवाल का थोड़ा और विस्तार से जवाब देने के लिए, और जैसा कि पावेल ने कहा, बैच नॉर्मलाइज़ेशन सिर्फ एक और परत है, इसलिए आप इसका उपयोग अपने वांछित नेटवर्क आर्किटेक्चर को बनाने के लिए कर सकते हैं।

सामान्य उपयोग का मामला आपके नेटवर्क में रैखिक और गैर-रेखीय परतों के बीच बीएन का उपयोग करना है, क्योंकि यह आपके सक्रियण फ़ंक्शन के इनपुट को सामान्य करता है, ताकि आप सक्रियण फ़ंक्शन (जैसे सिग्मॉइड) के रैखिक खंड में केंद्रित हों। यहाँ इसकी एक छोटी सी चर्चा है

ऊपर आपके मामले में, यह इस तरह दिख सकता है:


# 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: निश्चित बात, मूल रूप से मैंने इसे पूरी तरह से यहां के परिणामों पर आधारित किया, जहां रिले के बेहतर प्रदर्शन के बाद बैच मानदंड को रखा। FWIW मैं इसे एक तरह से लागू करने में सफलता नहीं मिली है या दूसरे पर मैंने कोशिश की है
क्लाउडी

32
दिलचस्प। बस फॉलो अप करने के लिए, यदि आप उस सारांश में पढ़ना जारी रखते हैं, तो यह कहता है कि उनका सबसे अच्छा मॉडल [GoogLeNet128_BN_lim0606] वास्तव में BN लेयर से पहले ReLU है। इसलिए जबकि बीएन एक्टिवेशन के बाद एक अलग मामले में सटीकता में सुधार कर सकता है, जब पूरे मॉडल का निर्माण किया जाता है, तो सबसे अच्छा प्रदर्शन करने से पहले। संभवत: यह संभव है कि सक्रियण के बाद बीएन रखने से सटीकता में सुधार हो सकता है, लेकिन संभावना समस्या निर्भर है।
लुकास रमादान

7
@ कार्लथोमे की तरह। उदाहरण के लिए ReginaldIII द्वारा यह रेडिट टिप्पणी देखें । वे कहते हैं: "बीएन एक कनवल्शन से आने वाली सुविधाओं के वितरण को सामान्य कर रहा है, कुछ [] इन सुविधाओं को नकारात्मक हो सकता है [और] ReLU जैसे गैर-रैखिकता द्वारा काट दिया जाता है। यदि आप सक्रियण से पहले सामान्य करते हैं तो आप इन नकारात्मक मूल्यों को शामिल कर रहे हैं। फीचर स्पेस से उन्हें खींचने से ठीक पहले सामान्यीकरण। सक्रियण के बाद बी.एन. सक्रिय रूप से सकारात्मक सुविधाओं को सामान्य कर देगा, बिना उन सुविधाओं के साथ पक्षपात किए बिना, जो इसे अगली संकरी परत के माध्यम से नहीं बनाते हैं। "
mab

60

यह धागा भ्रामक है। लुकास रमजान के जवाब पर टिप्पणी करने की कोशिश की, लेकिन मेरे पास अभी तक सही विशेषाधिकार नहीं हैं, इसलिए मैं इसे यहां डालूंगा।

सक्रियण फ़ंक्शन के बाद बैच सामान्यीकरण सबसे अच्छा काम करता है, और यहां या यहां क्यों है: यह आंतरिक कोवरिएट शिफ्ट को रोकने के लिए विकसित किया गया था। आंतरिक सहसंयोजक पारी तब होती है जब सक्रियण का वितरणएक परत के पूरे प्रशिक्षण में महत्वपूर्ण बदलाव होता है। बैच सामान्यीकरण का उपयोग किया जाता है ताकि इनपुट का वितरण (और ये इनपुट वास्तव में एक सक्रियण फ़ंक्शन का परिणाम है) प्रत्येक बैच से पैरामीटर अपडेट के कारण समय के साथ नहीं बदलता है (या कम से कम, इसे बदलने की अनुमति देता है एक लाभप्रद तरीके से)। यह सामान्य करने के लिए बैच के आँकड़ों का उपयोग करता है, और फिर बैच सामान्यीकरण मापदंडों (गामा और मूल पेपर में बीटा) का उपयोग करता है "यह सुनिश्चित करने के लिए कि नेटवर्क में डाला गया परिवर्तन पहचान परिवर्तन का प्रतिनिधित्व कर सकता है" (मूल पेपर से उद्धरण)। लेकिन मुद्दा यह है कि हम एक परत को इनपुट को सामान्य करने की कोशिश कर रहे हैं, इसलिए इसे हमेशा नेटवर्क में अगली परत से पहले जाना चाहिए। चाहे या नहीं '


27
मैंने अभी अभी deeplearning.ai वर्ग में देखा कि एंड्रयू एनजी कहते हैं कि डीप लर्निंग समुदाय में इस पर बहस चल रही है। वह गैर-रैखिकता से पहले बैच के सामान्यीकरण को लागू करना पसंद करता है।
shahensha

3
@kRazzyR मेरा मतलब था कि प्रो। एंड्रयू एन ने इस विषय पर अपने गहन अध्ययन कक्षाओं में deeplearning.ai के बारे में बात की। उन्होंने कहा कि समुदाय चीजों को करने के सही तरीके से विभाजित है और गैर-रैखिकता को लागू करने से पहले वह बैच सामान्यीकरण को प्राथमिकता देता है।
शाशेंशा

3
@jmancuso, BN सक्रियण से पहले लगाया जाता है। कागज से ही, समीकरण है g(BN(Wx + b)), जहां gसक्रियण समारोह है।
यशगर्ग १२३२

43

इस थ्रेड में इस बारे में काफी बहस है कि क्या बीएन को वर्तमान परत की गैर-रैखिकता से पहले या पिछली परत की सक्रियता से पहले लागू किया जाना चाहिए।

हालांकि इसका कोई सही उत्तर नहीं है, बैच सामान्यीकरण के लेखकों का कहना है कि इसे वर्तमान परत के गैर-रैखिकता से तुरंत पहले लागू किया जाना चाहिए। कारण (मूल पेपर से उद्धृत) -

"हम x = वू + बी को सामान्य करके nonlinearity के तुरंत पहले बीएन का रूपांतरण जोड़ते हैं। हम लेयर इनपुट्स को सामान्यीकृत कर सकते हैं, लेकिन चूंकि यू संभावना है कि यह एक और नॉनलाइनरिटी का आउटपुट है, इसलिए इसके वितरण का आकार बदलने की संभावना है। प्रशिक्षण, अपने पहले और दूसरे क्षणों को रोकना, कोवरिएट शिफ्ट को खत्म नहीं करेगा। इसके विपरीत, वू + बी में एक सममित, गैर-विरल वितरण होने की संभावना है, जो कि "अधिक गौसियन" (हाइवरविनन और ओजा, 2000) है। ; इसे स्थिर वितरण के साथ सक्रियता पैदा करने की संभावना है। "


3
अपने स्वयं के व्यक्तिगत अनुभव में, यह बहुत बड़ा अंतर नहीं करता है, लेकिन बाकी सभी समान हैं, मैंने बीएन को हमेशा थोड़ा बेहतर प्रदर्शन किया है जब बैच सामान्यीकरण को गैर-रैखिकता (सक्रियण फ़ंक्शन से पहले) में लागू किया जाता है।
ब्रैड हेस

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

यदि आप tensorflowबैकएंड के रूप में उपयोग कर रहे हैं तो @KRRR अलग नहीं है । यह यहाँ लिखा है क्योंकि उन्होंने इसे keras.applicationsमॉड्यूल से कॉपी किया है, जहाँ bn_axisदोनों स्वरूपों channels_firstऔर channels_lastस्वरूपों का समर्थन करने के लिए निर्दिष्ट करने की आवश्यकता है।
ldavid

9
क्या कोई कृपया बता सकता है कि यह ओपी प्रश्न से कैसे संबंधित है? (मैं एनएनएस के लिए शुरुआती हूं, इसलिए शायद मुझे कुछ याद
आए

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
शायद यह करने के लिए धक्का?
साचिन्रुक

6

यह एक अन्य प्रकार की परत है, इसलिए आपको इसे अपने मॉडल के उचित स्थान पर एक परत के रूप में जोड़ना चाहिए

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

यहां एक उदाहरण देखें: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py


1
बाद में मैंने बैचनैलाइज़ेशन जोड़ा, val_acc ने हर युग को बढ़ाना बंद कर दिया। मेरे द्वारा बैचन्युलाइज़ेशन जोड़ने के बाद प्रत्येक युग के बाद उसी संख्या में val_acc स्थिर रहा। मुझे लगा कि बैच नॉर्मलाइजेशन को val_acc को बढ़ाना चाहिए था। मुझे कैसे पता चलेगा कि यह ठीक से काम कर रहा है? क्या आप जानते हैं कि इसके कारण क्या हो सकते हैं?
pr338

दुर्भाग्य से लिंक अब मान्य नहीं है :(
user2324712

केरस के कांटों में उस उदाहरण की प्रतियां हैं (जैसे github.com/WenchenLi/kaggle/blob/master/otto/keras/… ), लेकिन मुझे नहीं पता कि इसे मूल केरस रेपो से क्यों हटाया गया था, और यदि कोड नवीनतम Keras संस्करणों के साथ संगत है।
पावेल सुरमेनोक

4

बैच नॉर्मलाइजेशन का उपयोग इनपुट परत के साथ-साथ छिपी परतों को सामान्य करने और सक्रियण के स्केलिंग को समायोजित करने के लिए किया जाता है। गहरे तंत्रिका नेटवर्क में अतिरिक्त परत के साथ इस सामान्य प्रभाव के कारण, नेटवर्क गायब या विस्फोट किए बिना उच्च शिक्षण दर का उपयोग कर सकता है। इसके अलावा, बैच सामान्यीकरण नेटवर्क को नियमित करता है जैसे कि इसे सामान्य करना आसान है, और इस प्रकार से कम करने के लिए ड्रॉपआउट का उपयोग करना अनावश्यक है।

कायर का उपयोग करते हुए रैखिक फ़ंक्शन की गणना करने के ठीक बाद, केरस में घने () या कन्वर्सेशन () का उपयोग करते हैं, हम बैचैर्निलाइज़ेशन () का उपयोग करते हैं जो एक परत में रैखिक फ़ंक्शन की गणना करता है और फिर हम गैर-रैखिकता को परत के साथ जुड़ाव () का उपयोग करते हुए जोड़ते हैं।

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)

बैच सामान्यीकरण कैसे लागू किया जाता है?

मान लें कि हमारे पास लेयर l के लिए [l-1] इनपुट है। इसके अलावा हमारे पास वेट l [l] और बायस यूनिट b [l] लेयर l के लिए है। ले [z] लेयर z और z [l] के लिए गैर-रैखिकता जोड़ने के बाद गणना की गई सक्रियण वेक्टर (गैर-रैखिकता जोड़ने के बाद) की गणना करें।

  1. [L-1] और W [l] का उपयोग करके हम लेयर l के लिए z [l] की गणना कर सकते हैं
  2. आमतौर पर फीड-फॉरवर्ड प्रचार में हम इस चरण में z [l] की तरह bias यूनिट को इस z [l] + b [l] में जोड़ देंगे, लेकिन बैच नॉर्मलाइज़ेशन में b [l] के अतिरिक्त के इस चरण की आवश्यकता नहीं है और नहीं b [l] पैरामीटर का उपयोग किया जाता है।
  3. Z [l] का अर्थ है गणना करें और इसे प्रत्येक तत्व से घटाएं
  4. डिवाइड (z [l] - माध्य) मानक विचलन का उपयोग करते हुए। इसे Z_temp [l] कहें
  5. अब नए मापदंडों को परिभाषित करें define और γ जो कि छिपी हुई परत के पैमाने को निम्नानुसार बदल देगा:

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

इस कोड अंश में, Dense () एक [l-1] लेता है, W [l] का उपयोग करता है और z / l की गणना करता है। फिर तत्काल बैचैनीकरण () z_norm [l] देने के लिए उपरोक्त चरणों का प्रदर्शन करेगा। और फिर तत्काल सक्रियण () तन [z_norm [l]) की गणना करने के लिए [l] यानी देगा

a[l] = tanh(z_norm[l])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.