【CS336】Lec 1 - Overview, tokenization

LLM 的现状与历史

神经网络之前

  • 香农提出用语言模型来测量熵 entropy
  • 有许多工作关注 n-gram 语言模型

神经网络时期

  • Bengio 提出第一个 NLM(神经网络语言模型)
  • Ilya 提出Seq-Seq 序列模型
  • Adam 优化器
  • 注意力机制
  • Transformer 架构
  • MoE
  • 模型并行化

早期基础模型

  • ELMo: 用 LSTM 预训练, 然后微调
  • BERT: 用 Transformer 预训练, 然后微调
  • T5: 把任何信息用 text-text 方式映射

拥抱 Scaling

开源模型

开源的不用程度

  • 闭源(GPT-4): 只能调用 API
  • 开放模型权重(DeepSeek): 权重完全开放, 详细介绍模型架构, 但是没有提及数据集相关内容
  • 开源模型(Qwen):开放权重和数据, 以及尽可能详尽的论文

课程构成

../../source/CS336overview.png

课程概览

基础知识 Basics

Tokenization

../../source/CS336tokenization.png
把一串自然语言分割成字符串序列, 并分别映射至向量空间之中
本节课主要讨论 BPE 分词器 (Byte-Pair Encoding)

模型架构

../../source/CS336Transformer.png
主要是 Transformer, 以及它的许多变体, 变化主要集中在以下方面:

  • 改变激活函数
  • 位置编码
  • 归一化的方式和位置
  • Attention 形式
  • MLP

训练

在训练相关的决策中, 也有许多考虑因素:

  • 优化器
  • 学习率调整
  • batch size
  • 正则化方式
  • 超参数

系统 Systems

主要聚焦于如何最大限度地利用现有计算资源

内核 kernels

../../source/CS336kernels.png
这是一个形象的类比, 数据通过一定带宽在内存和计算单元之间传输
因为我们需要尝试, 通过优化计算方式, 减少数据移动, 以此最大化利用 GPU
我们需要用一些工具来构建和编写 kernels

并行运算 Parallelism

../../source/CS336并行运算.png
训练大模型避免不了使用多张 GPU
这需要我们解决数据传输, 尽量减少传输量, 尽可能提高传输速度

推理 Inference

  • 目标: 在给定 prompt 的情况下生成 tokens
  • 训练是一次性的, 而推理则是每次交互都需要进行的, 成本随使用次数增加, 要求我们让推理更加高效
推理中的阶段
  1. Prefill: 接受提示词, 运行模型, 得到一些激活值: 基于现有 tokens, 可以一节计算 (限制是计算资源)
  2. 进行自回归, 生成 tokens: 需要按顺序生成 tokens(限制是内存大小)
提高推理速度的方法
  1. 使用成本更低的模型
  2. 推测解码
  3. 系统优化

扩展法则 Scaling Laws

目标: 做一个小规模实验, 并基于此预测大规模实验的超参数和 loss
寻找平衡: 小模型+大数据? 大模型+小数据?

数据 Data

根据期望的模型功能, 筛选数据
../../source/CS336data.png

评估 Evaluation

  • 困惑度
  • 标准测试
  • 指令遵循
  • 扩展运行时计算
  • 系统评估

数据筛选 Data curation

好的数据并非凭空产生, 随意获得
我们需要从数据源获取数据, 并且进行一些简单的处理
同时, 我们也需要处理各种各样类型的数据: HTML, PDF 等非文本数据

数据处理 Data Processing

  • 把 HTML/PDF 文件转换成文本
  • 对数据进行筛选, 去除有害信息
  • 对数据去重

对齐 Alignment

基础模型擅长预测下一个 token, 需要通过对齐/微调等方式激活潜在的能力

目的

  • 让模型遵循指令
  • 调整模型风格
  • 保证安全

阶段

  • 监督微调
  • 基于指令的学习
    • 偏好数据: 基于同一个 prompt, 让用户选择偏好, 并据此训练
    • 验证器
    • 算法: PPO, DPO, GRPO

词元化 tokenization

介绍

  • 将原始字符串转化为 token 序列
  • 将分词后的结果映射到语义空间之中, 实现文本-数字的映射和转换
  • 输入时, 将文本编码为 token; 输出时, 将 token 解码回文本

基于字符的分词

  • 一串字符串由一个 unicode 字符序列构成
  • 每一个字符都能映射为对应的数字, 这个过程同样可逆
  • 然而, 这样的问题是 : 这种做法相当于为词表中每一个字符分配对应的数字, 并不高效

基于字节的分词

  • 字符串可以用字节序列表示
  • 一些字符可以直接用 一个或多个 byte 表示
  • 一定程度上解决了上面的稀疏性问题, 问题是: 压缩比为 1, 序列很长, 效率同样不高

基于词的分词

  • 最朴素的 NLP 做法, 直接切分成多个词
  • 问题 : 词表没有上限, 无法处理错词和新词的问题

字节对编码 BPE

发展历史

  • 1994 年就被提出, 用于数据压缩
  • 后被引入 NLP, 用于机器翻译
  • 被 GPT-2 使用

基本概念

  • 在原始文本上训练分词器, 而非预先设定分词方法
  • 常见序列用单个 token 表示, 罕见序列用多个 token 表示
  • 先进行基于字节的分词, 然后根据共现的频繁程度, 进行合并

算法

  1. 初始化:把每个 byte 当作一个 token
    • 比如 “hello” → [“h”, “e”, “l”, “l”, “o”]
  2. 迭代合并:不断找到最常见的相邻 token 对,把它们合并成一个新 token
    • 例:[“h”, “e”] → “he”
    • 然后 [“he”, “l”, “l”, “o”] → [“he”, “l”, “l”, “o”]
    • 再合并 [“l”, “l”] → “ll”,得到 [“he”, “ll”, “o”]
  3. 重复,直到达到预设的词表大小。
Licensed under CC BY-NC-SA 4.0
最后更新于 Sep 16, 2025 09:22 UTC
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计