大模型日常:ValueError: Asking to pad but the tokenizer does not have a padding token.

问题背景

from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("Llama-3.2") # 替换实际模型路径
model = AutoModelForCausalLM.from_pretrained("Llama-3.2") # 替换实际模型路径

text = "禁止为出售、购买、利用野生动物或者禁止使用的猎捕工具发布广告。将这段话生成一个关键词"

#使用分词器将文本和前缀转换为输入ID和注意力掩码

input_ids = tokenizer.encode(text, return_tensors="pt", padding=True)
attention_mask = input_ids != tokenizer.pad_token_id

# 使用模型生成摘要输出ID

output_ids = model.generate(input_ids, max_new_tokens=256, attention_mask=attention_mask, pad_token_id=tokenizer.pad_token_id)

# 使用分词器将摘要输出ID转换为文本

summary = tokenizer.decode(output_ids[0], skip_special_tokens=True)

执行上述代码将报错:

ValueError: Asking to pad but the tokenizer does not have a padding token. Please select a token to use as `pad_token` `(tokenizer.pad_token = tokenizer.eos_token e.g.)` or add a new pad token via `tokenizer.add_special_tokens({'pad_token': '[PAD]'})`

问题分析

报错提示的比较明显了意思就是我们想在分词器进行填充,但是我们没有告诉分词器用什么填充。甚至将如何操作已经提示在报错中了。

在自然语言处理(NLP)任务中,我们经常需要对一批输入进行处理,例如文本分类、情感分析、机器翻译等。为了便于模型的处理,我们通常需要保证每个输入具有相同的长度。然而,实际的输入文本长度可能不一致。因此,为了使输入具有固定长度,我们会选择一种方式对输入进行填充。

在使用PyTorch TRANSFORMERS库时,我们通常会首先使用tokenizer对输入进行分词。然而,有些情况下,我们希望对输入进行填充,但是tokenizer并没有提供专门的填充标记。

第一种方案:tokenizer.pad_token = tokenizer.eos_token

from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("Llama-3.2") # 替换实际模型路径
model = AutoModelForCausalLM.from_pretrained("Llama-3.2") # 替换实际模型路径

text = "禁止为出售、购买、利用野生动物或者禁止使用的猎捕工具发布广告。将这段话生成一个关键词"

# 在输入文本到分词器前执行该行代码
tokenizer.pad_token = tokenizer.eos_token    

#使用分词器将文本和前缀转换为输入ID和注意力掩码

input_ids = tokenizer.encode(text, return_tensors="pt", padding=True)
attention_mask = input_ids != tokenizer.pad_token_id

# 使用模型生成摘要输出ID

output_ids = model.generate(input_ids, max_new_tokens=256, attention_mask=attention_mask, pad_token_id=tokenizer.pad_token_id)

# 使用分词器将摘要输出ID转换为文本

summary = tokenizer.decode(output_ids[0], skip_special_tokens=True)

tokenizer.pad_token = tokenizer.eos_token 这行代码的意思是将分词器(tokenizer)的填充令牌(pad token)设置为等于它的结束序列令牌(eos token)。

通过设置tokenizer.pad_token = tokenizer.eos_token,实际上是在告诉分词器,当需要对序列进行填充时,使用EOS令牌作为填充令牌。这在某些情况下可能是有用的,比如希望模型在处理填充部分时能够识别出序列的实际结束。

**第二种方案:**add a new pad token via tokenizer.add_special_tokens({'pad_token': '[PAD]'})

相当于使用了默认的特殊字符来充当填充物

'[PAD]' 是自定义的填充符号,在这段代码中被定义为 pad_token。这个填充符号通常是一个字符串,可以是任意定义的标记符号,但在很多情况下,像 [PAD] 这样的符号是一个通用的约定。

  • [PAD]:用于表示被填充的 token,它并不代表有意义的语言内容,而仅仅用于让模型在处理不同长度的输入时,忽略这些填充的部分。

添加的特殊字符有什么用?

在问答训练时会添加特殊字符框架协同训练,经过微调模型就知道这样的框架是在做问答,在推理时,只要将文本加入特殊字符组成的问答框架就可以进行回答。

同时,使用特殊字符,也能帮助模型训练时区分每一个句子间的层次关系。

总结

为什么有时候分词器会要求设置tokenizer.pad_token = tokenizer.eos_token?

这样处理往往是针对batch操作的,generate是允许batch处理,因此无论如何必须先设置好pad_token

pad_token 的作用

pad_token 是在自然语言处理任务中用于填充(padding)输入序列的特殊符号。在许多情况下,模型的输入需要具有相同的长度,因此需要对较短的序列进行填充。pad_token 的作用就是在输入序列不足时,补充这个填充符号以达到相同长度,从而使模型能够并行处理多个输入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值