文章

把字符级语言模型升级为中文分词版本:从数据到训练的完整改造

详解如何将字符级 GPT 训练流程迁移到中文分词 token 级方案,覆盖语料清洗、词表设计、数据管线与推理策略。

把字符级语言模型升级为中文分词版本:从数据到训练的完整改造

在英文名字数据集上做字符级建模,是一个非常好的入门起点。

但只要你开始处理中文,很快就会发现:

  • 字符级能跑,但上下文表达能力有限;
  • 训练步数变多,语义边界学习困难;
  • 输出常出现“字是对的,句子不顺”。

这篇文章我们就做一件事:

把字符级模型,升级为中文分词 token 级模型。


1. 先统一术语:字符级 vs 分词级

字符级(char-level)

  • 输入单位是单个汉字或符号;
  • 词表通常较小;
  • 序列长度较长;
  • 对“词边界”没有显式建模。

分词级(token-level)

  • 输入单位是词、词片段(subword)或 BPE 合并单元;
  • 词表更大;
  • 序列更短;
  • 更容易捕获稳定语义。

在中文任务里,推荐优先考虑 subword tokenizer(如 SentencePiece/BPE),而不是传统“纯词典分词”。

原因是它能平衡:

  • 未登录词处理能力;
  • 词表大小;
  • 训练稳定性。

2. 第一步:准备中文语料并清洗

最低限度要做三类清洗:

  1. 编码统一:全部转 UTF-8;
  2. 格式统一:换行、空白符、全角/半角规则;
  3. 噪声过滤:去掉明显乱码、超长重复片段、异常符号串。

建议额外保留几个特殊 token:

  • <pad>:批处理补齐;
  • <bos>:序列开始;
  • <eos>:序列结束;
  • <unk>:未知词。

如果你之后打算做指令微调,也可以预留 <system><user><assistant> 等角色标记。


3. 第二步:训练或加载中文 tokenizer

方案 A:直接用现成 tokenizer(最快)

优点:

  • 上手快;
  • 与开源模型生态兼容;
  • 减少 tokenizer 训练成本。

缺点:

  • 不一定贴合你的垂直领域语料。

方案 B:自己训练 tokenizer(更可控)

关键参数:

  • vocab_size:例如 8k / 16k / 32k;
  • model_type:BPE 或 Unigram;
  • character_coverage:中文通常接近 1.0。

实践建议:

  • 小数据集先试 8k;
  • 中等规模可试 16k;
  • 词表过大可能导致稀疏与训练不稳定。

4. 第三步:重写数据管线(核心改造点)

字符级版本常见逻辑是:

  • 按字符映射成 id;
  • 直接截取长度 T 的片段训练。

分词级版本要改成:

  1. 原文 -> tokenizer 编码得到 id 序列;
  2. block_size 切块;
  3. 构造 (x, y),其中 yx 右移一位;
  4. DataLoader 批量采样。

伪代码:

1
2
3
4
5
def build_sample(token_ids, block_size):
    i = torch.randint(0, len(token_ids) - block_size - 1, (1,)).item()
    x = torch.tensor(token_ids[i : i + block_size], dtype=torch.long)
    y = torch.tensor(token_ids[i + 1 : i + 1 + block_size], dtype=torch.long)
    return x, y

注意:中文分词后,vocab_size 会显著变大,你的 embedding 和 lm head 参数量也会随之上升。


5. 第四步:调整模型超参数,而不是照搬字符级配置

从字符级迁移到中文分词后,至少要重新审视:

  • vocab_size(显著增大);
  • block_size(可适当减小,因为每个 token 承载更多语义);
  • n_embd(通常要提升);
  • batch size(受显存影响)。

一个常见起步配置(仅供参考):

  • vocab_size = 16000
  • block_size = 256
  • n_layer = 6
  • n_head = 8
  • n_embd = 512

你可以先保证“能稳定收敛”,再迭代模型规模。


6. 第五步:训练阶段关注三个新指标

除了 loss,中文分词模型建议额外观察:

  1. 平均 token 长度:衡量分词粒度是否合理;
  2. UNK 占比:过高说明词表覆盖不足;
  3. 重复片段率:判断模型是否陷入循环生成。

如果出现“loss 降了但质量没提升”,优先排查 tokenizer 与语料清洗,而不是先怀疑模型结构。


7. 推理阶段:中文生成的实用技巧

字符级时代很多人靠 temperature 硬调,分词级后建议组合使用:

  • temperature(控制随机性);
  • top-k(限制候选数量);
  • top-p(核采样);
  • repetition penalty(抑制复读)。

示例策略:

  • 知识问答:temperature=0.7, top_p=0.9
  • 创意写作:temperature=0.9, top_p=0.95
  • 强约束输出:temperature=0.2, top_k=20

8. 迁移过程中最常见的 6 个坑

  1. 特殊 token 漏配:训练有 <bos>,推理忘了加。
  2. decode 空格处理错误:中英文混排时空格策略不一致。
  3. tokenizer 版本漂移:训练和推理加载了不同词表文件。
  4. 截断策略不一致:训练时前截断,推理时后截断。
  5. padding mask 漏传:批量推理时 attention 读到 padding。
  6. 评估样本偏差:只看短句,忽略长上下文质量。

9. 一套可执行的迁移 checklist

你可以逐项打勾:

  • 语料 UTF-8 + 清洗规则固定;
  • tokenizer 词表与 special tokens 固化;
  • 训练/验证/推理共用同一 tokenizer artifact;
  • 数据管线由字符切分改为 token 切分;
  • 模型超参数按 token 级重新设定;
  • 采样参数按中文场景调优;
  • 输出质量做人工抽检 + 自动指标记录。

10. 小结

把字符级模型改成中文分词版本,本质是一次“输入表示升级”。

重点并不在某个神奇模型技巧,而在三件事:

  • tokenizer 设计是否合理;
  • 数据管线是否一致可复现;
  • 训练与推理是否使用同一套约定。

当这三件事做对了,你会明显感受到中文输出质量的跃升。

下一篇我们继续:如何用可视化工具观察 attention 头到底在关注什么

本文由作者按照 CC BY 4.0 进行授权