[深度學習TF2][RNN-NPL數據預處理] -Tokenizer函數

1. 背景介紹

NLP問題比CV問題更難的一部分原因,就是文本都是離散化的數據,不像圖像數據都是連續的數值數據,所以我們要想辦法把一系列文本轉化成一系列數字
這裏的方法很多,我們這裏採用的方法是,給詞彙表中每一個詞一個index,用index代替那個詞。如一個語料庫共有1w個詞,那麼就設置1w個index,每個詞直接替換程index就行

那麼怎麼把你的單詞或漢字轉化爲數值Index呢。就要用到Tokenizer 這個函數了

2. 函數Tokenizer 介紹

2.1 設置要保留多少個高頻詞彙,

很多問題中,詞彙量巨大,但是可能大部分詞都是低頻詞,對訓練模型的貢獻很小,反而會嚴重拖累模型的訓練。所以,一般我們可以分析一下文本詞彙的詞頻分佈特徵,選取詞頻佔大頭的一批詞就行了。

例如,在本文的任務中,數據集共涉及到的詞彙量有8~9w,這樣訓練起來會很慢。經過分析,發現大概2w個詞就已經覆蓋了絕大部分篇幅,所以我就選取詞典大小爲2w。然後,對文本數值化的時候,那些低頻詞就直接過濾掉了,只留下高頻詞。這樣,模型訓練起來效率就會大大提高。

Tokenizer是一個類, 可以接收一個vocab_size的參數,也就是詞典大小。設置了詞典大小後,在後面生成文本的向量的時候,會把那些低頻詞(詞頻在10開外的)都篩掉。

X_orig = ["Robert DeNiro plays the most unbelievably intelligent illiterate of all time. ",
          "This movie is so wasteful of talent, it is truly disgusting. The script is unbelievable. "]
vocab_size = 10
maxlen = 5
print("Start fitting the corpus......")
t = keras.preprocessing.text.Tokenizer(vocab_size) # 要使得文本向量化時省略掉低頻詞,就要設置這個參數

2.2 訓練數據集, 得到一個統計信息

t.fit_on_texts 幫你統計詞頻,給每個詞分配index,形成字典

t.fit_on_texts(X_orig) # 在所有的評論數據集上訓練,得到統計信息
word_index = t.word_index # 不受vocab_size的影響
print('all_vocab_size',len(word_index), type(word_index))
print(word_index)

執行結果 , word_index 其實就得到一個dict (詞向量,單詞)

all_vocab_size 22 <class 'dict'>
{'is': 1, 'the': 2, 'of': 3, 'robert': 4, 'deniro': 5, 'plays': 6, 'most': 7, 'unbelievably': 8, 'intelligent': 9, 'illiterate': 10, 'all': 11, 'time': 12, 'this': 13, 'movie': 14, 'so': 15, 'wasteful': 16, 'talent': 17, 'it': 18, 'truly': 19, 'disgusting': 20, 'script': 21, 'unbelievable': 22}

2.3 把單詞轉化爲數值index

想獲取index和詞的對照字典的話,就使用t.word_index方法。注意,獲取字典的時候,不會篩掉那些低頻詞,是所有詞的一個字典。
然後,想把一個句子、段落,轉化成對應的index表示的向量怎麼辦呢?Tokenizer也提供了便捷的方法,不用你自己去慢慢查表,直接使用t.texts_to_sequences(X_orig)方法,就可以獲取每句話的index組成的向量表示。注意,這裏,就已經吧低頻詞給過濾掉了,比如一句話有100個詞,其中有30個低頻詞,那麼經過這個函數,得到的就是長度爲70的一個向量。

v_X = t.texts_to_sequences(X_orig) # 受vocab_size的影響
print("Start padding......")
print(v_X)

執行結果

[[4, 5, 6, 2, 7, 8, 9, 3], [1, 3, 1, 2, 1]]

2.4 把每一條數據(比如電影評論)甚至最大單詞數量。

得到每個句子的向量後,會發現大家長度各有不同,長的長短的短,這樣在後面的RNNs訓練時,就不方便批處理。所以,我們還需要對句子進行一個padding(填白,補全),把所有句子弄程統一長度,短的補上0,長的切掉。用的方法就是pad_sequences。

pad_X = keras.preprocessing.sequence.pad_sequences(v_X,maxlen=maxlen,padding='post')
print(pad_X)

執行結果

[[2 7 8 9 3]
 [1 3 1 2 1]]

3. 完整測試代碼

import tensorflow as tf
import tensorflow.keras as keras

X_orig = ["Robert DeNiro plays the most unbelievably intelligent illiterate of all time. ",
          "This movie is so wasteful of talent, it is truly disgusting. The script is unbelievable. "]
vocab_size = 10
maxlen = 5
print("Start fitting the corpus......")
t = keras.preprocessing.text.Tokenizer(vocab_size) # 要使得文本向量化時省略掉低頻詞,就要設置這個參數
t.fit_on_texts(X_orig) # 在所有的評論數據集上訓練,得到統計信息
word_index = t.word_index # 不受vocab_size的影響
print(X_orig)
print('all_vocab_size',len(word_index), type(word_index))
print(word_index)
print("Start vectorizing the sentences.......")
v_X = t.texts_to_sequences(X_orig) # 受vocab_size的影響
print("Start padding......")
print(v_X)
pad_X = keras.preprocessing.sequence.pad_sequences(v_X,maxlen=maxlen,padding='post')
print(pad_X)

執行結果

Start fitting the corpus......
['Robert DeNiro plays the most unbelievably intelligent illiterate of all time. ', 'This movie is so wasteful of talent, it is truly disgusting. The script is unbelievable. ']
all_vocab_size 22 <class 'dict'>
{'is': 1, 'the': 2, 'of': 3, 'robert': 4, 'deniro': 5, 'plays': 6, 'most': 7, 'unbelievably': 8, 'intelligent': 9, 'illiterate': 10, 'all': 11, 'time': 12, 'this': 13, 'movie': 14, 'so': 15, 'wasteful': 16, 'talent': 17, 'it': 18, 'truly': 19, 'disgusting': 20, 'script': 21, 'unbelievable': 22}
Start vectorizing the sentences.......
Start padding......
[[4, 5, 6, 2, 7, 8, 9, 3], [1, 3, 1, 2, 1]]
[[2 7 8 9 3]
 [1 3 1 2 1]]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章