केरस/टेन्सरफ्लो प्लेटोब्लॉकचैन डेटा इंटेलिजेंस में कोसाइन क्षय के साथ सीखने की दर वार्मअप। लंबवत खोज। ऐ.

केरस/टेन्सरफ्लो में कोसाइन क्षय के साथ सीखने की दर वार्मअप

गहन शिक्षण नेटवर्क में सीखने की दर एक महत्वपूर्ण हाइपरपैरामीटर है - और यह सीधे निर्देश देता है हद जिसमें वज़न के अद्यतन किए जाते हैं, जो किसी दिए गए नुकसान फ़ंक्शन को कम करने का अनुमान है। एसजीडी में:

$$
weight_{t+1} = weight_t - lr * फ़्रैक{डर}{dweight_t}
$$

सीखने की दर के साथ 0, अद्यतन वजन अपने आप में वापस आ गया है - भारt. सीखने की दर प्रभावी रूप से एक घुंडी है जिसे हम सीखने को सक्षम या अक्षम करने के लिए बदल सकते हैं, और वजन अपडेट की डिग्री को सीधे नियंत्रित करके, सीखने की मात्रा पर इसका बड़ा प्रभाव पड़ता है।

विभिन्न अनुकूलक सीखने की दरों का अलग-अलग उपयोग करते हैं - लेकिन अंतर्निहित अवधारणा समान रहती है। कहने की जरूरत नहीं है कि सीखने की दर कई अध्ययनों, पत्रों और अभ्यासकर्ताओं के बेंचमार्क का उद्देश्य रही है।

सामान्यतया, हर कोई इस बात से सहमत है कि एक स्थिर सीखने की दर में कटौती नहीं होगी, और प्रशिक्षण के दौरान सीखने की दर को ट्यून करने वाली अधिकांश तकनीकों में कुछ प्रकार की सीखने की दर में कमी होती है - चाहे वह एक मोनोटोनिक, कोसाइन, त्रिकोणीय या अन्य प्रकार की हो कमी।

एक तकनीक जो हाल के वर्षों में पैर जमा रही है, वह है सीखने की दर वार्मअप, जिसे व्यावहारिक रूप से किसी अन्य कमी तकनीक के साथ जोड़ा जा सकता है।

सीखने की दर वार्मअप

सीखने की दर वार्मअप के पीछे का विचार सरल है। प्रशिक्षण के शुरुआती चरणों में - भार अपने आदर्श राज्यों से बहुत दूर हैं। इसका मतलब है कि पूरे बोर्ड में बड़े अपडेट, जिन्हें प्रत्येक वजन के लिए "अति सुधार" के रूप में देखा जा सकता है - जहां दूसरे का कठोर अपडेट किसी अन्य वजन के अपडेट को नकार सकता है, जिससे प्रशिक्षण के प्रारंभिक चरण अधिक अस्थिर हो जाते हैं।

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

वह सीखने की दर वार्मअप है! कम (या 0) सीखने की दर से शुरू करना और सीखने की प्रारंभिक दर तक बढ़ना (आप वैसे भी क्या शुरू करेंगे)। यह वृद्धि वास्तव में किसी भी कार्य का अनुसरण कर सकती है, लेकिन आमतौर पर रैखिक होती है।

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

इस गाइड में, हम Keras/TensorFlow में सीखने की दर वार्मअप को a . के रूप में लागू करेंगे keras.optimizers.schedules.LearningRateSchedule उपवर्ग और keras.callbacks.Callback वापस कॉल करें। सीखने की दर में वृद्धि होगी 0 सेवा मेरे target_lr और कोसाइन क्षय लागू करें, क्योंकि यह एक बहुत ही सामान्य माध्यमिक अनुसूची है। हमेशा की तरह, केरस विभिन्न तरीकों से लचीले समाधानों को लागू करना और उन्हें आपके नेटवर्क के साथ शिप करना आसान बनाता है।

नोट: कार्यान्वयन सामान्य है और इससे प्रेरित है टोनी के केरस कार्यान्वयन में उल्लिखित तरकीबें "कन्वेन्शनल न्यूरल नेटवर्क्स के साथ इमेज क्लासिफिकेशन के लिए ट्रिक्स का बैग”.

केरस कॉलबैक के साथ सीखने की दर

किसी भी सीखने की दर अनुसूची को लागू करने का सबसे आसान तरीका एक ऐसा फ़ंक्शन बनाना है जो लेता है lr पैरामीटर (float32), इसे कुछ परिवर्तन के माध्यम से पारित करता है, और इसे वापस कर देता है। यह फ़ंक्शन तब को दिया जाता है LearningRateScheduler कॉलबैक, जो फ़ंक्शन को सीखने की दर पर लागू करता है।

अब, tf.keras.callbacks.LearningRateScheduler() सीखने की दर की गणना करने के लिए उपयोग किए जाने वाले फ़ंक्शन में युग संख्या पास करता है, जो कि बहुत मोटे है। प्रत्येक पर एलआर वार्मअप किया जाना चाहिए कदम (बैच), युग नहीं, इसलिए हमें प्राप्त करना होगा a global_step (सभी युगों में) इसके बजाय सीखने की दर की गणना करने के लिए, और उपवर्ग Callback क्लास को केवल फ़ंक्शन पास करने के बजाय एक कस्टम कॉलबैक बनाने के लिए, क्योंकि हमें प्रत्येक कॉल पर तर्कों को पारित करने की आवश्यकता होगी, जो कि फ़ंक्शन को पास करते समय असंभव है:

def func():
    return ...
    
keras.callbacks.LearningRateScheduler(func)

यह दृष्टिकोण अनुकूल है जब आप उच्च-स्तरीय अनुकूलन नहीं चाहते हैं और आप केरस के व्यवहार में हस्तक्षेप नहीं करना चाहते हैं lr, और विशेष रूप से यदि आप कॉलबैक का उपयोग करना चाहते हैं जैसे ReduceLROnPlateau() चूंकि यह केवल फ्लोट-आधारित के साथ काम कर सकता है lr. केरस कॉलबैक का उपयोग करके एक सीखने की दर वार्मअप को लागू करें, जो एक सुविधा फ़ंक्शन से शुरू होता है:

def lr_warmup_cosine_decay(global_step,
                           warmup_steps,
                           hold = 0,
                           total_steps=0,
                           start_lr=0.0,
                           target_lr=1e-3):
    
    learning_rate = 0.5 * target_lr * (1 + np.cos(np.pi * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))

    
    warmup_lr = target_lr * (global_step / warmup_steps)

    
    
    if hold > 0:
        learning_rate = np.where(global_step > warmup_steps + hold,
                                 learning_rate, target_lr)
    
    learning_rate = np.where(global_step < warmup_steps, warmup_lr, learning_rate)
    return learning_rate

प्रत्येक चरण पर, हम सीखने की दर और वार्मअप सीखने की दर (शेड्यूल के दोनों तत्व) की गणना करते हैं। start_lr और target_lr. start_lr आमतौर पर शुरू होगा 0.0, जबकि target_lr आपके नेटवर्क और अनुकूलक पर निर्भर करता है - 1e-3 एक अच्छा डिफ़ॉल्ट नहीं हो सकता है, इसलिए विधि को कॉल करते समय एलआर शुरू करने के लिए अपना लक्ष्य निर्धारित करना सुनिश्चित करें।

अगर global_step प्रशिक्षण में से अधिक है warmup_steps हमने सेट किया है - हम कोसाइन क्षय अनुसूची LR का उपयोग करते हैं। यदि नहीं, तो इसका मतलब है कि हम अभी भी वार्मअप कर रहे हैं, इसलिए वार्मअप LR का उपयोग किया जाता है। अगर hold तर्क निर्धारित है, हम पकड़ लेंगे target_lr वार्मअप के बाद और कोसाइन क्षय से पहले इतने चरणों के लिए। np.where() इसके लिए एक महान वाक्यविन्यास प्रदान करता है:

