在Python中,
要寫一個完整的「符元化類 Tokenizer Class」,
這個Class需要的功能有:
1.「編碼 Encode」:將「文本 Text」分割成「符元 Token」。
2.「詞彙 Vocabulary」:將「符元 Token」映射到「符元ID TokenID」的「文本對整數映射 String-to-Integer Mapping」
3.「解碼 Decode」:將「符元ID TokenID」轉換為「文本 Text」的「整數對文本映射 Integer-to-String Mapping」
如此,
就完成了「文本 Text」--> 「符元 Token」--> 「符元ID TokenID」--> 「文本 Text」的循環,
這就是為什麼訓練資料中的文本,
可以透過GPT的結構,轉回AI生成的文本的整個循環。
具體的Python code如:
```python
class SimpleTokenizerV1:
def __init__(self, vocab):
self.str_to_int = vocab
self.int_to_str = {i:s for s,i in vocab.items()}
def encode(self, text):
preprocessed = re.split(r'([,.?_!"()\']|--|\s)', text)
preprocessed = [
item.strip() for item in preprocessed if item.strip()
]
ids = [self.str_to_int[s] for s in preprocessed]
return ids
def decode(self, ids):
text = " ".join([self.int_to_str[i] for i in ids])
# Replace spaces before the specified punctuations
text = re.sub(r'\s+([,.?!"()\'])', r'\1', text)
return text
```
可以看到,在`SimpleTokenizerV1`這個類的「構建子 Constructor」,
設置了「文本到整數」的映射,是輸入的「詞彙 Vocabulary」,
也設置了「整數到文本」的映射,是透過查詢「詞彙 Vocabulary」來轉回文本。
而「編碼函數 def encode」將輸入的文本先切成一個一個的「符元 Token」,
接著透過詞彙來查這些Token的ID。
而「解碼函數 def decode」將給定的一串「符元 ID Token ID」,
也是透過詞彙來轉回文本。
實際使用的例子,看起來會像是
```python
tokenizer = SimpleTokenizerV1(vocab)
text = """"It's the last he painted, you know,"
Mrs. Gisburn said with pardonable pride."""
ids = tokenizer.encode(text)
print(ids)
```
則會得到一串Token ID
```
[1, 56, 2, 850, 988, 602, 533, 746, 5, 1126, 596, 5, 1, 67, 7, 38, 851, 1108, 754, 793, 7]
```
而這串Token ID 可以透過Decoder再轉回文本
```
tokenizer.decode(ids)
```
得到結果
```
'" It\' s the last he painted, you know," Mrs. Gisburn said with pardonable pride.'
```
如此,有足夠豐富的Vocabulary,就能各種文本都能學習與產生。