> 最小二乘法能够做序列预测吗

简单来说，最小二乘法本身不是“预测模型”，而是一种**参数估计方法**。只要你把“序列预测问题”转化为一个**回归问题**，就可以用最小二乘法来做。

一、最常见的做法：线性回归型序列预测
假设你有一个时间序列
y₁, y₂, …, yₜ

你可以用过去的值来预测未来的值，例如
yₜ = a₁ yₜ₋₁ + a₂ yₜ₋₂ + … + aₖ yₜ₋ₖ + ε

这就是一个**自回归（AR）模型**。
参数 a₁,…,aₖ 可以用最小二乘法估计，估计完以后就能做预测。

所以：
最小二乘法 + 合理的特征构造 ⇒ 序列预测 ✔

二、适合哪些情况
最小二乘法做序列预测，通常适合下面这些场景：

* 关系近似线性
* 序列比较平稳（均值、方差不剧烈变化）
* 噪声接近高斯分布
* 短期预测效果通常更好

比如：

* 传感器数据的短期趋势
* 平稳的经济或工业时间序列
* 简单趋势外推

三、不太适合的情况
如果你的序列具有：

* 强烈非线性
* 明显的季节性但未建模
* 长期依赖关系
* 突变或结构性变化

那么单纯用最小二乘法，预测效果往往会比较差，需要更复杂的模型。

---

> 我要做一个用来教学的最小二乘法做文本补全的模型，给你一个“最小二乘 n-gram 文本补全”的完整建模流程

这个例子非常好，也正好能说明**最小二乘法“理论上能用，但能力有限”**的边界。

结论先给出：
**可以用最小二乘法来训练一个“基于文本片段补全句子”的模型，但只能做到非常初级、线性、局部的补全，和现代语言模型在本质上不是一类东西。**

下面一步一步解释。

一、如何把“文本补全”变成最小二乘问题
关键在于两步：**数值化 + 回归建模**。

1）文本表示
你需要先把文本变成数值向量，比如：

* one-hot 编码
* n-gram 计数
* TF / TF-IDF
* 或者固定的词向量（不训练，只使用）

假设用 n-gram：
“我 喜欢 吃 苹果”
用前 k 个词预测下一个词。

2）构造回归目标
例如用前 k 个词的表示 x，预测下一个词 y：

xₜ = [wₜ₋ₖ, …, wₜ₋₁]

yₜ = wₜ

如果 y 用 one-hot 表示，那么模型就是：

ŷ = W x

W 可以用**最小二乘法**来估计（通常是多输出回归）。

这本质上是一个**线性语言模型**。

二、这种模型本质上是什么

用最小二乘法训练的文本补全模型，本质上等价于：

* 线性 n-gram 语言模型
* 或“连续空间里的条件概率近似”
* 或 softmax 之前的线性打分模型（但没有真正的概率建模）

它学到的是：

> “在向量空间中，哪些上下文线性地指向哪些词”

三、它能做到什么
在非常受限的条件下，它是能“补全”的：

* 高频、固定搭配
* 短距离依赖
* 语法非常简单的文本
* 领域很窄（如技术文档、模板化文本）

例如：
“机器 学习 是 一种 ____”

“线性 回归 的 目标 是 ____”

这种补全是可行的。

四、它做不到什么（关键限制）

1）语言是高度非线性的

词与词之间的关系不是线性可分的，最小二乘只能学到线性叠加。

2）无法建模长程依赖

最小二乘模型没有“记忆”和“状态”，上下文一长就失效。

3）概率解释很差

最小二乘最小化的是平方误差，而不是语言建模需要的对数似然。

4）组合泛化能力弱

没见过的结构，几乎无法合理补全。

5）输出空间巨大

词表一大，W 矩阵会非常庞大，数据效率极低。

五、和现代语言模型的本质区别
用一句话区分：

* 最小二乘文本补全：

  **“线性回归 + 手工上下文”**

* 现代语言模型（RNN / Transformer）：

  **“非线性表示学习 + 条件概率建模 + 深层结构”**

你可以把最小二乘法看成是：

> 语言模型发展史中，非常早期、非常基础的一层。

六、什么时候仍然值得用最小二乘法

在这些情况下，它依然有价值：

* 教学或理论分析
* 做可解释的 baseline
* 小语料、低算力
* 对线性结构本身感兴趣
* 研究语言统计特性，而不是“智能生成”

七、总结一句话
**最小二乘法可以训练一个“能补全句子”的模型，但它学到的不是语言，而是词共现的线性影子。**

---

