iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 26
0
AI & Data

輕鬆掌握 Keras 及相關應用系列 第 26

Day 26:Keras 自然語言處理(NLP)應用

前言

前一篇介紹了 RNN 的模型結構,接著我們來測試幾個完整的應用,藉以了解各個環節如何使用 Keras 撰寫,內容包括:

  1. 文字分類(Text Classification):影評情緒分析(Sentiment Analysis)。
  2. 翻譯(Text Translation):英文轉中文。

文字分類(Text Classification)

先實作一個簡單的例子,程式修改自【官網】,完整程式碼為 26_01_IMDB_Using_LSTM.ipynb。

  1. 載入套件及參數設定。
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers

# 只考慮 20000 個字彙
max_features = 20000  

# 每則影評只考慮前 200 個字
maxlen = 200  
  1. 建立模型,使用兩個雙向 LSTM。
# 可輸入不定長度的整數陣列
inputs = keras.Input(shape=(None,), dtype="int32")

x = layers.Embedding(max_features, 128)(inputs)
# 使用 2 個 bidirectional LSTM
x = layers.Bidirectional(layers.LSTM(64, return_sequences=True))(x)
x = layers.Bidirectional(layers.LSTM(64))(x)
# 分類
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs, outputs)
model.summary()
  1. 前置處理,若字數不足後面補0。
(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(
    num_words=max_features
)

# 不足長度,後面補0
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)
  1. 模型訓練與評估。
model.compile("adam", "binary_crossentropy", metrics=["accuracy"])
model.fit(x_train, y_train, batch_size=32, epochs=2, validation_split=0.2)

model.evaluate(x_test, y_test)

執行結果:

  1. 悲劇發生,上述程式只執行2個週期(epochs),GPU 記憶體竟然爆了,本機的獨立顯卡為GTX1050 Ti 4GB,可見 Tensorflow dataset 分批載入資料真的很重要。
  2. 程式搬到 Google Colab 執行,一切正常,只執行2個週期準確率約 85%,還不錯。
  3. Keras 內建資料集 IMDB 為整數向量,事先已將文字轉為數字,一般原始資料應為文字,應該如何處理,可看下面說明。

完整範例

這個程式修改自【官網】,完整程式碼為 26_02_IMDB_Using_LSTM_complete.ipynb。

  1. 【這裡】載入資料集。
  2. 解壓縮後,刪除 train\unsup 目錄。
  3. 從目錄轉為 dataset。
raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    "aclImdb/train",
    batch_size=batch_size,
    validation_split=0.2,
    subset="training",
    seed=1337,
)
  1. 前置處理:使用 TextVectorization,依序執行下列功能:
  • 轉成小寫,去除標點符號。
  • 分詞。
  • 重組為 ngrams。
  • 將單字對應成整數。
  • 把樣本轉換為向量。
vectorize_layer = TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features,
    output_mode="int",
    output_sequence_length=sequence_length,
)

# 去除 labels 欄位
text_ds = raw_train_ds.map(lambda x, y: x)
# 呼叫 adapt 函數建立字彙表
vectorize_layer.adapt(text_ds)
  1. 呼叫 vectorize_layer 轉換資料,並呼叫 cache/prefetch,獲得較佳的效能。
def vectorize_text(text, label):
    text = tf.expand_dims(text, -1)
    return vectorize_layer(text), label


# 呼叫 vectorize_layer 轉換資料
train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)

# 呼叫 cache/prefetch,獲得較佳的效能
train_ds = train_ds.cache().prefetch(buffer_size=10)
val_ds = val_ds.cache().prefetch(buffer_size=10)
test_ds = test_ds.cache().prefetch(buffer_size=10)
  1. 分別使用捲積模型(Conv1D)、Bidirectional LSTM 兩個模型測試,以下為後者程式。
# Input for variable-length sequences of integers
inputs = keras.Input(shape=(None,), dtype="int32")
# Embed each integer in a 128-dimensional vector
x = layers.Embedding(max_features, 128)(inputs)
# Add 2 bidirectional LSTMs
x = layers.Bidirectional(layers.LSTM(64, return_sequences=True))(x)
x = layers.Bidirectional(layers.LSTM(64))(x)
# Add a classifier
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs, outputs)
model.summary()
  1. 新資料預測:比較特別,使用已訓練好的權重作為模型 output,再作評估/預測。
inputs = tf.keras.Input(shape=(1,), dtype="string")
# Turn strings into vocab indices
indices = vectorize_layer(inputs)
# Turn vocab indices into predictions
outputs = model(indices)

# 建立一個模型,使用已訓練的權重(in outputs)
end_to_end_model = tf.keras.Model(inputs, outputs)
end_to_end_model.compile(
    loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"]
)

# Test it with `raw_test_ds`, which yields raw strings
end_to_end_model.evaluate(raw_test_ds)

翻譯

以深度學習進行翻譯工作,是一個很好的方向,因為,全世界有幾百種文字,兩兩對轉就有幾萬種,若採用人工整理,不知要花費多少人力資源。上述的模型只需要最後的結果,而翻譯是一個 Sequence to Sequence 模型,我們需要每一個隱藏層的輸出,如下圖,才能輸出完整的字句。
https://ithelp.ithome.com.tw/upload/images/20200926/20001976EbqQjLd0E5.png
圖一. Sequence to Sequence 模型,圖片來源:CIS 530, Computational Linguistics: Spring 2018

以下範例修改自【官網】,完整程式碼為 26_03_Translation.ipynb,原為英文翻法文,筆者改為英翻中。

  1. 【這裡】載入資料集。
  2. 解壓縮後檔名為cmn.txt,為簡體字,將全文丟進 MS Word,轉為繁體。
  3. 前置處理:讀取cmn.txt檔案,每列均以 tab 符號隔開,英文為input,中文為output
  • 整理兩種語言的字彙表
  • 將字彙表轉為字典
  • 利用字典將原文轉為數字
  1. 建立模型:使用 Autoencoder 模型,Decoder 使用 LSTM,參數 return_sequences=True,表示傳回序列資料,不只最後結果。
decoder_lstm = keras.layers.LSTM(latent_dim, return_sequences=True, return_state=True)
  1. 訓練模型:執行週期須設定較大值,準確率才能提高,範例設為 100。
model.fit(
    [encoder_input_data, decoder_input_data],
    decoder_target_data,
    batch_size=batch_size,
    epochs=epochs,
    validation_split=0.2,
)
  1. 進行預測,比較複雜,步驟如下:
  • 對input編碼,取得解碼器的初起狀態
  • 執行解碼:將解碼器的初起狀態及原始輸入進行解碼
  • 重複執行,取得序列資料
  1. 執行結果如下,翻譯均正確。
    https://ithelp.ithome.com.tw/upload/images/20200926/20001976sk2RUJMlur.png

結論

以上介紹自然語言處理(NLP)的簡單應用,還有許多的應用,尚待努力。

本篇範例包括 26_01_IMDB_Using_LSTM.ipynb、26_02_IMDB_Using_LSTM_complete.ipynb、26_03_Translation.ipynb,可自【這裡】下載。


上一篇
Day 25:Keras 自然語言處理(NLP)實作
下一篇
Day 27:使用Keras撰寫 生成式對抗網路(GAN)
系列文
輕鬆掌握 Keras 及相關應用30

尚未有邦友留言

立即登入留言