np.where(condition, value_if_true, value_if_false)

आप इसके साथ फ़ंक्शन की कल्पना कर सकते हैं:

steps = np.arange(0, 1000, 1)
lrs = []

for step in steps:
  lrs.append(lr_warmup_cosine_decay(step, total_steps=len(steps), warmup_steps=100, hold=10))
plt.plot(lrs)

अब, हम इस फ़ंक्शन को कॉलबैक के एक भाग के रूप में उपयोग करना चाहते हैं, और ऑप्टिमाइज़र चरण को इस रूप में पास करना चाहते हैं global_step एक मनमाना सरणी के एक तत्व के बजाय - या आप कक्षा के भीतर गणना कर सकते हैं। आइए उपवर्ग करें Callback वर्ग:

from keras import backend as K

class WarmupCosineDecay(keras.callbacks.Callback):
    def __init__(self, total_steps=0, warmup_steps=0, start_lr=0.0, target_lr=1e-3, hold=0):

        super(WarmupCosineDecay, self).__init__()
        self.start_lr = start_lr
        self.hold = hold
        self.total_steps = total_steps
        self.global_step = 0
        self.target_lr = target_lr
        self.warmup_steps = warmup_steps
        self.lrs = []

    def on_batch_end(self, batch, logs=None):
        self.global_step = self.global_step + 1
        lr = model.optimizer.lr.numpy()
        self.lrs.append(lr)

    def on_batch_begin(self, batch, logs=None):
        lr = lr_warmup_cosine_decay(global_step=self.global_step,
                                    total_steps=self.total_steps,
                                    warmup_steps=self.warmup_steps,
                                    start_lr=self.start_lr,
                                    target_lr=self.target_lr,
                                    hold=self.hold)
        K.set_value(self.model.optimizer.lr, lr)

सर्वोत्तम प्रथाओं, उद्योग-स्वीकृत मानकों और शामिल चीट शीट के साथ, Git सीखने के लिए व्यावहारिक मार्गदर्शिका देखें। Googling Git कमांड को रोकें और वास्तव में सीखना यह!

सबसे पहले, हम क्लास के लिए कंस्ट्रक्टर को परिभाषित करते हैं और उसके क्षेत्रों पर नज़र रखते हैं। समाप्त होने वाले प्रत्येक बैच पर, हम वैश्विक कदम बढ़ाएंगे, वर्तमान LR पर ध्यान देंगे और इसे अब तक LRs की सूची में जोड़ देंगे। प्रत्येक बैच की शुरुआत में - हम LR का उपयोग करके गणना करेंगे lr_warmup_cosine_decay() कार्य करें और उस LR को अनुकूलक के वर्तमान LR के रूप में सेट करें। यह बैकएंड के साथ किया जाता है set_value().

इसके साथ - बस कुल चरणों की गणना करें (लंबाई/बैच_साइज * युग) और उस संख्या का एक हिस्सा अपने लिए लें warmup_steps:


total_steps = len(train_set)*config['EPOCHS']



warmup_steps = int(0.05*total_steps)

callback = WarmupCosineDecay(total_steps=total_steps, 
                             warmup_steps=warmup_steps,
                             hold=int(warmup_steps/2), 
                             start_lr=0.0, 
                             target_lr=1e-3)

अंत में, अपना मॉडल बनाएं और कॉलबैक प्रदान करें fit() फोन:

model = keras.applications.EfficientNetV2B0(weights=None, 
                                            classes=n_classes, 
                                            input_shape=[224, 224, 3])
  
model.compile(loss="sparse_categorical_crossentropy",
                  optimizer='adam',
                  jit_compile=True,
                  metrics=['accuracy'])

प्रशिक्षण के अंत में, आप निम्न के माध्यम से परिवर्तित LRs प्राप्त कर सकते हैं और उनकी कल्पना कर सकते हैं:

