bert-base-chinese:中文 BERT 原始模型详解

一句话理解

bert-base-chinese 是 Google 2018 年发布的中文预训练 BERT 模型,是我们所有微调工作的"起点"。


基本信息

项目 内容
名称 bert-base-chinese
发布方 Google(2018 年 11 月)
论文 BERT: Pre-training of Deep Bidirectional Transformers
HuggingFace google-bert/bert-base-chinese
GitHub google-research/bert
许可证 Apache 2.0(可商用)

模型架构

bert-base-chinese = BERT-Base 架构 + 中文词表

参数规模:110M(1.1 亿)
文件大小:~400MB(PyTorch 格式)
参数 值 含义
L(层数) 12 Transformer 编码器层数
H(隐藏维度) 768 每个 token 的向量维度
A(注意力头数) 12 每层 12 个注意力头
参数量 110M 1.1 亿个可训练参数
最大序列长度 512 最多处理 512 个 token
词表大小 21,128 词表中包含 21,128 个词条

与 BERT-Large 对比:

对比 BERT-Base(我们用的) BERT-Large
层数 12 24
隐藏维度 768 1024
注意力头 12 16
参数量 110M 340M
推理速度 快 ✅ 慢
端侧部署 可行 ✅ 困难

💡 BERT-Base 的 110M 参数在端侧(香橙派、笔记本)可流畅运行,是性价比最优的选择。


词表(Vocabulary)

词表大小:21,128 个词条

