我们在提示学习或其它方式中经常需要对模板中的占位符,如 This is a demon, [X], it was a [MASK] 中的[X]进行替换并需要在随后的处理中取出它对应的向量。
此时,我们需要知道[X]所在的postion, 即偏移才可以正常处理。在transformers中,这个位置 真的不好推测 ,需要用transformers的tokenizer api进行处理。
怎么办?看代码:
temp 为模板,比如 it was a [X] news. labels是要替换的具体词。
def get_vector(args,tokenizer,model,temp,labels,method):
model.eval()
out=None
for label in labels:
tokens_temp=tokenizer.tokenize(label)# 获得label的token (不严格叫分词)
tokens=tokenizer.tokenize(temp) # 模板的分词
x_pos=tokens.index(PLACE_HODER) 得到place_hoder 即[X]的位置 ,注意 ,这个place_hoder需要事先 add_additional_tokens 进tokenizer, 否则不能被当作一个整体 对待。
mask_pos=[x_pos,x_pos+len(tokens_temp)] #找到要替换内容 的首尾位置,为了简化 后续切片操作,end 位置会多1
new_token=tokens[:x_pos]+label_token+tokens[x_pos+1:] #将替换内容放进模板中,变成实现的内容
# 注意 ,以下为了安全起见,没有直接 对new_tokens join成文本,而是用以下两个api处理。
text_ids=tokenizer.convert_tokens_to_ids(new_token)
text= tokenizer.decode(text_ids) # simplify the processing of replace tokens.
#下面就是对文本进行转换,得到mask之类了,避免 自己去拼mask,type_ids等
ids=tokenizer.encode_plus(text,return_offsets_mapping=True)
input_ids=torch.tensor(ids["input_ids"]).to(args.device)
input_type_id=torch.tensor(ids["token_type_ids"]).to(args.device)
input_mask=torch.tensor(ids["attention_mask"]).to(args.device)
offset_mapping=ids["offset_mapping"]
for item in offset_mapping:
if item[0] == mask_pos[0]:
mask_pos[0]+=item[1]-item[0]
mask_pos[1]+=item[1]-item[0]
break
out=model(input_ids,input_type_id,input_mask,mask_pos,method)
return out