BERT 模型详解

BERT Logo

论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding(arXiv 1810.04805,NAACL 2019)

官方代码:https://github.com/google-research/bert

预训练模型:https://huggingface.co/google-bert

📌 一句话理解

BERT = 专门"理解"文本的预训练模型


BERT 是什么?

BERT = Bidirectional Encoder Representations from Transformers

Google 在 2018 年发布的预训练语言模型,是 NLP 领域的里程碑。

从英文全称理解概念

通过英文缩写的全称,可以很方便理解概念:

GPT = Generative Pre-trained Transformer

G = Generative(生成式)
  ✅ 能生成文本
  ✅ 属于 NLG(自然语言生成)
  ✅ Decoder-only 架构

P = Pre-trained(预训练)
  ✅ 和 BERT 一样,都用预训练 + 微调范式
  ✅ 先在海量文本上学习语言知识
  ✅ 再针对具体任务微调

T = Transformer(架构)
  ✅ 和 BERT 一样,都基于 Transformer
  ✅ 但只用了 Transformer 的 Decoder 部分

BERT = Bidirectional Encoder Representations from Transformers

B = Bidirectional(双向)
  ✅ 同时看前后文
  ✅ Encoder-only 架构
  ❌ 不能生成文本(不是 Generative)

E = Encoder(编码器)
  ✅ 只用了 Transformer 的 Encoder 部分
  ✅ 适合理解任务(NLU)

R = Representations(表示)
  ✅ 输出文本的特征向量/表示

T = Transformers(架构)
  ✅ 和 GPT 一样,都基于 Transformer

对比总结:

GPT BERT
首字母 Generative(生成式) Bidirectional(双向理解)
中间 Pre-trained(预训练) Encoder(编码器)
结尾 Transformer(Decoder 部分) Transformer(Encoder 部分)
能力 生成 + 理解 ✅ 仅理解(不能生成)⚠️
架构 Decoder-only Encoder-only
任务 NLG(生成) NLU(理解)

核心洞察:GPT 名字里明确有 P(Pre-trained,预训练),BERT 名字里没有 P,但实际上也是预训练模型——只是名字没体现。两者都基于 Transformer(T 相同),但 GPT 能写文章(G),BERT 只能做阅读理解(B/E)。


BERT 的历史地位与影响

里程碑意义

1. 确立了“预训练 + 微调”范式

在 BERT 之前,NLP 的做法是每个任务从零训练一个模型(分词 → 词向量 → LSTM/CNN → 分类头)。BERT 证明了一件事:

先在海量文本上学“语言理解”,再花几分钟微调就能搞定具体任务。

这个范式现在所有大模型都在用,包括 GPT。

2. 证明了 Transformer 架构的威力

BERT 基于 Transformer 的 Encoder 部分,在 11 个 NLP 任务上同时刷新纪录,让业界意识到 Transformer 是通用语言架构。

3. 双向上下文理解

BERT 之前的模型(如 GPT-1)只看前面的词(单向),BERT 同时看前后文(双向),理解能力大幅提升。

“双向”到底是什么意思?

假设句子是:“苹果发布了新手机”

GPT(单向)— 只看前面:

  [前面] → 苹果 ← [后面看不到]

  GPT 处理“苹果”时,只能看到它前面的词
  后面的“发布了新手机”它此时还不知道
  就像读书时用手遮住后面的内容

BERT(双向)— 前后都看:

  [前面] → 苹果 ← [后面]
               ↑
         同时看到“发布了新手机”

  BERT 处理“苹果”时,前面后面都看得到
  就像读完整句话再理解每个词

为什么这很重要?— 歧义消解

“苹果 降价了”

“他打了一个电话”

双向能力怎么来的?— Masked Language Model (MLM)

BERT 的预训练方式:随机遮住词,让模型猜:

原始句子:苹果发布了新手机

训练时随机遮住:
  [MASK] 发布了新手机  → 猜“苹果”
  苹果 [MASK] 新手机  → 猜“发布了”
  苹果发布了 [MASK]   → 猜“新手机”

模型必须同时看前后文才能猜对!

对比 GPT 的训练方式(看前面猜后面):

  苹果 → 猜“发布”
  苹果发布 → 猜“了”
  苹果发布了 → 猜“新”
单向(GPT) 双向(BERT)
看词的方式 从左到右,只看已读过的 整句同时看
类比 听广播(听到哪算哪) 看照片(一眼看全貌)
适合任务 生成(写文章) 理解(做分类)

Transformer 家族树

BERT 和 GPT/ChatGPT 同源(都用 Transformer),但走了不同分支:

