Pytorch tokenizer使用及补充vocab词汇表
我們現在需要對一句話做分詞,然后轉換成index,作為Bert的輸入
tokenizer = BertTokenizer.from_pretrained(config.PRE_TRAINED_MODEL_NAME) text = '天空下著暴雨,o2正在給c1穿雨衣,他自己卻只穿著單薄的軍裝,完全暴露在大雨之中。角色: o2' input_ids =tokenizer.encode(text) output = tokenizer.decode(input_ids)
輸出的output長這樣,長度45:
'[CLS] 天 空 下 著 暴 雨 , o2 正 在 給 c1 穿 雨 衣 , 他 自 己 卻 只 穿 著 單 薄 的 軍 裝 , 完 全 暴 露 在 大 雨 之 中 。 角 色 : o2 [SEP]'
但是input_ids的長度是47,??難道不是一一對應
確實不是,一一與詞匯表對比,發現 'o2' 對應了兩個 id,'o'對應一個, '##2'對應一個(在bert的詞匯表里'##x'通常表示以'x'為后綴)
神奇的是 'c1' 詞匯表中是有的
也就是說,為了讓token和id一一對應起來,我們需要將不存在的token添加到vocab中,網上查到兩種方法:
1. 利用前100里的[unused]
https://github.com/google-research/bert/issues/396
將[unused]換成自己想要添加的
具體有多少個[unused]要看自己的預訓練模型,可能100個,可能1000個,但都有限
2. 利用transformers庫里有個 add_tokens 方法
https://github.com/huggingface/transformers/issues/1413
https://blog.csdn.net/qq_23944915/article/details/102781463
import torch
from transformers import BertTokenizer, BertModel
import ipdb
import config
tokenizer = BertTokenizer.from_pretrained(config.PRE_TRAINED_MODEL_NAME)
model = BertModel.from_pretrained(config.PRE_TRAINED_MODEL_NAME)
x = model.embeddings.word_embeddings.weight[-1, :]
print(len(tokenizer)) # 28996
tokenizer.add_tokens(["NEW_TOKEN"])
print(len(tokenizer)) # 28997
model.resize_token_embeddings(len(tokenizer))
# The new vector is added at the end of the embedding matrix
print(model.embeddings.word_embeddings.weight[-1, :])
# Randomly generated matrix
with torch.no_grad():
model.embeddings.word_embeddings.weight[-1, :] = torch.zeros([model.config.hidden_size])
print(model.embeddings.word_embeddings.weight[-1, :])
# outputs a vector of zeros of shape [768]
y = model.embeddings.word_embeddings.weight[-2, :]
print(x == y) # 會改變原來embedding weight 嗎? 不會
ipdb.set_trace()
這種方法,因為是添加token,需要修改embedding matrix
不知道它這個resize matrix會不會打擾預訓練的embeddings? 經測,不會
感覺兩種都行,待測
也有可能都沒必要,Bert可能能夠學會新的組合詞匯
個性簽名:時間會解決一切
總結
以上是生活随笔為你收集整理的Pytorch tokenizer使用及补充vocab词汇表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SAP Fiori smart temp
- 下一篇: CDS view里case - when