2019年2月16日 星期六

深度學習 - 使用Keras callbacks and TensorBoard

每次在訓練模型時,都要try一下跑幾個epochs,並藉由 matplotlib 將訓練過程的'acc' & 'loss' 畫出來,看大概在什麼時候會發生過擬合,然後再用較少次的epochs重新訓練模型,這樣的過程是多麼的繁瑣與浪費時間。
現在練習使用 Keras 的 callbacks 函數,可以在訓練過程中,訪問模型狀態與性能,還能對模型採取行動,中斷、保存、改變模型狀態等。

這邊列出幾個 callbacks : 更多的callbacks 與其用法請參考連結。
  1. keras.callbacks.ModelCheckpoint
  2. keras.callbacks.EarlyStopping
  3. keras.callbacks.LearningRateScheduler
  4. keras.callbacks.ReduceLROnPlateau
  5. keras.callbacks.CSVLogger
  • ModelCheckpoint 與 EarlyStopping 練習
    使用先前 IMDb數據集 - 原始文本結合GloVe預訓練詞嵌入模型 的程式碼來練習,加入callbacks函數
    #加入callback
    import keras
    callbacks_list = [keras.callbacks.EarlyStopping(monitor='acc',
                                                    patience=1,),
                      keras.callbacks.ModelCheckpoint(filepath='my_model.h5',
                                                      monitor='val_loss',
                                                      save_best_only=True,)]
    EarlyStopping : 表示在 acc 被觀察再下1輪之後沒有改善則停止模型的訓練。
    ex. epoch1:'acc'=80 epoch2:'acc'=79 epoch3:'acc'=80 =>繼續訓練。
          epoch4:'acc'=80 epoch5:'acc'=79 epoch6:'acc'=78 =>停止訓練。
    ModelCheckpoint : 表示會在每個epochs 保存模型,而當 'val_loss' 沒有改善的情況,模型不會覆蓋上一次的權重。
    可以看到使用callbacks後,訓練提早到第10次就停止了(編碼epochs=15),並保存了模型權重,因此不需要再浪費時間重新訓練模型。

  • Tensorboard 練習
    Tensorboard 為 Tensorflow 的可視化框架,只有在 Keras 使用 Tensorflow 做後端運算時才能夠使用。TensorBoard 的主要用途是,在訓練過程中幫助你以可視化的方法監控模型內部發生的一切。如果你監控了除模型最終損失之外的更多信息,那麼可以更清楚地了解模型做了什麼,並且能夠更快地取得進展。
    在這邊也是先用IMDb 來練習,完整程式碼見最後。
    #建立一個資料夾存放log
    log_dir = 'C:\\Users\\Lido_Lee\\Downloads\\IMDb_callback'
    #加入tensorboard callback
    import keras
    callbacks = [keras.callbacks.TensorBoard(log_dir=log_dir,
                                             histogram_freq=1,
                                             embeddings_freq=0,
                                             embeddings_layer_names=None,
                                             ),]

    接著執行"Anaconda Prompt"
    在終端機激活編譯環境 "pypy" ("pypy" 使我aconda 下的python編譯環境),見先前文章 windows 10 安裝 anaconda tensorflow gpu CUDA & cudnn
     $ activate pypy
    啟動 tensorboard
    $ tensorboard --logdir="C:\Users\Lido_Lee\Downloads\IMDb_callback"

    在瀏覽器中輸入 http://localhost:6006/ 即可連結到 tensorboard 頁面,如下:
    可以看到訓練精度與損失圖,非常的方便。
    另外,也有模型架構圖,可以理解輸入資料到輸出資料的過程,這也是為何先選用Keras框架模型入門深度學習是非常容易的。
    看到模型架構之後...,如果我一開始是由 tensorflow 開始著手練習刻出模型的話,應該很快就放棄了吧。(汗顏...)

    有趣的是,還可以看到每層 layer 的激發圖,可以了解層的過濾器的狀況。
    由dense_2 層可以看到輸出符合我們的預期,大部分激活分散在兩端,在此為二分類問題,由圖就可以幫助我們了解層的運作過程。

    真心覺得 Google 真的非常的強大阿!!

    後續再由Fashion MNIST 的數據庫練習,來看看 tensorboard 的 embedding 超強視覺呈現吧!!

完整程式碼:
import os
imdb_dir = 'C:\\Users\\Lido_Lee\\Downloads\\aclImdb'
train_dir = os.path.join(imdb_dir, 'train')
labels = []
texts = []
for label_type in ['neg','pos']:
    dir_name = os.path.join(train_dir, label_type)
    for fname in os.listdir(dir_name):
        if fname[-4:] == '.txt':
            # 'cp950' error 需在open中加入(encoding = 'utf-8-sig')
            f = open(os.path.join(dir_name, fname), encoding = 'utf-8-sig')
            texts.append(f.read())
            f.close()
            if label_type == 'neg':
                labels.append(0)
            else:
                labels.append(1)

#對IMDB 原始數據的文本進行分詞
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
import numpy as np
maxlen = 200
training_samples = 20000
validation_samples = 5000
max_words = 10000
tokenizer = Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))
data = pad_sequences(sequences, maxlen=maxlen)
labels = np.asarray(labels)
print('Shape of data tensor:', data.shape)
print('Shape of label tensor:', labels.shape)

#將數據劃分為訓練集和驗證集
"""
首先要打亂數據,因為一開始數據中的樣本是排好序的
(所有負面評論都在前面,然後是所有正面​​評論)
"""
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels = labels[indices]
x_train = data[:training_samples]
y_train = labels[:training_samples]
x_val = data[training_samples: training_samples + validation_samples]
y_val = labels[training_samples: training_samples + validation_samples]

embedding_dim = 100
#定義模型
from keras.models import Sequential
from keras.layers import Embedding, Flatten, Dense
model = Sequential()
model.add(Embedding(max_words, embedding_dim, input_length=maxlen,name='embed'))
model.add(Flatten())
model.add(Dense(32, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.summary()

#建立一個資料夾存放log
log_dir = 'C:\\Users\\Lido_Lee\\Downloads\\mnist_callback'
#加入tensorboard callback
import keras
callbacks = [keras.callbacks.TensorBoard(log_dir=log_dir,
                                         histogram_freq=1,
                                         embeddings_freq=0,
                                         embeddings_layer_names=None,
                                         ),]

#選擇優化器、損失函數、指標
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['acc'])

#丟進fit訓練模型
history = model.fit(x_train, y_train,
               batch_size = 32,
               epochs = 10,
               verbose = 1,
               callbacks=callbacks,
               validation_split=0.2)

#將訓練好的模型保存起來
model.save_weights('pre_trained_glove_model_callback_tensorboard.h5')

#畫出訓練過程
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

沒有留言:

張貼留言