# Tokenizer ## Week 29 ---- ## 說文解字 Byte 位元組 Character 字元 Word 單字、詞 Vocabulary 字典 ---- ## Byte 例如 `"Apple"` 可以表示成 `0x41/0x70/0x70/0x6C/0x65` 等 5 個位元組,每個英文字母佔 1 Byte ---- ## Byte 若是中文的「蘋果」則為 `0xE8/0x98/0x8B/0xE6/0x9E/0x9C` 等 6 個位元組,每個中文字佔 3 Bytes ---- ## Character 例如 `"Apple"` 可以分解成 `A/p/p/l/e` 等 5 個字元 而「蘋果」則是 2 個字元 ---- ## Word 例如 `"I have an apple"` 可以分解成 `I/have/an/apple` 等 4 個單字 ---- ## Chinese Word? 「我有一顆蘋果」可以分解成 `我有/一顆/蘋果` `我/有/一/顆/蘋果` 不同定義下有不同的切法 這在中文也稱為 「斷詞 (Word Segmentation)」 ---- ## Token Token 資訊歷史上最難翻譯的一個單字 比較理想的翻譯是「詞元」 若是當成 API Token 則會翻成「令牌」 但兩者的用法情境是不同的 ---- ## Token Tokenize 動詞,指分詞這個動作 Tokenization 名詞,指分詞的過程 Tokenizer 名詞,分詞器、詞元分析器 ---- ## 什麼是 Token 介在 Byte 與 Word 之間的單位 例如 `Apple` 可能是 1 個獨立的 Token 而 `Pineapple` 則可能被分解成 `Pine` 跟 `##apple` 兩個 Tokens ---- ## Too Many Tokens UTF-8 編碼可以表示九萬多種中日韓字元 整個 Unicode 包含了約 14 萬個字元 更遑論這些字元可以合併成更多單字詞 對模型訓練而言,這樣會產生非常高的維度 使模型尺寸相當大,難以訓練 ---- ## Byte-Level Token 把 Token 的單位縮減到 Byte-Level 就能在 256 個 Tokens 內表達所有文字 但是「文本壓縮率」就會很低 「我有一顆蘋果」需要 18 個 Tokens 來表示 ---- ## Tokenizer Training 透過一些統計的技巧 在字典大小與文本壓縮率之間取得平衡 除此之外,還要能夠應對未知詞 Out-of-Vocabulary, OOV --- # 訓練演算法 ---- ## 演算法種類 Character/Word-Level Unigram Word-Piece Byte-Pair Encoding (BPE) ---- ## Char/Word-Level 直接以字元/單字為單位 最單純的做法 不適合中日韓文字 ---- ## Unigram 統計單字詞之間的機率 介在 Char-Level 與 Word-Level 之間 比較能夠表達 OOV 文字 ---- ## Word-Piece 先將所有文本分析成 Words 再把每個 Word 拆解成 Pieces 例如已經有了 `photo, graphy` 兩字 則遇到 `photography` 可拆解成 `photo, ##graphy` 兩個 Tokens ---- ## Byte-Pair Encoding 先把所有文本拆解成 Bytes 再把常常出現的 Byte-Pair 組合在一起 例如已經有了 `a, g, h, o, p, r, t, y` 等 `photo` 很常配在一起,合併成一個 Token `graphy` 很常配在一起,合併成另一個 Token --- # 訓練工具 ---- ## 開源套件 [Hugging Face - Tokenizers](https://github.com/huggingface/tokenizers) (HF Tokenizer) [Google - SentencePiece](https://github.com/google/sentencepiece) (SPM) ---- ## 準備文本 可以參考國科會 TAIDE 計畫的[訓練資料](https://taide.tw/public/trainData) 或者 Hugging Face Hub 上的[繁體中文維基](https://huggingface.co/datasets/bigscience-data/roots_zh-tw_wikipedia) ---- ## Parquet 格式 [Apache Parquet](https://parquet.apache.org/) 是一種 **Column-Oriented** 的資料格式 具有不錯的壓縮率與讀寫速度 對機器學習相關任務相當友善 壓縮率 Gzip > Parquet >>> Raw 讀寫速度 Parquet > Raw >>> Gzip ---- ## Parquet 使用方法 寫入檔案 ```python= import pandas as pd dataset = [ dict(id=0, text="Hello"), dict(id=1, text="Hi"), ] dataset = pd.DataFrame(dataset) dataset.to_parquet("dataset.parquet") ``` 讀取檔案 ```python= import pandas as pd dataset = pd.read_parquet("dataset.parquet") print(dataset) ``` ---- ## 將資料存為純文字格式 ```python= import pandas as pd data = pd.read_parquet("wiki.parquet") with open("Raw.txt", "wt", encoding="UTF-8") as fp: for text in data["text"][:1000]: fp.write(text.strip()) fp.write("\n\n") ``` ---- ## 透過 HF Tokenizers 訓練 ```python= from tokenizers import Tokenizer, models, trainers model = models.BPE(byte_fallback=True, unk_token="[UNK]") trainer = trainers.BpeTrainer(special_tokens=["[UNK]"]) tokenizer = Tokenizer(model) files = ["Raw.txt"] tokenizer.train(files, trainer) tokenizer.save("Tokenizer.json") ``` ---- ## 透過 SentencePiece 訓練 ```bash= spm_train --input=Raw.txt --model_prefix=spm-model/tk --model_type=bpe ``` ---- ## Tokenizer 生態系 SPM 可以被轉成 HF Tokenizer HF Tokenizer 可以跟 Transformers 一起訓練 但 HF Tokenizer 比較難被轉回 SPM
{"title":"Week 29 - Tokenizer","description":"地獄貓旅行團第 41 週心得分享","contributors":"[{\"id\":\"c7cbb212-2c41-4dfa-8d85-f8e7fa769bf1\",\"add\":3644,\"del\":310}]","slideOptions":"{\"transition\":\"slide\"}"}
    599 views
   Owned this note