Python深度學習(使用 Keras 回撥函式和 TensorBoard 來檢查並監控深度學習模型)--學習筆記(十六)

呆萌的小透明發表於2020-11-16

7.2 使用 Keras 回撥函式和 TensorBoard 來檢查並監控深度學習模型

  • 使用model.fit()或model.fit_generator()在一個大型資料集上啟動數十輪的訓練,有點類似於扔一架飛機,一開始給它一點推力,之後你便再也無法控制其飛行軌跡或著陸點。如果想要避免不好的結果(並避免浪費紙飛機),更聰明的做法是不用紙飛機,而是用一架無人機,它可以感知其環境,將資料發揮給操作者,並且能夠基於當前狀態自主航行。

7.2.1 訓練過程中將回撥函式作用於模型

  • 訓練模型時,很多事情一開始都無法預測。尤其是你不知道需要多少輪才能得到最佳驗證損失。前面所有例子都採用這樣一種策略:訓練足夠多的輪次,這時模型已經開始過擬合,根據這第一次執行來確定訓練所需要的正確輪次,然後使用這個最佳輪數從頭開始再啟動一次新的訓練。
  • 處理這個問題的更好方法是,當觀測到驗證損失不再改善時就停止訓練。這可以使用Keras回撥函式來實現。回撥函式(callback)是在呼叫fit時傳入模型的一個物件(即實現特定方法的類例項),它在訓練過程中的不同時間點都會被模型呼叫。它可以訪問關於模型狀態與效能的所有可用資料,還可以採取行動:中斷訓練、儲存模型、載入一組不同的權重或改變模型的狀態。
  • 模型檢查點(model checkpointing):在訓練過程中的不同時間點儲存模型的當前權重。
  • 提前終止(early stopping):如果驗證損失不再改善,則中斷訓練(當然,同時儲存在訓練過程中得到的最佳模型)。
  • 在訓練過程中動態調節某些引數值:比如優化器的學習率。
  • 在訓練過程中記錄訓練指標和驗證指標,或將模型學到的表示視覺化(這些表示也在不斷更新):你熟悉的Keras進度條就是一個回撥函式。
  • keras.callbacks模組包含許多內建的回撥函式:keras.callbacks.ModelCheckpoint、keras.callbacks.EarlyStopping、keras.callbacks.LearningRateScheduler、keras.callbacks.ReduceLRonPlateau、keras.callbacks.CSVLogger。
1.ModelCheckpoint與EarlyStopping回撥函式
  • 如果監控的目標指標在設定的輪數內不再改善,可以用EarlyStopping回撥函式來中斷訓練。比如,這個回撥函式可以在剛開始過擬合的時候就中斷訓練,從而避免用更少的輪次重新訓練模型。這個回撥函式通常與ModelCheckpoint結合使用,後者可以在訓練過程中持續不斷地儲存模型(你也可以選擇只儲存目前的最佳模型,即一輪結束後具有最佳效能的模型)。
import keras

# 通過fit的callbacks引數將回撥函式傳入模型中,這個引數接收一個回撥函式的列表。可以傳入任意個數的回撥函式。
# 如果不再改善就中斷訓練,監控模型的驗證精度,如果精度在多於一輪的時間(即兩輪)內不再改善,中斷訓練。
# 在每輪過後儲存當前權重,目標模型檔案的儲存路徑,如果val_loss沒有改善,那麼不需要覆蓋模型檔案。這就可以始終儲存在訓練過程中見到的最佳模型
callbacks_list = [keras.callbacks.EarlyStopping(monitor='acc', patience=1,), keras.callbacks.ModelCheckpoint(filepath='my_model.h5', monitor='val_loss', save_best_only=True)]

# 監控精度,所以它應該是模型指標的一部分
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])

# 注意,由於回撥函式要監控驗證損失和驗證精度,所以在呼叫fit時需要傳入validation_data(驗證資料)

model.fit(x, y, epochs=10, batch_size=32, callbacks=callbacks_list, validation_data=(x_val, y_val))
ReduceLROnPlateau回撥函式
  • 如果驗證損失不再改善,可以使用這個回撥函式來降低學習率。在訓練過程中如果出現了損失平臺(loss plateau),那麼增大或減小學習率都是跳出區域性最小值的有效策略。
# 監控模型的驗證損失、觸發時將學習率除以10、如果驗證損失在10輪內都沒有改善,那麼就觸發這個回撥函式。
callbacks_list = [keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10)]

# 注意,因為回撥函式要監控驗證損失,所以你需要在呼叫fit時傳入validation_data(驗證資料)
model.fit(x, y, epochs=10, bacth_size=32, callbacks=callbacks_list, validation_data=(x_val, y_val))
3.編寫你自己的回撥函式
  • 如果你需要再訓練過程中採取特定行動,而這項行動又沒有包含在內建回撥函式中,那麼可以編寫你自己的回撥函式。回撥函式的實現方式是建立keras.callbacks.Callback類的子類。然後你可以實現下面這些方法,它們分別在訓練過程中的不同時間點被呼叫:on_epoch_begin(在每輪開始時被呼叫)、on_epoch_end(在每輪結束時被呼叫)、on_batch_begin(在處理每個批量之前被呼叫)、on_batch_end(在處理每個批量之後被呼叫)、on_train_begin(在訓練開始時被呼叫)、on_train_end(在訓練結束時被呼叫)。
  • 這些方法被呼叫時都有一個logs引數,這個引數就是一個字典,裡面包含前一個批量、前一個輪次或前一次訓練的資訊,即訓練指標和驗證指標等。此外,回撥函式還可以訪問下列屬性:(1)self.model:呼叫回撥函式的模型例項;(2)self.validation_data:傳入fit作為驗證資料的值。
