瞭解文字向量化的基礎知識,在IMDB Reviews資料集上建立使用神經網路訓練的詞嵌入模型,並使用TensorBoard嵌入投影儀對其進行視覺化
> Figure 1. Photo by Raphael Schaller on Unsplash
這是在本教程的第一部分"使用TensorFlow掌握10分鐘內掌握單詞嵌入"之後準備的後續教程,在其中我們介紹了幾種單詞向量化概念,例如"一次熱編碼"和"具有唯一ID值的編碼"。如果您是自然語言處理的新手,我強烈建議您閱讀本教程。
在本教程的第二部分中,我們將使用IMDB Reviews資料集對單詞進行向量化處理並訓練其值。本教程是我們自己對TensorFlow的單詞嵌入教程的理解。我們將使用簡單的Keras模型和IMDB Reviews資料集訓練單詞嵌入。然後,我們將使用Embedding Projector視覺化它們。
開始吧:
建立一個新的Google Colab筆記本首先,您需要環境來開始編碼。為了簡單起見,建議您使用Google Colab。它附帶了所有預安裝的庫,您不必擔心它們。您需要的只是一個Google帳戶,我確定您有一個。因此,建立一個新的Colab筆記本(請參見圖2)並開始編碼。
> Figure 2: Create a New Google Colab Notebook
初始匯入我們將從匯入TensorFlow和os庫開始。我們將使用os庫執行下面將要執行的某些目錄級別的操作,並將TensorFlow庫用於資料集載入,深度學習模型和文字預處理。
import tensorflow as tfimport os
下載IMDB評論資料集
IMDB評論資料集是由大型電影分級服務IMDB的Andrew L. Maas收集和準備的大型電影評論資料集。IMDB評論資料集用於二進位制情感分類,無論評論是肯定的還是否定的。它包含25,000條用於培訓的電影評論和25,000條用於測試的評論。所有這50,000條評論均帶有標籤資料,可用於監督式深度學習。此外,還有50,000個未加標籤的評論,在本案例研究中我們將不使用它們。在本案例研究中,我們將僅使用訓練資料集。
我們可以使用tf.keras.utils.get_file函式從斯坦福大學的相關目錄下載資料集,如下所示:
URL = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"dataset = tf.keras.utils.get_file(fname="aclImdb_v1.tar.gz", origin=URL, untar=True, cache_dir='.', cache_subdir='')
資料集建立我們需要一些整理工作以建立適當的資料集。讓我們從檢視主目錄開始
# View what's in the main directory ("/aclImdb")main_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')print(os.listdir(main_dir))
正如您在下面看到的,我們有我們的訓練和測試資料夾。對於本研究,我們將僅使用/ train資料夾
> Figure 3. The Content of Main Directory, "aclImdb"
在以下幾行中,讓我們檢視/ train子目錄下的內容:
# View what's in the "/aclImdb/train" foldertrain_dir = os.path.join(main_dir, 'train')print(os.listdir(train_dir))
這是:
> Figure 4. The Content of Sub-Directory, "aclImdb/train"
# The shutil module offers a number of high-level # operations on files and collections of files.import shutilremove_dir = os.path.join(train_dir, 'unsup')shutil.rmtree(remove_dir)print(os.listdir(train_dir))
如圖X所示,由於使用了shutil庫,我們刪除了unsup資料夾:
> Figure 4. The Content of Sub-Directory, "aclImdb/train" after we remove the "unsup" folder
建立資料集現在我們清理了目錄,我們可以建立資料集物件。為此,我們可以使用tf.keras.preprocessing.text_dataset_from_directory函式。顧名思義,text_dataset_from_directory函式允許我們直接從目錄建立文字資料集。我們選擇了80/20訓練和驗證拆分,但可以透過調整validation_split引數隨意操作。
# We create a training dataset and a validation # dataset from our "aclImdb/train" directory with a 80/20 split.train_ds = tf.keras.preprocessing.text_dataset_from_directory( 'aclImdb/train', batch_size=1024, validation_split=0.2, subset='training', seed=123)val_ds = tf.keras.preprocessing.text_dataset_from_directory( 'aclImdb/train', batch_size=1024, validation_split=0.2,
如您在圖5中看到的,我們有20,000條關於培訓的評論,以及5,000條關於驗證的評論。
> Figure 5. The volume of Our Train and Validation Dataset
讓我們使用.take()函式檢查資料集的外觀並執行for迴圈。請注意,我們的資料集是一個TensorFlow資料集物件。需要更多的精力來打印出其元素。下面的程式碼行:
# Let's see some examples from our dataset:for text_batch, label_batch in train_ds.take(1): for i in range(5): print(label_batch[i].numpy(), text_batch.numpy()[i])
這是圖6中的結果:
Figure 6. The First Five Reviews from the Training Dataset with Their Sentiment Info in
配置資料集現在,由於我們處於深度學習領域,因此最佳化對於可承受的培訓體驗至關重要。TensorFlow有一個實驗工具,我們可以使用它來最佳化工作量並縮短預處理,培訓和其他並行操作所需的時間。我們可以使用以下幾行來最佳化我們的管道:
# AUTOTUNE is a little experimental tool we can use to optimize the workload and shorten # the time needed for preprocessing, traning, and other parallel operationsAUTOTUNE = tf.data.experimental.AUTOTUNEtrain_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
文字預處理現在我們已經建立了資料集,是時候處理其元素了,以便我們的模型可以理解它們了。
定製標準化我們將建立一個自定義字串標準化函式,以充分利用標準化。標準化可以描述為NLP研究的一組預處理操作,包括下套管,標籤去除和標點剝離。在下面的程式碼中,我們正好實現了這些:
import reimport stringdef string_standardization(input_data): # Lowercase each input lowercase = tf.strings.lower(input_data) # Remove HTML break tags '<br />' in reviews to cleaning stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ') # Strip punctuation return tf.strings.regex_replace(stripped_html, '[%s]' % re.escape(string.punctuation), '')
現在,我們的自定義功能將使我們的資料更加標準化。
文字向量化由於我們建立了自定義標準化功能,因此可以在從TensorFlow匯入的TextVectorization層中傳遞它。TextVectorization是我們用來將字串對映為整數的一層。我們將傳遞自定義的標準化功能,最多使用10,000個唯一詞(詞彙),並且每次評論最多保留100個詞。檢查以下幾行:
# We will use Text Vectorization to map our strings to integers.from tensorflow.keras.layers.experimental.preprocessing import TextVectorizationvectorize_layer = TextVectorization( standardize=string_standardization, # Our custom standardization function max_tokens=10000, # Max amount of unique words to map output_mode='int', # Output of the operation output_sequence_length=100 # Max length of each sequence (mapped review) )
我們將從火車資料集中刪除標籤,並呼叫.adapt()函式來構建詞彙表,以備後用。請注意,我們尚未向量化資料集。剛用以下幾行建立了詞彙表:
reviews_only_ds = train_ds.map(lambda a, b: a) # Remove the labelsvectorize_layer.adapt(reviews_only_ds) # Call adapt to build the vocabulary
模型建立與訓練我們已經處理了我們的評論,現在該建立模型了。
模型製作我們將進行初始匯入,其中包括將在模型中使用的用於模型構建和嵌入的順序API,全域性平均池和密集層。
我們將嵌入維設定為16,因此每個單詞將具有16個代表值。與上面的程式碼並行,我們將詞彙量限制為10,000。
我們在Keras模型中新增以下圖層:
1 —一個TextVectorization層,用於將字串轉換為整數;
2 —嵌入層,用於轉換帶有16維向量的整數值;
4-具有16個神經元的緻密層和relu啟用層
以下行完成所有這些操作:
from tensorflow.keras import Sequentialfrom tensorflow.keras.layers import Embedding, GlobalAveragePooling1D, Densevocab_size = 10000embedding_dim=16model = Sequential([ vectorize_layer, Embedding(input_dim = vocab_size, output_dim = embedding_dim, name="embedding"), GlobalAveragePooling1D(), Dense(16, activation='relu'), Dense(1)])
為TensorBoard設定回撥由於我們想了解模型隨時間的變化和效能,因此我們將使用以下幾行來配置回撥設定:
# Setting up callbacks for TensorBoardtensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="logs")
我們將使用這些回撥在每個時期使用TensorBoard視覺化模型效能
配置模型然後,我們將配置模型,其中將Adam作為最佳化器,將Binary Crossentropy作為損失函式,因為它是二進位制分類任務,並選擇準確性作為我們的效能指標。
model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'])
開始訓練
現在我們的模型已配置,我們可以使用.fit()函式開始訓練。我們將執行15個紀元,並記錄TensorBoard的回撥。
model.fit( train_ds, validation_data=val_ds, epochs=15, callbacks=[tensorboard_callback])
這是訓練過程的螢幕截圖,如圖所示:
> Figure 7. Model Performance at Each Epoch
視覺化結果既然我們結束了模型訓練,我們就進行一些視覺化以更好地瞭解我們構建和訓練的內容。
模型總結我們可以使用.summary()函式輕鬆檢視模型的摘要,如下所示:
model.summary()
圖8顯示了我們的模型的外觀,並列出了每一層的引數數量和輸出形狀:
> Figure 8. Our Model Summary
跟蹤和視覺化損失和準確性測度視覺化模型圖檢視權重,偏差和其他張量值的演變顯示影象,文字和音訊資料和更多…# Load the TensorBoard notebook extension%load_ext tensorboard%tensorboard --logdir logs
> Figure 9. A Screenshot of Our Tensorboard Instance
在本教程中,我們將使用%load_ext載入TensorBoard並檢視日誌。上面的幾行將在我們的單元內執行一臺小型伺服器,以視覺化隨時間變化的指標值。
如您在左側看到的,隨著時間的流逝,我們的精度提高了,而損失值卻降低了。圖9顯示了我們的模型可以完成的工作,因為降低損耗值意味著我們的模型正在做一些事情以減少錯誤:學習。
嵌入式投影儀是在TensorBoard之上構建的工具。這是一種有用的工具,可以分析資料並可視化嵌入值相對於彼此的位置。使用Embedding Projector,我們可以使用PCA之類的演算法透過簡化圖形來表示高維嵌入。
獲取向量值和詞彙資料我們將從獲取每個單詞的16維嵌入值開始。同樣,我們將獲得所有嵌入的這些單詞的列表。我們可以使用以下程式碼完成這兩項任務:
# Get the word encoding from the "embedding" layerweights = model.get_layer('embedding').get_weights()[0]# Get the list of words (i.e., vocabulary) from the "vectorize_layer"vocab = vectorize_layer.get_vocabulary()
讓我們用一個隨機的例子看看我們的單詞及其向量值的外觀。我們選擇了索引編號為的單詞。500,並使用以下程式碼對其進行視覺化:
# Let's see an example of how it would lookindex_val = 500print("The word: ", vocab[index_val], "\n Its vector values:", weights[index_val])
向量值和索引編號的相應單詞。500如圖10所示:
將資料儲存到新檔案:
現在我們有了單詞(詞彙)的完整列表及其相應的16維向量值。我們將把單詞名稱儲存到metas.tsv檔案,將向量值儲存到vectors.tsv檔案。以下幾行建立新檔案,將我們的資料寫入這些新檔案,儲存資料,關閉檔案,然後將其下載到本地計算機:
import iofrom google.colab import files# OPEN: Create and open two files for vectors and metadataout_v = io.open('vectors.tsv', 'w', encoding='utf-8')out_m = io.open('metadata.tsv', 'w', encoding='utf-8')# WRITE: Save the vector values to vectors.tsv and the word itself to metadata.tsv# Note that we keep the same index order for both files# since we will use them together for visualizationfor index, word in enumerate(vocab): if index == 0: continue # skip 0, it's padding. out_m.write(word + "\n") out_v.write('\t'.join([str(x) for x in weights[index]]) + "\n")# CLOSE: Close the created filesout_v.close()out_m.close()# DOWNLOAD: Download the saved files to your local machinefiles.download('vectors.tsv')files.download('metadata.tsv')
訪問 http://projector.tensorflow.org/ 載入到嵌入式投影儀
請注意,嵌入投影儀執行PCA演算法以將16維向量空間縮小為3維,因為這是視覺化它的唯一方法。
恭喜您已經成功構建了一個神經網路來訓練單詞嵌入模型,並且要花很多精力才能實現這一目標。輕撫自己,並在自然語言處理領域不斷提高自己,因為仍然存在許多未解決的問題。