Tanulási sebesség bemelegítése koszinuszcsökkentéssel a Keras/TensorFlow PlatoBlockchain adatintelligenciában. Függőleges keresés. Ai.

Tanulási sebesség bemelegítés koszinuszcsökkentéssel a Keras/TensorFlow-ban

A tanulási sebesség fontos hiperparaméter a mély tanulási hálózatokban – és közvetlenül diktálja a fokozat amelyhez a súlyok frissítéseit hajtják végre, amelyek a becslések szerint minimálisra csökkentenek bizonyos veszteségfüggvényeket. SGD nyelven:

$$
súly_{t+1} = súly_t – lr * frac{hiba}{dweight_t}
$$

A tanulási arány 0, a frissített súly ismét magához tért – súlyt. A tanulási sebesség gyakorlatilag egy gomb, amellyel engedélyezhetjük vagy letilthatjuk a tanulást, és nagyban befolyásolja, hogy mennyi tanulás történik, közvetlenül szabályozva a súlyfrissítés mértékét.

A különböző optimalizálók eltérően használják fel a tanulási sebességet – de a mögöttes koncepció ugyanaz marad. Mondanunk sem kell, hogy a tanulási arány számos tanulmány, tanulmány és gyakorló referenciaérték tárgya volt.

Általánosságban elmondható, hogy nagyjából mindenki egyetért azzal, hogy a statikus tanulási sebesség nem csökkenti, és bizonyos típusú tanulási sebesség-csökkentés történik a legtöbb olyan technikában, amely a tanulási sebességet edzés közben hangolja – legyen az monoton, koszinusz, háromszög vagy más típusú tanulás. csökkentés.

Az utóbbi években egyre nagyobb teret hódító technika az tanulási sebesség bemelegítés, amely gyakorlatilag bármilyen más redukciós technikával párosítható.

Tanulási arány bemelegítés

A tanulási sebesség bemelegítésének ötlete egyszerű. Az edzés legkorábbi szakaszában a súlyok messze vannak az ideális állapotuktól. Ez mindenhol nagy frissítéseket jelent, amelyek minden súlynál „túlkorrekciónak” tekinthetők – ahol egy másik súly drasztikus frissítése érvénytelenítheti egy másik súly frissítését, instabilabbá téve az edzés kezdeti szakaszait.

Ezek a változások kiegyenlítik, de elkerülhetők, ha kezdetben alacsony tanulási sebességgel, stabilabb szuboptimális állapotot érünk el, majd nagyobb tanulási sebességet alkalmazunk. A hálózatot inkább a frissítésekbe könnyítheti, ahelyett, hogy megütné őket.

Ez a tanulási ráta bemelegítése! Kezdve alacsony (vagy 0) tanulási rátával, és növelve a kezdő tanulási arányig (amivel egyébként is kezdenéd). Ez a növekedés igazából bármilyen függvényt követhet, de általában lineáris.

A kezdeti sebesség elérése után más ütemezések, például koszinusz-csökkenés, lineáris redukció stb. alkalmazhatók a sebesség fokozatos csökkentésére az edzés végéig. A tanulási ütem bemelegítése általában egy kétütemes ütemezés része, ahol az LR bemelegítés az első, míg egy másik ütemterv veszi át az irányítást, miután az ütem elérte a kiindulási pontot.

Ebben az útmutatóban a tanulási sebesség bemelegítését hajtjuk végre a Keras/TensorFlow rendszerben, mint a keras.optimizers.schedules.LearningRateSchedule alosztály és keras.callbacks.Callback visszahív. A tanulási ráta től növekszik 0 nak nek target_lr és alkalmazza a koszinusz-bomlást, mivel ez egy nagyon gyakori másodlagos ütemezés. Ahogy az lenni szokott, a Keras egyszerűvé teszi a rugalmas megoldások különféle módokon való megvalósítását és a hálózattal való szállítását.