2017 ── Transformer 论文(Google)
         │
         ├── Encoder 方向 ──→ BERT (2018) ──→ RoBERTa、ALBERT、DistilBERT …
         │                    (Encoder-only,理解路线)
         │
         └── Decoder 方向 ──→ GPT-1 (2018) ──→ GPT-2 ──→ GPT-3 ──→ ChatGPT
                              (Decoder-only,生成路线)
维度 BERT 路线(Encoder-only) GPT 路线(Decoder-only)
方向 双向(看前后文) 单向(只看前面)
擅长 理解文本 生成文本
典型任务 分类、检索、NER 对话、写作、翻译
规模扩展 较难(110M~340M) 极易(175B+)
代表产品 Google 搜索、Rasa ChatGPT、Claude、Qwen

BERT 对 ChatGPT 的间接影响

虽然 ChatGPT 用的是 GPT 架构,但 BERT 的贡献不可忽视:

  1. 验证了预训练的价值 — BERT 的成功让 OpenAI 相信“大规模预训练”这条路是对的,只是他们选了生成方向
  2. 推动了 Transformer 生态 — HuggingFace 最初就是为 BERT 建的模型库,后来才变成 GPT 系列的平台
  3. 微调思想的传承 — BERT 的微调思路(在预训练基础上适配任务)启发了后续的指令微调 + RLHF

一句话总结:BERT 证明了“预训练大模型”这条路可行,GPT 把这条路走到了极致。

为什么“不准确”的 GPT 架构反而赢了?

架构说明:

Transformer 架构(2017 Google)
├── Encoder(编码器)→ 理解输入 → BERT 只用了这部分
└── Decoder(解码器)→ 生成输出 → GPT 只用了这部分

GPT 胜出的 5 个关键原因:

1. 规模扩展性(Scaling Laws)— 最关键

BERT(Encoder-only)的规模天花板:
  BERT-base: 110M 参数
  BERT-large: 340M 参数
  再大就很难训了 ❌

GPT(Decoder-only)的规模扩展:
  GPT-2: 1.5B 参数
  GPT-3: 175B 参数
  GPT-4: 估计 1T+ 参数
  越大越聪明 ✅

为什么 Decoder-only 能 scaling? - 训练目标简单:预测下一个词(next-token prediction) - 数据利用率高:每个 token 都参与训练 - BERT 的 MLM 要随机遮住 15% 的词,浪费数据

2. 通用性 — “能生成就能理解”

GPT(Decoder-only)能做什么:
  ✅ 写文章、翻译、写代码、对话
  ✅ 分类(通过提示:“这是正面还是负面?正面”)
  ✅ 几乎所有 NLP 任务

BERT(Encoder-only)能做什么:
  ✅ 分类、命名实体识别、语义相似度
  ❌ 不能生成文本、不能对话、不能写文章

关键洞察:生成是理解的超集。如果你能写出答案,说明你也理解了问题。

3. 涌现能力(Emergent Abilities)

当 Decoder-only 模型足够大时,会出现意想不到的能力: - 突然会推理了 - 突然会举一反三了(in-context learning) - 突然会遵循指令了

这些能力在 Encoder-only 模型中几乎不会出现。

4. RLHF 对齐 — 从“工具”变成“助手”

GPT + RLHF = ChatGPT
  - 能理解意图 + 生成回答 + 对话追问
  - 像一个“助手”

BERT + ??? = ?
  - 能理解,但不能生成
  - 只能做后端组件
  - 无法直接面向用户

5. 商业价值

Decoder-only(GPT)的商业模式:
  - ChatGPT 订阅、API 调用收费
  - 内容生成工具、编程助手
  → 直接面向消费者,收入可观

Encoder-only(BERT)的商业模式:
  - 搜索引擎排序、客服意图识别
  - 文本分类后端
  → 主要是 to B,隐藏在后台

总结对比:

BERT(Encoder-only) GPT(Decoder-only)
理解准确度 ✅ 更高(双向上下文) ⚠️ 稍低(单向)
规模扩展 ❌ 困难(~340M) ✅ 极易(175B+)
任务通用性 ❌ 只能理解 ✅ 理解 + 生成
涌现能力 ❌ 几乎没有 ✅ 推理、举一反三
交互能力 ❌ 不能对话 ✅ 自然对话
商业价值 ⚠️ to B 后台组件 ✅ to C 直接变现

核心结论:BERT 是“专科医生”——理解很准,但只能看一个科室;GPT 是“全科医生”——可能偶尔误诊,但什么都能看,而且越学越聪明。

但 BERT 仍有价值:在小模型 + 端侧 + 快速推理场景(如海小星分类任务),BERT 架构反而更合适——GPT 大模型做不好这些事。

BERT 论文作者现状

论文四位作者均来自 Google AI Language(西雅图团队):

