这篇笔记整理自《大模型：从基础到前沿》第一节课，主要记录课程介绍、大模型发展史、语言模型的基本概念、分词方法、BPE、统计语言模型与 N-gram 等内容。它既是课堂内容的索引，也可以作为之后复习 Transformer 与大语言模型基础时的起点。

## Reading Map

- **课程背景**：参考资料、学术流派和神经网络发展脉络。
- **语言模型基础**：token、概率语言模型、分词与 BPE。
- **统计语言模型**：N-gram、平滑、回退与插值方法。
- **讨论问题**：中文 BPE 的局限，以及 N-gram 模型的不足。

# 课程介绍

## 参考资料
- 《Speech and Language Processing》(Daniel Jurafsky and James H. Martin)
  https://probml.github.io/pml-book/book1.html
- 《Dive into Deep Learning》(Aston Zhang, Z. C. Lipton, Mu Li and A. J. Smola)
  https://d2l.ai/
- Natural Language Processing with Deep Learning (Stanford CS 224N)
  https://web.stanford.edu/class/cs224n/index.html
- Natural Language Processing (Princeton COS 484)
  https://nlp.cs.princeton.edu/cos484/

# 大模型发展史

## 学术流派
- 符号主义
- 连接主义（目前主流）
- 行为主义

## 神经网络
1. 人工神经元：模型参数固定，没有学习能力
2. 感知器：具有学习能力；无法解决非线性可分问题
3. **多层感知器**：可以解决非线形可分问题；可以利用*反向传播*算法进行训练
4. 卷积神经网络（CNN）：常应用于视觉处理
5. 循环神经网络（RNN）：常应用于自然语言处理

# 大模型
1. **Transformer**：2017年提出，新一代深度学习的基础模型
2. 大语言模型：2018：GPT-1,BERT
3. 视觉大模型：2020：ViT
4. 多模态大模型：2021：CLIP

# 语言模型

## 背景
人工智能的目标之一是实现机器能理解和使用人类语言，完成多项任务：人机对话、自动回答、机器翻译、写作······
两个基本能力：理解语言，生成语言

## 基本概念
语言模型（Language Model），通过计算文本的生成概率来理解和生成文本，也称概率语言模型（Probabilistic Language Model）
词元（token）：可以是词组、词、子词（词的一部分）、标点符号、甚至是字母
用token序列表示文本，便于计算机处理

> [! important]
> 给定一个句子
>
> $$
> S=w_1,w_2,w_3,...,w_n
> $$
>
> 其中$w_i \in V$ V是词表（所有出现词的集合）
> 语言模型要计算这个句子出现的概率:
>
> $$
> P(S)=P(w_1,w_2,w_3,...,w_n)
> $$
>
> 根据概率链式法则，可以写成
>
> $$
> P(S)=P(w_1)P(w_2|w_1)P(w_3|w_1,w_2)...P(w_n|w_1,w_2,w_3,...,w_{n-1})
> $$
>
> 因此，语言模型本质是根据前面给出的token预测下一个token

### 分类
1. 统计语言模型
2. 神经语言模型

## 分词（Tokenization）

### 定义：
将连续的文本字符串切分成一个个token的过程

### 作用：
自然语言是连续的符号序列，但是神经网络需要输入数值。因此，需要先把文本拆成一个个基本单元，再把这些单元转换成数字。

### 词级分词
依据空格和标点进行分词
优点：语义清晰，结果容易理解
缺点：需要词典且词表过大（一个词的多种形式都会进入词典），无法处理未登录词，中文分词困难（没有空格）

### 字符级分词
将文本拆成单个字母或汉字
优点：词表较小
缺点：拆分后的序列过长，丧失了词语的词义信息

### 子词级分词
高频词保留为token，低频词拆分成有意义的子词片段
优点：词表较小（一个词的多种形式会被分成最原始形式+有意义的子词片段），可以处理未登录词，保留一定语义信息

