3. PCA原理简介
老规矩,咱们在动手写代码检测批次效应之前,先把背后的数学底子摸一遍。PCA(主成分分析)说白了这个技术,就是用来做“降维”的。我记得刚接触组学数据那会儿,动不动就上万维特征,根本没法直接画图看。PCA 就是那个能把高维数据“压扁”到二维、三维,让我们肉眼能看出结构的工具。
核心思想:PCA 找到数据中“方差最大”的那些方向,然后把数据投影上去。方差大的方向,往往就藏着数据的主要结构——包括我们最头疼的批次效应。
3.1 主成分到底是什么?
你想想看,一堆样本,每个样本有几千个基因的表达值。这就是几千维的空间,不可视化。PCA 会在这团数据里,找出第一个方向,让所有样本投影到这个方向上之后,它们的“分散程度”(方差)最大。这个方向就是第一主成分(PC1)。
接着,PCA 找第二个方向。它必须跟 PC1 垂直(正交),并且在这个前提下让方差最大。这就是 PC2,以此类推。通常前几个 PC 就抓住了数据的大部分变化。
我个人习惯把主成分看作“隐藏的综合指标”。它不直接对应某个基因,而是多个基因的线性组合。举个例子:PC1 的系数可能是
PC1 = 0.3 * GeneA + (-0.1) * GeneB + 0.5 * GeneC + ...
哪个基因的系数绝对值大,就说明它对样本的分离贡献大。这个系数叫做“载荷”(loading)。
3.2 数学上是怎么算的?
其实背后的运算没那么玄乎,说白了就是线性代数里的那套东西。我尽量把关键步骤捋清楚。
- 数据中心化:每个基因的表达值减去它自己的均值。这一步是必须的,否则 PC1 会被均值偏移主导。
- 计算协方差矩阵:这是一个基因 x 基因的矩阵,对角线是每个基因的方差,非对角线是两个基因的协方差(共变的趋势)。
- 特征分解:对协方差矩阵求特征值和特征向量。特征值就是每个主成分的“方差大小”,特征向量就是主成分的方向(载荷)。
- 投影:用特征向量矩阵去乘原始数据,得到样本的新坐标(主成分得分)。
对我而言,PCA 最妙的地方就在这里:协方差矩阵把基因间的共变信息都浓缩起来了,特征分解又把最主要的共变模式提取出来。你如果做的是基因表达数据,不同批次的系统偏差一定会体现在某些共变模式里——所以 PCA 能一眼看出来。
| 概念 | 数学符号 | 实战意义 |
|---|---|---|
| 特征值 | λ | 代表该 PC 解释了总方差的多少。越大越重要。 |
| 特征向量 | v | 主成分的方向,由载荷系数构成。 |
| 载荷 | loading | 每个原始变量对 PC 的贡献度。绝对值越大越关键。 |
| 得分 | score | 样本在 PC 坐标系里的新坐标。用来画散点图。 |
经验之谈:我建议你在实战中不要只看 PC1 和 PC2。有时候批次效应藏在 PC3 甚至 PC5 里。记得多画几个配对图。
3.3 一个实例,帮你理解计算过程
光说理论太干,我拿一个极简例子走一遍。假设只有 2 个基因(X, Y)、3 个样本。
样本1: X=1, Y=2
样本2: X=2, Y=3
样本3: X=3, Y=4
第一步:中心化
X 均值 = (1+2+3)/3 = 2
Y 均值 = (2+3+4)/3 = 3
中心化后:
样本1: (-1, -1)
样本2: (0, 0)
样本3: (1, 1)
第二步:协方差矩阵
Var(X) = ((-1)^2 + 0^2 + 1^2)/2 = 1
Var(Y) = 1
Cov(X,Y) = ((-1)*(-1) + 0 + 1*1)/2 = 1
[[1, 1],
[1, 1]]
第三步:特征分解
特征值:λ1=2, λ2=0
特征向量:v1=(0.707, 0.707), v2=(-0.707, 0.707)
看到了吗?λ2=0,说明数据在垂直于 v1 的方向上没有任何变化。所有样本其实都落在一条直线上。这就是 PCA 帮我们抓到的结构。
避坑指南:上面的例子我在课堂上讲过很多次。但真实的组学数据里,变量(基因)远远多于样本数。这时候协方差矩阵会很大(上万维),直接分解算不动。我们实际用的是“奇异值分解”(SVD),原理相通但计算更高效。这个后面实战部分会具体讲到。
3.4 实践中,我踩过哪些坑
PCA 虽然基础,但用好也没那么简单。我把自己摔过的跟头列出来:
- 没做标准化:如果基因表达量差异太大(比如有的基因低表达均值为1,有的高表达均值为10000),未经标准化的 PCA 会被高表达基因完全主导。你不信可以试试——结果基本就是第一个 PC 等于总表达量。我踩过这么个坑,后来养成了做 Z-score 或 Scale 的习惯。
- 忽视离群点:单个异常样本可能会把 PC 方向带偏。我建议做 PCA 之前先做个简单的箱线图或距离矩阵,把严重离群的样本标出来。
- 只看 PC1 和 PC2:我之前处理一组合并单细胞数据时,批次效应偏偏在 PC4 和 PC5 才完全暴露。你想想看,如果只画 PC1 vs PC2,结果完美重叠,就以为自己数据没问题——那可真就误事了。
- 没有检查载荷:PC 图只能看到样本之间的分离趋势,但分离是由哪些基因驱动的?必须看载荷。如果载荷里全是批次特异的基因(比如只在一个批次中检测到的线粒体基因),那分离就很可能不是生物差异,而是批次效应。
为什么 PCA 能检测批次效应?
这就要回到 PCA 的核心:它找的是数据中方差最大的方向。批次效应通常在样本间引入很大的系统性偏差——比如批次 1 的样本整体表达量偏高,批次 2 偏低。这种偏差在所有基因上都存在,它产生的方差会比真实的生物学差异更大。所以,在 PC1 或 PC2 的散点图里,样本往往会按批次分成两团。这就是我们判断批次效应是否存在的核心依据。
嗯,这张图把 PCA 检测批次效应的完整路径串起来了。从原始数据开始,经过预处理、分解、可视化,最后落到判断和结论。你写代码的时候也可以按照这个流程一步步来。
总结一下:PCA 不是万能的,但它绝对是你在合并多批次数据时第一个该拿出来的工具。不需要特别复杂的参数,一行
from sklearn.decomposition import PCA
pca = PCA(n_components=5)
scores = pca.fit_transform(data_scaled)
就能看到数据的大致面貌。后续几章我们会在此基础上深入,讲怎么通过 PCA 图定量评估批次效应的严重程度,以及如何结合其他方法验证你的判断。