Özel TensorFlow/Keras Geri Aramaları Yazma Kılavuzu

Giriş

Keras modelinizin eğitim, değerlendirme veya tahmin sırasında bazı özel davranışlara sahip olmasını istediğinizi varsayalım. Örneğin, modelinizi her eğitim döneminde kaydetmek isteyebilirsiniz. Bunu yapmanın bir yolu Geri Arama kullanmaktır.

Genel olarak Geri Aramalar, bir olay gerçekleştiğinde çağrılan ve diğer işlevlere argüman olarak iletilen işlevlerdir. Keras söz konusu olduğunda, eğitim, değerlendirme veya çıkarım sırasında olsun, modelinizin davranışını özelleştirmek için bir araçtır. Bazı uygulamalar günlüğe kaydetme, model kalıcılığı, erken durdurma veya öğrenme oranını değiştirmedir. Bu, bir Geri Arama listesini argüman olarak ileterek yapılır. keras.Model.fit(),keras.Model.evaluate() or keras.Model.predict().

Geri aramalar için bazı yaygın kullanım durumları, öğrenme oranını değiştirme, günlüğe kaydetme, izleme ve eğitimin erken durdurulmasıdır. Keras'ın bir dizi yerleşik geri araması vardır, ayrıntılı
belgelerde
.

Ancak, bazı daha spesifik uygulamalar, özel bir geri arama gerektirebilir. Örneğin, bir bekleme süresinden sonra Kosinüs Azalması ile Öğrenme Hızı ısınması uygulamak şu anda yerleşik değildir, ancak bir zamanlayıcı olarak yaygın olarak kullanılır ve benimsenir.

Geri Çağırma Sınıfı ve Yöntemleri

Keras'ın belirli bir geri arama sınıfı vardır, keras.callbacks.Callback, eğitim, test ve genel, toplu iş veya dönem düzeyinde çıkarım sırasında çağrılabilen yöntemlerle. İçin özel geri aramalar oluştur, bir alt sınıf oluşturmamız ve bu yöntemleri geçersiz kılmamız gerekiyor.

The keras.callbacks.Callback sınıfın üç tür yöntemi vardır:

  • global metotlar: başında veya sonunda çağrılır fit(), evaluate() ve predict().
  • yığın düzeyinde yöntemler: bir toplu işlemin başında veya sonunda çağrılır.
  • çağ düzeyinde yöntemler: bir eğitim grubunun başında veya sonunda çağrılır.

Not: Her yöntemin adı verilen bir dict'e erişimi vardır. logs. anahtarları ve değerleri logs bağlamsaldır - yöntemi çağıran olaya bağlıdırlar. Ayrıca, her yöntemin içindeki modele, self.model özniteliği.

Biri eğitim, biri değerlendirme ve biri tahmin için olmak üzere üç özel geri arama örneğine göz atalım. Her biri, her aşamada modelimizin ne yaptığını ve hangi günlüklere erişimimiz olduğunu yazdıracaktır. Bu, her aşamada özel geri aramalarla neler yapılabileceğini anlamak için yararlıdır.

Bir oyuncak modeli tanımlayarak başlayalım:

import tensorflow as tf
from tensorflow import keras
import numpy as np

model = keras.Sequential()
model.add(keras.layers.Dense(10, input_dim = 1, activation='relu'))
model.add(keras.layers.Dense(10, activation='relu'))
model.add(keras.layers.Dense(1))
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=0.1),
    loss = "mean_squared_error",
    metrics = ["mean_absolute_error"]
)

x = np.random.uniform(low = 0, high = 10, size = 1000)
y = x**2
x_train, x_test = (x[:900],x[900:])
y_train, y_test = (y[:900],y[900:])

Özel Eğitim Geri Araması

İlk geri aramamız eğitim sırasında aranacak. alt sınıflara ayıralım Callback sınıf:

