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可能能夠學會新的組合詞匯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM