PCA 原理简介:核心思想、几何解释与数学推导
主成分分析(PCA),说白了就是降维。你不是搞 ADMET 批次效应检测嘛,手上少则几十个分子描述符,多则几百个,维度一高,距离度量失效、聚类乱成一团,批次效应肉眼根本看不出来。PCA 就是帮你抓住数据里“最值钱”的那些方向,丢掉冗余和噪声。
我个人习惯把 PCA 理解成三个层次:它想干什么(核心思想)、它干成了什么样子(几何解释)、它怎么算出来的(数学推导)。咱们一个层次一个层次拆开聊。
核心思想:方差最大与重构误差最小
你想想看,一堆点在空间中散布,哪个方向最“重要”?
PCA 给的答案是:方向上的投影方差越大,这个方向越重要。因为方差大意味着数据在这个方向上分得开、信息量足。相反,沿着某个方向投影后点都挤在一起,那这个方向基本是噪音,丢了也不心疼。
换个角度,PCA 也在找一组新坐标轴,使得把原数据投影到这些轴上后,重建回去的误差最小。这两个角度是等价的——我当年读论文时花了半天才想通这件事。
- 目标1:找到投影方差最大的方向(第一主成分)
- 目标2:在垂直方向上继续找方差最大的方向(第二主成分)
- 结果:前 k 个主成分保留了数据最大的信息量
几何解释:旋转坐标系,看到数据的骨架
几何上,PCA 就是做了一次刚性旋转和缩放。原始坐标轴(比如 logP、分子量、TPSA)通常互相关联,PCA 把它们旋转成一个新坐标系,新坐标轴(主成分)彼此垂直,并且按照方差大小排序。
我经常跟团队的人说:
“你别把 PCA 当成黑盒,它就是帮你找到一个能看清数据‘骨架’的视角而已。”
比如下面这个二维例子:
图中三个批次在原始坐标下混在一起,但沿 PC1 方向(红色箭头)明显分成了三层。PC2 方向方差小,说明批次内差异主要是随机波动——这就是 PCA 直观的“分离力”。
数学推导概要:协方差矩阵与特征值分解
好了,理论怎么落地?数学上分 4 步,我一个个说。
- 中心化:每个变量减去自己的均值,让数据中心回到原点。这一步不做的话,第一主成分会偏向数据重心,而方差信息会被偏移干扰。
- 算协方差矩阵:对于 p 维数据,得到一个 p×p 的对称矩阵,对角线上是每个变量的方差,非对角线上是变量间的协方差(线性相关程度)。
- 特征值分解:对协方差矩阵解特征方程,得到 p 个特征值和对应的特征向量。特征值越大,说明对应特征向量方向上的方差越大。
- 排序与投影:按特征值从大到小排序,取前 k 个特征向量组成投影矩阵 W,然后用 XW 得到降维后的数据(主成分得分)。
我这里写一段最简的 Python 实现,帮你看看数学在代码里长什么样:
import numpy as np
def pca_numpy(X, n_components):
# X: (n_samples, n_features)
# 1. 中心化
X_centered = X - X.mean(axis=0)
# 2. 协方差矩阵
cov = np.cov(X_centered, rowvar=False)
# 3. 特征值分解
eigenvalues, eigenvectors = np.linalg.eigh(cov)
# 特征值升序,取最后n_components个(即最大的)
idx = np.argsort(eigenvalues)[::-1][:n_components]
components = eigenvectors[:, idx]
# 4. 投影
return X_centered @ components, eigenvalues[idx]
# 示例:10个样本,4个描述符
X_example = np.random.randn(10, 4)
scores, evals = pca_numpy(X_example, 2)
print("主成分得分形状:", scores.shape)
print("前两个特征值:", evals)
np.linalg.eig 而不用 eigh。协方差矩阵是对称的,eigh 对实对称矩阵优化过,数值稳定性好得多。有次我用 eig,特征向量符号乱跳,导致批次聚类时前后跑出相反的分组颜色,排查了俩小时才找到原因。
方差解释率与主成分选择
拿到特征值以后,怎么判断取几个主成分够用?
标准做法是计算方差解释比例:
explained_variance_ratio = eigenvalues / eigenvalues.sum()
cumulative = np.cumsum(explained_variance_ratio)
通常建议取累计方差解释率 > 80% 或 > 90% 时的主成分个数。我自己的习惯是:先跑一次完整 PCA,看碎石图(scree plot),如果前两个主成分已经能解释 70% 以上,那检测批次效应时基本够用;如果连 50% 都不到,说明数据噪音很大,先做变量筛选再说。
| 主成分序号 | 特征值 | 方差解释率 | 累计方差解释率 |
|---|---|---|---|
| 1 | 2.85 | 47.5% | 47.5% |
| 2 | 1.32 | 22.0% | 69.5% |
| 3 | 0.94 | 15.7% | 85.2% |
| 4 | 0.53 | 8.8% | 94.0% |
| 5 | 0.36 | 6.0% | 100.0% |
你想想看,上表里前两个主成分解释了近 70% 的方差。用在批次效应检测上,PC1 vs PC2 的散点图大概率能看出批次分组。第三主成分还有 15%,要不要加进来?我的建议是先用二维图试,分不开再加第三个轴,不要一上来就把所有主成分都扔进去“碰运气”。
PCA 在批次效应检测中的特殊角色
前面讲的是普适原理。回到咱们课程的主题——ADMET 批次效应检测——PCA 之所以成为标配,是因为它无监督:不需要事先知道样本属于哪个批次,只凭数据自身的分布就能发现异常分组。
如果有批次效应,那么前几个主成分的散点图上,不同批次的样本会自然形成分离的簇。反过来,如果批次标签跟主成分得分毫无相关性,说明数据本身的系统偏差很小,可以放心往下做模型训练。
嗯,这里要注意一点:PCA 只能告诉你“有差异”,但分辨不出哪些差异是批次造成的、哪些是真实的生物学/化学差异。要区分这个,得用更高级的方法(比如 ComBat、Harmony),我们后面章节会讲。
以上就是 PCA 的核心思想、几何直觉和数学底子。下一段实操里,咱们就要把这些原理用到真实的 ADMET 数据上,亲手跑一遍、画一张 PCA 图,看看批次效应到底长什么样。