class TrainingCallback(keras.callbacks.Callback):
    def __init__(self):
        self.tabulation = {"train":"", 'batch': " "*8, 'epoch':" "*4}
    def on_train_begin(self, logs=None):
        tab = self.tabulation['train']
        print(f"{tab}Training!")
        print(f"{tab}available logs: {logs}")

    def on_train_batch_begin(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}Batch {batch}")
        print(f"{tab}available logs: {logs}")

    def on_train_batch_end(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}End of Batch {batch}")
        print(f"{tab}available logs: {logs}")

    def on_epoch_begin(self, epoch, logs=None):
        tab = self.tabulation['epoch']
        print(f"{tab}Epoch {epoch} of training")
        print(f"{tab}available logs: {logs}")

    def on_epoch_end(self, epoch, logs=None):
        tab = self.tabulation['epoch']
        print(f"{tab}End of Epoch {epoch} of training")
        print(f"{tab}available logs: {logs}")

    def on_train_end(self, logs=None):
        tab = self.tabulation['train']
        print(f"{tab}Finishing training!")
        print(f"{tab}available logs: {logs}")

Bu yöntemlerden herhangi biri geçersiz kılınmazsa, varsayılan davranış daha önce olduğu gibi devam eder. Örneğimizde – mevcut günlükleri ve geri aramanın uygulandığı düzeyi uygun girinti ile yazdırıyoruz.

Çıktılara bir göz atalım:

model.fit(
    x_train,
    y_train,
    batch_size=500,
    epochs=2,
    verbose=0,
    callbacks=[TrainingCallback()],
)
Training!
available logs: {}
    Epoch 0 of training
    available logs: {}
        Batch 0
        available logs: {}
        End of Batch 0
        available logs: {'loss': 2172.373291015625, 'mean_absolute_error': 34.79669952392578}
        Batch 1
        available logs: {}
        End of Batch 1
        available logs: {'loss': 2030.1309814453125, 'mean_absolute_error': 33.30256271362305}
    End of Epoch 0 of training
    available logs: {'loss': 2030.1309814453125, 'mean_absolute_error': 33.30256271362305}
    Epoch 1 of training
    available logs: {}
        Batch 0
        available logs: {}
        End of Batch 0
        available logs: {'loss': 1746.2772216796875, 'mean_absolute_error': 30.268001556396484}
        Batch 1
        available logs: {}
        End of Batch 1
        available logs: {'loss': 1467.36376953125, 'mean_absolute_error': 27.10252571105957}
    End of Epoch 1 of training
    available logs: {'loss': 1467.36376953125, 'mean_absolute_error': 27.10252571105957}
Finishing training!
available logs: {'loss': 1467.36376953125, 'mean_absolute_error': 27.10252571105957}


Modelin ne yaptığını ve hangi metriklere erişimimiz olduğunu her adımda takip edebileceğimizi unutmayın. Her partinin ve çağın sonunda, numune içi kayıp fonksiyonuna ve modelimizin metriklerine erişimimiz olur.

Özel Değerlendirme Geri Araması

Şimdi, arayalım Model.evaluate() yöntem. Bir partinin sonunda o andaki kayıp işlevine ve metriklere erişimimiz olduğunu ve değerlendirmenin sonunda genel kayıp ve metriklere erişimimiz olduğunu görebiliriz:

class TestingCallback(keras.callbacks.Callback):
    def __init__(self):
          self.tabulation = {"test":"", 'batch': " "*8}
      
    def on_test_begin(self, logs=None):
        tab = self.tabulation['test']
        print(f'{tab}Evaluating!')
        print(f'{tab}available logs: {logs}')

    def on_test_end(self, logs=None):
        tab = self.tabulation['test']
        print(f'{tab}Finishing evaluation!')
        print(f'{tab}available logs: {logs}')

    def on_test_batch_begin(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}Batch {batch}")
        print(f"{tab}available logs: {logs}")

    def on_test_batch_end(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}End of batch {batch}")
        print(f"{tab}available logs: {logs}")
res = model.evaluate(
    x_test, y_test, batch_size=100, verbose=0, callbacks=[TestingCallback()]
)
Evaluating!
available logs: {}
        Batch 0
        available logs: {}
        End of batch 0
        available logs: {'loss': 382.2723083496094, 'mean_absolute_error': 14.069927215576172}
Finishing evaluation!
available logs: {'loss': 382.2723083496094, 'mean_absolute_error': 14.069927215576172}

Özel Tahmin Geri Araması