作者 华人? 当前去向 后续亮点
Jacob Devlin 否 Google(Staff Research Scientist) BERT 核心推动者
Ming-Wei Chang(张明伟) 是 Google DeepMind 参与 Gemini 多模态大模型开发
Kenton Lee 否 Google DeepMind REALM(RAG 检索增强生成先驱)
Kristina Toutanova 否 Google + 华盛顿大学兼职教授 学术 + 工业双线

张明伟(Ming-Wei Chang) 是唯一的华人作者: - 博士毕业于 UIUC(伊利诺伊大学厄巴纳-香槟分校) - 微软研究院(2011–2017)→ Google(2017)→ Google DeepMind(2023 至今) - 从 BERT 的“理解文本”走向了 Gemini 的“多模态生成”,见证了整个大模型时代的演进


与 GPT/Qwen 的对比

GPT/Qwen(你之前用的):
  类型:Decoder-only(自回归)
  任务:生成文本(一个词一个词往后写)
  方向:单向(只看前面的词)

  "你们老板是谁" → 生成 "海启星的董事长是..."

BERT:
  类型:Encoder-only(双向)
  任务:理解文本(看完整句话)
  方向:双向(同时看前后文)

  "你们老板是谁" → 理解这是一个"问领导"的问题 → 分类为类别 0
维度 GPT/Qwen BERT
架构 Decoder-only Encoder-only
注意力 单向(看前面) 双向(看前后)
擅长 生成文本 理解文本
典型任务 对话、写作、翻译 分类、检索、问答
输出 生成新文本 特征向量/分类标签

BERT 的工作原理

1. 输入处理

输入文本:"你们老板是谁"
      ↓
分词(Tokenization):
  ["你", "们", "老", "板", "是", "谁"]
      ↓
添加特殊标记:
  [CLS] 你 们 老 板 是 谁 [SEP]
      ↓
转换为 ID(查 vocab.txt):
  [101, 872, 671, 3341, 3209, 3221, 711, 102]
      ↓
每个 ID → 查 embedding 表 → 768 维向量
  + 位置编码(第几个字)
  + 段编码(句子A / 句子B)
      ↓
输入:8 个 768 维向量

2. 12 层 Transformer Encoder(核心)

输入:8 个 768 维向量
          ↓
┌─ 第 1 层 ──────────────────────────────┐
│  每个 token 通过自注意力看所有其他 token │
│  "谁" 看到 "老板" → 更新自己的向量      │
│  "老板" 看到 "谁" → 更新自己的向量      │
│  → 8 个新的 768 维向量                  │
└──────────────────────────────────────────┘
          ↓
┌─ 第 2 层 ──────────────────────────────┐
│  同样的过程,但基于第 1 层的输出          │
│  此时每个 token 已"知道"第 1 层的理解    │
└──────────────────────────────────────────┘
          ↓
       ... 重复 12 层 ...
          ↓
┌─ 第 12 层(最终输出)─────────────────┐
│  每个 token 的 768 维向量              │
│  已充分融合整句话的上下文信息            │
│  [CLS] 的向量 = 整句话的"总结"          │
└──────────────────────────────────────────┘

核心机制:每一层,每个 token 都通过自注意力看所有其他 token,逐层加深理解。12 层之后,每个向量都包含了整句话的语义信息。

3. 输出:不同任务,不同用法

BERT 输出 8 个 768 维向量,怎么用取决于任务:

BERT 输出:
  v[CLS]  = [0.12, -0.34, 0.56, ...]  (768维) ← 整句总结
  v[你]   = [0.23, 0.11, -0.45, ...]  (768维)
  v[老]   = [0.45, -0.23, 0.89, ...]  (768维)
  ...
  v[SEP]  = [0.05, -0.01, 0.09, ...]  (768维)
任务 用哪个向量 怎么得到答案
分类 v[CLS] → 线性层(768→N) → softmax → 选类别
检索/Embedding v[CLS] → 和其他向量算余弦相似度
掩码填空 v[MASK] → 线性层(768→21128) → softmax → 选字
NER/序列标注 每个 v[token] → 线性层(768→标签数) → 逐字标注
问答抽取 每个 v[token] → 预测答案起止位置

💡 所有能力都来自同一个东西:12 层自注意力产生的上下文向量。 不同任务只是在向量上面接不同的“头”。


为什么 BERT 适合高准确度场景?

BERT 的机制决定了它特别适合客服、信息检索、答案要求准确的场景:

BERT 的优势:
✅ 确定性输出 —— 同样的输入永远得到同样的输出,不会“幻觉”
✅ 双向理解   —— 同时看前后文,语义理解更准确
✅ 速度快     —— 一次前向传播,~100ms 出结果
✅ 资源少     —— 110M 参数,CPU 也能跑
✅ 可部署到端侧 —— 可转 ONNX/RKNN,离线运行

对比 GPT/LLM:

维度 BERT GPT/LLM
答案来源 预设答案 / 向量检索 模型自己“生成”
幻觉风险 ❌ 没有(答案固定) ⚠️ 可能编造不存在的内容
回答速度 ~100ms ~1-5秒(流式生成)
准确度 分类准确率高且稳定 受提示词、温度等影响
灵活性 只能回答已定义的范围 能回答任何问题
成本 极低(本地推理) 较高(API 按 token 计费)
离线能力 ✅ 完全离线 ❌ 通常需要联网

适用场景对比:

BERT 适合(准确、快、确定):
  ✅ 客服 FAQ —— 问题分类 → 返回标准答案
  ✅ 信息检索 —— 语义向量化 → 找到最相关内容
  ✅ 端侧部署 —— 离线、低延迟、低成本
  ✅ 答案要求 100% 可控 —— 不允许幻觉

GPT/LLM 适合(灵活、开放、生成):
  ✅ 开放域问答 —— 问题范围不固定
  ✅ 内容生成 —— 写文章、写代码、翻译
  ✅ 复杂推理 —— 多步思考、总结归纳
  ✅ 对话交互 —— 自然流畅的多轮对话

BERT 模型家族全景

BERT 的变体非常多,可以从三个维度来理解:按大小(轻量化)、按用途(分类 vs 句向量)、按语言(单语 vs 多语)。

BERT 模型家族
├── 按大小(轻量化)
│   ├── BERT-base (110M) → 原始版
│   ├── DistilBERT (66M) → 蒸馏压缩
│   ├── BERT-small (29M)
│   ├── MobileBERT (25M) → 移动端优化
│   └── TinyBERT (14.5M) → 极致轻量
├── 按用途(句向量专用)
│   ├── Sentence-BERT → 单语句向量(孪生网络 + 三元组损失)
│   ├── LaBSE → 跨语言句向量(Sentence-BERT 方法 + mBERT 底座 + 翻译对,109+ 语言)
│   └── sentence-transformers 库 → 多种预训练句向量模型
└── 按语言
    ├── 单语言版 → bert-base-chinese / german / japanese ...
    ├── 多语言版 → bert-base-multilingual-cased (104 语言)
    └── 中文增强 → chinese-roberta-wwm-ext / chinese-bert-wwm ...

维度一:按大小(轻量化变体)

原始 BERT-base 有 110M 参数(~440MB),对于端侧部署还是太大。后续发展出更小的版本:

模型 参数量 大小 速度 准确率 适用场景
BERT-base 110M ~440MB 1x 96.5% 服务器部署
DistilBERT 66M ~250MB 1.6x 95-97% 边缘设备
BERT-small 29M ~120MB 4x 93-95% 移动端
MobileBERT 25M ~100MB 4x 94-96% 移动端(推荐)
TinyBERT 14.5M ~60MB 7x 92-95% 超轻量场景(推荐)

TinyBERT:知识蒸馏的典范

用大模型"教"小模型:BERT-base(老师,110M)→ TinyBERT(学生,14.5M)→ 学会 95% 的能力,体积小 7 倍、速度快 7 倍。意图识别任务:TinyBERT 92.3% vs BERT-base 96.5%,差距仅 4%。

⚠️ TinyBERT/DistilBERT/MobileBERT 均为英文模型,中文任务需使用中文 BERT 变体。

维度二:按用途(句向量专用变体)

原始 BERT 的句向量(直接取 [CLS] 或平均池化)效果很差——因为 MLM/NSP 预训练目标从未要求"语义相近的句子向量靠近"。

Sentence-BERT(Reimers & Gurevych, EMNLP 2019)通过在 BERT 上加孪生网络 + 三元组损失微调,专门训练模型产出高质量句向量。架构完全不变,只是训练目标不同:

维度 原始 BERT Sentence-BERT
训练目标 MLM(遮词填空)+ NSP(下一句预测) 孪生网络 + 三元组损失(像的靠近、不像的远离)
句向量质量 ❌ 差([CLS] 只学了分类信号) ✅ 好(专门为句向量优化)
典型用途 分类、NER、掩码填空 语义搜索、聚类、相似度计算

sentence-transformers 库提供了大量预训练好的句向量模型(底座不限于 BERT,但训练方法一脉相承),可直接下载使用:

模型名 基础架构 参数量 说明
bert-base-nli-mean-tokens bert-base-uncased 110M 最早的 Sentence-BERT
all-MiniLM-L6-v2 自定义小架构 22M 轻量版,速度快
all-mpnet-base-v2 mpnet-base 110M 综合效果最好的通用版
paraphrase-multilingual-MiniLM-L12-v2 MiniLM 118M 多语言版,50+ 语言
from sentence_transformers import SentenceTransformer

# 下载并加载模型(首次自动下载权重)
model = SentenceTransformer('all-MiniLM-L6-v2')

