[TensorFlow Certification Day7] 挑戰NLP (5hrs)


Posted by Kled on 2020-08-20

Natural Language Processing in TensorFlow(Week1/2)

這兩周沒有習題, 但是因為沒有接觸過太多NLP的東西, 光看懂code就花了不少時間
處理NLP因為不像圖像或raw data是數字的data, 必須要把文字轉換成數字

Tokenizer

因此第一步就是把文字編碼成數字, 這裡採用keras已有的API, Tokenizer

from tensorflow.keras.preprocessing.text import Tokenizer

sentences = [
    'I love my dog',
    'I love my cat'
]
tokenizer = Tokenizer(num_words = 100)
word_index = tokenizer.word_index
print(word_index)
#{'i': 1, 'my' : 3, 'dog' : 4, 'cat' : 5, 'love' : 2}
#加標點符號不影響, 不會因為dog!, 就增加一個index
#透過空格或, 分割語句
#不分大小寫 I = i
#tokenizer會依照出現的頻率來排序, 越前面的出現頻率越高

sequences = tokenizer.texts_to_sequences(sentences)
print(sequences)

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

test_data = [
    'i really love my dog',
    'my dog loves my manatee'
]

test_seq = tokenizer.texts_to_sequences(sentences)
print(test_seq)

#[[4, 2, 1, 3], [1, 3, 1]
#可以看到沒看過的詞不會出現在裡面

上面可以看到當tokenizer沒有出現過的詞, 在texts_to_sequence會自動跳過那些詞, 如果要避免自動跳過這些詞有下面兩種方法

  1. 需要大量的訓練數據才能得到廣泛的詞彙
  2. 是否可以給予不知道的詞一個特殊的詞

OOV_token, Padding

除此之外, 送到model training之前還有一個問題是, data input必須要等長, 所以必須有padding的動作
加入OOV_token, 會自動把沒看過的詞用OOV_token取代

#要特別注意<OOV>不能跟真實數據的詞一樣, 否則會混淆
#num_words限定只抓100個最常見的詞出來token
tokenizer = Tokenizer(num_words = 100, oov_token="<OOV>")

from tensorflow.keras.preprocessing.sequence import pad_sequences
#會把每一段padding補0到相同長度, 會自動找語句最長的當maxlen
padded = pad_sequences(sequences)
#maxlen限制最長的語句長度, post是指把pad補0補在後面, 預設是'pre'
padded = pad_sequences(sequences, padding='post', maxlen=5)

下面這段可以讓tokenizer自動去fit給定的sentences (list)裡面有多少詞就fit出多少個token

tokenizer = Tokenizer(oov_token="<OOV>")
#會自動找出總共長度有多少
tokenizer = fit_on_texts(sentences)

Word Embeddings

詞轉換成數字之後, 目前的數字只代表常出現與否, 是否有更好的表示方式?
把單詞投影到空間中的向量, 使得這些數字變得有向量意義
舉例來說 : 可愛, 漂亮, 帥氣都是正面詞, 他們彼此在正面與反面的空間中應該比較相近, 相反的, 醜陋, 易怒, 難看這種詞就是反面詞, 會與前面的詞的距離比較遠
因此提出Word Embedding的方式將Word投影到不同意義的空間

Embedding是多維的array
詳細的Embedding code就不放上來了, 大家自己跟著課程練習
大致上的用法慢慢看都能看得懂
Quiz也不難
還有提供https://projector.tensorflow.org/
可以把embedded向量放上來看可視化

NLP很容易會發生overfit, 就是訓練上升但是validate下降, 有幾個作法

  1. 嘗試把句子簡短, 減少padding的數目, 通常會起到一點效果
  2. 更改embedding層數目, 但效果看起來還好
  3. 使用subword

Subword

這邊稍微google了一下subword的用意,

與傳統空格分隔tokenization技術的對比

  • 傳統詞表示方法無法很好的處理未知或罕見的詞彙(OOV問題)
  • 傳統詞tokenization方法不利於模型學習詞綴之間的關係
    • Eg 模型學到的“old”, “older”, and “oldest”之間的關係無法泛化到“smart”, “smarter”, and “smartest”。
  • Character embedding作為OOV的解決方法粒度太細 (不是很理解這句)
  • Subword粒度在詞與字符之間,能夠較好的平衡OOV問題

實際subword怎麼做的還要再study

但subword這邊練習的時候有一個小坑, 在tf version 2.x好像會遇到
就是tensorflow_datasets出來的imdb data需要expand_dim
如果沒有處理直接把train_data送進去model.fit就會出現問題

print(train_data)
#<PrefetchDataset shapes: ((None,), ()), types: (tf.int64, tf.int64)>
train_data = train_data.map(lambda x_text, x_label: (x_text, tf.expand_dims(x_label, -1)))
test_data = test_data.map(lambda x_text, x_label: (x_text, tf.expand_dims(x_label, -1)))
print(train_data)
#<MapDataset shapes: ((None,), (1,)), types: (tf.int64, tf.int64)>
num_epochs = 10

心得 : NLP沒接觸過, 因此課堂影片來回看了幾次, 好在沒有習題, 但是為了熟悉度還是要跟著課堂上的範例走一遍
還是一樣的想法, model本身並不難建, 難的是要怎麼處理數據, 並讓model使用這些數據


#AI #機器學習 #TensorFlow #tensorFlow Certification #machine learning #人工智慧 #Deep Learning #DL #ML







Related Posts

ES6 解構賦值

ES6 解構賦值

氣泡排序(Bubble Sort)、插入排序(Insertion Sort)、選擇排序(Selection Sort)

氣泡排序(Bubble Sort)、插入排序(Insertion Sort)、選擇排序(Selection Sort)

[Golang] gorm 2.0 insert on duplicate update

[Golang] gorm 2.0 insert on duplicate update


Comments