斯坦福大学 CS336 Lecture 01 Overview and Tokenization
目录
2.1 Character-based tokenization
1.Overview
1.1 一些我觉得有点道理的小点
①. The reason why we should learn how to build language models from scratch
现状:研究人员与底层技术脱节。抽象层(隐藏底层复杂性,只提供简单接口的中间层)为研究人员带来了便利,更高的抽象层次(从代码 → 模型 → API调用)让研究人员能更快地验证想法、做实验,不用重复造轮子。但完美的抽象层并不存在,总会有leaky的时候。底层细节并不会完全被抽象屏蔽,当出现问题时,仍然需要理解底层机制。

②. Problems about small scales
a. Fraction of FLOPs spent in attention versus MLP changes with scale
随着模型规模变大,重心更多偏移向FFN层(Feed-Forward Network,前馈网络),而不是MHA层(Multi-Head Attention)。
b. Emergency of behavior with scale

③. Goal of an Individual Research
max efficiency: efficiency is the driving principle to design
要解决的问题:what is the best model we can build given a certain compute and data budget
accuracy = efficiency * resources
efficiency是硬件和算法的组合
1.2 Course Composition

1.2.1 Basics
1.2.1.1 Tokenization

Tokenization(分词/令牌化) 是让计算机理解文本的第一步。它的核心任务是:把人类写的连续文本(“Hello world”)切分成模型能处理的最小单元(“Hello”、“world”)。
神经网络(包括大语言模型)本质上只能处理数字(向量、矩阵),无法直接理解字符或单词。所以需要一个转换过程:人类文本 → [Tokenization] → 数字序列 → 模型处理
Tokenizer 内部维护一个词汇表,里面包含它认识的所有 token。它读入文本时,会尽可能把文本切分成词汇表中存在的 token。
不同Tokenizer切分得到的字段不同。所以在设计Tokenizer时,要注意词汇表和序列长度之间的权衡:
-
大词汇表:文本被切成更少的token → 序列更短 → 计算更快,但模型参数更多
-
小词汇表:文本被切成更多token → 序列更长 → 计算更慢,但模型更小
以 " Hello World ! " 为例,大词汇表认识 Hello、World、! 这三个独立的token;小词汇表只有单个字母和标点。对于大词汇表:
序列更短 → 计算更快:因为Transformer模型的计算量(大致)和序列长度的平方成正比。上面例子中,处理3个token(计算量≈9)肯定比处理12个token(计算量≈144)要快得多。
模型参数更多:为了能直接认出 Hello、World 这些词,词汇表里就需要存储这些词的嵌入向量。假设每个词用一个768维的向量表示,词汇表里每增加1万个词,就会多出 768 × 10000 = 7,680,000 个参数。这就是“模型变得更大”的原因。
本课程中:BPE Tokenizer (Byte Pair Encoding)。但还有一种Tokenizer-free approach值得关注。
1.2.1.2 Model Architecture

现有的框架基本上还是以Transform作为骨架,但有许多改进:

这个图里的东西基本上我都看不懂,希望听完后能有更深的理解
1.2.1.3 Training

There will be order of magnitude diffierence between a well-tuned architecture and a vanilla transform.
1.2.2 Systems
goal :squeeze the most out of the hardware
components :kernels, parallelism, inference
1.2.2.1 Kernels

(介绍GPU架构,翻出了以前搞TA做compute shader的图,图形学还在追我,流泪)
kernel可以理解成一种为了最大化利用GPU成千上万个计算核心的在 GPU 上运行的底层并行计算函数。核心作用是:把大任务拆成小任务,让 GPU 上千核心同时处理。Kernel是告诉GPU如何并行执行算法的指令集,它定义了每个核心做什么、怎么协作、怎么访问数据等。
1.2.2.2 Parallelism

①.核心硬件:
a.GPU(A100) ;HBM(High Bandwidth Memory, 高带宽显存),放置数据的地方。
b.CPU & DRAM
②.连接、传输组件:
a.PCIe Gen4 (Peripheral Component Interconnect Express):一种高速数据传输总线,CPU和GPU之间、CPU和其他设备之间的公共通道。把数据从CPU/DRAM搬运到GPU。所有GPU共享这条通道,所以如果8个GPU同时跟CPU通信,每个分到的带宽会很少。
b.PCLe Switch:PCIe的扩展器/交换机。因为CPU提供的PCIe通道数量有限(比如只有64条),插不了8块GPU。Switch就像一个集线器,把PCIe通道“一拖多”,让一块CPU能连接多块GPU。
c.NVLink:让两块GPU直接通信,不需要绕道CPU和PCIe。尤其适合GPU之间频繁交换数据(比如并行训练中的梯度同步)。
d. NVSwitch:如果不加Switch,NVLink只能点对点连接(比如GPU0连GPU1,GPU1连GPU2...),形成一条长链,跨GPU通信要走多跳,延迟高。有了NVSwitch,任意两个GPU都能直接全速通信(全网状连接)。图中8块A100通过6个NVSwitch实现了两两之间全连接。
为啥要用6个,理论上一个不就够了?因为一个NVSwitch芯片上能插的NVLink接口数量是有限的。
通常来讲,一块A100 GPU有12个NVLink接口。为了达到最高的通信带宽,这12个接口理论上应该全部同时处于工作状态。而在NVIDIA的典型设计中,每个NVSwitch芯片可以提供36个NVLink端口。工程师们会把A100的12个NVLink接口平均分配给6个NVSwitch。每一块GPU都与每一个NVSwitch芯片建立了2条连接(因为12个接口 ÷ 6个交换机 = 2条连路/每交换机)。

