7

Keras 教學 - 訓練 IMDB Reviews CNN 網路模型

 3 years ago
source link: https://blog.toright.com/posts/6929/keras-imdb-reviews-cnn.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Keras 教學 - 訓練 IMDB Reviews CNN 網路模型

Keras 教學 - 利用二元分類器訓練 IMDB 深度學習演算法

前一篇文章介紹了機器學習最基本的 Hello World = MNIST 模型訓練。今天換一個 IMDB Reviews 的 Play Data 例子玩看看,對於如何透過 Keras 訓練神經網路的基本概念,可以參考前一篇「Keras MNIST 手寫辨識 x 深度學習的 HelloWorld」文章介紹。

二元分類或稱兩類分類可能是在機器學習中應用最廣泛問題。只要處理的問題只有兩個結果,就可以適用。在這個例子中,我們將根據 IMDB 評論的文本內容將電影評論分為「正面」評論和「負面」評論。

關於 IMDB Dataset 資料集

IMDB Dataset 是來自 Internet 電影數據庫 50,000 條評論文字。他們分為 25,000 條訓練數據和 25,000 條測試數據,每組皆包含包括 50% 的負面評論和 50% 的正面評論。

我們可以直接透過 Keras Datasets 函式庫載入已經整理好的資料集。這些資料集已經經過處理,會將評論依據單詞順序,排列為整數序列,其中每個整數代表字典中的特定單詞。如下:

from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

num_words=10000 表示我們只採用前 10000 個常出現的字詞,此外在 label 中 0 表示負評 1 表示正評。

max([max(sequence) for sequence in train_data])

也可以透過字典檔,將資料組合回評論文字。

word_index = imdb.get_word_index()
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
decoded_review = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]])
# show
decoded_review

IMDB Reviews 資料前處理

我們無法將代表字典檔索引位置的整數資料直接送進網路進行訓練,因此需要對資料進行轉換。由於我們只採用前 10000 常用字詞作為資料集,因此輸入資料可以轉換為 10000 維度的 one-hot-encode,例如 [3, 18] 表示一個全部都是 0 的陣列,只有 index 3, 18 是 1。我們會將這樣的資料格式作為張量進行訓練,轉換如下:

import numpy as np
def vectorize_sequences(sequences, dimension=10000):
    # Create an all-zero matrix of shape (len(sequences), dimension)
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
        results[i, sequence] = 1.  # set specific indices of results[i] to 1s
    return results
# Our vectorized training data
x_train = vectorize_sequences(train_data)
# Our vectorized test data
x_test = vectorize_sequences(test_data)

將結果標記進行正規化

# Our vectorized labels
y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

建立 CNN 網路架構

這裡我們預計使用三層網路,全連接層僅使用兩層 16 個神經元的網路,啟動函數設定為 relu,連接最後使用一個神經元輸出(表示正評或負評),並使用 sigmoid 作為最後輸出的啟動函數。由下而上網路架構如下:

預計採用的 CNN 詳細定義如下:

  • 訓練 Dataset:25,000
  • 測試 Dataset:25,000
  • 優化器:RMSprop
  • 損失函數:二元分類
  • Batch Size:512
  • Epochs:100
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

將優化器設定為 rmsprop,損失函數使用 binary_crossentropy,將網路進行 Compile

model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])

訓練 CNN 模型

先將準備訓練的 25000 筆資料集,抽出 10000 筆資料集用在訓練時期的驗證資料,好讓我們監控訓練過程的準確性變化。如下:

x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]

開始訓練模型

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=100,
                    batch_size=512,
                    validation_data=(x_val, y_val))

如果是是透過 Colab 的 GPU 進行訓練,每一個 Epoch 差不多 3 秒多一點,訓練結果如下:

IMDB-Reviews-CNN-training

訓練的過程會把相關資訊存放在 history,透過事後分析訓練過程的資訊可以幫助我們優化參數。

history_dict = history.history
history_dict.keys()

訓練結果圖表分析

透過上面的方法可以取得訓練 History 包含的資訊,然後我們將資訊繪製成為圖表,首先觀察 loss 變化,如下:

#@title
import matplotlib.pyplot as plt
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

執行結果:

接著透過以下程式產生圖表來觀察正確率的變化:

plt.clf()   # clear figure
acc_values = history_dict['accuracy']
val_acc_values = history_dict['val_accuracy']
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

執行結果:

由上面的數據可以看出來,以現在的網路架構,其實在第 3 次 Epoch 就已經獲得最佳的結果,之後的訓練已經造成過度擬合 (Over Fitting),因此在這個案例中將 Epoch 設定為 3 或 4 是取得最佳訓練模型的方法。今天的範例程式可以在 GitHub 取得 ipynb 檔案,需要請自行下載。

原來算比較久不一定比較好 R~實務上,建議透過訓練過程的監控,可以選擇某一個 Epoch 獲得表現最好的 Model 作為最佳解。此外,模型的參數也是很重要的,下一篇文章我們就來介紹一下各種參數的使用情境,敬請期待.......

這是真的廣告


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK