Skip to content
← 主成分分析与降维

/knowledge/notes/autoencoders-vs-pca

概念笔记 · 主成分分析与降维

自编码器与 PCA

两者都把每一行压成更少的数再还原。线性自编码器会精确地落到 PCA 的答案上,非线性才让它能跟着曲线走。

学于
面向数据科学的多元统计MAST90138 · MAST30034
时间
墨尔本大学,2021–2024
应用于
多元统计实验室 · 信号源分离实验室
阅读 / 复习
约 5 分钟阅读2026-10-21

PCA 和自编码器回应的是同一个要求:把每一行压缩成更少的几个数,再尽可能好地从这几个数里把这一行还原出来。PCA 用一条直线或一个平面来压缩,有闭式解。自编码器则把压缩和还原学成两个小神经网络。真正有用的,是知道两者在哪里完全一致,又在哪里分道扬镳。

01

基本想法

两种方法的结构一样。编码器把有 dd 个数的一行 xx 变成有 kk 个数的编码 zz,kk 比 dd 小。解码器再把编码变回一行 x^\hat{x}。训练就是在编码允许的范围内,让 x^\hat{x} 尽量接近 xx。中间那段窄口,也就是瓶颈,逼着方法留下最重要的信息,放掉其余的。

在 PCA 里,两半都是线性的。编码器投影到 kk 个方向上,解码器再把这些方向加回去。按平方误差算,最好的方向就是协方差矩阵最大的几个特征向量,所以根本不需要训练。每次得到的答案都一样,只是每个方向的正负号可能不同。

在自编码器里,两半都是神经网络。隐藏层用了非线性激活函数,编码就能沿着一条曲线或一个弯曲的面走,于是一个数就能描述弯曲形状上的一个点,而这个形状没有任何直线拟合得了。

反过来的联系更值得记住:把激活函数去掉,让每一层都是线性的,再用平方误差训练,自编码器最后张成的子空间正好就是 PCA 找到的那个。Baldi 和 Hornik 在 1989 年证明了,只有一个隐藏层时,这个损失函数除了 PCA 的解之外没有别的局部极小值。线性层叠得再多,算的仍然只是一个线性映射,不可能做得更好。非线性才是全部意义所在。

02

数学

把数据按均值 μ\mu 中心化,构造协方差矩阵 SS。它的特征向量 vjv_j 就是主方向,每个特征值 λj\lambda_j 是沿这个方向的方差。

S=1n∑i=1n(xi−μ)(xi−μ)⊤,S vj=λjvj,λ1≥λ2≥⋯≥λdS = \frac{1}{n} \sum_{i=1}^{n} (x_i - \mu)(x_i - \mu)^{\top}, \qquad S\, v_j = \lambda_j v_j, \quad \lambda_1 \ge \lambda_2 \ge \dots \ge \lambda_d

这里除以 n 而不是 n − 1,是为了让下面的误差等式精确成立,不影响方向。

把最大的 kk 个特征向量排成矩阵 VkV_k 的列。PCA 的重建就是投影到这些方向上,它的平均平方误差正好等于被丢掉的方差。

x^=μ+VkVk⊤(x−μ),1n∑i=1n∥xi−x^i∥2=∑j>kλj\hat{x} = \mu + V_k V_k^{\top} (x - \mu), \qquad \frac{1}{n} \sum_{i=1}^{n} \lVert x_i - \hat{x}_i \rVert^2 = \sum_{j > k} \lambda_j

Eckart–Young 定理说,按平方误差算,没有哪个秩为 k 的线性映射能做得更好。

自编码器把投影换成两个学出来的函数,编码器 fθf_\theta 和解码器 gϕg_\phi,在同一个损失上用梯度下降来拟合。

z=fθ(x),x^=gϕ(z),min⁡θ, ϕ  1n∑i=1n∥xi−gϕ(fθ(xi))∥2z = f_\theta(x), \quad \hat{x} = g_\phi(z), \qquad \min_{\theta,\, \phi} \; \frac{1}{n} \sum_{i=1}^{n} \bigl\lVert x_i - g_\phi\bigl(f_\theta(x_i)\bigr) \bigr\rVert^2

如果 f 和 g 都是线性的,最好的 g∘f 就是 PCA 的投影。如果它们能弯,重建就能贴着曲面走。

能弯是有代价的,代价就是 PCA 从来不需要的那些东西:层的大小和激活函数要选,学习率要定,起点是随机的,什么时候停要有规则,拟合出来的形状还可能绕着噪声转。PCA 只有一个决定要做,就是 kk,而保留下来的方差比例 ∑j≤kλj/∑jλj\sum_{j \le k} \lambda_j / \sum_j \lambda_j 能帮你做这个决定。

03

动手试

下面的工具把 80 个点各压成一个数,再还原回来。虚线是 PCA 的答案。红色曲线是一个小自编码器,结构是 2、6、1、6、2 个单元,就在你的浏览器里用 Adam 训练 1,200 步。两者都在训练点和同一条曲线上新抽的 80 个点上计分。

1.00
0.05

自编码器的层

显示误差

种子 1
  • 训练点
  • PCA,一个主成分
  • 自编码器,一个数的编码

第一主成分保留了 78% 的方差。

每个点的平均重建误差平方,分别在 80 个训练点和同一条曲线上新抽的 80 个点上计算。
方法训练新数据
PCA0.09210.0911
自编码器(tanh)0.00240.0033

在新数据点上,PCA 的误差为 0.0911,tanh 自编码器为 0.0033。自编码器跟上了 PCA 的直线跟不上的弯。

数据点和网络的初始值都带种子,所以同一组设置每次都训练出同一条曲线。红色曲线就是自编码器那个一维编码能表达的全部,每个重建出来的点都落在它上面。
  • 把层切换成“线性”。红色曲线被拉直,落在虚线上,两列误差和 PCA 一直到小数点后四位都相同,正如 Baldi 和 Hornik 所预言的。
  • 切回 tanh、弯曲程度为 1 时,曲线跟着弯走,它在新数据上的误差比 PCA 小二十倍以上。
  • 把弯曲程度拖到 0。这时数据真的是一条直线,PCA 几乎保留了全部方差,自编码器无可添加。
  • 弯曲程度保持为 0,把噪声调到 0.20,再按两次“换一组数据”到种子 3。tanh 自编码器在训练点上赢了 PCA,在新数据上却输了。它把自己弯去迁就噪声了。
  • 在弯曲的设置下显示 PCA 的误差。误差线在弯的两端最长,那里直线离数据最远。

04

我在哪用到它

05

容易出错的地方

06

参考资料