owned this note changed 2 years ago
Published Linked with GitHub

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 (HF Tokenizer)

Google - SentencePiece (SPM)


準備文本

可以參考國科會 TAIDE 計畫的訓練資料

或者 Hugging Face Hub 上的繁體中文維基


Parquet 格式

Apache Parquet 是一種
Column-Oriented 的資料格式
具有不錯的壓縮率與讀寫速度
對機器學習相關任務相當友善

壓縮率 Gzip > Parquet >>> Raw
讀寫速度 Parquet > Raw >>> Gzip


Parquet 使用方法

寫入檔案

import pandas as pd dataset = [ dict(id=0, text="Hello"), dict(id=1, text="Hi"), ] dataset = pd.DataFrame(dataset) dataset.to_parquet("dataset.parquet")

讀取檔案

import pandas as pd dataset = pd.read_parquet("dataset.parquet") print(dataset)

將資料存為純文字格式

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 訓練

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 訓練

spm_train --input=Raw.txt --model_prefix=spm-model/tk --model_type=bpe

Tokenizer 生態系

SPM 可以被轉成 HF Tokenizer

HF Tokenizer 可以跟 Transformers 一起訓練

但 HF Tokenizer 比較難被轉回 SPM

Select a repo