Jegyzet: A megvalósítás általános és inspirálta Tony Keras megvalósítása fejezetben vázolt trükkök közülZsák trükkök a képosztályozáshoz konvolúciós neurális hálózatokkal”.

Tanulási arány Keras visszahívásokkal

A tanulási ütem ütemezésének legegyszerűbb módja egy olyan függvény létrehozása, amely a lr paraméter (float32), átengedi valamilyen átalakításon, és visszaadja. Ezt a funkciót ezután továbbítja a LearningRateScheduler visszahívás, amely a függvényt a tanulási sebességre alkalmazza.

Most, a tf.keras.callbacks.LearningRateScheduler() átadja az epochaszámot annak a függvénynek, amelyet a tanulási sebesség kiszámításához használ, ami elég durva. Az LR bemelegítést mindegyiken el kell végezni lépés (kötegelt), nem epoch, tehát le kell vezetnünk a global_step (minden korszakban) a tanulási sebesség kiszámításához, és alosztályba sorolja a Callback osztályt, hogy egyéni visszahívást hozzon létre, ahelyett, hogy egyszerűen átadná a függvényt, mivel minden hívásnál argumentumokat kell átadnunk, ami lehetetlen, ha csak a függvényt adjuk át:

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

Ez a megközelítés akkor előnyös, ha nem akar magas szintű testreszabást, és nem akar beleavatkozni abba, ahogy a Keras kezeli a lr, és különösen, ha olyan visszahívásokat szeretne használni, mint a ReduceLROnPlateau() mivel csak float alapúval tud működni lr. Valósítsunk meg egy tanulási sebesség bemelegítést Keras visszahívással, kezdve egy kényelmi funkcióval:

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

Minden lépésnél kiszámítjuk a tanulási sebességet és a bemelegítési sebességet (mindkét ütemterv eleme), tekintettel a start_lr és a target_lr. start_lr általában órakor kezdődik 0.0, amíg a target_lr hálózatától és optimalizálójától függ – 1e-3 lehet, hogy nem jó alapértelmezett, ezért ügyeljen arra, hogy a metódus meghívásakor állítsa be a cél kezdő LR-t.

Ha a global_step a képzésben magasabb, mint a warmup_steps beállítottuk – az LR koszinusz-csökkentési ütemezést használjuk. Ha nem, az azt jelenti, hogy még mindig bemelegítünk, tehát a warmup LR használatos. Ha a hold argumentum be van állítva, megtartjuk a target_lr ennyi lépésszámra a bemelegítés után és a koszinusz-bomlás előtt. np.where() nagyszerű szintaxist biztosít ehhez:

np.where(condition, value_if_true, value_if_false)

A funkciót a következőkkel vizualizálhatja:

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)

Most ezt a függvényt a visszahívás részeként szeretnénk használni, és az optimalizáló lépést a következőként adjuk át global_step nem pedig egy tetszőleges tömb eleme – vagy elvégezheti a számítást az osztályon belül. Alkalmazzuk a Callback osztály:

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)

Tekintse meg gyakorlatias, gyakorlati útmutatónkat a Git tanulásához, amely tartalmazza a bevált gyakorlatokat, az iparág által elfogadott szabványokat és a mellékelt csalólapot. Hagyd abba a guglizást a Git parancsokkal, és valójában tanulni meg!

Először is meghatározzuk az osztály konstruktorát, és nyomon követjük a mezőit. Minden egyes befejezett kötegnél növeljük a globális lépést, figyelembe vesszük az aktuális LR-t, és hozzáadjuk az eddigi LR-ek listájához. Minden köteg elején – kiszámítjuk az LR-t a lr_warmup_cosine_decay() függvényt, és állítsa be ezt az LR-t az optimalizáló aktuális LR-jeként. Ez a háttérrel történik set_value().

Ha ez megtörtént – csak számítsa ki az összes lépést (hossz/kötegelt_méret*korszakok), és vegyen egy részt ebből a számból 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)

Végül készítse el a modellt, és adja meg a visszahívást a fit() hívás:

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'])

