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

如何让LineByLineTextDataset按词而非字符切分文本语料

问题解决方案

核心根因

你代码中的自定义分词器被默认加载的RobertaTokenizerFast覆盖,导致实际生效的是Roberta默认的子词拆分逻辑,而非你实现的WordLevel空格分词规则。同时需确认词表中已包含你需要保留的完整数字字符串条目。

具体修正步骤

  • 第一步:删除覆盖自定义分词器的代码
    你已经实现了符合要求的WordLevelBertTokenizer,不需要再调用RobertaTokenizerFast.from_pretrained重新加载,直接使用自定义分词器即可。如果需要使用Fast接口的特性,可直接将自定义的分词器转换为Fast类型,无需重复加载。
  • 第二步:补全词表条目
    确认你的vocab.json中已添加所有需要作为完整token处理的数字字符串(比如"1234"),WordLevel分词器只会将词表中存在的完整字符串映射为单个id,未收录的内容才会触发拆分或返回。
  • 第三步:适配数据集读取逻辑
    LineByLineTextDataset默认读取原始文本字符串后直接传入分词器,不会提前做分词处理。如果你的语料已经用空格分隔好了所有token,可直接使用自定义分词器替换原代码中的分词器即可;如果需要自行实现拆分,推荐自行写数据集加载逻辑,按行读取后先按空格拆分,再传入分词器并指定is_split_into_words=True参数。

修正后核心代码示例

from tokenizers.implementations import BaseTokenizer
from tokenizers import Tokenizer, pre_tokenizers
from tokenizers.models import WordLevel
from tokenizers.processors import BertProcessing
from transformers import RobertaConfig, RobertaForMaskedLM, LineByLineTextDataset

class WordLevelBertTokenizer(BaseTokenizer):
    """ WordLevelBertTokenizer
    代表适用于BERT的简单词级别分词器
    """
    def __init__(self, vocab_file: str):
        tokenizer = Tokenizer(WordLevel.from_file(vocab_file))
        tokenizer.pre_tokenizer = pre_tokenizers.WhitespaceSplit()
        
        sep_token_id = tokenizer.token_to_id("</s>")
        if sep_token_id is None:
            raise TypeError("sep_token not found in the vocabulary")
        cls_token_id = tokenizer.token_to_id("<s>")
        if cls_token_id is None:
            raise TypeError("cls_token not found in the vocabulary")

        tokenizer.post_processor = BertProcessing(
            ("</s>", sep_token_id), ("<s>", cls_token_id)
        )

        parameters = {
            "model": "WordLevel",
            "sep_token": "</s>",
            "cls_token": "<s>",
            "pad_token": "<pad>",
            "mask_token": "<mask>",
        }
        super().__init__(tokenizer, parameters)

# 直接使用自定义分词器,不要覆盖
tokenizer = WordLevelBertTokenizer("./wordlevel/vocab.json")

config = RobertaConfig(
    vocab_size=tokenizer.get_vocab_size(),
    max_position_embeddings=514, # 注意该参数是最大序列长度,不要误填词表大小,默认514即可
    num_attention_heads=12,
    num_hidden_layers=6,
    type_vocab_size=1,
)

model = RobertaForMaskedLM(config=config)
print(f'Num of model parameters = {model.num_parameters()}')

# 直接传入自定义分词器构建数据集
dataset = LineByLineTextDataset(
    tokenizer=tokenizer,
    file_path="./optiver.txt",
    block_size=128,
)

测试验证代码

# 假设词表中已存在"1234"条目
test = ["1234"]
print(tokenizer.encode(test, is_split_into_words=True))
# 预期输出会包含"1234"对应的单个id,而非拆分后的多个数字id

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:54:02