Lecture 1 Overview and Tokenization 课程笔记
当前研究者与底层技术脱节
8年前,研究人员会实施并训练自己的模型
6年前,研究人员会下载一个模型并进行微调
但现在,研究人员只是prompt一个专有模型(例如,GPT-4/Claude/Gemini)。
事实上 提高抽象层次可以提高生产力,但是
这些抽象是泄漏的,实际应用中,抽象背后的底层细节会不可避免地暴露出来,导致抽象的简化效果打折扣。
仍有一些基础研究需要撕毁堆栈,有些基础研究要突破现有抽象框架的限制,甚至推翻既有的层级结构,从底层重新探索,才能解决根本性问题 —— 因为现有抽象可能掩盖了深层矛盾,只有打破层级,才能触及本质。
所以充分了解这项技术对抗基础研究很有必要
本课程是通过实现来理解它
语言模型的产业化
GPT-4 据称具有 1.8T 参数。
GPT-4 的训练成本据称为 $100M。
此外,关于如何构建前沿模型的公开细节也没有。
![![[Pasted image 20250804162458.png]]](https://i-blog.csdnimg.cn/direct/0d50d8b7ee434db09e57bd363c71e459.png)
由于竞争和安全原因,不会公开细节
所以前沿模型对我们来说是遥不可及的
但是如果构建小型语言模型可能并不能代表大型语言模型
![![[Pasted image 20250804162631.png]]](https://i-blog.csdnimg.cn/direct/c1ede88307db48b3b37e1089acae9415.png)
随着参数变大,FFN(MLP)的所消耗的计算量(FLOPs)会越来越大,而MMA(注意力)的计算量会变小,所以随着参数变大,大模型中 FFN 的优化优先级可能高于注意力
大模型的涌现能力
![![[Pasted image 20250804162857.png]]](https://i-blog.csdnimg.cn/direct/cf7bbd67fafe4112b10d1d1e50c12d37.png)
随着参数变大,正确率会突然增加
在这门课程中能学到什么
事物工作的机制(什么是 Transformer,模型并行性如何利用 GPU)
对待规模和硬件的心态(规模定律)
哪些数据和建模会产生良好准确性的直觉(只能部分教授,因为小规模存在的规律可能在大规模上不存子啊)
直觉?
有些抉择根本不合理,但是实验结果好
![![[Pasted image 20250804163141.png]]](https://i-blog.csdnimg.cn/direct/6b6a48bab8fe4a288289f36d9188295b.png)
惨痛的教训
规模最重要,算法不重要❌
重要的是扩展的算法✅(deepseek?)
准确性=效率x资源
规模越大,效率更重要(不浪费资源)
在一定计算和预算下,效率最大的模型是最佳的
之前的语言模型:
1950年测量英语熵的语言模型
2007年大量关于 n-gram 语言模型的工作(用于机器翻译、语音识别)
2010年代后:
2003:第一个神经网络模型
2014序列到序列建模(用于机器翻译)
2014 注意力机制(用于机器翻译)
2017Transformer 架构(用于机器翻译)
2017 专家混合
2019 模型并行
早期基础模型 2010年代后期:
2018 ELMo:使用 LSTM 进行预训练,微调有助于任务
2018 BERT:用 Transformer 进行预训练,微调助力任务
2019 Google 的 T5 (11B):将所有内容转换为文本转文本
拥抱规模化,更封闭:
OpenAI 的 GPT-2 (1.5B):流畅的文本,零样本的初步迹象,分阶段发布
缩放定律:为缩放提供希望/可预测性
OpenAI 的 GPT-3 (175B):上下文学习,封闭式
谷歌的 PaLM (540B):大规模,训练不足
DeepMind 的 Chinchilla (70B):计算最优扩展定律
开源模型:
EleutherAI 的开放数据集 (The Pile) 和模型 (GPT-J)
Meta 的 OPT (175B):GPT-3 复制,很多硬件问题
Hugging Face / BigScience 的 BLOOM:专注于数据来源
Meta’s Llama models Meta 的 Llama 模型
Alibaba’s Qwen models 阿里巴巴的 Qwen 模型
DeepSeek’s models DeepSeek 的模型
AI2’s OLMo 2 AI2 的 OLMo 2
开放程度:
封闭模型(例如 GPT-4o):仅 API 访问
开放权重模型(例如 DeepSeek):权重可用,包含架构详细信息的论文,一些训练细节,没有数据细节
开源模型(例如 OLMo):权重和可用数据,包含大多数细节的论文(但不一定是基本原理,失败的实验)
前沿模型:
OpenAI ’s o3
Anthropic’s Claude Sonnet 3.7
xAI’s Grok 3
Google’s Gemini 2.5
Meta’s Llama 3.3
DeepSeek’s r1
Alibaba’s Qwen 2.5 Max
Tencent’s Hunyuan-T1
一切都和效率有关
资源:数据+硬件(计算、内存、通信带宽)
在一组固定的资源的情况下,如何训练最佳模型?
示例:给定一个 Common Crawl 转储和 32 个 H100 2 周,应该怎么做?
设计决策:
![![[Pasted image 20250804164846.png]]](https://i-blog.csdnimg.cn/direct/70ffc3cf460c4913bc94d6af256f2a58.png)
基础 系统 尺度定律 数据 对齐
基础
目标:获得完整管道工作的基本版本
组件:分词器、模型架构、训练
分词器
在字符串和整数序列(标记)之间进行转换
![![[Pasted image 20250804165116.png]]](https://i-blog.csdnimg.cn/direct/8e1b02c0b7714561877e3ac0c91e64a7.png)
直觉:将字符串分解为片段
字节对编码 (BPE) 分词器 简单并且仍然在使用
无分词器的方法:
直接使用字节,很有前途,但尚未扩展到前沿。
模型架构:
原版Transformer
![![[Pasted image 20250804165242.png]]](https://i-blog.csdnimg.cn/direct/4d5505b25c0a400ab3243b78fca648f3.png)
变种(改进):
激活函数:ReLU、SwiGLU
位置编码:正弦、RoPE
规范化:LayerNorm、RMSNorm
归一化的位置:前规范与后规范
MLP:密集、专家混合
注意:全推拉窗,线性
低维注意力:群体查询注意力(GQA)、多头潜在注意力(MLA)
国家空间模型:鬣狗
训练:
优化器(例如 AdamW、Muon、SOAP)
学习率表(例如余弦、WSD)
批量大小(例如 g,临界批量大小)
正则化(例如,辍学、权重衰减)
超参数(头数、隐藏维度):网格搜索
作业一:
实现 BPE 分词器
实现 Transformer、交叉熵损失、AdamW 优化器、训练循环(可使用Pytorch部分函数)
在 TinyStories 和 OpenWebText 上进行训练
排行榜:在 H100 上给定 90 分钟时,最大限度地减少 OpenWebText 的困惑
系统:
核心:
GPU (A100) 是什么样子的:
![![[Pasted image 20250804165659.png]]](https://i-blog.csdnimg.cn/direct/375b053a01084a5889b44ab529a800ec.png)
类比于仓库和工厂
![![[Pasted image 20250804165715.png]]](https://i-blog.csdnimg.cn/direct/b718ad61be534396be6afecd9f2110a9.png)
技巧:通过最大限度地减少数据移动来组织计算以最大限度地提高 GPU 的利用率
并行化:
![![[Pasted image 20250804165815.png]]](https://i-blog.csdnimg.cn/direct/cb712f8ac91a4090b9abfcea6c1e715c.png)
如果我们有多个 GPU(8 个 A100)怎么办?
GPU 之间的数据移动速度甚至更慢,但同样的“最小化数据移动”原则成立
使用集合操作(例如,收集、减少、全部减少)
跨 GPU 的分片(参数、激活、梯度、优化器状态)
如何拆分计算:{data,tensor,pipeline,sequence} parallelism
推理:
在提示下生成token(需要实际使用模型)
强化学习、测试时计算、评估也需要推理
在全球范围内,推理计算(每次使用)超过训练计算(一次性成本)
两个阶段:预填充和解码
![![[Pasted image 20250804170255.png]]](https://i-blog.csdnimg.cn/direct/6fa2f596b8ef4c3aa342b00ca736fa58.png)
Prefill(类似于训练):给出令牌,可以一次性处理所有(计算绑定)
Decode:需要一次生成一个令牌(内存绑定,很难充分利用GPU)
加速解码的方法:
使用更便宜的模型(通过模型修剪、量化、蒸馏)
推测解码:使用更便宜的“草稿”模型生成多个tokens,然后使用完整模型并行评分(精确解码!)
系统优化:KV 缓存、批处理
作业2:
在 Triton 中实现融合的 RMSNorm 内核
实现分布式数据并行训练
实现优化器状态分片
对实施进行基准测试和分析
规模定律:
目标:做小规模实验,大尺度预测超参数/损失
问题:给定 FLOP 预算(CCC),使用更大的模型($N 美元)还是训练更多token($D 美元)?
计算最优缩放定律
![![[Pasted image 20250804170723.png]]](https://i-blog.csdnimg.cn/direct/eddde6f3620b4b6aab5a8afa0f50c4ae.png)
但这还没有考虑到推理成本!
作业三:
我们根据以前的运行定义了一个训练 API(超参数 -> 损失)
提交“训练作业”(在 FLOP 预算下)并收集数据点
将缩放定律拟合到数据点
提交纵向扩展超参数的预测
排行榜:在失败预算的情况下最大限度地减少损失
数据(关键):
问题:我们希望模型具备哪些功能?多语言?代码 ?数学?
![![[Pasted image 20250804171231.png]]](https://i-blog.csdnimg.cn/direct/56e75ecac8074d5aa7dc36dcf00c9d2e.png)
评估:
困惑:语言模型的教科书评估
标准化测试(例如 MMLU、HellaSwag、GSM8K)
遵循指令(例如,AlpacaEval、IFEval、WildBench)
扩展测试时计算:思维链、集成
LM-as-a-judge:评估生成任务
完整系统:RAG、agents
数据创造:
数据不是从天而降的。
来源:从互联网、书籍、arXiv 论文、GitHub 代码等中抓取的网页。
诉诸合理使用以进行版权数据训练?
可能需要许可数据(例如,使用 Reddit 数据的 Google)
格式:HTML、PDF、目录(不是文本!)
数据处理:
转换:将 HTML/PDF 转换为文本(保留内容、部分结构、重写)
过滤:保留高质量数据,删除有害内容(通过分类器)
重复数据删除:节省计算,避免记忆;使用 Bloom 过滤器或 MinHash
作业四:
将 Common Crawl HTML 转换为文本
训练分类器以过滤质量和有害内容
使用 MinHash 进行重复数据删除
排行榜:在给定token预算的情况下最大限度地减少困惑
对齐:
到目前为止,一个基础模型是原始潜力,非常擅长完成下一个token。
对齐使模型真正有用。
对其的目标:
获取语言模型以遵循说明
调整风格(格式、长度、语气等)
纳入安全(例如,拒绝回答有害问题)
作业五:
实施监督微调
收集了一组对话,然后进行监督学习
直觉:基础模型已经具备了技能,只需要几个例子就可以浮出水面。,例子越多,结果越好
监督学习:微调模型以最大化 p(response | prompt)。
实现直接偏好优化 (DPO)
实施组相对偏好优化 (GRPO)
从反馈中学习:
现在我们有一个初步的指令遵循模型。
让我们在没有昂贵的注释的情况下让它变得更好。
偏好数据:
数据:使用模型(例如,[A,B])生成对给定提示的多个响应。
用户提供偏好(例如,A < B 或 A > B)。
验证器:
形式验证器(例如,用于代码、数学)
学习验证者:针对 LM 作为jueger进行训练
算法:
强化学习的近端策略优化 (PPO)
直接策略优化 (DPO):对于偏好数据,更简单
组相对偏好优化 (GRPO):去除值函数
效率推动设计决策
今天,我们受到计算限制,因此设计决策将反映出充分利用给定硬件。
数据处理:避免在不良/不相关的数据上浪费宝贵的计算更新
标记化:使用原始字节很优雅,但对于当今的模型架构来说,计算效率低下。
模型架构:许多由减少内存或 FLOP 驱动的更改(例如,共享 KV 缓存、滑动窗口注意力)
训练:我们可以在一个epoch中逃脱惩罚!
规模定律:在较小的模型上使用更少的计算来进行超参数优化
对齐:如果将模型更多地调整到所需的用例,则需要更小的基本模型
Tokenization
原始文本通常表示为 Unicode 字符串。
string = “Hello, 🌍! 你好!”
语言模型在标记序列(通常由整数索引表示)上放置概率分布。
indices = [15496, 11, 995, 0]
所以我们需要一个将字符串编码为标记的过程。
我们还需要一个将标记解码回字符串的过程。
分词器是实现编码和解码方法的类。
现象:
单词及其前面的空格是同一标记的一部分(例如,“世界”)。
开头和中间的单词表示方式不同(例如,“hello hello”)。
数字被标记为每几位数字。
压缩比:
每个令牌代表1.6个字节
![![[Pasted image 20250804173902.png]]](https://i-blog.csdnimg.cn/direct/55183be7d7574450866b5f4598479d23.png)
基于字符的标记化
Unicode 字符串是 Unicode 字符序列。
每个字符都可以通过 ord 转换为一个代码点(整数)。
assert ord(“a”) == 97
assert ord(“🌍”) == 127757
可以通过 chr 转换回。
assert chr(97) == “a”
assert chr(127757) == “🌍”
问题 1:这是一个非常大的词汇量。
问题 2:许多字符非常罕见(例如,🌍),这是词汇的低效使用。
基于字节的标记化
Unicode 字符串可以表示为字节序列,可以用 0 到 255 之间的整数表示。
最常见的 Unicode 编码是 UTF-8
一些 Unicode 字符由一个字节表示:
assert bytes(“a”, encoding=“utf-8”) == b"a"
其他占用多个字节:
assert bytes(“🌍”, encoding=“utf-8”) == b"\xf0\x9f\x8c\x8d"
现在让我们构建一个 Tokenizer 并确保它往返:
tokenizer = ByteTokenizer()
string = “Hello, 🌍! 你好!”
indices = tokenizer.encode(string)
reconstructed_string = tokenizer.decode(indices)
assert string == reconstructed_string
词汇量很好,而且很小:一个字节可以代表 256 个值。
问题:
压缩比为1
这意味着序列会太长。
鉴于 Transformer 的上下文长度是有限的(因为注意力是二次的),这看起来不太好…
基于单词的标记化
![![[Pasted image 20250804174451.png]]](https://i-blog.csdnimg.cn/direct/f0cbfd6382634752ba39eb95c82637d3.png)
另一种方法(更接近 NLP 中的经典方法)是将字符串拆分为单词。
string = “I’ll say supercalifragilisticexpialidocious!”
segments = regex.findall(r"\w+|.", string) # @inspect segments
此正则表达式将所有字母数字字符(单词)放在一起。
但也有问题:
单词数量很大(就像 Unicode 字符一样)。
许多单词很少见,模型不会对它们了解太多。
这显然没有提供固定的词汇量。
在训练中没有看到的新单词获得一个特殊的 UNK 标记,这很丑陋,并且会扰乱困惑度计算。
字节对编码(BPE)
基本思想:在原始文本上训练分词器以自动确定词汇量。
直觉:常见的字符序列由单个标记表示,罕见序列由许多标记表示。
GPT-2 论文使用基于单词的标记化将文本分解为初始片段,并在每个片段上运行原始的 BPE 算法。
从每个字节作为标记开始,依次合并最常见的相邻标记对。
训练分词器
string = “the cat in the hat” # @inspect string
params = train_bpe(string, num_merges=3)
![![[Pasted image 20250804174804.png]]](https://i-blog.csdnimg.cn/direct/5f69d4455d9b41b6aa6545b79ae9d735.png)

PE 是自然语言处理中常用的子词分词算法:
- 函数定义:
train_bpe接收两个参数(输入字符串string和合并次数num_merges),返回一个BPETokenizerParams对象,包含训练好的词汇表和合并规则。 - 初始化:
- 将输入字符串编码为 UTF-8 字节序列,并转换为整数列表
indices merges字典记录合并规则(键为待合并的索引对,值为新索引)vocab字典构建初始词汇表,包含所有 256 个可能的字节值
- 将输入字符串编码为 UTF-8 字节序列,并转换为整数列表
- 核心训练循环(执行
num_merges次合并):- 统计当前
indices中所有相邻索引对的出现次数 - 找到出现次数最多的索引对
pair - 为这个合并对创建新索引(从 256 开始递增)
- 记录合并规则并在词汇表中添加新条目(合并后的字节序列)
- 使用
merge函数更新indices列表,将所有出现的该索引对替换为新索引
- 统计当前
- 返回结果:将训练好的词汇表和合并规则封装成
BPETokenizerParams对象返回
整个过程从最基础的字节开始,通过不断合并最频繁出现的相邻对,逐步构建更复杂的子词单元,最终形成适合特定文本的分词器参数。
总结:
分词器:字符串<>标记(索引)
基于字符、基于字节、基于单词的标记化高度次优
BPE 是一种有效的启发式方法,它着眼于语料库统计数据
标记化是一种必要的邪恶,也许有一天我们会从字节开始…
总结:
-
当前研究者与底层技术的关系及基础研究的需求是什么?
当前研究者逐渐依赖专有模型(如 GPT-4),与底层技术脱节;但抽象存在泄漏性,基础研究需打破现有框架,触及底层细节以解决根本问题,因此充分理解技术对基础研究至关重要。 -
大语言模型(LLM)的关键特征是什么?
具有超大参数规模(如 GPT-4 据称 1.8T 参数)、高昂训练成本(如 GPT-4 约 1 亿美元)、细节封闭(因竞争和安全);随参数增大,FFN 计算占比上升,且存在涌现能力(参数达临界点后正确率骤升)。 -
语言模型相关课程的核心学习内容包括哪些?
涵盖基础(分词器、Transformer 架构、训练流程)、系统(GPU 利用、并行化、推理优化)、规模定律(小实验预测大模型性能)、数据(处理、评估、创造)、对齐(使模型有用,如监督微调、偏好优化)。 -
分词器的作用及主流技术是什么?
作用是实现字符串与标记(整数序列)的转换;主流技术为字节对编码(BPE),从字节级开始,通过合并语料中高频相邻标记对,构建适应特定文本的子词词汇表,平衡压缩比与词汇量。 -
效率在语言模型设计中的核心地位是什么?
效率是固定资源(数据、硬件)下优化模型性能的关键,体现在数据处理(避免浪费计算)、架构设计(减少内存 / FLOP)、训练策略(计算最优缩放)等方面,最终目标是在有限资源下实现最高准确性。 -
数据在语言模型中的角色及处理要点是什么?
数据决定模型功能(如多语言、代码能力),需经过转换(HTML/PDF 转文本)、过滤(保留高质量内容)、去重(节省计算);数据非天然存在,需从互联网、书籍等来源获取,涉及版权问题。 -
语言模型 “对齐” 的目标及实现方式是什么?
目标是使基础模型有用,包括遵循指令、调整风格、确保安全;实现方式包括监督微调(用对话数据训练)、从反馈学习(如 DPO/GRPO 利用偏好数据优化)。