Son olarak, arayalım Model.predict() yöntem. Her partinin sonunda, modelimizin tahmin edilen çıktılarına erişimimiz olduğuna dikkat edin:

class PredictionCallback(keras.callbacks.Callback):
    def __init__(self):
        self.tabulation = {"prediction":"", 'batch': " "*8}

    def on_predict_begin(self, logs=None):
        tab = self.tabulation['prediction']
        print(f"{tab}Predicting!")
        print(f"{tab}available logs: {logs}")

    def on_predict_end(self, logs=None):
        tab = self.tabulation['prediction']
        print(f"{tab}End of Prediction!")
        print(f"{tab}available logs: {logs}")

    def on_predict_batch_begin(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}batch {batch}")
        print(f"{tab}available logs: {logs}")

    def on_predict_batch_end(self, batch, logs=None):
        tab = self.tabulation['batch']
        print(f"{tab}End of batch {batch}")
        print(f"{tab}available logs:n {logs}")
res = model.predict(x_test[:10],
                    verbose = 0, 
                    callbacks=[PredictionCallback()])

En iyi uygulamalar, endüstri tarafından kabul edilen standartlar ve dahil edilen hile sayfası ile Git'i öğrenmek için uygulamalı, pratik kılavuzumuza göz atın. Googling Git komutlarını durdurun ve aslında öğrenmek o!

Predicting!
available logs: {}
        batch 0
        available logs: {}
        End of batch 0
        available logs:
 {'outputs': array([[ 7.743822],
       [27.748264],
       [33.082104],
       [26.530678],
       [27.939169],
       [18.414223],
       [42.610645],
       [36.69335 ],
       [13.096557],
       [37.120853]], dtype=float32)}
End of Prediction!
available logs: {}

Bunlarla – davranışı özelleştirebilir, izleme ayarlayabilir veya eğitim, değerlendirme veya çıkarım süreçlerini başka şekilde değiştirebilirsiniz. Alt kablolamaya bir alternatif, LambdaCallback.

LambaCallback'i Kullanma

Keras'taki yerleşik geri aramalardan biri, LambdaCallback sınıf. Bu geri arama, nasıl davrandığını ve ne yaptığını tanımlayan bir işlevi kabul eder! Bir anlamda, herhangi bir işlevi geri arama olarak kullanmanıza izin verir, böylece özel geri aramalar oluşturmanıza olanak tanır.

Sınıf isteğe bağlı parametrelere sahiptir:
-on_epoch_begin

  • on_epoch_end
  • on_batch_begin
  • on_batch_end
  • on_train_begin
  • on_train_end

Her parametre kabul eder bir işlev ilgili model olayında çağrılır. Örnek olarak, model eğitimini bitirdiğinde e-posta göndermek için bir geri arama yapalım:

import smtplib
from email.message import EmailMessage

def send_email(logs): 
    msg = EmailMessage()
    content = f"""The model has finished training."""
    for key, value in logs.items():
      content = content + f"n{key}:{value:.2f}"
    msg.set_content(content)
    msg['Subject'] = f'Training report'
    msg['From'] = '[email protected]'
    msg['To'] = 'receiver-email'

    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.starttls()
    s.login("[email protected]", "your-gmail-app-password")
    s.send_message(msg)
    s.quit()

lambda_send_email = lambda logs : send_email(logs)

email_callback = keras.callbacks.LambdaCallback(on_train_end = lambda_send_email)

model.fit(
    x_train,
    y_train,
    batch_size=100,
    epochs=1,
    verbose=0,
    callbacks=[email_callback],
)

Kullanarak özel geri aramamızı yapmak için LambdaCallback, sadece çağrılmasını istediğimiz işlevi uygulamamız gerekiyor, onu bir lambda işleve aktarın ve
LambdaCallback parametre olarak sınıf

Görselleştirme Modeli Eğitimi için Geri Arama

Bu bölümde, eğitim sırasında modelimizin performansını iyileştiren bir animasyon yapan özel bir geri arama örneği vereceğiz. Bunu yapmak için, günlüklerin değerlerini her partinin sonunda saklarız. Ardından, eğitim döngüsünün sonunda kullanarak bir animasyon oluşturuyoruz. matplotlib.

