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

如何阻止Tokenizer进一步拆分单词?及合并带##子词的高效方法

问题描述

使用Hugging Face Transformers的AutoTokenizer调用obi/deid_bert_i2b2模型分词时,即使设置do_basic_tokenize=False,部分单词仍会被拆分。执行代码如下:

from transformers import AutoTokenizer
text = "Patient John Doe visited the hospital on 01/05/2023 with complaints of chest pain."
tokenizer = AutoTokenizer.from_pretrained("obi/deid_bert_i2b2", tokenizer_args={"do_basic_tokenize": False})
tokens = tokenizer.tokenize(text, truncation=True, padding=True, return_tensors="pt")
model = AutoModelForTokenClassification.from_pretrained("obi/deid_bert_i2b2")
tokens

得到的分词结果:

['Pat',
 '##ient',
 'John',
 'Do',
 '##e',
 'visited',
 'the',
 'hospital',
 'on',
 '01',
 '/',
 '05',
 '/',
 '202',
 '##3',
 'with',
 'complaints',
 'of',
 'chest',
 'pain',
 '.']

疑问:

  1. 这种拆分是模型的固有特性吗?
  2. 能否通过配置阻止单词被拆分?
  3. 是否存在高效的方法或工具可将带##的子词与前后词合并?
解决方案与解释

1. 拆分是模型的固有特性吗?

是的,这种拆分是BERT类模型基于WordPiece分词算法的固有特性。obi/deid_bert_i2b2属于BERT衍生模型,预训练阶段就用WordPiece分词构建词汇表,若词汇表中未收录Patient、Doe这类完整单词,分词时就会自动拆分为子词。

do_basic_tokenize=False仅关闭了基础分词(比如空格切分、标点分离这类初步处理),但不会跳过WordPiece的子词拆分逻辑——这是BERT类分词器的核心步骤,和基础分词是独立的两个阶段。

2. 能否通过配置阻止单词被拆分?

很难完全阻止,因为WordPiece的拆分逻辑和模型预训练用的词汇表强绑定:如果单词不在词汇表中,就一定会被拆分为子词。不过可以尝试两种方式:

  • 添加自定义词汇到分词器:把需要保留完整的单词(比如Patient、Doe)添加到分词器的词汇表中,再调整模型的词嵌入层。但这种方式可能影响模型推理效果,因为模型预训练时未见过这些完整单词的嵌入。
    示例代码:
    tokenizer.add_tokens(["Patient", "Doe"])
    model.resize_token_embeddings(len(tokenizer))
    
  • 更换非子词类分词器:换用基于空格分词的模型(如部分规则分词器),但这意味着无法继续使用obi/deid_bert_i2b2。

3. 高效合并带##的子词

有两种高效方式:

手动遍历合并

直接遍历分词结果,手动拼接子词,逻辑清晰且无额外依赖:

def merge_subwords(tokens):
    merged = []
    current_word = ""
    for token in tokens:
        if token.startswith("##"):
            current_word += token[2:]
        else:
            if current_word:
                merged.append(current_word)
                current_word = ""
            merged.append(token)
    if current_word:
        merged.append(current_word)
    return merged

# 调用示例
merged_tokens = merge_subwords(tokens)
# 输出:['Patient', 'John', 'Doe', 'visited', 'the', 'hospital', 'on', '01', '/', '05', '/', '2023', 'with', 'complaints', 'of', 'chest', 'pain', '.']

使用Tokenizer内置方法

Hugging Face的Tokenizer自带convert_tokens_to_string方法,可自动处理子词合并:

merged_text = tokenizer.convert_tokens_to_string(tokens)
# 输出:"Patient John Doe visited the hospital on 01 / 05 / 2023 with complaints of chest pain."

该方法会自动合并##子词,但会给标点、符号添加空格,若需要严格还原原始格式,可在合并后做微调处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:22:08