词表组成:
├── 中文字(主体)     → "海": 3330, "洋": 3982, "监": 4567
├── 英文单词           → "chicago": 10268, "model": 9264
├── 日文假名           → "しの": 10270
├── 韩文               → 也有少量
├── emoji              → "##❤": 10269, "##😎": 21127
├── 数字/符号          → "001": 9263
├── 子词(##前缀)     → "##ing": 8124, "##的": 5678
└── 特殊标记(5 个)   → [PAD]=0, [UNK]=100, [CLS]=101, [SEP]=102, [MASK]=103

为什么中文模型里有英文和日文?

bert-base-chinese 继承自 BERT 原始词表:
  Google 的 WordPiece 算法从多语言语料中统计生成
  → 中文约 ~21,000 字 + 英文约 ~30,000 词 + 其他语言碎片
  → bert-base-chinese 保留了完整词表,只是训练数据以中文为主

所以:
  词表 = 多语言(继承自原始 BERT)
  能力 = 中文最强,英文能用,日文/韩文勉强

## 前缀:子词延续标记

"chicago"    → 完整词,词表里有,直接匹配
"##❤"        → ## 表示"子词延续",不能单独出现
               比如 "I❤you" → ["I", "##❤", "you"]
"##ing"      → "playing" → ["play", "##ing"]

特殊标记(5 个)

ID 标记 作用
0 [PAD] 填充(短句子补到固定长度)
100 [UNK] 未知字(词表里没有的字)
101 [CLS] 句子开头(其输出向量 = 整句语义摘要)
102 [SEP] 句子结尾
103 [MASK] 遮盖(预训练时随机遮盖,让模型猜)

分词方式

中文:逐字切分(Character-based)

bert-base-chinese 对中文采用"逐字切分"策略:

输入:"海洋监测技术"
分词:["海", "洋", "监", "测", "技", "术"]
ID:  [3330, 3982, 4567, 5892, 4123, 6789]

每个中文字 = 1 个 token

为什么不按"词"切分?

中文分词本身就是个难题:
  "南京市长江大桥" → "南京市/长江/大桥" 还是 "南京/市长/江大桥"?

BERT 的策略:不纠结,逐字切
  → 简单、不会分错
  → 靠 Transformer 的注意力机制自己学会"词"的概念
  → 虽然 token 数多了一点,但效果好

英文/其他语言:WordPiece 子词切分

输入:"playing games"
分词:["play", "##ing", "games"]
       ↑完整词  ↑子词延续  ↑完整词

WordPiece 算法:
  从语料中统计最优的子词切分方式
  常见词 → 完整词(play)
  罕见词 → 拆成子词(un + ##happy → ["un", "##happ", "##y"])
  未知词 → [UNK]

完整分词流程

用户输入:"海洋监测"
    ↓
① Normalizer(预处理)
   清理文本,中文字前后加空格 → " 海 洋 监 测 "
    ↓
② Pre-tokenizer(预切分)
   按空格切分 → ["海", "洋", "监", "测"]
    ↓
③ WordPiece(查词表)
   每个字查词表 → [3330, 3982, 4567, 5892]
    ↓
④ Post-processor(加特殊标记)
   加 [CLS] 和 [SEP] → [101, 3330, 3982, 4567, 5892, 102]
    ↓
⑤ Padding(填充到固定长度)
   补 [PAD] 到 64 → [101, 3330, ..., 102, 0, 0, 0, ...]
    ↓
最终输出:input_ids(64 个数字)→ 送入模型

预训练数据

训练语料

bert-base-chinese 的预训练数据:
├── 中文 Wikipedia(维基百科中文版)  ← 主要来源
├── 其他公开中文语料
└── 总计:约数十亿中文字符

训练环境:
  4-16 块 Cloud TPU,训练数天
  (一次性成本,之后所有人直接用)

预训练的两个任务

任务 1:掩码语言模型(Masked Language Model, MLM)

随机遮盖 15% 的字,让模型猜被遮住的字:

输入:海 洋 [MASK] 测 技术
目标:海 洋 监 测 技术

→ 模型学会了:根据上下文理解每个字的含义
→ 这就是"双向理解"的来源

任务 2:下一句预测(Next Sentence Prediction, NSP)

给模型两句话,判断是否是连续的:

句子A:海洋监测是重要的技术手段。
句子B:它可以帮助科学家了解海流变化。
标签:IsNext(✅ 是连续的)

句子A:海洋监测是重要的技术手段。
句子B:今天天气真不错。
标签:NotNext(❌ 不连续)

→ 模型学会了:理解两句话之间的关系

预训练 vs 微调

对比 预训练(Google 做的) 微调(我们做的)
数据 数十亿字(维基百科) 680 条问答数据
时间 数天(TPU 集群) 几分钟(Colab GPU)
成本 极高(几万美元) 几乎为 0(Colab 免费)
目的 学习通用语言能力 学习特定任务(分类)
谁做的 Google 我们

类比:

预训练 = 从小学到大学(学通用知识,时间长,成本高)
微调   = 入职培训(学公司特定业务,时间短,成本低)

模型文件结构

HuggingFace 格式(原始)

bert-base-chinese/
├── config.json              ← 模型架构配置(层数、维度等)
├── model.safetensors        ← 模型权重(~400MB,PyTorch 格式)
├── tokenizer.json           ← 分词规则表(21,128 词条,~21,000 行)
├── tokenizer_config.json    ← 分词器配置(23 行)
└── vocab.txt                ← 词表文件(纯文本,每行一个词)

我们微调 + 转换后的格式(ONNX)

output_onnx/
├── model.onnx               ← 计算图 + 权重(ONNX 格式)
├── model.onnx.data          ← 外置权重数据
├── tokenizer.json           ← 分词规则(继承自 bert-base-chinese)
├── tokenizer_config.json    ← 分词配置(继承自 bert-base-chinese)
└── categories.json          ← 我们新增:类别 → 预设答案查找表

在项目中的角色

bert-base-chinese(原始模型)
    ↓ Colab 微调(680 条问答数据,100 个类别)
    ↓ 变成"懂海小星业务的分类器"
    ↓ 导出 ONNX(跨平台推理格式)
    ↓
output_onnx/(部署到笔记本 / 香橙派 / 公司服务器)
    ↓
海小星(HXXedge)端侧分类器
    用户提问 → BERT 分类 → categories.json 查表 → 返回预设答案
阶段 模型状态 能力
原始 bert-base-chinese 通用中文理解 能理解中文,但不知道海小星业务
微调后(ONNX) 专用分类器 能判断用户问题属于哪个类别
+ categories.json 完整问答系统 分类 → 查表 → 返回预设答案

与其他中文 BERT 变体对比

模型 来源 参数量 特点
bert-base-chinese Google 110M 官方原版,稳定可靠,我们用的
chinese-bert-wwm HFL(哈工大) 110M 全词掩码(WWM)训练,效果更好
chinese-roberta-wwm-ext HFL 110M RoBERTa 改进,多项任务 SOTA
chinese-mobilebert HFL ~25M 轻量版,适合资源受限的端侧

💡 我们选择 bert-base-chinese 是因为:官方出品、文档完善、社区支持好、端侧部署成熟。后续如果追求更好效果,可以尝试 chinese-roberta-wwm-ext。


官方资源

资源 链接
论文 https://arxiv.org/abs/1810.04805
GitHub https://github.com/google-research/bert
HuggingFace https://huggingface.co/google-bert/bert-base-chinese
本地模型文件 Edge/models/huggingface/bert-base-chinese/
测试脚本 extern/attachments/topic/LLMs/BERT/test.py

📝 创建:2026-09-11
🔄 标签:BERT、bert-base-chinese、中文NLP、词表、分词、WordPiece、预训练

相关笔记