iT邦幫忙

2022 iThome 鐵人賽

DAY 10
1

在自然語言處理的領域,tokenization 一般會翻譯做分詞,而 tokenizer 一般會翻譯成分詞器。但是在許多程式設計的領域,會把 tokenization 翻譯成標記化或是記號化,這一點特別要注意其差異。

分詞可以說是自然語言處裡中最重要的一個項目了。一長串的文本要直接塞給程式來做分析,是一件非常困難的事情,我們會把文本的裡面的字或詞切分成一個個的小小單元,進而交給 Transformer 做處理。我們今天先來看比較入門的 tokenization 吧!

Character tokenization

Character tokenization 的概念很簡單,就是把一串文本的每個字母都單獨切分開來。

  1. 程式碼很簡單,在 Python 裡一行就可以完成 Character tokenization。
string = "Only those who will risk going too far can possibly find out how far one can go."
tokenized_str = list(string)
print(tokenized_str)

會得到下面的輸出:

['O', 'n', 'l', 'y', ' ', 't', 'h', 'o', 's', 'e', ' ', 'w', 'h', 'o', ' ', 'w', 'i', 'l', 'l', ' ', 'r', 'i', 's', 'k', ' ', 'g', 'o', 'i', 'n', 'g', ' ', 't', 'o', 'o', ' ', 'f', 'a', 'r', ' ', 'c', 'a', 'n', ' ', 'p', 'o', 's', 's', 'i', 'b', 'l', 'y', ' ', 'f', 'i', 'n', 'd', ' ', 'o', 'u', 't', ' ', 'h', 'o', 'w', ' ', 'f', 'a', 'r', ' ', 'o', 'n', 'e', ' ', 'c', 'a', 'n', ' ', 'g', 'o', '.']
  1. 一般在做完 tokenization 之後,還會 numericalization,讓這些文字去 mapping 成一個 integer。
token2idx = {ch: idx for idx, ch in enumerate(sorted(set(tokenized_str)))}
print(token2idx)

會得到下面的輸出:

{' ': 0, '.': 1, 'O': 2, 'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7, 'f': 8, 'g': 9, 'h': 10, 'i': 11, 'k': 12, 'l': 13, 'n': 14, 'o': 15, 'p': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'w': 21, 'y': 22}
  1. 接著我們再把原始的句子,根據上面這個 set,轉換為數字。
input_ids = [token2idx[token] for token in tokenized_str]
print(input_ids)

會得到下面的輸出:

[2, 14, 13, 22, 0, 19, 10, 15, 18, 7, 0, 21, 10, 15, 0, 21, 11, 13, 13, 0, 17, 11, 18, 12, 0, 9, 15, 11, 14, 9, 0, 19, 15, 15, 0, 8, 3, 17, 0, 5, 3, 14, 0, 16, 15, 18, 18, 11, 4, 13, 22, 0, 8, 11, 14, 6, 0, 15, 20, 19, 0, 10, 15, 21, 0, 8, 3, 17, 0, 15, 14, 7, 0, 5, 3, 14, 0, 9, 15, 1]

以上就是 Character tokenization 的概念。

Word tokenization

Character tokenization 是把文本裡的每個字母都分開,當然也有把文本裡的每個單字都分開的做法,Word tokenization 就是之一。

  1. 一樣我們可以用一行程式碼來達到 Word tokenization。
string = "Only those who will risk going too far can possibly find out how far one can go."
tokenized_str = string.split()
print(tokenized_str)

會得到下面的輸出

`['Only', 'those', 'who', 'will', 'risk', 'going', 'too', 'far', 'can', 'possibly', 'find', 'out', 'how', 'far', 'one', 'can', 'go.']`
  1. 一樣我們可以把 Word tokenization 做 numericalization。
token_word2idx = {ch: idx for idx, ch in enumerate(sorted(set(tokenized_str)))}
print(token_word2idx)

會得到下面的輸出

{'Only': 0, 'can': 1, 'far': 2, 'find': 3, 'go.': 4, 'going': 5, 'how': 6, 'one': 7, 'out': 8, 'possibly': 9, 'risk': 10, 'those': 11, 'too': 12, 'who': 13, 'will': 14}
  1. 一樣 mapping 回 set。
input_ids = [token_word2idx[token] for token in tokenized_str]
print(input_ids)

會得到下面的輸出

[0, 11, 13, 14, 10, 5, 12, 2, 1, 9, 3, 8, 6, 2, 7, 1, 4]

這時候問題就來了,我們做 Character tokenization 時,因為英文字母只有 26 個,加上標點符號也只會多出幾個,但是做 Word tokenization 時,是用每個單字來做 numericalization 的,如果我們有 100 萬個不重覆的單字,在神經網路的第一層時要有 1000 個 dimension 的向量的話,那麼就是 100 萬 * 1000 = 十億個權重了。

再還有一個問題,就是單字的變形要怎麼算。像是 fast,faster,fastest。或者是一些拼寫錯誤的字,都會造成我們的神經網路的權重大幅的提升。

為了解決這類的問題,於是發展出了 Subword tokenization 的算法。明天就是我們鐵人賽開始比較學術的部份了,來為大家介紹比較當代的 tokenization algorithm。


上一篇
# Day9-載入極巨大的 Dataset -- Stream 篇
下一篇
# Day11-當代的 Tokenizer algorithm
系列文
變形金剛與抱臉怪---NLP 應用開發之實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言