You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向bert-base-uncased分词器添加[EOT]类自定义特殊标记?

问题原因

你使用的bert-base-uncased是小写预训练模型,对应的分词器默认会将所有输入字符转为小写后再做分词。你通过add_tokens添加的是大写的[EOT]标记,但实际输入文本里的[EOT]会被先转成[eot],和你添加的标记无法匹配,就会被拆分为[、e、##ot、]多个子词。

正确添加自定义特殊标记的方法

不要用普通的add_tokens方法添加特殊标记,改用add_special_tokens方法,该方法添加的标记会被分词器优先匹配,不会被做大小写转换、子词拆分处理,修改后的代码如下:

from transformers import AutoTokenizer, AutoModelForSequenceClassification
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")

# 新增特殊标记
special_tokens_dict = {'additional_special_tokens': ['[EOT]']}
num_added_toks = tokenizer.add_special_tokens(special_tokens_dict)
# 调整模型嵌入层尺寸
model.resize_token_embeddings(len(tokenizer))

text_to_encode = '''QUERY: I want to ask a question. [EOT]
ANSWER: Sure, ask away. [EOT]
QUERY: How is the weather today? [EOT]
ANSWER: It is nice and sunny. [EOT]
QUERY: Okay, nice to know. [EOT]
ANSWER: Would you like to know anything else?'''

enc = tokenizer.encode_plus(
  text_to_encode,
  max_length=128,
  add_special_tokens=True,
  return_token_type_ids=False,
  return_attention_mask=False,
)['input_ids']

print(tokenizer.convert_ids_to_tokens(enc))

运行后就可以看到[EOT]会被识别为独立标记,不会被拆分。

是否可以用[SEP]替代自定义标记

更推荐直接用原生[SEP]标记分隔对话轮次,理由如下:

  • [SEP]在BERT预训练阶段就被用来分隔不同文本片段,本身就具备“文本边界”的语义,不需要额外训练就能发挥作用,在小数据集上效果远好于随机初始化的自定义特殊标记
  • 不需要修改分词器和模型嵌入层,实现更简单,不存在适配问题
  • 这也是对话分类、对话状态追踪等常见对话任务的通用处理方式,工业界和学术界都有大量实践验证

只有当你的数据集规模足够大(百万级以上对话样本),且你需要明确区分“单轮对话结束”和“整段对话结束”两种边界时,才需要额外新增自定义[EOT]标记。


内容的提问来源于stack exchange,提问作者sid8491

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:09:03