LLM 課程文件
歸一化和預分詞
並獲得增強的文件體驗
開始使用
歸一化和預分詞
在深入瞭解 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!
< > 在 GitHub 上更新