> [! example]
> 给出一个句子 I love unbelievable LLM courses.
> 词级分词结果：["I","love","unbelievable","LLM","courses","."]
> 字符级分词结果：["I","l","o","v","e","u","n","b","e","l","i","e","v","a",......]
> 子词级分词结果：["I","love","un","believ","able","LLM","course","s","."]
> 随后被转换成数值序列，如[29,32,4342,123,65,1]

### BPE：Byte Pair Encoding
核心思想：不依赖人工语言学规则，而是通过统计语料中相邻符号对的出现频率，自动学习如何切分文本
是一种子词级分词方法
具体步骤：
1. 准备语料库，统计词频，每个词语末尾加入结束符号
2. 初始化词表，包括所有出现的单个字符以及结束符号
3. 统计语料中所有相邻符号对的出现频率
4. 将最高频率的符号对合并成一个token放入词表
5. 将原语料库中出现该符号对的地方改成新token
6. 重复步骤3,4,5直到：词表大小达到预设目标/合并达到上限/没有足够高频的符号对可以继续合并
7. 对于一个新文本，从左到右扫描文本，尽可能找词表中最长的子词进行匹配

> [!example]- BPE 完整示例：`low / lower / high`
> ## 初始语料库
>
> | 单词 | 出现次数 |
> |---|---:|
> | `low` | 5 |
> | `lower` | 8 |
> | `high` | 6 |
>
> ---
>
> ## 1. 加入词尾符号
>
> 用 `_` 表示一个词的结束位置。
>
> | 原词 | 初始切分 | 频率 |
> |---|---|---:|
> | `low` | `l o w _` | 5 |
> | `lower` | `l o w e r _` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 初始词表为：
>
> `_, e, g, h, i, l, o, r, w`
>
> ---
>
> ## 2. 第 0 轮：统计所有相邻符号对
>
> | 相邻符号对 | 来源 | 出现次数 |
> |---|---|---:|
> | `l o` | `low`, `lower` | `5 + 8 = 13` |
> | `o w` | `low`, `lower` | `5 + 8 = 13` |
> | `w _` | `low` | 5 |
> | `w e` | `lower` | 8 |
> | `e r` | `lower` | 8 |
> | `r _` | `lower` | 8 |
> | `h i` | `high` | 6 |
> | `i g` | `high` | 6 |
> | `g h` | `high` | 6 |
> | `h _` | `high` | 6 |
>
> 最高频符号对是 `l o` 和 `o w`，都出现 13 次。
>
> 如果出现并列，BPE 本身没有唯一规定。这里采用“从左到右优先”的策略，先合并 `l o`。
>
> ---
>
> ## 3. 第 1 次合并：`l + o -> lo`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `lo w _` | 5 |
> | `lower` | `lo w e r _` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 词表新增：
>
> `lo`
>
> 当前词表：
>
> `_, e, g, h, i, l, o, r, w, lo`
>
> 重新统计后，最高频符号对是：
>
> `lo w`，出现 13 次。
>
> ---
>
> ## 4. 第 2 次合并：`lo + w -> low`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `low e r _` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 词表新增：
>
> `low`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `low e` | 8 |
> | `e r` | 8 |
> | `r _` | 8 |
> | `h i` | 6 |
> | `i g` | 6 |
> | `g h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对并列：`low e`、`e r`、`r _`，都出现 8 次。
>
> 继续按从左到右优先，合并 `low e`。
>
> ---
>
> ## 5. 第 3 次合并：`low + e -> lowe`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lowe r _` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 词表新增：
>
> `lowe`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `lowe r` | 8 |
> | `r _` | 8 |
> | `h i` | 6 |
> | `i g` | 6 |
> | `g h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对并列：`lowe r` 和 `r _`，都出现 8 次。
>
> 继续按从左到右优先，合并 `lowe r`。
>
> ---
>
> ## 6. 第 4 次合并：`lowe + r -> lower`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower _` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 词表新增：
>
> `lower`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `lower _` | 8 |
> | `h i` | 6 |
> | `i g` | 6 |
> | `g h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对是 `lower _`，出现 8 次。
>
> ---
>
> ## 7. 第 5 次合并：`lower + _ -> lower_`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `h i g h _` | 6 |
>
> 词表新增：
>
> `lower_`
>
> `lower_` 表示完整单词 `lower`，并且包含词尾结束符。
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `h i` | 6 |
> | `i g` | 6 |
> | `g h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对并列：`h i`、`i g`、`g h`、`h _`，都出现 6 次。
>
> 继续按从左到右优先，合并 `h i`。
>
> ---
>
> ## 8. 第 6 次合并：`h + i -> hi`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `hi g h _` | 6 |
>
> 词表新增：
>
> `hi`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `hi g` | 6 |
> | `g h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对并列：`hi g`、`g h`、`h _`，都出现 6 次。
>
> 合并 `hi g`。
>
> ---
>
> ## 9. 第 7 次合并：`hi + g -> hig`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `hig h _` | 6 |
>
> 词表新增：
>
> `hig`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `hig h` | 6 |
> | `h _` | 6 |
>
> 最高频符号对并列：`hig h` 和 `h _`，都出现 6 次。
>
> 合并 `hig h`。
>
> ---
>
> ## 10. 第 8 次合并：`hig + h -> high`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `high _` | 6 |
>
> 词表新增：
>
> `high`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
> | `high _` | 6 |
>
> 最高频符号对是 `high _`。
>
> ---
>
> ## 11. 第 9 次合并：`high + _ -> high_`
>
> | 单词 | 合并后切分 | 频率 |
> |---|---|---:|
> | `low` | `low _` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `high_` | 6 |
>
> 词表新增：
>
> `high_`
>
> 重新统计：
>
> | 相邻符号对 | 出现次数 |
> |---|---:|
> | `low _` | 5 |
>
> 最后还可以继续合并 `low _`。
>
> ---
>
> ## 12. 第 10 次合并：`low + _ -> low_`
>
> | 单词 | 最终切分 | 频率 |
> |---|---|---:|
> | `low` | `low_` | 5 |
> | `lower` | `lower_` | 8 |
> | `high` | `high_` | 6 |
>
> 词表新增：
>
> `low_`
>
> 此时语料库中已经没有可以继续合并的相邻符号对。
>
> ---
>
> ## 最终合并顺序
>
> 1. `l + o -> lo`
> 2. `lo + w -> low`
> 3. `low + e -> lowe`
> 4. `lowe + r -> lower`
> 5. `lower + _ -> lower_`
> 6. `h + i -> hi`
> 7. `hi + g -> hig`
> 8. `hig + h -> high`
> 9. `high + _ -> high_`
> 10. `low + _ -> low_`
>
> 最终词表可以看作：
>
> `_, e, g, h, i, l, o, r, w, lo, low, lowe, lower, lower_, hi, hig, high, high_, low_`
>
> ---
>
> ## 对新文本进行编码
>
> 假设新文本是：
>
> `lower high low`
>
> 先给每个词加上词尾符号：
>
> | 原词 | 初始形式 |
> |---|---|
> | `lower` | `l o w e r _` |
> | `high` | `h i g h _` |
> | `low` | `l o w _` |
>
> 按照前面学到的合并顺序，从前到后应用。
>
> ---
>
> ## 编码 `lower`
>
> 初始：
>
> `l o w e r _`
>
> 逐步合并：
>
> 1. `l o -> lo`
>
> `lo w e r _`
>
> 2. `lo w -> low`
>
> `low e r _`
>
> 3. `low e -> lowe`
>
> `lowe r _`
>
> 4. `lowe r -> lower`
>
> `lower _`
>
> 5. `lower _ -> lower_`
>
> 最终：
>
> `lower_`
>
> ---
>
> ## 编码 `high`
>
> 初始：
>
> `h i g h _`
>
> 逐步合并：
>
> 6. `h i -> hi`
>
> `hi g h _`
>
> 7. `hi g -> hig`
>
> `hig h _`
>
> 8. `hig h -> high`
>
> `high _`
>
> 9. `high _ -> high_`
>
> 最终：
>
> `high_`
>
> ---
>
> ## 编码 `low`
>
> 初始：
>
> `l o w _`
>
> 逐步合并：
>
> 10. `l o -> lo`
>
> `lo w _`
>
> 11. `lo w -> low`
>
> `low _`
>
> 12. `low _ -> low_`
>
> 最终：
>
> `low_`
>
> ---
>
> ## 最终编码结果
>
> 所以：
>
> `lower high low`
>
> 会被编码为：
>
> `lower_ high_ low_`
>
> 如果不显示词尾符号，也可以理解成：
>
> `lower high low`
>
> 三个词都已经被 BPE 学成了完整 token。
>
> ---
>
> ## 重要提醒
>
> 实际 BPE 中通常不会一直合并到不能合并为止，而是会设置一个目标词表大小。  
> 当词表达到目标大小时，就停止合并。

# 统计语言模型

## 基础模型
给定一个序列$S=t_1,t_2,t_3,...,t_L$,词汇量$\lvert V\rvert=N$ ,要求 $P(S)$
由此前内容我们已知：

$$
P(S)=\prod_{i=1}^{L} P(t_i|t_1,t_2,...,t_{i-1})
$$

*用频次估计概率，可得*

$$
P(t_1)=\frac{Count(t_1)}{\sum_{t \in V} Count(t)}
$$

$$
P(t_2 \mid t_1)=\frac{Count(t_1,t_2)}{Count(t_1)}
$$

$$
P(t_L \mid t_1,t_2,\cdots,t_{L-1})
=
\frac{Count(t_1,t_2,\cdots,t_{L-1},t_L)}
{Count(t_1,t_2,\cdots,t_{L-1})}
$$

其中$\sum_{t \in V} Count(t)$ 是所有token出现次数的总和

> [!problem] 统计语言模型存在的问题
> **1. 参数数量爆炸**
>
> 需要考虑的概率数量为：
>
> $$
> N+N^2+N^3+...+N^L=\frac{N^{L+1}-1}{N-1}
> $$
>
> N,L 稍微大一点这个数值会非常恐怖
>
> **2. 严重依赖语料频次**
>
> 如果某个句子没有在语料中出现过，即使它是合理的，模型也可能给出非常低的概率
 
## 马尔可夫假设 
k阶马尔可夫假设：
`当前token出现的概率只与其前的𝑘个token有关，与再之前的token独立` 
即：

$$
P(t_l|t_1,t_2,...,t_{l-1})=P(t_l|t_{l-k},t_{l-k+1},...,t_{l-1})
$$

### Unigram 模型
Unigram 模型假设当前词元与前面的词元无关。

$$
P(t_l \mid t_1,t_2,\cdots,t_{l-1})=P(t_l)
$$

因此整个序列的概率可以写成：

$$
P(t_1,t_2,\cdots,t_L)
=
\prod_{l=1}^{L}P(t_l)
$$

也就是说，Unigram 模型只考虑每个词元本身出现的概率，不考虑词元之间的顺序关系。

###  Bigram 模型
Bigram 模型假设当前词元只依赖前一个词元。

$$
P(t_l \mid t_1,t_2,\cdots,t_{l-1})
=
P(t_l \mid t_{l-1})
$$

因此整个序列的概率可以写成：

$$
P(t_1,t_2,\cdots,t_L)
=
\prod_{l=1}^{L}P(t_l \mid t_{l-1})
$$

其中，模型参数为：

$$
P(t_l \mid t_{l-1})
$$

它表示在词元 $t_{l-1}$ 出现之后，词元 $t_l$ 接在后面的概率。

### N-gram 模型
更一般地，N-gram 模型假设当前词元只依赖前面 $n-1$ 个词元。

$$
P(t_l \mid t_1,t_2,\cdots,t_{l-1})
=
P(t_l \mid t_{l-n+1},\cdots,t_{l-1})
$$

因此：

$$
P(t_1,t_2,\cdots,t_L)
=
\prod_{l=1}^{L}
P(t_l \mid t_{l-n+1},\cdots,t_{l-1})
$$

###  Bigram 参数估计
给定语料库后，可以通过统计频次来估计 Bigram 条件概率。

$$
P(t_l \mid t_{l-1})
=
\frac{Count(t_{l-1},t_l)}
{Count(t_{l-1})}
$$

其中：
- $Count(t_{l-1},t_l)$ 表示词元对 $(t_{l-1},t_l)$ 在语料库中连续出现的次数。
- $Count(t_{l-1})$ 表示词元 $t_{l-1}$ 在语料库中出现的次数。

也就是说：

$$
P(t_l \mid t_{l-1})
=
\frac{\text{前一个词后面接当前词的次数}}
{\text{前一个词出现的总次数}}
$$

> [!example]- Bigram 语言模型示例
> ## 1. 原始语料库
>
> 假设语料库中有 5 个句子：
>
> | 编号 | 句子 |
> |---|---|
> | 1 | `<s>小王看见一只小猫爬树</s>` |
> | 2 | `<s>小猫爬树</s>` |
> | 3 | `<s>一只啄木鸟在啄树</s>` |
> | 4 | `<s>小猫打架</s>` |
> | 5 | `<s>我爬山了</s>` |
>
> 其中：
>
> - `<s>` 表示句子开始。
> - `</s>` 表示句子结束。
>
> ---
>
> ## 2. 分词后的语料库
>
> 分词后得到：
>
> | 编号 | 分词结果 |
> |---|---|
> | 1 | `<s>` 小王 看见 一只 小猫 爬 树 `</s>` |
> | 2 | `<s>` 小猫 爬 树 `</s>` |
> | 3 | `<s>` 一只 啄木鸟 在 啄 树 `</s>` |
> | 4 | `<s>` 小猫 打架 `</s>` |
> | 5 | `<s>` 我 爬 山 了 `</s>` |
>
> ---
>
> ## 3. 生成 Bigram 词元对
>
> 对每个句子，从左到右取相邻两个词元，得到 Bigram：
>
> | 句子 | Bigram 词元对 |
> |---|---|
> | `<s>` 小王 看见 一只 小猫 爬 树 `</s>` | `<s>` 小王；小王 看见；看见 一只；一只 小猫；小猫 爬；爬 树；树 `</s>` |
> | `<s>` 小猫 爬 树 `</s>` | `<s>` 小猫；小猫 爬；爬 树；树 `</s>` |
> | `<s>` 一只 啄木鸟 在 啄 树 `</s>` | `<s>` 一只；一只 啄木鸟；啄木鸟 在；在 啄；啄 树；树 `</s>` |
> | `<s>` 小猫 打架 `</s>` | `<s>` 小猫；小猫 打架；打架 `</s>` |
> | `<s>` 我 爬 山 了 `</s>` | `<s>` 我；我 爬；爬 山；山 了；了 `</s>` |
>
> ---
>
> ## 4. 部分频次统计
>
> | 统计对象 | 出现次数 |
> |---|---:|
> | `Count(<s>)` | 5 |
> | `Count(<s>, 小猫)` | 2 |
> | `Count(小猫)` | 3 |
> | `Count(小猫, 爬)` | 2 |
> | `Count(小猫, 啄)` | 0 |
> | `Count(爬)` | 3 |
> | `Count(爬, 树)` | 2 |
> | `Count(啄)` | 1 |
> | `Count(啄, 树)` | 1 |
>
> ---
>
> ## 5. 计算条件概率
>
> 根据 Bigram 参数估计公式：
>
> $$
> P(t_l \mid t_{l-1})
> =
> \frac{Count(t_{l-1},t_l)}
> {Count(t_{l-1})}
> $$
>
> 可以得到：
>
> $$
> P(\text{小猫}\mid \langle s\rangle)
> =
> \frac{Count(\langle s\rangle,\text{小猫})}
> {Count(\langle s\rangle)}
> =
> \frac{2}{5}
> $$
>
> $$
> P(\text{爬}\mid \text{小猫})
> =
> \frac{Count(\text{小猫},\text{爬})}
> {Count(\text{小猫})}
> =
> \frac{2}{3}
> $$
>
> $$
> P(\text{啄}\mid \text{小猫})
> =
> \frac{Count(\text{小猫},\text{啄})}
> {Count(\text{小猫})}
> =
> \frac{0}{3}
> =
> 0
> $$
>
> $$
> P(\text{树}\mid \text{啄})
> =
> \frac{Count(\text{啄},\text{树})}
> {Count(\text{啄})}
> =
> \frac{1}{1}
> =
> 1
> $$
>
> $$
> P(\text{树}\mid \text{爬})
> =
> \frac{Count(\text{爬},\text{树})}
> {Count(\text{爬})}
> =
> \frac{2}{3}
> $$
>
> ---
>
> ## 6. 比较两个句子的概率
>
> 现在比较两个候选句子：
>
> 1. 小猫爬树
> 2. 小猫啄树
>
> 加入句首和句尾符号后：
>
> - `<s>` 小猫 爬 树 `</s>`
> - `<s>` 小猫 啄 树 `</s>`
>
> ---
>
> ## 7. 句子 1：小猫爬树
>
> 按照 Bigram 模型：
>
> $$
> P(\langle s\rangle,\text{小猫},\text{爬},\text{树},\langle /s\rangle)
> =
> P(\text{小猫}\mid \langle s\rangle)
> P(\text{爬}\mid \text{小猫})
> P(\text{树}\mid \text{爬})
> P(\langle /s\rangle \mid \text{树})
> $$
>
> 课件示例中给出的计算形式为：
>
> $$
> P(\langle s\rangle,\text{小猫},\text{爬},\text{树},\langle /s\rangle)
> =
> \frac{2}{5}
> \times
> \frac{2}{3}
> \times
> \frac{2}{3}
> \times
> \frac{1}{5}
> =
> \frac{8}{225}
> $$
>
> 因为该概率大于 0，所以模型认为“小猫爬树”是一个可能出现的句子。
>
> ---
>
> ## 8. 句子 2：小猫啄树
>
> 同理：
>
> $$
> P(\langle s\rangle,\text{小猫},\text{啄},\text{树},\langle /s\rangle)
> =
> P(\text{小猫}\mid \langle s\rangle)
> P(\text{啄}\mid \text{小猫})
> P(\text{树}\mid \text{啄})
> P(\langle /s\rangle \mid \text{树})
> $$
>
> 代入频次：
>
> $$
> P(\langle s\rangle,\text{小猫},\text{啄},\text{树},\langle /s\rangle)
> =
> \frac{2}{5}
> \times
> 0
> \times
> 1
> \times
> \frac{1}{5}
> =
> 0
> $$
>
> 因为：
>
> $$
> P(\text{啄}\mid \text{小猫})=0
> $$
>
> 所以整个句子的概率为 0。
>
> ---
>
> ## 9. 结论
>
> 在这个 Bigram 语言模型中：
>
> | 句子 | 概率 |
> |---|---:|
> | 小猫爬树 | $\frac{8}{225}$ |
> | 小猫啄树 | $0$ |
>
> 因此，模型更倾向于认为：
>
> **小猫爬树**
>
> 比：
>
> **小猫啄树**
>
> 更符合语料库中的语言规律。
>
> ---
>
> ## 10. 重要提醒
>
> Bigram 模型只看前一个词元，因此它的上下文能力有限。
>
> 例如：
>
> $$
> P(t_l \mid t_1,t_2,\cdots,t_{l-1})
> \approx
> P(t_l \mid t_{l-1})
> $$
>
> 这种近似计算简单，但会丢失更长距离的上下文信息。
>
> 另外，如果某个 Bigram 在语料库中从未出现过，那么它的概率会被估计为 0。  
> 这也是为什么后续需要引入平滑方法，例如 Add-one smoothing。

## 评估

### 1. 评估目标
好的语言模型应该：
- 给真实、常见、自然的句子更高概率
- 给语法错误、罕见、不自然的句子更低概率

模型参数来自训练语料，但评估应在测试集上进行。

> [!important]
> 测试集不能参与模型训练，否则评估结果不公平。

### 2. 外部评估
外部评估是把语言模型放到具体 NLP 任务中测试效果。
常见任务包括：
- 拼写纠错
- 机器翻译
- 问答系统

评价方式：
- 比较模型 A 和模型 B 在具体任务上的准确率或效果
- 哪个模型让任务表现更好，哪个模型就更优

缺点：
- 比较耗时
- 依赖具体任务
- 不适合快速比较多个语言模型

### 3. 内部评估
内部评估不依赖具体任务，而是直接衡量模型在测试语料上的表现。
常用指标是：
**困惑度**，即 perplexity。

### 4. 困惑度
给定文本：

$$
S=t_1,t_2,\cdots,t_L
$$

语言模型 $LM$ 在该文本上的困惑度定义为：

$$
PPL(S,LM)=P(t_1,t_2,\cdots,t_L)^{-\frac{1}{L}}
$$

其中：
- $P(t_1,t_2,\cdots,t_L)$ 是语言模型给整个句子的概率
- $L$ 是句子长度
- 困惑度越小，说明模型越好

困惑度可以理解为：
> 模型面对下一个词时有多“不确定”。
- 困惑度越低，模型越确定
- 困惑度越高，模型越困惑

因此：

$$
\text{最小化困惑度}
\Longleftrightarrow
\text{最大化生成概率}
$$

## 概率修正

### 1.问题
N-grams语言模型只统计训练语料中出现的grams的信息，实际可能的grams远多于训练语料中的grams，很多条件概率值为0，极大限制了模型的泛化能力

### 2.平滑法

#### 核心思想
平滑法通过加入虚拟的“伪计数”来调整概率：
- 给没有出现过的词元组合分配一个非零概率
- 避免概率值为 0
- 同时让所有概率仍然满足归一化

代表性方法：
- 拉普拉斯平滑
- 利德斯通平滑

#### 拉普拉斯平滑
拉普拉斯平滑也叫 **加 1 估计（Add-one estimation）**。
在 Bigram 模型中，原始最大似然估计为：

$$
P(v_i \mid v_j)
=
\frac{Count(v_j,v_i)}
{Count(v_j)}
$$

如果 $Count(v_j,v_i)=0$，则：

$$
P(v_i \mid v_j)=0
$$

这会造成零概率问题。
拉普拉斯平滑给每一种可能的后继词都加上 1 个伪计数：

$$
P(v_i \mid v_j)
=
\frac{Count(v_j,v_i)+1}
{Count(v_j)+\lvert V\rvert}
$$

其中：
- $Count(v_j,v_i)$ 表示 Bigram $(v_j,v_i)$ 出现次数
- $Count(v_j)$ 表示前一个词 $v_j$ 出现次数
- $\lvert V\rvert$ 表示词表大小
- 分子加 1，表示每个 Bigram 至少出现过一次
- 分母加 $\lvert V\rvert$，表示给词表中每个词都补了 1 次计数

#### 利德斯通平滑
利德斯通平滑是拉普拉斯平滑的推广，也叫 **Add-$\alpha$ smoothing**。
它不是固定加 1，而是加一个参数 $\alpha$：

$$
P(v_i \mid v_j)
=
\frac{Count(v_j,v_i)+\alpha}
{Count(v_j)+\alpha \lvert V\rvert}
$$

其中：
- $\alpha=1$ 时，就是拉普拉斯平滑
- $\alpha=0.5$ 时，在实际应用中常常效果更好
- $\alpha$ 越小，对原始频次的扰动越弱

> [!note]- 利德斯通平滑的贝叶斯解释
> 利德斯通平滑可以用贝叶斯方法解释：给概率参数加入一个 **狄利克雷先验**。
>
> 设：
>
> $$
> x_i \triangleq P(v_i \mid v_j)
> $$
>
> 即 $x_i$ 表示在词元 $v_j$ 后面出现词元 $v_i$ 的概率。
>
> 假设概率向量 $x$ 服从狄利克雷分布：
>
> $$
> x \sim Dir(\alpha)
> $$
>
> 其中：
>
> $$
> \alpha = \{\alpha_i = \alpha\}
> $$
>
> 表示每个可能的后继词都先分配一个相同的先验伪计数 $\alpha$。
>
> 观测语料 $D$ 后，后验分布仍然是狄利克雷分布：
>
> $$
> P(x \mid D)
> =
> \frac{P(D \mid x)P(x)}
> {P(D)}
> \sim
> Dir(\tilde{\alpha})
> $$
>
> 其中：
>
> $$
> \tilde{\alpha}
> =
> \{\tilde{\alpha_i}\}
> $$
>
> 并且：
>
> $$
> \tilde{\alpha_i}
> =
> Count(v_j,v_i)+\alpha
> $$
>
> 也就是说，后验参数等于：
>
> $$
> \text{真实计数} + \text{先验伪计数}
> $$
>
> 对狄利克雷分布来说，后验均值为：
>
> $$
> E[x_i \mid D]
> =
> \frac{\tilde{\alpha_i}}
> {\sum_k \tilde{\alpha_k}}
> $$
>
> 代入 $\tilde{\alpha_i}=Count(v_j,v_i)+\alpha$：
>
> $$
> E[x_i \mid D]
> =
> \frac{Count(v_j,v_i)+\alpha}
> {\sum_k\left(Count(v_j,v_k)+\alpha\right)}
> $$
>
> 展开分母：
>
> $$
> \sum_k\left(Count(v_j,v_k)+\alpha\right)
> =
> \sum_k Count(v_j,v_k)
> +
> \sum_k \alpha
> $$
>
> 因为：
>
> $$
> \sum_k Count(v_j,v_k)=Count(v_j)
> $$
>
> 且词表大小为 $\lvert V\rvert$，所以：
>
> $$
> \sum_k \alpha = \alpha \lvert V\rvert
> $$
>
> 因此：
>
> $$
> E[x_i \mid D]
> =
> \frac{Count(v_j,v_i)+\alpha}
> {Count(v_j)+\alpha \lvert V\rvert}
> $$
>
> 这正是利德斯通平滑公式：
>
> $$
> P(v_i \mid v_j)
> =
> \frac{Count(v_j,v_i)+\alpha}
> {Count(v_j)+\alpha \lvert V\rvert}
> $$
>
> 直观理解：利德斯通平滑相当于在观察真实语料之前，先假设每个可能的 Bigram 都已经出现了 $\alpha$ 次，从而避免概率为 0。

### 3.折扣法
折扣法的核心思想是：**把已经出现过的 n-gram 的概率稍微降低一点，把省出来的概率分配给没有出现过的 n-gram**。
它不是简单地给所有词都加一个固定伪计数，而是直接调整概率分布。
特点：
- 词的原始频次和总频次保持不变
- 对已出现事件进行“折扣”
- 把折扣出来的概率质量留给未见事件
- 代表方法：**绝对折扣法**

简单理解：
> 已经见过的词组合，不要把概率占得太满；留一点概率给没见过但可能出现的组合。

### 4.回退法
回退法的核心思想是：**如果高阶 n-gram 没有见过，或估计不可靠，就退回到低阶模型**。

### 5.插值法
插值法的核心思想是：**不只选择一个模型，而是把多个阶数的模型加权混合**。

# 讨论

> [!question] 用 BPE 切分中文有什么问题
> - 中文不像英文有天然空格，BPE 很难直接知道真正的词边界。
> - BPE 只根据字符/字节组合的频率合并，不一定符合中文语义，可能把词切碎，也可能把不该合并的字合在一起。
> - 对低频词、人名、地名、新词等切分不稳定，可解释性较弱。
> - 因此，BPE 能缓解未登录词问题，但不能完全解决中文分词中的语义边界问题。

> [!warning] 统计语言模型（N-gram）的不足
> - 数据稀疏严重：$n$ 越大，可能的词序列组合越多，很多组合在训练语料中没有出现，概率容易为 $0$。
> - 上下文长度有限：N-gram 只看前面固定数量的词，难以捕捉长距离依赖。
> - 泛化能力弱：主要依赖词的表面共现频率，难以理解语义相似性。
> - 参数规模大：高阶 N-gram 需要统计大量组合，存储和计算成本较高。
> - 因此，N-gram 通常需要配合平滑、回退、插值等方法改进。