lrs = callback.lrs 
plt.plot(lrs)

केरस/टेन्सरफ्लो प्लेटोब्लॉकचैन डेटा इंटेलिजेंस में कोसाइन क्षय के साथ सीखने की दर वार्मअप। लंबवत खोज। ऐ.

यदि आप एलआर वार्मअप के साथ और बिना प्रशिक्षित मॉडल के इतिहास की साजिश रचते हैं - तो आपको प्रशिक्षण की स्थिरता में एक अलग अंतर दिखाई देगा:

केरस/टेन्सरफ्लो प्लेटोब्लॉकचैन डेटा इंटेलिजेंस में कोसाइन क्षय के साथ सीखने की दर वार्मअप। लंबवत खोज। ऐ.

LearningRateSchedule उपवर्ग के साथ सीखने की दर

कॉलबैक बनाने का एक विकल्प a . बनाना है LearningRateSchedule उपवर्ग, जो एलआर में हेरफेर नहीं करता है - यह इसे बदल देता है। यह दृष्टिकोण आपको Keras/TensorFlow के बैकएंड में थोड़ा और अधिक उत्पादन करने की अनुमति देता है, लेकिन जब उपयोग किया जाता है, तो इसे अन्य LR-संबंधित कॉलबैक के साथ नहीं जोड़ा जा सकता है, जैसे कि ReduceLROnPlateau(), जो LRs को फ्लोटिंग पॉइंट नंबरों के रूप में पेश करता है।

इसके अतिरिक्त, उपवर्ग का उपयोग करने के लिए आपको इसे क्रमबद्ध करने की आवश्यकता होगी (ओवरलोड get_config()) क्योंकि यह मॉडल का एक हिस्सा बन जाता है, अगर आप मॉडल के वज़न को बचाना चाहते हैं। एक और ध्यान देने वाली बात यह है कि वर्ग विशेष रूप से इसके साथ काम करने की अपेक्षा करेगा tf.Tensorएस। शुक्र है, हमारे काम करने के तरीके में केवल कॉलिंग का अंतर होगा tf.func() के बजाय np.func() चूंकि TensorFlow और NumPy API आश्चर्यजनक रूप से समान और संगत हैं।

आइए सुविधा को फिर से लिखें lr_warmup_cosine_decay() इसके बजाय TensorFlow संचालन का उपयोग करने के लिए कार्य करें:

def lr_warmup_cosine_decay(global_step,
                           warmup_steps,
                           hold = 0,
                           total_steps=0,
                           start_lr=0.0,
                           target_lr=1e-3):
    
    
    learning_rate = 0.5 * target_lr * (1 + tf.cos(tf.constant(np.pi) * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))

    
    warmup_lr = target_lr * (global_step / warmup_steps)

    
    
    if hold > 0:
        learning_rate = tf.where(global_step > warmup_steps + hold,
                                 learning_rate, target_lr)
    
    learning_rate = tf.where(global_step < warmup_steps, warmup_lr, learning_rate)
    return learning_rate

convinience फ़ंक्शन के साथ, हम उपवर्ग कर सकते हैं LearningRateSchedule कक्षा। प्रत्येक पर __call__() (बैच), हम फ़ंक्शन का उपयोग करके एलआर की गणना करेंगे और इसे वापस कर देंगे। आप स्वाभाविक रूप से उपवर्ग वर्ग के भीतर भी गणना को पैकेज कर सकते हैं।

वाक्य रचना की तुलना में क्लीनर है Callback sublcass, मुख्य रूप से क्योंकि हम तक पहुँच प्राप्त करते हैं step क्षेत्र, अपने दम पर इसका ट्रैक रखने के बजाय, बल्कि वर्ग गुणों के साथ काम करना थोड़ा कठिन बना देता है - विशेष रूप से, इससे इसे निकालना मुश्किल हो जाता है lr एक से tf.Tensor() किसी सूची में ट्रैक रखने के लिए किसी अन्य प्रकार में। इसे उत्सुक मोड में चलाकर तकनीकी रूप से बाधित किया जा सकता है, लेकिन डिबगिंग उद्देश्यों के लिए एलआर का ट्रैक रखने के लिए परेशानी प्रस्तुत करता है और इससे बचा जाता है:

