並獲得增強文件體驗
開始
規範化和預標記化
在我們更深入地研究 Transformer 模型中使用的三種最常見的子詞標記化演算法(位元組對編碼 [BPE]、WordPiece 和 Unigram)之前,我們將首先了解每個標記器對文字應用的預處理。以下是標記化管道中步驟的高階概述
在根據其模型將文字拆分為子標記之前,標記器會執行兩個步驟:規範化和預標記化。
規範化
規範化步驟涉及一些常規清理,例如去除多餘的空格、小寫化和/或去除重音符號。如果您熟悉Unicode 規範化(例如 NFC 或 NFKC),這也是標記器可能應用的內容。
🤗 Transformers 的 tokenizer 有一個名為 backend_tokenizer 的屬性,它可以訪問 🤗 Tokenizers 庫中的底層標記器
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
print(type(tokenizer.backend_tokenizer))<class 'tokenizers.Tokenizer'>tokenizer 物件的 normalizer 屬性有一個 normalize_str() 方法,我們可以使用它來檢視規範化是如何執行的
print(tokenizer.backend_tokenizer.normalizer.normalize_str("Héllò hôw are ü?"))'hello how are u?'在這個例子中,由於我們選擇了 bert-base-uncased 檢查點,因此應用的規範化進行了小寫化並去除了重音符號。
✏️ 試試看!從 bert-base-cased 檢查點載入標記器,並將相同的示例傳遞給它。您可以在標記器的區分大小寫版本和非區分大小寫版本之間看到哪些主要區別?
預標記化
正如我們將在接下來的章節中看到的,標記器不能僅在原始文字上進行訓練。相反,我們首先需要將文字拆分為小的實體,例如單詞。這就是預標記化步驟發揮作用的地方。正如我們在第 2 章中看到的,基於單詞的標記器可以簡單地根據空格和標點符號將原始文字拆分為單詞。這些單詞將成為標記器在其訓練期間可以學習的子標記的邊界。
要檢視快速標記器如何執行預標記化,我們可以使用 tokenizer 物件的 pre_tokenizer 屬性的 pre_tokenize_str() 方法
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")[('Hello', (0, 5)), (',', (5, 6)), ('how', (7, 10)), ('are', (11, 14)), ('you', (16, 19)), ('?', (19, 20))]請注意,標記器已經在跟蹤偏移量,這就是它如何能夠為我們提供我們在上一節中使用的偏移量對映的原因。這裡標記器忽略了兩個空格並將它們替換為一個,但偏移量在 are 和 you 之間跳轉以考慮這一點。
由於我們使用的是 BERT 標記器,因此預標記化涉及根據空格和標點符號進行拆分。其他標記器在此步驟中可能具有不同的規則。例如,如果我們使用 GPT-2 標記器
tokenizer = AutoTokenizer.from_pretrained("gpt2")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")它也將根據空格和標點符號進行拆分,但它會保留空格並將其替換為 Ġ 符號,使我們能夠在解碼標記時恢復原始空格
[('Hello', (0, 5)), (',', (5, 6)), ('Ġhow', (6, 10)), ('Ġare', (10, 14)), ('Ġ', (14, 15)), ('Ġyou', (15, 19)),
('?', (19, 20))]另請注意,與 BERT 標記器不同,此標記器不會忽略雙空格。
作為最後一個示例,讓我們看一下基於 SentencePiece 演算法的 T5 標記器
tokenizer = AutoTokenizer.from_pretrained("t5-small")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are you?")[('▁Hello,', (0, 6)), ('▁how', (7, 10)), ('▁are', (11, 14)), ('▁you?', (16, 20))]與 GPT-2 標記器一樣,此標記器保留空格並將其替換為特定標記(_),但 T5 標記器僅根據空格進行拆分,而不是標點符號。另請注意,它在句子的開頭(在 Hello 之前)預設添加了一個空格,並忽略了 are 和 you 之間的雙空格。
現在我們已經瞭解了一些不同的標記器如何處理文字,我們可以開始探索底層演算法本身。我們將首先快速瞭解廣泛適用的 SentencePiece;然後,在接下來的三個部分中,我們將研究用於子詞標記化的三種主要演算法的工作原理。
SentencePiece
SentencePiece 是一種用於文字預處理的標記化演算法,您可以將其與我們將在接下來的三個部分中看到的任何模型一起使用。它將文字視為 Unicode 字元序列,並將空格替換為特殊字元 。與 Unigram 演算法結合使用(參見第 7 節),它甚至不需要預標記化步驟,這對於不使用空格字元的語言(如中文或日語)非常有用。
SentencePiece 的另一個主要特徵是可逆標記化:由於沒有對空格進行特殊處理,因此解碼標記只需將它們連線起來並將 _ 替換為空格即可——這將導致規範化的文字。正如我們之前看到的,BERT 標記器會刪除重複的空格,因此其標記化不可逆。
演算法概述
在以下各節中,我們將深入探討三種主要的子詞標記化演算法:BPE(例如 GPT-2 等使用)、WordPiece(例如 BERT 使用)和 Unigram(例如 T5 等使用)。在我們開始之前,這裡簡要概述了它們各自的工作原理。如果您還沒有理解,請不要猶豫,在閱讀完下一節後返回此表。
| 模型 | BPE | WordPiece | Unigram |
|---|---|---|---|
| 訓練 | 從一個小詞彙表開始,學習合併標記的規則 | 從一個小詞彙表開始,學習合併標記的規則 | 從一個大詞彙表開始,學習刪除標記的規則 |
| 訓練步驟 | 合併對應於最常見對的標記 | 合併對應於得分最高的對的標記,該得分基於對的頻率,優先考慮每個單獨標記頻率較低的對 | 刪除詞彙表中所有會最小化在整個語料庫上計算的損失的標記 |
| 學習 | 合併規則和詞彙表 | 僅詞彙表 | 帶有所關聯分數的詞彙表 |
| 編碼 | 將單詞拆分為字元,並應用訓練期間學習的合併規則 | 從開頭找到最長的子詞,該子詞位於詞彙表中,然後對單詞的其餘部分執行相同的操作 | 找到最可能的標記拆分,使用訓練期間學習的分數 |
現在讓我們深入瞭解BPE!