深度學習模型除錯和監控(7.2)

語言: CN / TW / HK

Keras 高階用法:函式式 API 7.1(二)

Keras 高階用法:函式式 API 7.1(一)

7.2 深度學習模型除錯和監控

本小節學習如何監控模型訓練的過程。

7.2.1 模型訓練中應用回撥

當你訓練模型時,有許多情況是在起始階段預估不了的。比如,你不能給出具體需要多少個epoch達到優化的驗證損失。到目前為止的所有例子,都是採用先訓練足夠的epoch直到開始過擬合,然後使用前面得到的最優epoch值重新訓練一次模型。當然這種方法有點浪費資源。

解決上述問題的更好方式是,當你監測到驗證損失不再優化時停止模型訓練。這可以通過Keras callback實現。callback是一個類例項物件,呼叫 fit 函式時傳入模型,並在模型訓練過程呼叫。它可以訪問模型狀態和效能的各種資料,也能中斷模型訓練、儲存模型、載入不同的權重資料或者改變模型狀態。

下面是使用 callback 的各種方式:

  • 模型快照:在模型訓練過程中,在不同的時間點儲存模型的當前權重

  • Early stopping :當驗證損失不再優化時,中斷模型訓練

  • 動態調整引數值:比如,優化器的學習率

  • 記錄訓練集和驗證集指標,或者視覺化表示學習:

keras.callbacks 模組包含一系列內建的callback,不限於下面的列表:

keras.callbacks.ModelCheckpoint
keras.callbacks.EarlyStopping
keras.callbacks.LearningRateScheduler keras.callbacks.ReduceLROnPlateau
keras.callbacks.CSVLogger

下面講解 ModelCheckpoint、EarlyStopping和ReduceLROnPlateau。

ModelCheckpoint和EarlyStopping回撥

EarlyStopping回撥可以使模型訓練固定epoch後終止。比如,當一開始過擬合時終止模型訓練,這能避免重新訓練模型。EarlyStopping回撥需要和ModelCheckpoint結合使用,ModelCheckpoint回撥能在模型訓練過程中持續的儲存模型,你也可以選擇只保留當前最新的模型。

import keras

'''Callbacks are passed to the model
via the callbacks argument in fit,
which takes a list of callbacks.
You can pass any number of callbacks.
'''
callbacks_list = [
  '''Interrupts training when improvement stops
  '''
  keras.callbacks.EarlyStopping(
    '''Monitors the model’s validation accuracy
    '''
    monitor='acc',
    '''Interrupts training when accuracy
    has stopped improving for more than
    one epoch (that is, two epochs)
    '''
    patience=1, 
  ),
  '''Saves the current weights after every epoch
  '''
  keras.callbacks.ModelCheckpoint(
    ''' Path to the destination model file
    '''
    filepath='my_model.h5', 
    '''These two arguments mean you won’t overwrite
    the model file unless val_loss has improved,
    which allows you to keep the best model
    seen during training.
    '''
    monitor='val_loss', 
    save_best_only=True,
  )
]

model.compile(optimizer='rmsprop', 
              loss='binary_crossentropy',
              '''You monitor accuracy,
              so it should be part of the model’s metrics.
              '''
              metrics=['acc'])

'''Note that because the callback will
monitor validation loss and validation accuracy,
you need to pass validation_data to the call to fit.
'''
model.fit(x, y, 
          epochs=10,
          batch_size=32, 
          callbacks=callbacks_list, 
          validation_data=(x_val, y_val))

ReduceLROnPlateau回撥

當驗證損失不再優化時,使用 ReduceLROnPlateau 回撥減小學習率。減小或者增加學習率可以擺脫模型訓練中的區域性極小值。下面是 ReduceLROnPlateau 回撥的示例:

callbacks_list = [
  keras.callbacks.ReduceLROnPlateau(
    '''Monitors the model’s validation loss
    '''
    monitor='val_loss', 
    '''Divides the learning rate by 10
    when triggered
    '''
    factor=0.1, 
    '''The callback is triggered after the validation
    loss has stopped improving for 10 epochs.
    '''
    patience=10,
  ) 
]

'''Because the callback will monitor
the validation loss, you need to pass
validation_data to the call to fit.
'''
model.fit(x, y, 
          epochs=10,
          batch_size=32, 
          callbacks=callbacks_list, 
          validation_data=(x_val, y_val))

編寫自定義回撥

在模型訓練中,如果你需要執行的某操作沒有相應的內建回撥callback,可以通過實現keras.callbacks.Callback的子類自定義實現callback。你能實現任意數量的下列方法,它們在模型訓練的不同時間點呼叫:

on_epoch_begin:在每個epoch開始時呼叫
on_epoch_end:在每個epoch結尾時呼叫
on_batch_begin:在每個batch處理前呼叫
on_batch_end:在每個batch處理後呼叫
on_train_begin:在每個訓練開始時呼叫
on_train_end:在每個訓練結尾時呼叫

上述方法以logs引數呼叫。logs引數是一個字典,其包含了一系列與當前batch或epoch相關的資訊:比如訓練集和驗證集指標等。除此之外,callback可以訪問下面的屬性:

  • self.model:回撥呼叫的模型引用

  • self.validation_data:傳入fit函式作為驗證集的資料