class WarmUpCosineDecay(keras.optimizers.schedules.LearningRateSchedule):
    def __init__(self, start_lr, target_lr, warmup_steps, total_steps, hold):
        super().__init__()
        self.start_lr = start_lr
        self.target_lr = target_lr
        self.warmup_steps = warmup_steps
        self.total_steps = total_steps
        self.hold = hold

    def __call__(self, step):
        lr = lr_warmup_cosine_decay(global_step=step,
                                    total_steps=self.total_steps,
                                    warmup_steps=self.warmup_steps,
                                    start_lr=self.start_lr,
                                    target_lr=self.target_lr,
                                    hold=self.hold)

        return tf.where(
            step > self.total_steps, 0.0, lr, name="learning_rate"
        )

पैरामीटर समान हैं, और उनकी गणना पहले की तरह ही की जा सकती है:


total_steps = len(train_set)*config['EPOCHS']



warmup_steps = int(0.05*total_steps)

schedule = WarmUpCosineDecay(start_lr=0.0, target_lr=1e-3, warmup_steps=warmup_steps, total_steps=total_steps, hold=warmup_steps)

और प्रशिक्षण पाइपलाइन केवल इस मायने में भिन्न है कि हम ऑप्टिमाइज़र के LR को सेट करते हैं schedule:

model = keras.applications.EfficientNetV2B0(weights=None, 
                                            classes=n_classes, 
                                            input_shape=[224, 224, 3])
  
model.compile(loss="sparse_categorical_crossentropy",
                  optimizer=tf.keras.optimizers.Adam(learning_rate=schedule),
                  jit_compile=True,
                  metrics=['accuracy'])

history3 = model.fit(train_set,
                    epochs = config['EPOCHS'],
                    validation_data=valid_set)

यदि आप मॉडल को सहेजना चाहते हैं, तो WarmupCosineDecay शेड्यूल को ओवरराइड करना होगा get_config() तरीका:

    def get_config(self):
        config = {
          'start_lr': self.start_lr,
          'target_lr': self.target_lr,
          'warmup_steps': self.warmup_steps,
          'total_steps': self.total_steps,
          'hold': self.hold
        }
        return config

अंत में, मॉडल लोड करते समय, आपको पास करना होगा a WarmupCosineDecay एक कस्टम वस्तु के रूप में:

model = keras.models.load_model('weights.h5', 
                                custom_objects={'WarmupCosineDecay', WarmupCosineDecay})

निष्कर्ष

इस गाइड में, हमने लर्निंग रेट वार्मअप के पीछे के अंतर्ज्ञान पर एक नज़र डाली है - तंत्रिका नेटवर्क को प्रशिक्षित करते समय सीखने की दर में हेरफेर करने के लिए एक सामान्य तकनीक।

हमने कोसाइन क्षय के साथ एक सीखने की दर वार्मअप लागू किया है, जो वार्मअप के साथ जोड़ा गया एलआर कमी का सबसे सामान्य प्रकार है। आप कमी के लिए किसी अन्य फ़ंक्शन को लागू कर सकते हैं, या सीखने की दर को बिल्कुल भी कम नहीं कर सकते - इसे अन्य कॉलबैक पर छोड़ दें जैसे कि ReduceLROnPlateau(). हमने केरस कॉलबैक के साथ-साथ केरस ऑप्टिमाइज़र शेड्यूल के रूप में सीखने की दर वार्मअप को लागू किया है और युगों के माध्यम से सीखने की दर को प्लॉट किया है।

समय टिकट:

से अधिक स्टैकब्यूज