神經網絡訓練中回調函數的實用教程

做者|Andre Ye
編譯|VK
來源|Towards Data Sciencepython

回調函數是神經網絡訓練的重要組成部分安全

回調操做能夠在訓練的各個階段執行,多是在epoch之間,在處理一個batch以後,甚至在知足某個條件的狀況下。回調能夠利用許多創造性的方法來改進訓練和性能,節省計算資源,並提供有關神經網絡內部發生的事情的結論。網絡

本文將詳細介紹重要回調的基本原理和代碼,以及建立自定義回調的過程。機器學習


ReduceLROnPlateau是Keras中默認包含的回調。神經網絡的學習率決定了梯度的比例因子,所以太高的學習率會致使優化器超過最優值,而學習率太低則會致使訓練時間過長。很難找到一個靜態的、效果很好的、不變的學習率。ide

顧名思義,「下降高原學習率」就是在損失指標中止改善或達到穩定時下降學習率。通常學習率減小2到10倍,這有助於磨練參數的最佳值。函數

要使用ReduceLROnPlateau,必須首先建立回調對象。有四個參數很重要:性能

  • monitor,它用來監視指標
  • factor,它是新的學習率將被下降(乘以)的因子
  • persistence,回調激活以前等待的停滯epoch數
  • min_lr,它能夠下降到的最小學習率。這能夠防止沒必要要和不有益的減小。
from keras.callbacks import ReduceLROnPlateau
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
                              patience=5, min_lr=0.001)
model.fit(X_train, Y_train, callbacks=[reduce_lr])

當使用model.fit時,能夠指定回調參數。注意,這能夠接受一個列表,所以能夠安排多個回調。學習

LearningRateScheduler是ReduceLROnPlateau的另外一種選擇,它容許用戶根據epoch來安排學習率。若是你知道(可能來自之前的研究或實驗)網絡的學習率在從epochs 1-10時應該是x, 在epochs 10-20是應該是y,LearningRateScheduler能夠幫助實現這些變化。以上epoch的數字能夠任意變化。優化

建立學習率調度器須要一個用戶定義的函數,該函數將epoch和learning rate做爲參數。返回對象應該是新的學習率。ui

from keras.callbacks import LearningRateScheduler

def scheduler(epoch, lr): #定義回調schedule
   if lr < 0.001: return lr * 1.5 #若是lr過小,增長lr
   elif epoch < 5: return lr #前五個epoch,不改變lr
   elif epoch < 10: return lr * tf.math.exp(-0.1) #第五到第十個epoch,減小lr
   else: return lr * tf.math.exp(-0.05) #第10個epoch以後,減小量更少
  
callback = LearningRateScheduler(scheduler) #建立回調對象
model.fit(X_train, y_train, epochs=15, callbacks=[callback])

而後,將其轉換爲Keras回調後,就能夠用於模型的訓練。這些調度程序很是有用,容許對網絡進行控制,但建議在第一次訓練網絡時使用ReduceLROnPlateau,由於它更具適應性。而後,能夠進行可視化模型,看是否能提供關於如何構造一個適當的LR調度器的相關想法。

此外,你能夠同時使用ReduceLROnPlateau和LearningRateScheduler,例如,使用調度程序硬編碼一些學習速率(例如在前10個epoch不更改),同時利用自適應能力,在高原上下降學習率以提高性能。

EarlyStopping能夠很是有助於防止在訓練模型時產生額外的冗餘運行。冗餘運行會致使高昂的計算成本。當網絡在給定的時間段內沒有獲得改善時,網絡完成訓練並中止使用計算資源。與ReduceLROnPlateau相似,EarlyStopping須要monitor。

from keras.callbacks import EarlyStopping
  
callback = EarlyStopping(monitor='loss', patience=5)
model.fit(X_train, y_train, epochs=15, callbacks=[callback])

TerminateOnNaN有助於防止在訓練中產生梯度爆炸問題,由於輸入NaN會致使網絡的其餘部分發生爆炸。若是不採用TerminateOnNaN,Keras並不阻止網絡的訓練。另外,nan會致使對計算能力的需求增長。爲了防止這些狀況發生,添加TerminateOnNaN是一個很好的安全檢查。

rom keras.callbacks import TerminateOnNaN
model.fit(X_train, y_train, epochs=15, callbacks = [TerminateOnNaN()])