A képzés végén megszerezheti és megjelenítheti a megváltozott LR-eket az alábbi módon:

lrs = callback.lrs 
plt.plot(lrs)

Tanulási sebesség bemelegítése koszinuszcsökkentéssel a Keras/TensorFlow PlatoBlockchain adatintelligenciában. Függőleges keresés. Ai.

Ha felvázolja egy LR bemelegítéssel és anélkül kiképzett modell történetét – egyértelmű különbséget fog látni az edzés stabilitásában:

Tanulási sebesség bemelegítése koszinuszcsökkentéssel a Keras/TensorFlow PlatoBlockchain adatintelligenciában. Függőleges keresés. Ai.

Tanulási arány a LearningRateSchedule alosztályon

A visszahívás létrehozásának alternatívája az a LearningRateSchedule alosztály, amely nem manipulálja az LR-t, hanem helyettesíti. Ez a megközelítés lehetővé teszi, hogy egy kicsit többet nyúljon a Keras/TensorFlow hátterébe, de ha használják, nem kombinálható más, LR-hez kapcsolódó visszahívásokkal, mint pl. ReduceLROnPlateau(), amely az LR-eket lebegőpontos számként kezeli.

Ezenkívül az alosztály használatához szerializálhatóvá kell tenni (túlterhelés get_config()), mivel a modell részévé válik, ha el szeretné menteni a modell súlyait. Egy másik dolog, amit meg kell jegyezni, hogy az osztály elvárja, hogy kizárólag velük dolgozzon tf.Tensors. Szerencsére az egyetlen különbség a munkánk módjában a hívás lesz tf.func() helyett np.func() mivel a TensorFlow és a NumPy API-k elképesztően hasonlóak és kompatibilisek.

Írjuk át a kényelmet lr_warmup_cosine_decay() függvény helyett TensorFlow műveleteket használjon:

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

A kényelmi függvénnyel alosztályozhatjuk a LearningRateSchedule osztály. Mindegyiken __call__() (batch), a függvény segítségével kiszámítjuk az LR-t, és visszaadjuk. A számítást természetesen az alosztályon belül is csomagolhatja.

A szintaxis tisztább, mint a Callback sublcass, elsősorban azért, mert hozzáférünk a step ahelyett, hogy magunk nyomon követnénk, hanem némileg megnehezíti az osztálytulajdonságokkal való munkát – különösen megnehezíti a lr egy tf.Tensor() bármely más típusba, hogy nyomon kövesse a listában. Ez technikailag megkerülhető, ha buzgó módban fut, de bosszúságot okoz az LR nyomon követése hibakeresés céljából, és ezt a legjobb elkerülni:

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

A paraméterek megegyeznek, és nagyjából ugyanúgy számíthatók ki, mint korábban:


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)

A képzési folyamat pedig csak annyiban tér el, hogy az optimalizáló LR-jét a 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)

Ha el szeretné menteni a modellt, a WarmupCosineDecay ütemezésnek felül kell írnia a get_config() eljárás:

    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

Végül a modell betöltésekor át kell adnia a WarmupCosineDecay egyéni objektumként:

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

Következtetés

Ebben az útmutatóban a Learning Rate Warmup mögött meghúzódó intuíciót vettük szemügyre – ez egy gyakori technika a tanulási sebesség manipulálására a neurális hálózatok betanítása közben.

Bevezettük a tanulási sebesség bemelegítését koszinuszcsillapítással, amely a bemelegítéssel párosított LR-csökkentés leggyakoribb típusa. Bármilyen más funkciót megvalósíthat a tanulási sebesség csökkentésére, vagy egyáltalán nem csökkentheti – ezt más visszahívásokra hagyva, mint pl ReduceLROnPlateau(). Megvalósítottuk a tanulási sebesség bemelegítését Keras visszahívásként, valamint Keras Optimizer ütemezésként, és ábrázoltuk a tanulási sebességet a korszakokon keresztül.

Időbélyeg:

Még több Stackabus