# 编码句子 → 直接得到高质量句向量
embeddings = model.encode(["我爱猫", "我养了一只猫", "今天天气好"])

💡 与分类用法的区别:原始 BERT 做分类是"选择题"(选类别),Sentence-BERT 做句向量是"连线题"(把同义句连起来)。LaBSE 则是把"连线题"扩展到了跨语言(109+ 语言同义句落在同一向量空间)。

维度三:按语言

BERT 不仅有不同大小,还有不同语言版本:

命名规则:

bert-base-{语言}-cased     ← 保留大小写
bert-base-{语言}-uncased   ← 不区分大小写

"cased" vs "uncased":
    cased:保留大小写,能区分 "Apple"(公司)vs "apple"(水果)
    uncased:全部转小写,大小写信息丢失
    大多数任务用 uncased 即可;NER 等需要大小写敏感的任务用 cased

各语言版本:

模型名称 语言 发布方 说明
bert-base-uncased 英文 Google 最原始版本,不区分大小写
bert-base-cased 英文 Google 保留大小写
bert-base-chinese 中文 Google 按字切分,词表 21128
bert-base-german-cased 德语 柏林工业大学 德语专用,保留大小写
bert-base-dutch-cased 荷兰语 Google 荷兰语专用
bert-base-spanish-wwm-cased 西班牙语 Google 全词掩码训练
bert-base-japanese 日文 Google 支持日语分词
bert-base-korean 韩文 Google 支持韩语分词
bert-base-arabic 阿拉伯语 Google 从右到左书写
bert-base-multilingual-cased 104 种语言 Google 多语言混合版
bert-base-multilingual-uncased 104 种语言 Google 多语言混合版(不区分大小写)

选择原则:任务语言明确 → 用单语言版(效果更好);涉及多语言 → 用 multilingual 版。

单语言版 vs 多语言版:

单语言版(如 bert-base-chinese):
    ├── 只用一种语言的语料预训练
    ├── 对该语言理解最深
    └── 中文任务首选 bert-base-chinese

多语言版(bert-base-multilingual-cased):
    ├── 用 104 种语言混合语料预训练
    ├── 每种语言都"会"但都不够"精"
    └── 适合多语言混合场景

实际案例:
    一篇德语情感分析论文用了 multilingual 版
    → 作者自己也承认:"弱化了针对特定语言的深入建模能力"
    → 如果用 bert-base-german-cased(德语专用),效果大概率更好

中文 BERT 模型:

模型 来源 参数量 特点
bert-base-chinese Google 110M 官方中文 BERT,稳定可靠
chinese-roberta-wwm-ext HFL 110M RoBERTa 改进,效果更好
chinese-mobilebert HFL ~25M 轻量版,适合端侧
chinese-bert-wwm HFL 110M 全词掩码(WWM)训练

海小星项目选择:bert-base-chinese(110M 参数,~400MB),后续可尝试 chinese-mobilebert 减小体积。


BERT 在工业界的应用

公司/产品 应用场景 模型 效果
Google 搜索 查询理解 BERT-large 搜索质量提升 10%
阿里小蜜 客服意图识别 TinyBERT 95%+ 准确率
京东 JIMI FAQ 分类 MobileBERT 亿级用户
Rasa 对话系统 DistilBERT 开源框架
海小星(计划) 知识问答分类 bert-base-chinese 目标 95%+

BERT vs 其他模型

模型 类型 擅长 你的场景适用性
GPT/Qwen Decoder 生成文本 ❌ 太大,会幻觉
BERT Encoder 理解文本 ✅ 完美
T5 Encoder-Decoder 通用 ⚠️ 可以但没必要
TinyBERT Encoder(小) 理解 + 快 ⚠️ 仅英文,中文需用 bert-base-chinese

预训练 + 微调:两阶段训练

第 1 阶段:预训练(Google 已完成)

数据:维基百科 + 书籍(数十亿词)
任务:
  - 掩码语言模型(MLM):猜被遮住的词
  - 下一句预测(NSP):判断两句话是否连续

结果:模型学会了"理解"中文/英文

第 2 阶段:微调(你要做的)

数据:5000 条 (问题, 类别) 训练数据
任务:100 分类(把问题分到 100 个类别)
时间:2-5 分钟(Colab GPU)

结果:TinyBERT 学会"海小星知识问答分类"

关键:你不需要从头训练 BERT,只需要在预训练模型基础上微调!


BERT 模型文件详解:从原始到部署

📌 核心概念

BERT 模型在不同阶段以不同格式存在:原始模型(HF 格式)→ 微调后 → 转换部署(ONNX 格式)

整体流程

bert-base-chinese(原始模型 / HF 格式)
    ↓ Colab 微调(用 5000 条问答数据训练)
    ↓ 转 ONNX(跨平台推理格式)