因爲許多緣由,ModelCheckpoint能夠以某種頻率(也許每隔10個左右的epoch)保存模型的權重,所以它很是有用。

  • 若是訓練模型時忽然中斷,則不須要徹底從新訓練模型。

  • 若是,好比說,在第30個epoch,模型開始顯示出過擬合的跡象或其餘問題,好比梯度爆炸,咱們能夠用最近保存的權重從新加載模型(好比在第25個epoch),並調整參數以免該問題,而無需從新進行大部分訓練。

  • 可以提取某個epoch的權重並將其從新加載到另外一個模型中有利於遷移學習。

在下面的場景中,ModelCheckpoint用於存儲具備最佳性能的模型的權重。在每一個epoch,若是模型比其餘記錄的epoch表現更好,則其權重存儲在一個文件中(覆蓋前一個的權重)。在訓練結束時,咱們使用model.load_weights進行加載.

from keras.callbacks import ModelCheckpoint

callback = ModelCheckpoint( #建立回調
    filepath='/filepath/checkpoint', #告訴回調要存儲權重的filepath在哪
    save_weights_only=True, #只保留權重(更有效),而不是整個模型
    monitor='val_acc', #度量
    mode='max', #找出使度量最大化的模型權重
    save_best_only=True #只保留最佳模型的權重(更有效),而不是全部的權重
)

model.fit(X_train, y_train, epochs=15, callbacks=[callback])
model.load_weights(checkpoint_filepath) #將最佳權重裝入模型中。

或者,若是須要基於頻率的保存(每5個epoch保存一次),請將save_freq設置爲5

編寫自定義回調是Keras包含的最好的特性之一,它容許執行高度特定的操做。可是,請注意,構造它比使用默認回調要複雜得多。

咱們的自定義回調將採用類的形式。相似於在PyTorch中構建神經網絡,咱們能夠繼承keras.callbacks.Callback回調,它是一個基類。

咱們的類能夠有許多函數,這些函數必須具備下面列出的給定名稱以及這些函數將在什麼時候運行。例如,將在每一個epoch開始時運行on_epoch_begin函數。下面是Keras將從自定義回調中讀取的全部函數,可是能夠添加其餘「helper」函數。

class CustomCallback(keras.callbacks.Callback): #繼承keras的基類
    def on_train_begin(self, logs=None):
        #日誌是某些度量的字典,例如鍵能夠是 ['loss', 'mean_absolute_error']
    def on_train_end(self, logs=None): ...
    def on_epoch_begin(self, epoch, logs=None): ...
    def on_epoch_end(self, epoch, logs=None): ...
    def on_test_begin(self, logs=None): ...
    def on_test_end(self, logs=None): ...
    def on_predict_begin(self, logs=None): ...
    def on_predict_end(self, logs=None): ...
    def on_train_batch_begin(self, batch, logs=None): ...
    def on_train_batch_end(self, batch, logs=None): ...
    def on_test_batch_begin(self, batch, logs=None): ...
    def on_test_batch_end(self, batch, logs=None): ...
    def on_predict_batch_begin(self, batch, logs=None): ...
    def on_predict_batch_end(self, batch, logs=None): ...

根據函數的不一樣,你能夠訪問不一樣的變量。例如,在函數on_epoch_begin中,該函數既能夠訪問epoch編號,也能夠訪問當前度量、日誌的字典。若是須要其餘信息,好比學習率,可使用keras.backend.get_value.

而後,能夠像對待其餘回調函數同樣對待你自定義的回調函數。

model.fit(X_train, y_train, epochs=15, callbacks=[CustomCallback()])

自定義回調的一些常見想法:

  • 在JSON或CSV文件中記錄訓練結果。

  • 每10個epoch就經過電子郵件發送訓練結果。

  • 在決定什麼時候保存模型權重或者添加更復雜的功能。

  • 訓練一個簡單的機器學習模型(例如使用sklearn),經過將其設置爲類變量並以(x: action, y: change)的形式獲取數據,來學習什麼時候提升或下降學習率。


當在神經網絡中使用回調函數時,你的控制力加強,神經網絡變得更容易擬合。

原文連接:https://towardsdatascience.com/a-short-practical-guide-to-callbacks-in-neural-network-training-3a4d69568aef

歡迎關注磐創AI博客站:
http://panchuang.net/

sklearn機器學習中文官方文檔:
http://sklearn123.com/

歡迎關注磐創博客資源彙總站:
http://docs.panchuang.net/

相關文章
相關標籤/搜索