3.1 数据准备 —— 从零开始的完全指南
用费曼学习法彻底讲透数据准备的每一个细节,12岁小孩也能看懂
📖 目录
🎯 开篇:三个灵魂问题
在开始之前,先问自己三个问题:
问题1:为什么需要数据准备?
如果把大语言模型比作一个学生,数据就是它要读的所有课本。课本质量差、内容少,学生怎么可能学好?
问题2:计算机怎么”看懂”文字?
答案:它看不懂!
计算机只认识0和1。你看到的”你好”,在计算机眼里是一串数字。所以我们需要把文字”翻译”成数字。
问题3:这一章你会学到什么?
- 计算机如何存储文字(编码)
- 如何把文字变成数字(分词)
- 如何训练一个分词器(BPE算法)
- 数据从哪来,如何清洗
- 完整的文字处理流程
第一部分:计算机如何理解文字
这一部分解决什么问题?
核心问题:计算机只认识0和1,但我们要让它处理文字。如何把”你好”这样的文字变成计算机能存储的0和1?
解决方案:编码(Encoding)—— 一套”翻译规则”,规定每个字对应什么数字。
为什么重要:这是一切的基础。如果不理解编码,你就无法理解后面的分词、词表、Embedding等概念。
1.1 最底层的真相:计算机只认识0和1
计算机的世界只有两个数字:0和1。
你看到的:你好
计算机看到的:01011001 01101111 01110101 ...
所有信息在计算机里都是用0和1表示的:
- 文字是0和1
- 图片是0和1
- 声音是0和1
- 视频是0和1
那问题来了:怎么用0和1表示”你好”这两个字?
答案:需要一个”翻译规则”,这个规则就叫编码。
1.2 什么是编码?从密码本说起
编码 = 一个”翻译规则”,规定每个字对应什么数字。
例子1:我们自己发明一个编码
我的编码规则:
A = 1
B = 2
C = 3
那么 “ABC” 就变成 [1, 2, 3]。
计算机存储 [1, 2, 3],显示时再翻译回 “ABC”。
例子2:密码本类比
想象你和朋友约定一个密码本:
密码本:
"见面" = 001
"取消" = 002
"推迟" = 003
你发短信 “001”,朋友查密码本,知道是”见面”。
编码就是这样一个”密码本”,只不过是计算机和人类之间的密码本。
1.3 编码的演变:ASCII → GBK → UTF-8
ASCII(最早的编码,1963年)
A = 65
B = 66
a = 97
b = 98
空格 = 32
! = 33
...
ASCII 只有 128 个位置(0-127),只够放:
- 英文大小写字母(52个)
- 数字 0-9(10个)
- 标点符号(30多个)
- 控制字符(换行、回车等)
问题:中文怎么办?
中文有几万个字,128个位置根本不够!
GBK 编码(中国1995年发明)
GBK = 国标扩展(Guo Biao Kuo zhan)
"你" = 47872
"好" = 48391
"中" = 42208
"国" = 42368
GBK 用 2 个字节(16 位)来存一个中文字:
- 2 个字节 = 16 位 = 2^16 = 65536 个位置
- 可以表示 2 万多个汉字
问题:如果一篇文章里既有中文又有英文怎么办?
GBK 可以混用,但很复杂。而且日文、韩文、阿拉伯文怎么办?
UTF-8(全世界通用的编码 ✅)
设计思路:不同字符用不同长度的字节
英文字母:1 个字节
"A" = 01000001
中文:3 个字节
"你" = 11100100 10111101 10100000
emoji:4 个字节
"😀" = 11110000 10011111 10011000 10000000
优点:
- 兼容 ASCII(英文还是 1 个字节)
- 支持全世界所有语言
- 现在几乎所有网站、程序都用 UTF-8
为什么现在不用GBK?
| GBK | UTF-8 | |
|---|---|---|
| 支持语言 | 只有中文 | 全世界所有语言 |
| 国际化 | 只在中国用 | 全球通用 |
| 网页支持 | 老网站 | 几乎所有现代网站 |
| 兼容性 | 差 | 好 |
1.4 为什么会出现乱码?
12岁版类比:
你和朋友约定密码:
- 你的规则:A=1, B=2, C=3
- 朋友的规则:A=3, B=2, C=1
你写了 1 2 3,意思是 “ABC”。
朋友用他的规则解读,变成了 “CBA”!
这就是乱码:
你用 GBK 编码存了"你好"
→ 计算机存储:[47872, 48391]
别人用 UTF-8 解码
→ 把 47872 当成 UTF-8 来读
→ 变成乱码:"浣犲ソ"
解决办法:统一用 UTF-8!
1.5 为什么是256个字节?不能是128个吗?
答案:256是计算机的”天然选择”
1个字节 = 8位(bit)
1位:可以表示 2 种(0或1)
2位:可以表示 4 种(00, 01, 10, 11)
3位:可以表示 8 种
...
8位:可以表示 2^8 = 256 种
所以256不是人为选的,而是1个字节天然就能表示256种。
如果用128个呢?
128 = 7位
7位可以表示 2^7 = 128 种
问题:
- 计算机的基本单位是字节(8位)
- 如果只用7位,剩下1位浪费了
- 存储和处理都不方便
类比:就像你有一个8格的鸡蛋盒,但只用7格,剩下1格空着。浪费空间,不符合标准。
历史上确实有128的编码:ASCII
ASCII(1963年发明):
- 只用7位
- 可以表示128个字符
- 包括:英文大小写字母、数字、标点符号、控制字符
编码范围:0-127
例子:
'A' = 65
'a' = 97
'0' = 48
空格 = 32
问题:只够英文用,中文、日文、阿拉伯文等完全放不下。
256个字节的强大之处
用1个字节:256种 用2个字节:256² = 65,536种 用3个字节:256³ = 16,777,216种 用4个字节:256⁴ = 4,294,967,296种 用N个字节:256^N种
UTF-8就是这么设计的:
- 英文用1个字节(够用256种)
- 中文用3个字节(够用1600万种)
- emoji用4个字节(够用42亿种)
所以256个基础字节可以通过不同长度的组合表示任何文字。
总结:为什么是256?
- ✅ 1个字节 = 8位 = 2^8 = 256(天然的)
- ✅ 符合计算机的基本单位(字节)
- ✅ 存储和处理都方便
- ✅ 通过组合可以表示任何字符
第一部分小结:编码与分词的关系
理清两个概念
编码(Encoding):计算机如何存储文字
- 作用:把”你好”变成字节序列
[228, 189, 160, 229, 165, 189]- 目的:让计算机能保存文字
- 标准:UTF-8
分词(Tokenization):模型如何处理文字
- 作用:把”你好”变成Token ID序列
[1234, 5678]- 目的:让模型能理解文字
- 方法:BPE算法
关系:编码是底层存储,分词是上层处理。先有编码,才能有分词。
第二部分:分词(Tokenization)
这一部分解决什么问题?
核心问题:编码解决了存储问题,但模型不能直接处理字节。为什么?
- 如果按字节处理,一个中文字需要3个字节,序列太长
- 如果按字处理,词表太大(汉字有几万个)
- 如果按词处理,新词、生僻词无法处理
解决方案:分词(Tokenization)—— 找到一个平衡点,把文字切成”子词”单元。
突破点:BPE算法自动学习最优的切分方式,既不会太细(字节级),也不会太粗(词级)。
2.1 为什么要分词?
先理解一个根本问题:计算机不认识文字。
你看到的”你好”,在计算机眼里不过是一串 0 和 1。
分词就是:把文字变成数字序列的过程。
想象一本字典,每个词都有一个编号:
字典(词表):
"猫" → 1
"狗" → 2
"吃" → 3
"鱼" → 4
"骨头" → 5
"了" → 6
...
句子 "猫吃鱼" → [1, 3, 4]
句子 "狗吃骨头" → [2, 3, 5]
模型看到的不是”猫吃鱼”,而是 [1, 3, 4]。这就是分词做的事。
那关键问题来了:字典怎么编?按什么粒度切?
2.2 词和数字如何对应?
两步走
第一步:建立词表(字典)
词表(就是一个列表):
位置 0: "猫"
位置 1: "狗"
位置 2: "吃"
位置 3: "鱼"
位置 4: "骨头"
位置 5: "了"
第二步:查表
句子:"猫吃鱼"
查表:
"猫" → 位置 0
"吃" → 位置 2
"鱼" → 位置 3
结果:[0, 2, 3]
模型看到的不是”猫吃鱼”,而是 [0, 2, 3] 这三个数字。
2.3 三种切分方法对比
原始句子:"我今天学习了深度学习"
方法1:按字切(每个字一个编号)
["我", "今", "天", "学", "习", "了", "深", "度", "学", "习"]
→ 10 个 Token
→ 问题:太碎了!"深度学习"被切成4个独立的字,
模型很难理解这4个字组合在一起是一个概念。
方法2:按词切(每个词一个编号)
["我", "今天", "学习", "了", "深度学习"]
→ 5 个 Token
→ 问题:中文有几十万个词!还不断有新词出现
(比如"ChatGPT"、"YYDS"),词典装不下。
方法3:按子词切(BPE,当前主流 ✅)
["我", "今天", "学习", "了", "深度", "学习"]
→ 6 个 Token
→ 常用的组合保留为整体,罕见的词拆成更小的碎片
既不会太碎,词典大小也可控(通常 3-15 万)
2.4 BPE算法详解
BPE = Byte Pair Encoding
拆解每个单词:
- Byte:字节(计算机存储的最小单位)
- Pair:一对(两个挨在一起的东西)
- Encoding:编码(变成数字)
12岁版翻译:把经常挨在一起的字节对,合并成一个新符号。
核心思想
找最常出现的一对邻居,把它们合并成一个新词。反复重复。
超级简单的例子
假设我们有文本:"aaabdaaabac"
第 0 步:从最小单位开始
[a, a, a, b, d, a, a, a, b, a, c]
词表:{a, b, c, d} (只有4个符号)
第 1 轮:统计谁和谁最经常挨在一起?
"aa" 出现了 4 次 ← 最多!
"ab" 出现了 2 次
"bd" 出现了 1 次
→ 合并 "aa" 为新符号 "AA"
→ 词表变为:{a, b, c, d, AA}
文本变成:[AA, a, b, d, AA, a, b, a, c]
第 2 轮:再统计
"AAa" 出现了 2 次 ← 最多!
→ 合并 "AAa" 为新符号 "AAA"
→ 词表变为:{a, b, c, d, AA, AAA}
文本变成:[AAA, b, d, AAA, b, a, c]
第 3 轮:继续...
不断重复,直到词表达到目标大小(比如 50000)
真实例子:英文文本
原始文本:"the cat sat on the mat"
第 0 层(单个字母):
[t, h, e, 空格, c, a, t, 空格, s, a, t, ...]
第 1 轮合并:
统计整个训练数据(几十亿个字符):
"th" 出现了 80 万次 ← 最多!
→ 合并 "th"
→ 词表从 256 变为 257
文本变成:[th, e, 空格, c, a, t, ...]
第 2 轮合并:
"he" 出现了 65 万次 ← 最多!
→ 合并 "he"
→ 词表从 257 变为 258
第 3 轮合并:
"the" (th+e) 出现了 50 万次 ← 最多!
→ 合并 "the"
→ 词表从 258 变为 259
...
第 49744 轮合并:
"algorithm" 出现了 800 次 ← 最多!
→ 合并 "algorithm"
→ 词表变为 50000 → 停止!
关键问题解答
Q1:出现多少次才会被合并?
答案:没有固定次数!每轮选最多的那一对。
类比:班级选班长
- 不是”得票超过20才能当”
- 而是”谁票最多谁就当”
每轮只合并一对,合并完词表就多了一个新词。
你提前设定好词表总共要多少词(比如50000),合并到50000个就停。
具体到数字举个例子:
假设训练数据有 1000 万个字符
第 1 轮:"th" 出现了 80 万次 → 合并!词表从 256 变为 257
第 2 轮:"he" 出现了 65 万次 → 合并!词表从 257 变为 258
第 3 轮:"the" 出现了 50 万次 → 合并!词表从 258 变为 259
...
第 49744 轮:"algorithm" 出现了 800 次 → 合并!词表变为 50000 → 停止!
你可以看到:
- 前期合并的都是超高频的字母组合(th, he, in, er...)
- 中期合并的是常用单词(the, and, for...)
- 后期合并的是较长但频率还可以的词(algorithm, learning...)
- 非常罕见的词永远不会被合并成一个整体,而是被拆成已有的子词
Q2:th 和 he 如何合并?它们会冲突吗?
答案:它们不会直接合并!
关键点:只有”紧挨着”的符号对才会被考虑。
"the" 这个词:
第 1 轮:[t, h, e]
可能的对:(t,h) 和 (h,e)
假设 (t,h) 在整个数据里最多 → 合并
变成:[th, e]
第 2 轮:[th, e]
可能的对:(th, e)
如果 (th,e) 在整个数据里最多 → 合并
变成:[the]
th 和 he 不会”抢”,因为:
- “th” 先和 “e” 合并成 “the”
- “he” 可能在别的地方(比如 “hello”)和其他字母合并
Q3:合并是一层层往上走的吗?
是的!就像搭积木。
层级结构:
第 0 层(最底层):单个字母
[t] [h] [e] [c] [a] [t]
第 1 层:常见的2字母组合
[th] [e] [c] [a] [t]
第 2 层:常见的3字母组合
[the] [c] [a] [t]
第 3 层:常见的4字母组合
[the] [cat]
...
越往上,组合越长,但出现频率越低。
初始词表从哪来?
现代 BPE 从 256 个 UTF-8 字节开始。
什么意思?
UTF-8 用 256 个基础字节编码所有字符。
即使遇到从没见过的文字(比如生僻的藏文),也能用字节拼出来。
这保证了:任何文字都能被分词,不会出现”不认识”的情况。
12岁版类比:
想象你有 256 个乐高积木(编号 0-255)。
英文字母 "A" = 用 1 个积木(编号 65)
中文 "你" = 用 3 个积木拼起来
积木 228 + 积木 189 + 积木 160
emoji "😀" = 用 4 个积木拼起来
积木 240 + 积木 159 + 积木 152 + 积木 128
所以初始词表就是这 256 个”基础积木”。
2.5 其他分词方法
| 方法 | 谁在用 | 和 BPE 的区别 |
|---|---|---|
| BPE | GPT 全系列 | 按出现频率合并 |
| WordPiece | BERT(Google) | 合并时考虑”合并后对整体更有帮助”(用概率计算),而不是只看频率 |
| SentencePiece | LLaMA、Qwen | 一个工具库,支持 BPE 和 Unigram 两种模式。最大特点:不需要预切词,直接处理原始字节。特别适合中日韩等没有空格的语言 |
12岁版解释:BPE 像是”谁出现次数多就合并谁”,WordPiece 是”合并谁最有助于理解全文就合并谁”,SentencePiece 是”什么语言都能处理的万能版”。
为什么主流用 BPE?
三个原因:
- 简单:原理容易理解,实现简单
- 通用:适用于所有语言
- 效果好:在实践中表现优秀
学会 BPE,其他的一看就懂。
各模型的分词器参数
| 模型 | 分词方法 | 词表大小 | 一句话说明 |
|---|---|---|---|
| GPT-2 | BPE | 50,257 | 英文为主 |
| GPT-4 | BPE (cl100k) | ~100,000 | 大幅增加多语言 Token |
| BERT | WordPiece | 30,522 | 面向英文理解任务 |
| LLaMA-2 | SentencePiece | 32,000 | 英文为主 |
| Qwen-2 | BPE | 151,646 | 专门优化中文 |
2.6 词表大小如何选择?
答案:人为设定,根据需求平衡
类比:记笔记要不要发明缩写?
词表小(比如 1000)
几乎不发明缩写,每个字都单独写。
"人工智能" → [人, 工, 智, 能]
优点:词表小,占内存少
缺点:写得很慢,效率低
词表大(比如 100000)
发明很多缩写。
"人工智能" → [人工智能]
优点:写得快,效率高
缺点:要记很多缩写,词表占内存大
词表大小的权衡表
| 词表大小 | 优点 | 缺点 |
|---|---|---|
| 小(1万) | 占内存少 训练快 推理快 | 很多词被拆碎 表达能力弱 序列变长 |
| 中(5万) | 平衡 ✅ | 平衡 |
| 大(15万) | 常用词保持完整 表达能力强 序列变短 | 占内存多 训练慢 推理慢 罕见词浪费空间 |
具体例子
句子:"我今天学习了人工智能和深度学习"
词表小(1万):
→ [我, 今, 天, 学, 习, 了, 人, 工, 智, 能, 和, 深, 度, 学, 习]
→ 15个Token
→ 序列长,计算慢
词表中(5万):
→ [我, 今天, 学习, 了, 人工智能, 和, 深度, 学习]
→ 8个Token
→ 平衡 ✅
词表大(15万):
→ [我, 今天, 学习了, 人工智能, 和, 深度学习]
→ 6个Token
→ 序列短,但词表占内存大
为什么不是越大越好?
1. 内存占用
词表大小5万,向量维度768:
Embedding层参数 = 50,000 × 768 = 3840万个参数
占内存约150 MB
词表大小15万,向量维度768:
Embedding层参数 = 150,000 × 768 = 1.152亿个参数
占内存约450 MB
多了300 MB!
2. 罕见词浪费空间
词表里有15万个词,但:
- 前1万个词覆盖了95%的文本
- 后5万个词可能一年都用不到一次
这5万个罕见词占了大量内存,但几乎不用。
3. 训练效率
词表越大 → 输出层越大 → 计算概率分布越慢
输出层要计算词表中每个词的概率:
词表5万:计算5万个概率
词表15万:计算15万个概率(慢3倍)
结论:不是越大越好,而是根据需求平衡。
经验法则:3万到10万之间比较常见。
第三部分:从分词到模型的完整流程
这一部分解决什么问题?
核心问题:分词得到的只是数字ID(如1234、5678),这些ID本身没有任何意义。模型如何理解这些ID代表的”含义”?
解决方案:Embedding层 —— 把每个ID映射成一个高维向量,向量中包含了词的语义信息。
为什么不用Word2Vec:Word2Vec是预训练好的固定向量,无法随着模型学习而优化。现代模型的Embedding层和模型一起训练,能学到更准确的语义表示。
3.1 Tokenization vs Word2Vec vs Embedding
这是个超级重要的问题!很多人都混淆。
核心区别表
| Tokenization | Word2Vec | Embedding | |
|---|---|---|---|
| 做什么 | 把文字变成数字ID | 把词变成向量 | 把词ID变成向量 |
| 输出 | 整数(0, 1, 2, …) | 向量([0.2, -0.5, 0.8, …]) | 向量([0.2, -0.5, 0.8, …]) |
| 输出维度 | 1个数字 | 通常300个数字 | 通常768个数字 |
| 目的 | 让计算机能”读”文字 | 让计算机理解词的”意思” | 让计算机理解词的”意思” |
| 是否包含语义 | ❌ 不包含 | ✅ 包含 | ✅ 包含 |
| 训练方式 | 统计算法(BPE) | 预训练好,固定不变 | 和模型一起训练 |
| 现在用吗 | ✅ 必须用 | ❌ 基本废弃 | ✅ 必须用 |
详细解释
Tokenization(分词):
"猫吃鱼" → [0, 2, 3]
这里的 0, 2, 3 只是"编号",没有任何意义。
就像学号:
张三是1号
李四是2号
1和2之间没有任何关系,只是个标识。
Word2Vec(词向量,2013年的老技术):
"猫" → [0.8, 0.9, 0.1, -0.3, 0.2, ...] (300个数字)
"狗" → [0.7, 0.85, 0.15, -0.25, 0.18, ...]
"鱼" → [-0.2, 0.1, 0.9, 0.8, -0.5, ...]
这里的向量包含"意义":
- "猫"和"狗"的向量很接近(因为都是动物)
- "猫"和"鱼"的向量较远(一个是动物,一个是食物)
可以做数学运算:
"国王" - "男人" + "女人" ≈ "女王"
Embedding(嵌入,现代做法):
和Word2Vec类似,但:
- 不是预先训练好的
- 和模型一起训练
- 会根据上下文动态调整
为什么Word2Vec被废弃了?
Word2Vec的致命问题:一个词只有一个向量
"银行"的Word2Vec向量:[0.2, 0.5, -0.3, ...]
问题:
"我去银行取钱" ← 银行(金融机构)
"我坐在河银行" ← 银行(河岸)
Word2Vec给这两个"银行"同样的向量!
它分不清上下文。
Transformer + Embedding的优势:根据上下文动态生成向量
"我去银行取钱"
→ "银行"的向量:[0.8, 0.2, 0.1, ...](偏向金融)
"我坐在河银行"
→ "银行"的向量:[0.1, 0.9, 0.3, ...](偏向河岸)
同一个词,不同上下文,不同向量!
结论:现在主流都用Transformer + Embedding,Word2Vec基本退出历史舞台了。
现代做法(代码示例)
import torch.nn as nn
class GPT(nn.Module):
def __init__(self, vocab_size, d_model):
super().__init__()
# 这个 Embedding 层会和模型一起训练
# 不需要预先用 Word2Vec 训练
self.token_embedding = nn.Embedding(vocab_size, d_model)
# vocab_size: 词表大小(比如 50000)
# d_model: 向量维度(比如 768)
def forward(self, x):
# x: [batch_size, seq_len] 词 ID 序列
# 输出: [batch_size, seq_len, d_model] 词向量
return self.token_embedding(x)3.2 完整的文字处理流程图
从输入到输出的完整路径
这个流程图展示了用户输入的文字如何一步步被处理,最终生成回复。理解这个流程,你就理解了大语言模型的核心工作原理。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
完整流程
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
用户输入:"今天天气很好"
↓
┌─────────────────────────────────────┐
│ [Tokenization] 分词 │
│ 技术:BPE算法 │
│ 作用:文字 → 数字ID │
└─────────────────────────────────────┘
↓
数字ID序列:[1234, 5678, 9012, 3456]
↓
┌─────────────────────────────────────┐
│ [Embedding] 嵌入层 │
│ 技术:神经网络的一层 │
│ 作用:数字ID → 向量 │
│ 替代了:Word2Vec │
└─────────────────────────────────────┘
↓
向量序列:
[0.8, 0.9, 0.1, -0.3, ...] ← 词1234的向量
[0.7, 0.85, 0.15, -0.25, ...] ← 词5678的向量
[0.1, -0.5, 0.7, 0.2, ...] ← 词9012的向量
[-0.2, 0.1, 0.9, 0.8, ...] ← 词3456的向量
↓
┌─────────────────────────────────────┐
│ [Transformer] 模型架构 │
│ 技术:注意力机制 │
│ 作用:理解向量之间的关系 │
└─────────────────────────────────────┘
↓
输出向量
↓
┌─────────────────────────────────────┐
│ [输出层] 预测下一个词 │
│ 输出:词表中每个词的概率 │
└─────────────────────────────────────┘
↓
概率分布:
词0: 0.001
词1: 0.003
...
词7890: 0.85 ← 最高
...
↓
选中词ID:7890
↓
┌─────────────────────────────────────┐
│ [反向查表] 词ID → 文字 │
└─────────────────────────────────────┘
↓
输出:"明天"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3.3 GPT-4如何使用词表?
普通人以为的
用户输入:"今天天气怎么样?"
↓
GPT-4直接理解文字
↓
GPT-4直接生成文字:"今天天气很好!"
实际上的
用户输入:"今天天气怎么样?"
↓
[预处理] Tokenization
"今天天气怎么样?" → [1234, 5678, 9012, 3456]
↓
[GPT-4真正看到的]
[1234, 5678, 9012, 3456]
↓
[GPT-4内部处理]
数字 → 向量 → Transformer计算 → 概率分布
↓
[GPT-4输出]
[7890, 2345, 6789, 1234, 5678]
↓
[后处理] Detokenization
[7890, 2345, 6789, 1234, 5678] → "今天天气很好!"
↓
用户看到:"今天天气很好!"
所以GPT-4从头到尾都在处理数字,从来没有”看到”过文字!
类比
你和一个只会说法语的人交流:
你说中文 → 翻译成法语 → 他理解 → 他说法语 → 翻译成中文 → 你理解
GPT-4就是那个"只会说数字语言"的人。
Tokenization就是翻译官。
GPT-4生成文字的详细流程
用户输入:"今天天气"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[步骤1] Tokenization(用词表)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"今天天气" → 查词表 → [1234, 5678]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[步骤2] 模型处理
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入:[1234, 5678]
模型内部计算...(Transformer 的复杂运算)
输出:下一个词的概率分布(词表中每个词都有一个概率)
概率分布(词表有 50000 个词):
词 0("的"): 0.001
词 1("不"): 0.0005
词 2("是"): 0.003
...
词 9527("很"): 0.85 ← 概率最高!
...
词 49999("。"): 0.002
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[步骤3] 选择一个词
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
从概率分布中选择:
- 贪心:选概率最高的(词 9527)
- 采样:按概率随机选(让输出更多样)
选中:词 9527
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[步骤4] 把词 ID 转回文字(用词表)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
9527 → 查词表 → "很"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[步骤5] 继续生成下一个词
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入变成:[1234, 5678, 9527]
重复步骤2-4
生成词 ID:12345 → 查词表 → "好"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
最终输出:"今天天气很好"
关键点
GPT-4 的输出不是直接生成文字,而是:
- 输出一个概率分布(词表中每个词的概率)
- 从概率分布中选一个词(的 ID)
- 把词 ID 转回文字(查词表)
- 重复上述过程,一个词一个词地生成
所以词表是必需的!
- 输入需要词表:文字 → 词 ID
- 输出需要词表:词 ID → 文字
词表大小和生成能力的关系
词表小(比如 1000):
模型每次只能从 1000 个词里选
→ 表达能力弱
→ 很多词要拆成碎片
例子:
"人工智能" → ["人", "工", "智", "能"]
生成时也只能一个字一个字选
词表大(比如 100000):
模型每次可以从 100000 个词里选
→ 表达能力强
→ 可以生成更多样化的文字
→ 常用词组保持完整
例子:
"人工智能" → ["人工智能"]
生成时可以直接选中"人工智能"这个词
GPT-4 的词表约 10 万个,所以它每次可以从 10 万个选项中选择最合适的词。
类比:自动贩卖机
词表小 = 贩卖机只有 10 种饮料
→ 你只能从这 10 种里选
→ 选择少
词表大 = 贩卖机有 1000 种饮料
→ 你可以选到更精确的饮料
→ 选择多
GPT-4 就像一个有 10 万种选项的”词汇贩卖机”,每次生成时都从这 10 万个词里选一个最合适的。
第四部分:概念关系图
4.1 Tokenization → Embedding → Transformer → GPT-4
简化版关系
Tokenization(分词)
↓ 把文字变成数字ID
Embedding(嵌入)
↓ 把数字ID变成向量
Transformer(架构)
↓ 处理向量
GPT-4(具体模型)
↓ 用Transformer架构实现的生成模型
Word2Vec(老技术)
↓ 被Embedding取代了
完整流程图(从输入到输出)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
完整流程
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
用户输入:"今天天气很好"
↓
┌─────────────────────────────────────┐
│ [Tokenization] 分词 │
│ 技术:BPE算法 │
│ 作用:文字 → 数字ID │
└─────────────────────────────────────┘
↓
数字ID序列:[1234, 5678, 9012, 3456]
↓
┌─────────────────────────────────────┐
│ [Embedding] 嵌入层 │
│ 技术:神经网络的一层 │
│ 作用:数字ID → 向量 │
│ 替代了:Word2Vec │
└─────────────────────────────────────┘
↓
向量序列:
[0.8, 0.9, 0.1, -0.3, ...] ← 词1234的向量
[0.7, 0.85, 0.15, -0.25, ...] ← 词5678的向量
[0.1, -0.5, 0.7, 0.2, ...] ← 词9012的向量
[-0.2, 0.1, 0.9, 0.8, ...] ← 词3456的向量
↓
┌─────────────────────────────────────┐
│ [Transformer] 模型架构 │
│ 技术:注意力机制 │
│ 作用:理解向量之间的关系 │
└─────────────────────────────────────┘
↓
输出向量
↓
┌─────────────────────────────────────┐
│ [输出层] 预测下一个词 │
│ 输出:词表中每个词的概率 │
└─────────────────────────────────────┘
↓
概率分布:
词0: 0.001
词1: 0.003
...
词7890: 0.85 ← 最高
...
↓
选中词ID:7890
↓
┌─────────────────────────────────────┐
│ [反向查表] 词ID → 文字 │
└─────────────────────────────────────┘
↓
输出:"明天"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
它们的定位
| 概念 | 类型 | 作用 | 在流程中的位置 |
|---|---|---|---|
| Tokenization | 预处理技术 | 文字→数字ID | 最开始 |
| Embedding | 神经网络层 | 数字ID→向量 | Tokenization之后 |
| Word2Vec | 老技术 | 数字ID→向量 | 被Embedding取代 |
| Transformer | 模型架构 | 处理向量 | Embedding之后 |
| GPT-4 | 具体模型 | 完整系统 | 包含上面所有 |
类比理解
建造一栋房子:
Tokenization = 把原材料(木头)切成标准尺寸的木板
↓
Embedding = 给每块木板编号,记录它的属性(长度、重量、材质)
↓
Transformer = 建筑设计图(怎么把木板组装成房子)
↓
GPT-4 = 完整的房子(用Transformer设计图建成的)
Word2Vec = 老式的木板编号方法(已经不用了)
4.2 BERT vs GPT:理解模型 vs 生成模型
BERT = Bidirectional Encoder Representations from Transformers
中文:双向编码器表示
BERT的训练方式:完形填空
原始句子:"我今天去[MASK]吃饭"
BERT的任务:猜[MASK]是什么词
可能的答案:
"餐厅" - 概率80%
"食堂" - 概率15%
"家里" - 概率5%
关键特点:
- 可以看左边的词(“我今天去”)
- 也可以看右边的词(“吃饭”)
- 所以叫”双向”
GPT和BERT的核心区别
GPT(自回归,只看左边):
输入:"我今天去"
任务:预测下一个词
只能看左边 →→→
"我今天去" → 预测 → "餐厅"
BERT(掩码,看左右两边):
输入:"我今天去[MASK]吃饭"
任务:猜中间的词
可以看左边和右边 ←→
"我今天去" ← [MASK] → "吃饭"
综合左右信息 → 猜 → "餐厅"
BERT当时的意义(2018年)
革命性突破!
2018年之前:
- Word2Vec:词向量是固定的
- 不考虑上下文
2018年BERT:
- 词向量根据上下文动态变化
- "银行"在不同句子里有不同的向量
结果:
- 在11个NLP任务上刷新记录
- 引发了"预训练+微调"的范式
BERT证明了:
- Transformer架构非常强大
- 大规模预训练有效
- 双向理解比单向更好(对于理解任务)
BERT现在的意义(2025年)
地位下降,但仍有价值
✅ BERT还在用的地方:
- 搜索引擎(Google搜索用BERT理解查询)
- 文本分类(垃圾邮件检测、情感分析)
- 问答系统(理解问题)
- 信息抽取(从文本中提取关键信息)
❌ BERT不适合的地方:
- 文本生成(写文章、聊天)
- 代码生成
- 创意写作
为什么BERT不适合生成?
BERT的训练方式:
"我今天去[MASK]吃饭" → 猜中间的词
问题:
- 它只会"填空",不会"续写"
- 生成文本需要一个词一个词往后写
- BERT做不到
GPT的训练方式:
"我今天去" → 预测下一个词 → "餐厅"
"我今天去餐厅" → 预测下一个词 → "吃"
"我今天去餐厅吃" → 预测下一个词 → "饭"
天然适合生成!
总结对比
| BERT | GPT | |
|---|---|---|
| 训练方式 | 完形填空(掩码) | 预测下一个词 |
| 看的方向 | 双向(左右都看) | 单向(只看左边) |
| 擅长 | 理解任务 | 生成任务 |
| 典型应用 | 搜索、分类、问答 | 写作、聊天、代码生成 |
| 代表模型 | BERT、RoBERTa | GPT-2/3/4、LLaMA |
| 现在地位 | 特定领域还在用 | 主流 |
4.3 Gemini是什么?
Gemini = Google的GPT竞品
OpenAI(美国):
GPT-2 → GPT-3 → GPT-4
Google(美国):
BERT(2018) → LaMDA(2021) → PaLM(2022) → Gemini(2023)
关键点:
- BERT是2018年的技术,主要用于理解任务(搜索、分类)
- Gemini是2023年的技术,是生成模型,和GPT-4竞争
- Gemini不是基于BERT,而是基于Transformer的自回归生成模型(和GPT一样)
完整时间线
2013年:Word2Vec
→ 词向量的开端
2017年:Transformer
→ 注意力机制,统治NLP
2018年:BERT(Google)
→ 双向理解,刷新记录
→ 证明了预训练的威力
2018年:GPT-1(OpenAI)
→ 单向生成
2019年:GPT-2
→ 生成能力大幅提升
2020年:GPT-3
→ 1750亿参数,震惊世界
2022年:ChatGPT
→ GPT-3.5 + RLHF
→ 引爆AI热潮
2023年:GPT-4
→ 多模态,更强大
2023年:Gemini(Google)
→ Google的GPT竞品
→ 也是生成模型,不是BERT
第五部分:数据收集与清洗
这一部分解决什么问题?
核心问题:前面讲了如何处理文字(编码、分词、Embedding),但这些文字从哪来?如何保证质量?
解决方案:数据收集与清洗 —— 从互联网爬取海量文本,然后过滤掉垃圾数据,只保留高质量内容。
为什么重要:垃圾进,垃圾出(Garbage In, Garbage Out)。数据质量直接决定模型质量。GPT-4之所以强大,很大程度上是因为训练数据的质量极高。
5.1 数据从哪来?
想象你要教一个完全不懂人类语言的外星人学中文。你会怎么做?
最简单的办法:给它海量的中文文章去读。它读得越多、越广,就越能理解中文。
大语言模型学语言的方式和这完全一样——给它大量文本去”阅读”。
那这些文本从哪来?
| 数据来源 | 通俗解释 | 举例 |
|---|---|---|
| 互联网爬虫 | 一个自动程序,像蜘蛛一样爬遍网页,把文字复制下来 | Common Crawl 每月抓取 30-50 亿网页 |
| 书籍 | 电子书的文字版本 | 小说、教材、百科全书 |
| 代码 | 程序员写的代码 | GitHub 上几十亿行代码 |
| 百科 | 维基百科等知识型网站 | 约 400 万篇英文维基文章 |
| 论文 | 科学家写的研究成果 | arXiv 上几百万篇论文 |
| 论坛/社交 | 人们日常聊天、提问的内容 | Reddit、知乎、贴吧 |
什么是互联网爬虫?
打个比方:你想收集全班同学的笔记,但不想一个个去问。于是你写了一个”机器人”,它自动去每个同学那里,把笔记拍照复制回来。互联网爬虫就是这样一个自动程序——它访问网页,把页面上的文字”复制”下来保存。
Common Crawl 是世界上最大的公开爬虫项目,它每个月爬一遍互联网,积累了 PB 级(1 PB = 1,000 TB = 1,000,000 GB)的数据。
5.2 数据清洗的5个步骤
你爬下来的网页不是全都有用。想想看,一个网页上有:
- 文章正文 ✅(我们要的)
- 导航栏”首页 | 关于我们 | 联系方式” ❌
- 广告”点击领取优惠券!” ❌
- 乱码 “ä½ ” ❌
- 重复内容(同一篇文章被100个网站转载) ❌
所以必须清洗——把垃圾去掉,只留好的。
清洗要做的事:
原始爬虫数据(几百 TB)
│
├── 第1步:去除 HTML 标签
│ 网页代码长这样:<p>今天天气<b>很好</b></p>
│ 清洗后:今天天气很好
│
├── 第2步:语言过滤(用 fastText)
│ │
│ │ ❓ 什么是 fastText?
│ │ fastText 是 Facebook(Meta)开发的一个通用文本分类器。
│ │
│ │ 你训练它做什么分类,它就能做什么分类:
│ │ - 训练数据是"各种语言的文本 + 语言标签" → 它就能识别语言
│ │ - 训练数据是"邮件 + 垃圾/正常标签" → 它就能识别垃圾邮件
│ │ - 训练数据是"商品评论 + 好评/差评标签" → 它就能识别情感
│ │
│ │ 在数据清洗中,我们用它来识别语言:
│ │ 输入 "Hello world" → 英语(99%)
│ │ 输入 "今天天气很好" → 中文(98%)
│ │
│ │ 如果你要训练中文模型,就只保留中文文本。
│ │
│ └── 只保留目标语言的文本
│
├── 第3步:质量过滤
│ │
│ ├── ① 删掉太短的文本(<50个字)
│ │ 为什么?太短的文字通常是导航菜单、按钮文字、页脚
│ │ 这种碎片。比如 "返回顶部 | 下一页" 对模型毫无营养。
│ │ 实际做法:设置一个最低字数阈值,低于阈值直接丢弃。
│ │
│ ├── ② 删掉广告和推广内容
│ │ 怎么判断是不是广告?常用两种方法:
│ │ 方法A:关键词黑名单——包含"限时优惠""点击领取""加微信"
│ │ 等词汇的文本直接过滤。
│ │ 方法B:训练一个小分类模型——用人工标注的"广告/非广告"
│ │ 数据训练一个小模型(比如用 fastText),让它自动
│ │ 判断每段文字是不是广告。
│ │ (和你在邮箱里的"垃圾邮件过滤"原理一样)
│ │
│ ├── ③ 删掉乱码和编码错误
│ │ 什么是编码错误?
│ │ 计算机用"编码"来存储文字。中文最常用 UTF-8 编码。
│ │ 如果一段文字用 GBK 编码存储,但你当 UTF-8 来读,
│ │ 就会变成乱码:原文"你好" → 乱码"浣犲ソ"。
│ │ 检测方法:
│ │ - 统计"不可识别字符"的比例,超过阈值(如10%)就丢弃
│ │ - 用 chardet 库自动检测编码是否正确
│ │
│ └── ④ 删掉有害/违法内容
│ 为什么?如果训练数据包含暴力、色情、歧视性内容,
│ 模型学到这些后也会生成类似内容——这是非常危险的。
│ 做法:
│ - 用关键词列表初筛(包含敏感词的直接删除)
│ - 用专门训练的"有害内容检测模型"深度过滤
│ - 人工抽样审核(随机抽取一部分数据,人工检查)
│
├── 第4步:去重
│ │
│ │ ❓ 为什么要去重?
│ │ 如果同一篇文章出现了100遍,模型就会"死记硬背"这篇
│ │ 文章,而不是真正学到语言规律。就像你考试只背一道题,
│ │ 换个题就不会了。
│ │
│ │ ❓ 怎么去重?
│ │ 用 MinHash 算法:它能快速判断两段文字是否"差不多"。
│ │ 不需要逐字对比,只需要算一个"指纹",指纹相似的就是重复。
│ │ (就像每个人有指纹,两个指纹一样就知道是同一个人)
│ │
│ └── 删除近似重复的文本
│
└── 第5步:隐私过滤
└── 删除包含个人信息(手机号、邮箱、身份证号)的内容
│
↓
清洗后的干净数据(通常只剩原来的 10%-30%)
实际数据:
- GPT-3 的训练数据:清洗后约 570 GB 纯文本
- LLaMA 的数据:原始 Common Crawl 中只用了约 67%(其余被清洗掉了)
5.3 不同语言如何处理?
训练时遇到多种语言怎么办?比如你想让模型既懂中文又懂英文。
方法1:混合训练(最主流 ✅)
把所有语言的文本混在一起训练。模型自动学会区分语言。
训练数据示例:
第1条:The cat sat on the mat.(英文)
第2条:今天天气真好。(中文)
第3条:今日はいい天気です。(日文)
第4条:The weather is nice today.(英文)
...
模型自己会学到不同语言的模式
但有一个关键问题:语言比例。
如果你 90% 放英文、10% 放中文,模型英文会很强、中文会很弱。 LLaMA-2 就因为中文数据太少,导致中文能力不行。 Qwen(通义千问)为了增强中文,专门提高了中文数据比例和中文词表。
方法2:分词器要支持多语言
如果你的分词器是纯英文 BPE 训练出来的,那中文字会被切成一个个 UTF-8 字节:
英文分词器处理中文:
"你好" → [ä½, 好] ← 完全是乱七八糟的字节碎片!效率极低
多语言分词器处理中文:
"你好" → [你好] ← 保留完整含义,效率高
12岁版解释:就像一本只有英文单词的字典,你要用它来查中文,只能把”你”拆成笔画来查,又慢又不准。正确做法是字典里本来就收录了中文词。
方法3:针对特定语言微调
先用多语言数据预训练一个通用模型,再专门用中文数据继续训练,强化中文能力。 这就是为什么国内模型(Qwen、DeepSeek、ChatGLM)的中文能力普遍比 LLaMA 强。
5.4 需要多大的数据集?
简短回答:取决于模型大小。有一条经验法则叫 Chinchilla 定律。
什么是 Chinchilla 定律?
2022 年,Google DeepMind 做了大量实验后发现:给定固定的计算预算,模型大小和训练数据量应该同步增长。不是越大越好——数据不够多的大模型,还不如数据充足的小模型。
具体的公式:
通俗解释:如果你的模型有 10 亿个参数,你大约需要 200 亿个 Token 来训练它。
| 模型参数量 | 最优 Token 数 | 大约多少文字 | 文件大小约 |
|---|---|---|---|
| 125M(实验级) | 2.5B | ~37 亿字 | ~5 GB |
| 1B(小型) | 20B | ~300 亿字 | ~40 GB |
| 7B(LLaMA 级) | 140B | ~2100 亿字 | ~280 GB |
| 70B(大型) | 1.4T | ~2 万亿字 | ~2.8 TB |
一个直观感受:一本 20 万字的书约 0.3 MB。训练一个 7B 模型需要约 100 万本书的文字量。
注意:LLaMA-3 等后续研究发现,给小模型喂更多数据(超过 Chinchilla 建议量)也能获得很好的效果。所以上面的数字是起点,不是上限。
如果你只是想学习和实验:
- 入门实验:几 MB 文本就够了
- 微调现有模型:几千到几万条 (指令, 回答) 对
- 训练一个能聊天的小模型:至少几 GB 中文纯文本
获取数据的最方便渠道:
# 用 HuggingFace Datasets,一行代码下载数据集
pip install datasets
from datasets import load_dataset
# 下载中文维基百科
dataset = load_dataset("wikipedia", "20220301.zh")
# 下载 RedPajama(英文大型数据集)
dataset = load_dataset("togethercomputer/RedPajama-Data-1T")常用中文数据集:
- WuDao(悟道)—— 中国最大开源中文数据集
- CLUECorpus2020 —— 约 100GB 中文文本
- 中文维基百科 —— 约 1.5GB
🧪 自我检验:20道思考题
如果你能回答这些问题,说明你真的掌握了3.1数据准备的所有内容:
基础题(检验概念理解)
- 为什么计算机需要编码?计算机能直接理解”你好”这两个字吗?
- ASCII、GBK、UTF-8 有什么区别?为什么现在都用UTF-8?
- 为什么会出现乱码?举一个具体的例子。
- 为什么是256个字节,而不是128个或512个?
- 256个字节如何表示所有文字?
- 什么是分词(Tokenization)?它的作用是什么?
- 按字切、按词切、按子词切有什么区别?各有什么优缺点?
中等题(检验原理理解)
- BPE是什么意思?每个字母代表什么?
- BPE算法的核心思想是什么?用一句话概括。
- BPE训练时,出现多少次才会被合并成一个Token?
- “th”和”he”在BPE中会冲突吗?为什么?
- BPE的初始词表是什么?为什么是256个字节?
- Tokenization和Word2Vec有什么区别?
- 为什么现代模型不用Word2Vec了?
- 什么是Embedding?它和Word2Vec的关系是什么?
进阶题(检验应用理解)
- GPT-4生成文字时,词表在哪些步骤用到?
- 词表越大越好吗?为什么?
- BERT和GPT的核心区别是什么?
- BERT擅长什么任务?GPT擅长什么任务?
- Gemini是基于BERT的吗?它是什么类型的模型?
📚 参考答案
基础题答案
-
为什么计算机需要编码? 计算机只认识0和1(二进制),无法直接理解”你好”这样的文字。编码就是一套”翻译规则”,规定每个字对应什么数字,这样计算机才能存储和处理文字。
-
ASCII、GBK、UTF-8的区别
- ASCII:只用7位,能表示128个字符,只够英文用
- GBK:中国制定的编码,能表示2万多个汉字,但只适用于中文
- UTF-8:国际标准,用可变长度字节(1-4个)表示所有语言的文字,现在的主流标准
-
为什么会出现乱码? 编码和解码用的规则不一致。例如:用GBK编码存储”你好”得到字节序列,但用UTF-8解码这个字节序列,就会得到乱码”浣犲ソ”。
-
为什么是256个字节? 1个字节=8位,8位可以表示2
-
256个字节如何表示所有文字? 通过组合不同长度的字节:英文用1个字节(256种),中文用3个字节(256³=1600万种),emoji用4个字节(256⁴=42亿种)。
-
什么是分词? 分词(Tokenization)是把文字变成数字ID序列的过程。例如”猫吃鱼”→[1, 3, 4]。模型处理的是数字,不是文字。
-
三种切分方法的区别
- 按字切:每个字一个Token,词表小但序列长
- 按词切:每个词一个Token,序列短但词表大,且无法处理新词
- 按子词切(BPE):平衡点,既能处理新词,词表也不会太大
中等题答案
-
BPE是什么意思? Byte Pair Encoding(字节对编码)。Byte=字节,Pair=配对,Encoding=编码。核心是找出最常出现的字节对,合并成新Token。
-
BPE的核心思想 从256个基础字节开始,反复找出出现频率最高的字节对,合并成新Token,直到达到目标词表大小。
-
BPE训练时的合并条件 没有固定次数要求。每轮合并时,选择当前出现频率最高的字节对进行合并,重复这个过程直到词表达到目标大小。
-
“th”和”he”会冲突吗? 不会。BPE是贪婪算法,从左到右匹配。“the”会先匹配到”th”(如果”th”已经是一个Token),然后再处理”e”。
-
BPE的初始词表 256个UTF-8基础字节(编号0-255)。这保证了任何文字都能被分词,即使是从未见过的生僻字。
-
Tokenization和Word2Vec的区别
- Tokenization:把文字变成数字ID(如”猫”→1),只是编号,没有语义
- Word2Vec:把词变成向量(如”猫”→[0.8, 0.9, …]),包含语义信息
-
为什么不用Word2Vec? Word2Vec是预训练好的固定向量,无法随模型学习而优化。现代模型用Embedding层,和模型一起训练,能学到更准确的语义表示。
-
什么是Embedding? Embedding是神经网络的一层,把Token ID映射成高维向量。它和Word2Vec的作用类似(都是把词变成向量),但Embedding是可训练的,会随着模型学习而优化。
进阶题答案
-
GPT-4使用词表的步骤
- 输入阶段:用词表把文字转成Token ID(“今天”→1234)
- 输出阶段:模型预测出Token ID(7890),再用词表转回文字(7890→“明天”)
- 词表就像一个双向字典,输入输出都要用到
-
词表越大越好吗? 不是。词表大的优点是序列短、表达精确,但缺点是占内存大、计算慢、罕见词浪费空间。需要权衡,通常3万到10万之间比较合适。
-
BERT和GPT的核心区别
- BERT:双向模型,能看左边和右边的词,擅长理解任务(完形填空)
- GPT:单向模型,只能看左边的词,擅长生成任务(预测下一个词)
-
BERT和GPT擅长的任务
- BERT:文本分类、情感分析、问答系统、命名实体识别等理解任务
- GPT:文本生成、对话、续写、翻译等生成任务
-
Gemini是什么类型的模型? Gemini是Google的生成模型,和GPT类似,不是基于BERT。它是单向自回归模型,擅长生成任务。BERT的时代已经过去,现在主流都是GPT类的生成模型。
📚 核心要点总结
你必须记住的10个核心概念
- ✅ 计算机只认识0和1,所有文字都需要编码成数字
- ✅ UTF-8是现代标准,用256个基础字节通过组合表示所有文字
- ✅ 分词是把文字变成数字ID,模型处理的是数字,不是文字
- ✅ BPE是主流分词算法,通过合并高频字符对来构建词表
- ✅ 词表大小需要权衡,不是越大越好,要平衡内存、速度、表达能力
- ✅ Tokenization ≠ Embedding,前者是编号,后者是向量
- ✅ Word2Vec已被淘汰,现代模型用Embedding层和模型一起训练
- ✅ GPT-4从头到尾处理数字,输入输出都需要词表转换
- ✅ BERT是理解模型,GPT是生成模型,训练方式和应用场景不同
- ✅ 数据质量比数量更重要,清洗后的数据通常只剩原来的10%-30%
🎓 费曼学习法检验
最终测试:找一个完全不懂AI的朋友,用你自己的话给他讲解:
- 计算机如何存储文字?
- 什么是分词?为什么需要分词?
- BPE算法是怎么工作的?
如果你能讲清楚,让朋友听懂,说明你真的掌握了。
如果讲不清楚,回到对应章节重新学习。
🚀 下一步
恭喜你完成了3.1数据准备章节!
现在你已经理解了:
- 计算机如何理解文字
- 如何把文字变成模型能处理的数字
- 数据从哪来,如何清洗
- 完整的文字处理流程
接下来学习:
- 3.2 Transformer架构 - 模型的”大脑结构”
- 3.3 预训练 - 让模型”阅读”海量文本
- 3.4 对齐与微调 - 让模型”听话”、“有用”
📖 参考资料
如果你想深入学习,推荐这些资源:
论文:
- Neural Machine Translation of Rare Words with Subword Units (BPE原论文, 2016)
- Attention Is All You Need (Transformer原论文, 2017)
- BERT: Pre-training of Deep Bidirectional Transformers (BERT原论文, 2018)
代码实现:
- HuggingFace Tokenizers: https://github.com/huggingface/tokenizers
- SentencePiece: https://github.com/google/sentencepiece
可视化工具:
- OpenAI Tokenizer: https://platform.openai.com/tokenizer
- 可以看到任何文本如何被分词
💡 记住:理解比记忆更重要。如果你能用自己的话解释这些概念,你就真的学会了。
💡 费曼学习法核心:如果你不能用简单的话讲清楚,说明你还没真正理解。