上一篇講了「分詞」的概念,眾所周知,概念講完就是要投入實戰!
Tokenizer
是 Hugging Face 貼心準備的工具包,歸屬在 Transformers 中,事不宜遲我們就直接從實作中學吧
AutoTokenizer
from transformers import AutoTokenizer我相信第一、三行應該不用多解釋了~我們就直接從第五行開始!
string = "All you need in this life is ignorance and confidence, and then success is sure."
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
token = tokenizer(string, padding=True, truncation=True)
print(token)
# {'input_ids': [101, 1398, 1128, 1444, 1107, 1142, 1297, 1110, 21326, 1105, 6595, 117, 1105, 1173, 2244, 1110, 1612, 119, 102],
# 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
- 第五行:
AutoTokenizer.from_pretrained()
會自動選用與模型相對應的 tokenizer 並從 Hugging Face 模型庫下載(這裡用的是 WordPiece tokenizer),括號中填入模型名稱(bert-base-cased 是會區分大小寫的 BERT 模型) - 第六行:用剛剛選的 tokenizer 進行分詞
padding=True
:用 0 補齊到預設批次中最大輸入的長度(這裡的範例是單句,會保留原長度,不會補 0),請看底下*註一範例truncation=True
:若字串超過模型最大長度(BERT 是 512),則會截斷(本範例其實用不到)
- 第八行:執行結果會輸出一個字典,主要由三個部分組成:
- input_ids:將句子中的每個子詞轉換成 BERT 詞彙表中的對應編號,眼尖的朋友會發現,頭跟尾分別是 101 跟 102,這些就是所謂的「Special Token」*我有將這部分單獨整理在下面
- token_type_ids:區分句子屬於哪一句,通常用於問答、連續對話,BERT 模型在預訓練過程中就利用了兩個句子來進行「下一句預測(Next Sentence Prediction, NSP)」的訓練,所以預設輸出 token_type_ids。單句的話一律都顯示 0
- attention_mask:1 表示為有效 token;0 表示 padding(本範例沒有 padding 所以都是 1)
- 第五行:

執行結果

Special Token
- Token-Token ID :說明
- [PAD]-0:就是上面提到的 padding。模型會忽略這些(
attention_mask = 0
) - [UNK]-100:Unknown Token,詞彙表中找不到的字會顯示
- [CLS]-101:句子開頭的 special token,用來提取整句表示(classification 任務)
- [SEP]-102:分隔句子 A 與句子 B;代表一單句的結尾
- [MASK]-103:在 BERT 預訓練階段用於遮蔽字詞以進行預測(Masked Language Modeling)
*註一範例
from transformers import AutoTokenizer
str1 = "I have no idea."
str2 = ["I have no idea.", "I do not have any idea."]
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
token1 = tokenizer(str1, padding=True, truncation=True)
token2 = tokenizer(str2, padding=True, truncation=True)
print(token1) # {'input_ids': [101, 146, 1138, 1185, 1911, 119, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1]}
print(token2) # {'input_ids': [[101, 146, 1138, 1185, 1911, 119, 102, 0, 0], [101, 146, 1202, 1136, 1138, 1251, 1911, 119, 102]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1]]}
第十行 token2 的 input_ids
中,第一個 list 的後面多了兩個 0,而剛好跟後面那個 list 一樣是 9 個值,沒錯,padding=True
就是用 0 把長短不一的輸入變得一樣長。看到後面輸出的 attention_mask 也是有補 0,代表那東西不需要理他
而這樣你就知道為什麼 token1 不需要補 0 了,因為他壓根就只有一句:)
如果想要試試中文,可以用 bert-base-chinese 這個模型喔~
喜歡我的內容也請幫我按個讚喔~非常感謝🥹