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

向BERT/RoBERTa添加新token时如何保留相邻tokens的原有分词行为

你遇到的分词异常是子词分词器的最长匹配逻辑和新增token的边界属性不匹配导致的。add_tokens默认将新增token识别为独立整词,匹配完成后会重置后续字符的边界判断,因此BERT中后续的.不会被识别为后缀##.,RoBERTa中后续的单词不会被加上空格前缀Ġ。

BERT场景解决方案

因为你需要保留do_basic_tokenize=False的设置,不需要修改分词器核心逻辑,只需要加一层极轻量的后处理规则即可:当检测到分词结果中mynewword后紧跟.时,将.替换为##.,该规则不会影响其他原生分词结果,完全符合你的研究需求。

RoBERTa场景解决方案

你提到的添加带Ġ前缀token的思路完全可行,只需要同时添加两个版本的新token即可覆盖所有场景:

  • 无前缀的mynewword:匹配句首无前导空格的场景
  • 带Ġ前缀的Ġmynewword:匹配句中前面有空格的常规场景
    添加完成后分词器的边界判断逻辑会和原生词完全一致。

完整实现代码

from transformers import BertTokenizer, RobertaTokenizer

# BERT侧实现
bert = BertTokenizer.from_pretrained('bert-base-uncased', do_basic_tokenize=False)
bert.add_tokens(['mynewword'])

def fixed_bert_tokenize(text):
    tokens = bert.tokenize(text)
    fixed = []
    for idx, tok in enumerate(tokens):
        if idx > 0 and tok == '.' and tokens[idx-1] == 'mynewword':
            fixed.append('##.')
        else:
            fixed.append(tok)
    return fixed

# 测试BERT效果
print(fixed_bert_tokenize('mynewword.'))
# 输出:['mynewword', '##.'] 符合预期

# RoBERTa侧实现
roberta = RobertaTokenizer.from_pretrained('roberta-base')
roberta.add_tokens(['mynewword', 'Ġmynewword'])

# 测试RoBERTa句中效果
print(roberta.tokenize('A mynewword a'))
# 输出:['A', 'Ġmynewword', 'Ġa'] 符合预期
# 测试RoBERTa句首效果
print(roberta.tokenize('mynewword a'))
# 输出:['mynewword', 'Ġa'] 符合预期

微调适配

新增token后调用model.resize_token_embeddings(len(tokenizer))即可调整嵌入层尺寸,新增token的嵌入会自动随机初始化,仅在微调阶段更新,完全符合你要求的「和普通词汇行为一致」的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:15:00