Transformers 文件
分詞器
並獲得增強的文件體驗
開始使用
分詞器
分詞器將文字轉換為數字陣列,即張量,作為文字模型的輸入。分詞演算法有幾種,但它們都有相同的目的。根據一些規則將文字分割成更小的詞或子詞(標記),並將其轉換為數字(輸入 ID)。Transformers 分詞器還會返回一個注意力掩碼,以指示哪些標記應該被關注。
在分詞器摘要文件中瞭解最流行的分詞演算法。
呼叫from_pretrained()從 Hugging Face Hub 或本地目錄載入分詞器及其配置。預訓練的分詞器儲存在tokenizer.model檔案中,其中包含所有相關的詞彙檔案。
將字串文字傳遞給分詞器,以返回輸入 ID 和注意力掩碼,並設定框架張量型別,使用 return_tensors
引數返回。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
無論使用哪種分詞器,請確保分詞器詞彙表與預訓練模型的分詞器詞彙表相同。如果您使用自定義分詞器且其詞彙表與預訓練模型分詞器的詞彙表不同,這一點尤其重要。
本指南簡要概述了分詞器類以及如何使用它預處理文字。
分詞器類
所有分詞器都繼承自PreTrainedTokenizerBase類,該類為所有分詞器提供了通用方法,例如from_pretrained()和batch_decode()。有兩種主要的分詞器類建立在基類之上。
- PreTrainedTokenizer是 Python 實現,例如LlamaTokenizer。
- PreTrainedTokenizerFast是來自Tokenizers庫的基於 Rust 的快速實現,例如LlamaTokenizerFast。
有兩種載入分詞器的方法,使用AutoTokenizer或特定於模型的分詞器。
AutoClass API 是一種快速簡便的載入分詞器的方法,無需瞭解是提供 Python 還是 Rust 實現。預設情況下,AutoTokenizer 會嘗試載入一個快速分詞器(如果可用),否則會載入 Python 實現。
使用from_pretrained()載入分詞器。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library.", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
透過將其詞彙表文件傳遞給from_pretrained()來載入您自己的分詞器。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("./model_directory/my_vocab_file.txt")
多模態分詞器
除了文字標記,多模態分詞器還包含來自其他模態的標記,作為其屬性的一部分,以便於訪問。
要將這些特殊標記新增到分詞器,請將它們作為字典傳遞給from_pretrained()中的extra_special_tokens
引數。下面的示例將image_token
新增到視覺-語言模型。
儲存分詞器,以便您可以直接訪問image_token
、boi_token
和eoi_token
並重復使用它。
vision_tokenizer = AutoTokenizer.from_pretrained(
"llava-hf/llava-1.5-7b-hf",
extra_special_tokens={"image_token": "<image>", "boi_token": "<image_start>", "eoi_token": "<image_end>"}
)
print(vision_tokenizer.image_token, vision_tokenizer.image_token_id)
("<image>", 32000)
vision_tokenizer.save_pretrained("./path/to/tokenizer")
快速分詞器
PreTrainedTokenizerFast或*快速分詞器*是來自Tokenizers庫的基於 Rust 的分詞器。它在批次分詞方面明顯更快,並且與基於 Python 的分詞器相比提供了額外的對齊方法。
AutoTokenizer如果支援,會自動載入一個快速分詞器。否則,您需要顯式載入快速分詞器。
本節將向您展示如何訓練一個快速分詞器並在 Transformers 中重用它。
要訓練位元組對編碼 (BPE) 分詞器,請建立一個Tokenizer
和BpeTrainer
類,並定義未知標記和特殊標記。
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
trainer = BpeTrainer(special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"])
在Whitespace
上分割標記,以建立不相互重疊的標記。
from tokenizers.pre_tokenizers import Whitespace
tokenizer.pre_tokenizer = Whitespace()
在文字檔案和訓練器上呼叫train
以開始訓練。
files = [...] tokenizer.train(files, trainer)
使用save
將分詞器配置和詞彙表儲存到 JSON 檔案。
tokenizer.save("tokenizer.json")
現在,您可以將分詞器物件傳遞給PreTrainedTokenizerFast中的tokenizer_object
引數,從而在 Transformers 中載入和重用它。
from transformers import PreTrainedTokenizerFast
fast_tokenizer = PreTrainedTokenizerFast(tokenizer_object=tokenizer)
要從其 JSON 檔案載入已儲存的分詞器,請將檔案路徑傳遞給PreTrainedTokenizerFast中的tokenizer_file
引數。
from transformers import PreTrainedTokenizerFast
fast_tokenizer = PreTrainedTokenizerFast(tokenizer_file="tokenizer.json")
tiktoken
tiktoken 是 OpenAI 的一種位元組對編碼 (BPE) 分詞器。它包含幾種分詞方案或編碼,用於文字如何進行分詞。
目前,tiktoken 已經訓練併發布了兩個模型:GPT2 和 Llama3。Transformers 支援帶有 tokenizer.model tiktoken 檔案的模型。tiktoken 檔案會自動轉換為 Transformers 基於 Rust 的 PreTrainedTokenizerFast。
在from_pretrained()中新增subfolder
引數以指定tokenizer.model
tiktoken 檔案的位置。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct", subfolder="original")
建立 tiktoken 分詞器
tiktoken tokenizer.model
檔案不包含關於附加標記或模式字串的資訊。如果這些很重要,請將分詞器轉換為 tokenizer.json
(PreTrainedTokenizerFast 的適當格式)。
使用tiktoken.get_encoding函式生成 tiktoken tokenizer.model
檔案,並使用convert_tiktoken_to_fast將其轉換為tokenizer.json
。
from transformers.integrations.tiktoken import convert_tiktoken_to_fast
from tiktoken import get_encoding
# Load your custom encoding or the one provided by OpenAI
encoding = get_encoding("gpt2")
convert_tiktoken_to_fast(encoding, "config/save/dir")
生成的tokenizer.json
檔案儲存到指定目錄,並使用from_pretrained()載入。
tokenizer = PreTrainedTokenizerFast.from_pretrained("config/save/dir")
預處理
Transformers 模型期望輸入是 PyTorch、TensorFlow 或 NumPy 張量。分詞器的作用是將文字預處理為這些張量。使用return_tensors
引數指定要返回的框架張量型別。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library.", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
將文字轉換為輸入 ID 的分詞過程分為兩步。
在第一步中,透過tokenize()函式將字串文字分割成標記。文字的分割方式取決於分詞演算法。
tokens = tokenizer.tokenize("We are very happy to show you the 🤗 Transformers library")
print(tokens)
['We', '▁are', '▁very', '▁happy', '▁to', '▁show', '▁you', '▁the', '▁🤗', '▁Transformers', '▁library']
Gemma 使用SentencePiece分詞器,它用下劃線_
替換空格。
在分詞器演練場中視覺化不同分詞器的工作方式。
特殊標記
特殊標記為模型提供了關於文字的一些額外資訊。
例如,如果您比較直接將文字傳遞給分詞器和從convert_tokens_to_ids()獲得的標記,您會注意到添加了一些額外的標記。
model_inputs = tokenizer("We are very happy to show you the 🤗 Transformers library.")
[2, 1734, 708, 1508, 4915, 577, 1500, 692, 573, 156808, 128149, 9581]
tokenizer.convert_tokens_to_ids(tokens)
[1734, 708, 1508, 4915, 577, 1500, 692, 573, 156808, 128149, 9581]
當您解碼() ID 時,您會看到字串開頭有<bos>
。這用於向模型指示句子的開頭。
print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))
'<bos>We are very happy to show you the 🤗 Transformers library.'
'We are very happy to show you the 🤗 Transformers library'
並非所有模型都需要特殊標記,但如果需要,分詞器會自動新增它們。
批次分詞
預處理*批次*文字比一次處理一個句子更快、更高效。快速分詞器尤其擅長並行化分詞。
將字串文字列表傳遞給分詞器。
batch_sentences = [
"But what about second breakfast?",
"Don't think he knows about second breakfast, Pip.",
"What about elevensies?",
]
encoded_inputs = tokenizer(batch_sentences, return_tensors="pt")
print(encoded_inputs)
{
'input_ids':
[[2, 1860, 1212, 1105, 2257, 14457, 235336],
[2, 4454, 235303, 235251, 1742, 693, 9242, 1105, 2257, 14457, 235269, 48782, 235265],
[2, 1841, 1105, 29754, 37453, 235336]],
'attention_mask': [[1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]]
}
填充
在填充和截斷指南中瞭解更多填充策略。
在上面的輸出中,input_ids
的長度不同。這是一個問題,因為 Transformers 期望它們的長度相同,以便可以打包成批次。長度不等的序列無法批次處理。
填充會新增一個特殊的*填充標記*,以確保所有序列的長度相同。設定padding=True
會將序列填充到批次中最長序列的長度。
encoded_inputs = tokenizer(batch_sentences, padding=True, return_tensors="pt")
print(encoded_inputs)
分詞器將特殊填充標記0
新增到左側(左填充),因為 Gemma 和通用 LLM 沒有訓練以從填充標記繼續生成。
截斷
在填充和截斷指南中瞭解更多截斷策略。
模型只能處理特定長度的序列。如果嘗試處理超出模型處理能力的序列,它會崩潰。
截斷會從序列中移除標記,以確保它不超過最大長度。設定truncation=True
會將序列截斷到模型接受的最大長度。您還可以使用max_length
引數自行設定最大長度。
encoded_inputs = tokenizer(batch_sentences, max_length=8, truncation=True, return_tensors="pt")
print(encoded_inputs)