Görselleştirmeyi geliştirmek için, kayıp ve metrikler günlük ölçeğinde çizilecektir:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
from IPython import display

class TrainingAnimationCallback(keras.callbacks.Callback):
    def __init__(self, duration = 40, fps = 1000/25):
        self.duration = duration
        self.fps = fps
        self.logs_history = []

    def set_plot(self):   
        self.figure = plt.figure()
        
        plt.xticks(
            range(0,self.params['steps']*self.params['epochs'], self.params['steps']),
            range(0,self.params['epochs']))
        plt.xlabel('Epoch')
        plt.ylabel('Loss & Metrics ($Log_{10}$ scale)')

        self.plot = {}
        for metric in self.model.metrics_names:
          self.plot[metric], = plt.plot([],[], label = metric)
          
        max_y = [max(log.values()) for log in self.logs_history]
        
        self.title = plt.title(f'batches:0')
        plt.xlim(0,len(self.logs_history)) 
        plt.ylim(0,max(max_y))

           
        plt.legend(loc='upper right')
  
    def animation_function(self,frame):
        batch = frame % self.params['steps']
        self.title.set_text(f'batch:{batch}')
        x = list(range(frame))
        
        for metric in self.model.metrics_names:
            y = [log[metric] for log in self.logs_history[:frame]]
            self.plot[metric].set_data(x,y)
        
    def on_train_batch_end(self, batch, logs=None):
        logarithm_transform = lambda item: (item[0], np.log(item[1]))
        logs = dict(map(logarithm_transform,logs.items()))
        self.logs_history.append(logs)
       
    def on_train_end(self, logs=None):
        self.set_plot()
        num_frames = int(self.duration*self.fps)
        num_batches = self.params['steps']*self.params['epochs']
        selected_batches = range(0, num_batches , num_batches//num_frames )
        interval = 1000*(1/self.fps)
        anim_created = FuncAnimation(self.figure, 
                                     self.animation_function,
                                     frames=selected_batches,
                                     interval=interval)
        video = anim_created.to_html5_video()
        
        html = display.HTML(video)
        display.display(html)
        plt.close()

Öncekiyle aynı modeli kullanacağız, ancak daha fazla eğitim örneğiyle:

import tensorflow as tf
from tensorflow import keras
import numpy as np

model = keras.Sequential()
model.add(keras.layers.Dense(10, input_dim = 1, activation='relu'))
model.add(keras.layers.Dense(10, activation='relu'))
model.add(keras.layers.Dense(1))
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=0.1),
    loss = "mean_squared_error",
    metrics = ["mean_absolute_error"]
)

def create_sample(sample_size, train_test_proportion = 0.9):
    x = np.random.uniform(low = 0, high = 10, size = sample_size)
    y = x**2
    train_test_split = int(sample_size*train_test_proportion)
    x_train, x_test = (x[:train_test_split],x[train_test_split:])
    y_train, y_test = (y[:train_test_split],y[train_test_split:])
    return (x_train,x_test,y_train,y_test)

x_train,x_test,y_train,y_test = create_sample(35200)


model.fit(
    x_train,
    y_train,
    batch_size=32,
    epochs=2,
    verbose=0,
    callbacks=[TrainingAnimationCallback()],
)

Çıktımız, eğitim sürecinde değiştikçe metriklerin ve kayıp fonksiyonunun bir animasyonudur:

Tarayıcınız HTML videoyu desteklemiyor.

Sonuç

Bu kılavuzda, Keras'ta özel geri aramaların uygulanmasına bir göz attık.
Özel geri aramaları uygulamak için iki seçenek vardır – alt sınıflama yoluyla keras.callbacks.Callback sınıf veya kullanarak keras.callbacks.LambdaCallback sınıf.

Kullanan pratik bir örnek gördük. LambdaCallbackeğitim döngüsünün sonunda bir e-posta göndermek için ve Callback eğitim döngüsünün bir animasyonunu oluşturan sınıf.

Keras'ın birçok yerleşik geri araması olmasına rağmen, özel bir geri aramanın nasıl uygulanacağını bilmek daha spesifik uygulamalar için yararlı olabilir.

Zaman Damgası:

Den fazla Yığın kötüye kullanımı