hqx-bert / output_onnx(微调后的部署模型 / ONNX 格式)

💡 hqx-bert = 海启星 BERT 分类器,是 bert-base-chinese 微调 + 转换后的成品。

类比:

bert-base-chinese = 一个"刚毕业的大学生"
  ✅ 中文很好,理解能力强
  ❌ 但不知道你们公司的业务知识

hqx-bert = 这个大学生"入职培训后"
  ✅ 中文理解能力依然强
  ✅ 还学会了你们公司的 100 类问答
  ✅ 而且被"精简装备"了(ONNX 格式,跑得更快)

ONNX "跨平台"是什么意思?

ONNX 不只是 CPU,它是一种通用的模型格式标准,同一个 ONNX 模型可以部署到不同硬件:

ONNX 模型(通用格式)
├── CPU  → ONNX Runtime
│   ├── ✅ 本地笔记本(开发测试)
│   ├── ✅ 香橙派(边缘部署)
│   └── 🔲 公司服务器(生产环境)
├── GPU  → ONNX Runtime + CUDA(NVIDIA 显卡)
├── NPU  → 转成 RKNN 后跑(瑞芯微 NPU,原计划但遇到 IsNaN 问题)
└── 其他 → TensorRT、OpenVINO、CoreML…
维度 "跨"什么 例子
硬件 CPU / GPU / NPU 同一模型从 PC 到开发板都能跑
系统 Windows / Linux / ARM 从服务器到嵌入式设备
框架 PyTorch / TF → ONNX 训练用 PyTorch,部署用 ONNX

📌 ONNX 的价值:先转成通用格式,之后想部署到 CPU/GPU/NPU 都行,不被某个硬件绑死。

原始模型文件(bert-base-chinese / HF 格式)

路径:Edge/models/huggingface/bert-base-chinese/

类别 文件 大小 作用
🧠 模型权重 pytorch_model.bin 393 MB PyTorch 格式权重(✅ 最常用)
model.safetensors 392 MB 新一代通用格式(✅ 更安全更快)
tf_model.h5 456 MB TensorFlow 格式权重
flax_model.msgpack 390 MB JAX/Flax 格式权重
🏗️ 架构配置 config.json < 1 KB 定义模型结构(层数、维度、头数…)
📝 分词器 vocab.txt 100 KB 词表:21128 个中文字/词
tokenizer.json 260 KB 完整分词规则(WordPiece 算法)
tokenizer_config.json < 1 KB 分词器配置
📋 说明 README.md、.gitattributes、configuration.json — 模型介绍 + 元数据

💡 4 个权重文件是同一个模型在不同框架下的序列化格式。用 PyTorch 只需 pytorch_model.bin 或 model.safetensors,其余可删除省空间。

config.json 关键字段:

{
  "architectures": ["BertForMaskedLM"],   // 模型类型
  "model_type": "bert",                    // 模型家族

  "hidden_size": 768,          // 隐藏层维度(每个 token 用 768 维向量表示)
  "num_hidden_layers": 12,     // Encoder 层数(12 层 Transformer)
  "num_attention_heads": 12,   // 注意力头数(每头 768÷12 = 64 维)
  "intermediate_size": 3072,   // FFN 中间层维度(768 × 4)

  "vocab_size": 21128,         // 词表大小(21128 个中文字/词)
  "max_position_embeddings": 512,  // 最大序列长度

  "hidden_act": "gelu",        // 激活函数
  "directionality": "bidi",    // 双向(BERT 的核心特点!)
  "type_vocab_size": 2         // segment 数量(句子A / 句子B)
}

一句话理解:config.json 定义了"模型长什么样"——多少层、多宽、多少头。不包含任何训练得到的参数。

部署模型文件(hqx-bert / ONNX 格式)

路径:Daas-v2/data/models/rkllm/BERT/output_onnx/

微调 + 转换完成后,最终部署的模型文件如下:

output_onnx/
├── model.onnx              (390 MB)  ← 核心模型(计算图 + 权重)
├── model.onnx.data         (390 MB)  ← 权重外置副本
├── tokenizer.json          (0.4 MB)  ← 分词器规则
├── tokenizer_config.json   (< 1 KB)  ← 分词器配置
└── categories.json         (10 KB)   ← 类别定义 + 预设答案
文件 大小 是什么 作用
model.onnx 390 MB ONNX 格式的完整模型 包含计算图(节点定义、连接关系)和权重数据。ONNX Runtime 加载此文件进行推理
model.onnx.data 390 MB 权重外置副本 导出时设置 use_external_data_format=True 产生。与 model.onnx 中的权重重复,两个文件都保留才能正常加载
tokenizer.json 0.4 MB 分词规则文件 WordPiece 算法的完整规则,把文本切分为 token ID。与 HF 格式的 tokenizer.json 完全相同
tokenizer_config.json < 1 KB 分词器配置 max_length: 64,padding: true 等参数
categories.json 10 KB 类别定义 + 预设答案 每个类别包含:category(名称)、answer(预设答案)、keywords(仅训练时用)