当GPU0和GPU1之间要传递数据时,数据被均匀分配到GPU0的12个接口上。然后每个接口分别将数据传送到对应的NVSwitch上,数据从6个Switch并行传输到GPU1。
③.数据流:
-
CPU 从硬盘读取训练数据,放到 DRAM。
-
CPU 通过 PCIe Switch 和 PCIe,把数据分发给8块 A100 GPU 的 HBM 中。
-
GPU 开始计算。计算过程中,GPU0 可能需要 GPU1 的中间结果 → 数据通过 NVLink 和 NVSwitch 直达,不经过CPU。
-
每轮计算结束,8块 GPU 通过 NVLink + NVSwitch 互相同步梯度(高速聚合)。
-
GPU 把最终结果通过 PCIe 传回 CPU/DRAM,由CPU写回硬盘或输出。
④.总结
训练大语言模型时必须做并行,因为单卡显存放不下。NVLink、NVSwitch、PCIe Switch等硬件设计,本质上都是为了让GPU之间能以最快速度交换中间结果(数据之间的传输是一个重要的bottleneck),从而支持张量并行和流水线并行这两种模型拆分策略。(DS抄下来的,几个啥并行不知道具体啥意思)
1.2.2.3 Inference
goal:generate tokens given a prompt (needed to actually use models)
two phases:prefill and decode

Prefill:一次性读完输入。计算量大,天生并行。首先要明确的是,该阶段不是单纯的输入,也是有输出的。当输入“computer science is”时:
①.Tokenization:将“computer”、“science”、“is”分别转成token id
②.Embedding:将token id转成向量
③.通过Transformer层计算:模型会把这三个向量一次性送进所有Transformer层,每层都进行Self-Attention(每个词都会看所有词)和FFN。天生并行体现在这里,GPU可以并行计算“computer”、“science”、“is”三个词的输出。
④.输出:Prefill阶段结束时,模型会输出三个向量,分别对应 “computer”、“science”、“is” 这三个位置的最终表示。这三个输出向量不是最终回答,而是“对输入的理解结果”,会被用来预测第一个输出词。
Decoding:逐词生成,期间用KV-Cache缓存历史信息避免重复计算,直到遇到<EOS>结束符。
1.2.3 Scaling Laws
goal:do experiments at small scale and predict hyperparameters / loss at a larger scale
这里要解决的问题是:在固定的计算资源下,应该优先扩大模型规模(N),还是优先增加训练数据(D)?
解决方法:Chinchilla 缩放定律(Scaling Laws) : D ≈ 20 × N 即:训练一个70亿参数的模型(7B),大约需要1400亿个训练tokens
1.2.4 Data
主要探究:
①. 如何评估模型:perplexity(困惑度)、各种衡量指标以及像 MMLU 这样的标准化测试
②. 数据筛选(Data Curation)
③.数据处理(Data Processing):Transform,Filtering(via classifiers),Deduplication
1.2.5 Alignment
a.goals:
①语言模型需要遵循指令
②输出内容的风格(格式、长度、语气等)
③安全(拒绝回答有害问题等)
b.two phases:
supervised finetuning (SFT):通过输入若干“输入-期望输出”对,教模型遵循特定的对话格式和风格
learning from feedback:训练一个独立的模型用于“评分”。让主模型生成回答,然后打分,通过这个分数来更新主模型的参数。PPO(Proximal Policy Optimization, 近端策略优化)、DPO(Direct Preference Optimization, 直接偏好优化)和GRPO(Group Relative Policy Optimization, 群体相对策略优化)等用来调优主模型。
2.Tokenization
一些观察结果:
①. A word and its preceding space are part of the same token.
②. A word at the begging and in the middle are represented differently.

黄色world有前置空格,故表示不同
③. Numbers are tokenized into every few digits.

④. Different languages have different compression ratio.
2.1 Character-based tokenization
例如:单个字母、数字、符号对应它们各自的ASCII码,然后中文设定常用文字的对照。然后一些emoji符号等。所有的Unicode characters大概有150k,基本上就是这种方法的词汇表。
问题:视频里说这种词汇表的大小非常庞大。但我认为这不应该算小的吗,单个字符的数量肯定比字符之间组合凑成的数组短语啥的数量小啊。不是很理解这一点。
我认为这种分词方法的缺点在于:一是缺乏语义单位,例如“ing”很难学到表示正在进行;二是相同token数量,能容纳的信息太少了。三是一定有的字符的使用频率远远高于其他字符,这种使用过程中的稀疏性需要解决。
感觉可以优化啊,在使用过程中进行一次训练,把使用次数多的字符组合可以单独提取出来作成token,是不是就可以带有语义信息了。
2.2 Byte-based tokenization
把每个字节(byte)当作一个独立的 token。一个字节有 256 种可能的值(0x00 到 0xFF),所以词汇表大小固定为 256(应该是最小的吧)。并且永远不会有OOV (Out of Vocabulary) 问题。
在UFT- 8 条件下,一个英文字母占1字节;一个汉字占3字节,一个emoji字符占4字节。
缺点是序列长度太长了
2.3 Word tokenization
利用正则表达式将一个句子切分成若干单词以及标点。

2.4 Byte Pair Encoding (BPE)
我超我真是天才吧,见2.1优化。只不过这里的起点是从Byte tokenization开始的,我是从Character Tokenization开始的(但其实对英文文献来讲,这两者好像没啥区别)。
Lecture 01 搞定,耗时三天
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)