好，这个教学目标非常清晰，而且**“最小二乘 n-gram 文本补全”正好是一个既完整、又能暴露局限性的经典例子**。

下面我给你一个**从数学建模到训练与预测的完整流程**，每一步都尽量保持“最小二乘味道”，方便课堂讲解和板书推导。

---

一、问题形式化（教学起点）

给定一个文本序列
w₁, w₂, …, wₜ

目标：
在已知前 k 个词的情况下，预测下一个词
(wₜ₋ₖ, …, wₜ₋₁) → wₜ

这是一个**监督学习 + 序列回归**问题。

---

二、文本离散化与词表构建

1）构建词表
从语料库中统计所有出现的词，得到词表
V = {v₁, v₂, …, v_|V|}

词表大小记为 |V| = N。

教学建议：

* 可以限制词表大小（如只取高频词）
* 未登录词统一映射为 `<UNK>`

2）词的数值表示（one-hot）

每个词 vᵢ 用一个 N 维 one-hot 向量表示：

vᵢ ↦ eᵢ = (0, …, 1, …, 0)ᵀ

这是最“线性代数友好”的表示方式，非常适合最小二乘教学。

---

三、n-gram 上下文向量构造

假设使用 k-gram（k 个历史词预测 1 个词）。

1）输入向量 xₜ

将前 k 个词的 one-hot 向量拼接：

```
xₜ = [ 
    e(wₜ₋ₖ)
    e(wₜ₋ₖ₊₁)    
    …
    e(wₜ₋₁) 
]
```

则
xₜ ∈ ℝ^(kN)

2）输出向量 yₜ

目标词仍然是 one-hot：

yₜ = e(wₜ) ∈ ℝ^N

---

四、线性模型假设（核心）

假设一个**纯线性映射**：

ŷₜ = W xₜ

其中
W ∈ ℝ^(N × kN)

解释给学生时可以说：

> W 的每一行，对应“生成某个词的线性规则”。

---

五、最小二乘目标函数

给定训练样本 { (xₜ, yₜ) }，t = 1,…,T

目标是最小化平方误差：

min_W ∑ₜ ‖ yₜ − W xₜ ‖²

写成矩阵形式更漂亮：

1）构造数据矩阵

X = [x₁, x₂, …, x_T] ∈ ℝ^(kN × T)

Y = [y₁, y₂, …, y_T] ∈ ℝ^(N × T)

2）整体目标函数

min_W ‖ Y − W X ‖_F²

这是**标准的多输出线性最小二乘问题**。

---

六、解析解（最小二乘解）

如果 X Xᵀ 可逆，则解析解为：

Ŵ = Y Xᵀ (X Xᵀ)⁻¹

这是教学中非常重要的一步，因为你可以强调：

* 不需要梯度下降
* 一步到位
* 完全是线性代数问题

如果 X Xᵀ 不可逆，可以自然引出：

* 伪逆
* 或岭回归（L2 正则）

岭回归形式：

Ŵ = Y Xᵀ (X Xᵀ + λI)⁻¹

---

七、预测与“文本补全”

给定一个新的上下文 x：

1）线性输出

ŷ = Ŵ x ∈ ℝ^N

注意：
ŷ 不是概率，只是一个实值打分向量。

2）选择补全词

最简单、最符合最小二乘精神的方式：

ŵ = argmax_i ŷ_i

也可以顺便对比说明：

* 这里没有 softmax
* 没有对数似然
* 所以它不是标准语言模型

---

八、模型的可解释性（教学亮点）

这个模型有一个非常适合教学的优点：**完全可解释**。

* W 的一个子块，对应
  “在第 j 个位置出现词 v，对预测词的线性贡献”
* 可以画成一个 n-gram 权重表
* 和传统统计语言模型形成直观对比

你甚至可以展示：

> “这个模型本质上在学习一个加权共现矩阵”。

---

九、模型局限（自然收尾）

在完整流程讲完后，非常自然地指出局限：

* 线性假设过强
* one-hot 维度爆炸
* 无法建模语义相似性
* 无法处理长程依赖
* 平方误差 ≠ 语言建模目标

这一步非常适合作为**过渡**，引出：

* softmax + 交叉熵
* 词向量
* 神经语言模型
* Transformer

---

十、一句话总结（可作为课件最后一页）

> 最小二乘 n-gram 文本补全模型
> = one-hot 表示 + 上下文拼接 + 线性回归 + argmax 预测
>
> 它不是“理解语言”，而是**线性地记住共现结构**。

---