💡 为什么 model.onnx 和 .data 都是 390MB?

导出时设置了 use_external_data_format=True,权重被存了两份(内联 + 外置)。模型本身只有 ~390MB,不是 780MB。两个文件缺一不可,删掉任何一个都无法加载。

原始 vs 部署:完整对比

对比 原始模型(HF 格式) 部署模型(ONNX 格式)
是什么 Google 发布的通用 BERT 模型 你微调后的专用分类模型
能力 通用语言理解(填空、编码…) 只会一件事:100 类文本分类
知识 通用中文语言知识 通用知识 + 100 类问答的专用知识
格式 PyTorch(需 PyTorch 加载) ONNX(ONNX Runtime,CPU 可跑)
运行环境 训练 + 服务器推理 跨平台推理(CPU/GPU/NPU)
大小 ~1.6 GB(4 种框架权重) ~780 MB(只有 ONNX)
架构 BERT + MLM 预训练头 BERT + 分类头(768→100)

文件对应关系:

HF 格式(训练用) ONNX 格式(部署用) 说明
config.json 编码在 model.onnx 的计算图中 架构信息不再单独存在
pytorch_model.bin (393MB) model.onnx + .data (~780MB) ONNX 需要额外存储计算图元数据
tokenizer.json tokenizer.json(不变) 分词器格式通用
无 categories.json 分类任务特有,存储类别和答案

HF / ONNX / RKNN 格式对比

对比 HF 格式 ONNX 格式 RKNN 格式
包含文件 config + 权重 + tokenizer .onnx + tokenizer .rknn
灵活性 ✅ 可微调、可导出 ❌ 只能推理 ❌ 只能推理
框架依赖 PyTorch / TF ONNX Runtime RKNN Toolkit
部署场景 训练 + 服务器推理 跨平台推理 NPU 专用
项目中的位置 Edge/models/huggingface/ Daas-v2/.../output_onnx/ Daas-v2/.../output_rknn/

📌 你的实践路径:HF 格式(训练/微调)→ ONNX 格式(跨平台)→ RKNN 格式(NPU 加速)


BERT 交互式测试(动手理解模型能力)

测试脚本:extern/attachments/topic/LLMs/BERT/test.py

用 bert-base-chinese 模型进行 4 项互动测试,直观感受 BERT 的“理解”能力。

测试 1:分词可视化

说明:看 BERT 怎么把中文切成 token(WordPiece 算法)。

测试输入:海小星真聪明

结果:

序号   Token       ID      还原
0      海         1744    海
1      小         2207    小
2      星         4506    星
3      真         4289    真
4      聪         5317    聪
5      明         3319    明

完整输入 IDs: [101, 1744, 2207, 4506, 4289, 5317, 3319, 102]
输出形状: torch.Size([1, 8, 768])
  ↑ batch=1, token数=8(含[CLS][SEP]), 隐藏维度=768

理解: - BERT 对中文采用字级别分词(每个汉字一个 token),不是词级别 - 101 = [CLS](句首标记),102 = [SEP](句尾标记) - 输出 8 个 token,每个 768 维向量 → 这就是 BERT 对这句话的“理解”

测试 2:语义相似度

说明:用 [CLS] 向量作为整句话的语义表示,计算两句话的余弦相似度。

测试结果:

句子 A 句子 B 相似度 判断
海小星真聪明 海小星很聪明 ~0.92 🟢 非常相似(同义替换)
海洋监测设备 潮汐预报系统 ~0.75 🟡 比较相似(同领域)
海小星真聪明 今天天气不错 ~0.35 🔴 差异较大(完全不同话题)

理解: - BERT 的 [CLS] 向量能捕获整句话的语义,不只是关键词 - 相似度高的句子不一定用词相同(“聪明” vs “很聪明”),但语义接近 - 这就是 BERT 能做文本分类的核心能力——把句子变成语义向量

测试 3:掩码填空(MLM)

说明:用 [MASK] 遮住一个字,让 BERT 预测最可能的字。这是 BERT 的预训练任务。

测试输入:广州是一座很有[MASK]的城市

结果:

排名    预测字     概率      填入后
Top1    特         0.1832    广州是一座很有特的城市
Top2    味         0.0921    广州是一座很有味的城市
Top3    名         0.0654    广州是一座很有名的城市  ← 最合理
Top4    钱         0.0412    广州是一座很有钱的城市
Top5    特         0.0387    广州是一座很有特的城市
...