下面是一個簡單的自定義函式,它將驗證集的第一個樣本每個epoch結尾處模型的每個layer的啟用函式儲存到磁碟上(比如Numpy陣列):

import keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
  
  def set_model(self, model):
      '''Called by the parent model before training,
      to inform the callback of what model will be calling it
      '''
    self.model = model
    layer_outputs = [layer.output for layer in model.layers] 
    '''Model instance that returns the activations of every layer
    '''
    self.activations_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.')
      
    '''Obtains the first input sample of the validation data
    '''
    validation_sample = self.validation_data[0][0:1]
    activations = self.activations_model.predict(validation_sample)
    '''Saves arrays to disk
    '''
    f = open('activations_at_epoch_' + str(epoch) + '.npz', 'w')
    np.savez(f, activations)
    f.close()

上述的自定義回撥函式看似挺容易。你可以繼續深挖Keras的callback。

7.2.2 TensorBoard介紹

TensorBoard是TensorFlow視覺化框架。為了更好的研究或者開發模型,你需要豐富、頻繁的回撥來對模型進行實驗。實驗的關鍵點在於獲取模型效能的各種資訊。

這小節介紹TensorBoard,它是TensorFlow基於瀏覽器的視覺化工具。注意,TensorBoard只適用於以TensorFlow為後端的Keras模型。

TensorBoard主要目的是輔助使用者視覺化地監控模型訓練的細節。你可以在瀏覽器上訪問到以下資訊:

  • 視覺化監測指標

  • 視覺化模型結構

  • 視覺化啟用函式和梯度的直方圖

  • 三維視覺化詞嵌入

下面用一個簡單的例子展示上述功能。你將訓練一個 1D 卷積模型解決IMDB情感分析的任務。

# Listing 7.7 Text-classification model to use with TensorBoard

import keras
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

'''Number of words to consider as features
'''
max_features = 2000 
'''Cuts off texts after this number of words
(among max_features most common words)
'''
max_len = 500

(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.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy', 
              metrics=['acc'])

使用TensorBoard前你需要建立儲存log檔案的目錄。

# Listing 7.8 Creating a directory for TensorBoard log files
$ mkdir my_log_dir

接著啟動帶有TensorBoard callback例項的模型訓練。這個callback將在指定位置寫入log事件。

# Listing 7.9 Training the model with a TensorBoard callback

callbacks = [
  keras.callbacks.TensorBoard(
    '''Log files will be written at this location.
    '''
    log_dir='my_log_dir', 
    '''Records activation histograms every 1 epoch
    '''
    histogram_freq=1, 
    '''Records embedding data every 1 epoch
    '''
    embeddings_freq=1,
  ) 
]

history = model.fit(x_train, y_train, 
                    epochs=20,
                    batch_size=128, 
                    validation_split=0.2, 
                    callbacks=callbacks)

這時可以通過命令列啟動TensorBoard服務,其tensorboard可用pip安裝:

$ tensorboard --logdir=my_log_dir

然後你可以通過http://localhost:6006 訪問模型訓練,見圖7.10。除了訓練集和驗證集指標外,你也可以看到直方圖,見圖7.11。

圖 7.10 TensorBoard指標監控

圖 7.11 TensorBoard:啟用函式直方圖

詞嵌入標籤可以檢視字典中1000個單詞的詞嵌入位置和空間的關係。因為詞嵌入空間是128維,TensorBoard根據所選的降維演算法(比如,PCA或者t-SNE)自動降為2D或者3D。在圖7.12中,你能清晰地看到兩個簇:褒義詞和貶義詞。

圖7.12 TensorBoard:3D互動詞嵌入視覺化

Graph標籤顯示Keras模型中low-level的TensorFlow操作圖,見圖7.13。你用Keras構建模型時可能看似簡單,但其實挺複雜,它有許多相關的梯度下降過程。這只是Keras簡化了原始TensorFlow從頭定義模型。

圖7.13 TensorBoard:TensorFlow圖視覺化

Keras也提供layer級別的模型視覺化:keras.utils.plot_model工具。使用該工具需要安裝Python的pydot和pydot-ng庫,以及graphviz庫。下面來簡單看下:

from keras.utils import plot_model
plot_model(model, to_file='model.png')

上述程式碼生成PNG圖見7.14。

圖7.14 用plot_model繪製的模型layer視覺化

你也可以顯示layer圖的形狀資訊,用plot_model和show_shapes選項,見圖7.15:

from keras.utils import plot_model
plot_model(model, show_shapes=True, to_file='model.png')

圖7.15 帶形狀資訊的模型

7.2.3 小結

  • Keras callback能監控模型訓練,以及基於模型狀態採取行動

  • TensorBoard可以在瀏覽器上視覺化模型。你也可以在Keras模型中用TensorBoard的callback。

未完待續。。。

俠天,專注於大資料、機器學習和數學相關的內容,並有個人公眾號:bigdata_ny分享相關技術文章。

若發現以上文章有任何不妥,請聯絡我。