如果你需要，我可以下一步帮你做三件事之一：

1）给一个**极小语料的完整数值算例**（可以手算）

2）把这个模型改写成**矩阵/概率语言模型的对照版**

3）给一份**适合课堂展示的推导结构大纲**




---
这个脚本**完整演示**：

* one-hot 编码
* n-gram 构造
* 最小二乘解析解
* 用 argmax 做预测

1）这是**严格的最小二乘法**

* 没有 softmax
* 没有交叉熵
* 没有神经网络

2）预测本质是

> 在 one-hot 空间里做线性打分，然后 argmax

3）它学到的是

* 高频共现
* 模板结构
  而不是“语言理解”。

————————

五、非常适合的课堂延伸

你可以顺着这个例子自然引出：

* 为什么平方误差不适合语言
* 为什么要 softmax
* 为什么需要词向量
* 为什么线性模型不够

如果你愿意，我可以下一步帮你：

* 把这个脚本改成**岭回归版本**
* 画出 W 中某些权重的可解释含义
* 或给你一版**板书级数学推导对应代码**

---

> RuntimeWarning: divide by zero encountered in matmul W = Y @ X.T @ np.linalg.inv(X @ X.T + lam * I)

这个问题你碰到得非常好，而且它本身就是一个很有教学价值的点：
👉 最小二乘在 one-hot + n-gram 这种极度稀疏、小样本设置下，数值上必然会出问题。

我先给你结论版，再解释原因，最后给你一份稳定、不报警、适合教学的修正版代码。


一、结论先说清楚

你这个 warning **不是 bug，也不是你代码写错了**，而是：

1）`X X^T` 极度病态（rank 严重不足）

2）`pinv` 在数值上产生了 `inf / nan`

3）后续矩阵乘法就全部“炸掉”了

这是**经典的最小二乘数值不稳定问题**，在你这个设置下几乎是必然的。

——
二、为什么一定会出问题（这是重点）

我们来量化一下你的矩阵规模：

* 词表 V = 23
* 输入维度 = 2V = 46
* 训练样本 T ≈ 30 左右

于是：

X ∈ ℝ^(46 × 30)

XXᵀ ∈ ℝ^(46 × 46)

但问题是：

1）X 的每一列只有 **2 个 1，其余全是 0**

2）很多上下文组合从未出现

3）大量维度在所有样本中始终为 0

结果就是：

* rank(X) ≪ 46
* XXᵀ 有大量 **零特征值**
* 数值伪逆时 → 除以接近 0 的奇异值
* 直接产生 overflow / divide by zero

⚠️ 这在“理论最小二乘”里是允许的，在“数值计算”里是灾难。

——

三、教学上**正确**的修复方式（推荐）

不是“硬消 warning”，而是**引入岭回归（L2 正则）**，并且明确告诉学生：

> 这是为了数值稳定性，而不是为了提升语言能力。

数学上只改一行：

W = Y Xᵀ (X Xᵀ + λI)⁻¹

这一步在教学上**非常自然、非常合理**。

——
五、这是一个**非常好的教学切入点**

你现在正好可以顺着这个报错讲清楚几件事：

1）理论最小二乘 ≠ 数值最小二乘

2）高维 + 稀疏 + 小样本 ⇒ 病态矩阵

3）为什么“正则化不是魔法，而是稳定性工具”

4）为什么语言模型不能只靠线性回归

这比“模型预测得准不准”要重要得多。

六、如果你愿意继续深入

我可以再帮你做三件**非常适合课堂**的事之一：

1）把 `λ` 从 0 → 很大，现场演示预测如何变化
2）画出 `X Xᵀ` 的特征值分布，直观看病态性
3）把这个模型改写成 **softmax + 交叉熵** 的对照版（结构几乎一样）

## 修复总结

**问题原因：**
- 矩阵 `XXT` 是奇异的或接近奇异的（秩远小于维度：17 vs 46），导致条件数为 `inf`
- 直接计算 `Y @ X.T @ np.linalg.pinv(XXT)` 时产生数值不稳定，引发 NaN 和 Inf

**解决方案：**
1. **使用 `np.linalg.lstsq()` 替代伪逆计算** - 这是更稳定的最小二乘求解方法，内部使用奇异值分解（SVD），能很好地处理奇异矩阵
2. **对每一行分别求解** - 将问题分解为多个独立的最小二乘问题，增强数值稳定性
3. **显式转换 `idx` 为 `int`** - 避免 numpy 整数类型与 Python 内置整数类型的不匹配

脚本现在运行顺利，无任何警告！✅