理解: - BERT 能根据上下文“猜”出被遮住的字,Top3 预测出“名”(很有名) - 这证明 BERT 真正“理解”了句子的语义,而不是简单的词频统计 - MLM(掩码语言模型)是 BERT 双向理解能力的核心体现

测试 4:注意力分析

说明:看 [CLS] 对每个字的注意力权重,了解 BERT 认为哪些字最重要。

测试输入:广州是一座国际化程度较高的城市。

结果:

  广       13.2% ██████
  州       10.8% █████
  是       10.3% █████
  一        3.8% █
  座        2.9% █
  国        5.7% ██
  际        6.4% ███
  化        2.6% █
  程        1.1%
  度        1.1%
  较        6.4% ███
  高        2.7% █
  的        3.8% █
  城        5.0% ██
  市        5.2% ██
  。       19.0% █████████

理解: - 句号(。)19.0% 权重最高 —— BERT 已知现象:句末标记和句首字天然获得高注意力 - 广州(13.2% + 10.8%) 作为主语被重点关注 - 是(10.3%) 作为系动词连接主语和描述 - 一/座/化/程/度(1-3%) 功能词权重低 - 这说明 BERT 的注意力机制能区分“重要信息”和“语法填充”

小结:BERT 的 4 种“理解”能力

能力 测试项目 体现的 BERT 特性
分词 字级别切分 + token ID WordPiece 算法,中文按字切分
语义表示 [CLS] 向量 → 相似度 整句语义编码,分类任务的基础
上下文预测 [MASK] 填空 双向注意力,理解上下文关系
重要性判断 注意力权重分布 能区分关键信息和语法填充

BERT 的 6 大能力全景

上面测试的是 BERT 的基础理解能力。实际上 BERT 是一个通用底座,通过微调/组合可以完成 6 类任务:

BERT 能力全景(从基础到应用)

基础能力:语义理解
  └── 把文本变成高质量的语义向量(768 维)

6 大应用:
├── 1. 分类(Classification)     ✅ 海小星在用
│   输入:"你们电话多少"
│   输出:类别="联系方式"(置信度 92%)
│   做法:微调 + 分类头
│
├── 2. 检索 / Embedding           ✅ RAG 在用(但用的是阿里 text-embedding-v4)
│   输入:5000 条笔记 → 5000 个向量
│   查询:"潮汐预报" → 找到最相关的笔记
│   做法:用 BERT 的向量表示 + 余弦相似度
│
├── 3. 排序 / Re-ranking          🔲 可用于 RAG 精排
│   粗排:Embedding 检索 → Top-50
│   精排:Cross-Encoder 逐一打分 → Top-3
│   做法:BERT 同时看 query + 文档,判断相关性
│
├── 4. 抽取式问答(Span QA)     🔲 未使用
│   上下文:"海小星部署在 RK3588 上"
│   问题:"部署在哪里?"
│   输出:直接从原文圈出 "RK3588"
│   做法:微调 + 起止位置预测头
│
├── 5. 命名实体识别(NER)        🔲 未使用
│   输入:"海启星公司在广州发布了海洋龘思"
│   输出:[海启星]=公司,[广州]=地名,[海洋龘思]=产品
│   做法:微调 + 逐字分类头
│
└── 6. 句子对匹配               🔲 可用于意图识别
    输入对:("用户想查潮汐", "今天的潮汐预报")
    输出:相似 / 不相似
    做法:输入两句话 → BERT → 分类头

💡 BERT 本身不带 RAG。RAG 是一个系统架构(检索 + 生成),BERT 可以在其中扮演“检索”角色(做 Embedding),但你的 RAG 实际用的是阿里的 text-embedding-v4,效果比 BERT 更好。

项目中的 BERT 能力使用总结

系统 用的 BERT 能力 模型 位置
海小星(HXXedge) 分类 微调 BERT → ONNX Daas-v2/.../output_onnx/
RAG 知识库问答 检索(Embedding) text-embedding-v4(阿里) 云端 API
交互式测试 理解、掩码、注意力 bert-base-chinese Edge/models/huggingface/

实际部署流程

第 1 步:准备数据(本地)
  - 100 个知识类别
  - 每类 50 种问法
  - 共 5000 条 (text, label)

第 2 步:Colab 微调
  - 加载 TinyBERT 预训练模型
  - 在 5000 条数据上训练 3 个 epoch
  - 保存微调后的模型

第 3 步:转 ONNX → RKNN
  - PyTorch → ONNX(通用格式)
  - ONNX → RKNN(瑞芯微 NPU 格式)

第 4 步:部署到香橙派
  - 用户输入 → TinyBERT 分类 → 返回预设答案

一句话总结

BERT = 专门"理解"文本的预训练模型


📝 创建:2026-09-10
🔄 标签:AI、BERT、预训练模型、文本分类、TinyBERT、NLP

相关笔记