# 下面是一個自定義回撥函式的簡單示例,它可以在每輪結束後將模型每層的啟用儲存到硬碟(格式為Numpy陣列),這個啟用是對驗證集的第一個樣本計算得到的。
import keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
    def set_model(self, model):
        # 在訓練之前由父模型呼叫,告訴回撥函式哪個模型在呼叫它。
        self.model = model
        layer_outputs = [layer.output for layer in model.layers]
        # 模型例項,返回每層的啟用
        self.activation_model = keras.models.Model(model.input, layer_outputs)

    def on_epoch_end(self, epoch, logs=None):
        if self.validation_data is None:
            raise RuntimeError('Requires validation_data.')

        # 獲取驗證資料的第一個輸入樣本
        validation_sample = self.validation_data[0][0:1]
        activations = self.activation_model.predict(validation_sample)
        f = open('activations_at_epoch_' + str(epoch) + '.npz', 'w')
        np.savez(f, activations)
        f.close()

7.2.2 TensorBoard簡介:Tensorflow的視覺化框架

  • 想要做好研究或開發出好的模型,在實驗過程中你需要豐富頻繁的反饋,從而知道模型內部正在發生什麼。這正是執行實驗的目的:獲取關於模型表現好壞的資訊,越多越好。取得進展是一個反覆迭代的過程(或迴圈):首先你有一個想法,並將其表述為一個實驗,用於驗證你的想法是否正確。你執行這個實驗,並處理其生成的資訊,這又激發了你的下一個想法。在這個迴圈中實驗的迭代次數越多,你的想法也就變得越來越精確、越來越強大。Keras可以幫你在最短的時間內將想法轉化成實驗,而高速GPU可以幫你儘快得到實驗結果。但如何處理實驗結果呢?這就需要TensorBoard發揮作用了。
  • TensorBoard是一個內建於Tensorflow中的基於瀏覽器的視覺化工具。注意,只有當Keras使用Tensorflow後端時,這一方法才能用於Keras模型。
  • TensorBoard的主要用途是,在訓練過程中幫助你以視覺化的方法監控模型內部發生的一切。如果你監控了除模型最終損失之外的更多資訊,那麼可以更清楚地瞭解模型做了什麼、沒做什麼,並且能夠更快速地取得進展。TensorBoard具有下列巧妙的功能,都在瀏覽器中實現:在訓練過程中以視覺化的方式監控指標、將模型架構視覺化、將啟用和梯度的直方圖視覺化、以三維的形式研究嵌入。
# 使用了TensorBoar的文字分類模型
import keras
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 2000 # 作為特徵的單詞個數
max_len = 500 # 在這麼多單詞之後截斷文字(這些單詞都屬於前max_featurs個最常見的單詞)

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)

model = keras.models.Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len, name='embed'))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(1))
print(model.summary())
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
  • 在開始使用TensorBoard之前,需要建立一個目錄,用於儲存它生成的日誌檔案。我們用一個TensorBoard回撥函式例項來啟動訓練。這個回撥函式會將日誌事件寫入硬碟的指定位置。
# 使用一個TensorBoard回撥函式來訓練模型
# 日誌檔案將被寫入這個位置、每一輪之後記錄啟用直方圖、每一輪之後記錄嵌入資料
callbacks = [keras.callbacks.TensorBoard(log_dir='my_log_dir', histogram_freq=1, embeddings_freq=1)]

history = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2, callbacks=callbacks)
  • 現在可以在命令列啟動TensorBoard伺服器,指示它讀取回撥函式當前正在寫入的日誌。在安裝TensorFlow時(比如通過pip),tensorboard程式應該已經自動安裝到計算機裡了。
tensorboard --logdir=my_log_dir
  • 然後可以用瀏覽器開啟http://localhost:6006,並插卡模型的訓練過程。
  • 注意,Keras還提供了另一種更簡潔的方法-keras.utils.plot_model函式,它可以將模型繪製為層組成的圖,而不是TensorFlow運算組成的圖。使用這個函式需要安裝Python的pydot和pydot-ng庫,還需要安裝graphviz庫。
from keras.utils import plot_model

plot_model(model, to_file='model.png')
  • 你還可以選擇在層組成的圖中顯示形狀資訊。
from keras.utils import plot_model
plot_model(model, show_shapes=True, to_file='model.png')

7.2.3 小結

  • Keras回撥函式提供了一種簡單的方法,可以在訓練過程中監控模型並根據模型狀態自動採取行動。
  • 使用TensorFlow時,TensorBoard是一種在瀏覽器中獎模型活動視覺化的好方法。在Keras模型中你可以通過TensorBoard回撥函式來使用這種方法。

相關文章