想象你是一名被空投到巨型城市的地图绘制师:两万条街道在脚下交错纵横,每条都长得差不多,而你手里的白纸只有巴掌大。这座城市就是如今组学数据的缩影——一次基因表达检测产生两万多个特征,可用样本却只有几百例。想画出真正有用的地图,你得学会“降维”这门手艺:先扔掉冗余路牌(特征选择),再乘直升机俯瞰主干道(PCA),钻进街区走访邻里(t-SNE),铺开智能路网平衡全局(UMAP),最后沿河流追踪连续轨迹(PHATE)。这篇文章用“城市制图”这条故事线,带你理解四种经典方法的原理、优劣对比与工程落地路径——让你在拿到高维数据时,心里始终有一张清晰的“地图选择指南”。

岗位关联

掌握特征选择与降维,你就能在高维数据中“看见”真实结构——这是生物信息学、精准医疗与一切高维业务分析的基本功,也是 AI 从业者把原始数据转化为业务洞察的核心能力之一。

目录
  1. 可视化演示
  2. 维度灾难:高维迷宫的陷阱
  3. 特征选择基础:先扔掉冗余路标
  4. PCA 原理:直升机俯瞰主干道
  5. t-SNE 原理:钻进街区走访邻居
  6. UMAP 原理:智能路网铺开
  7. PHATE 原理:追踪河流与轨迹
  8. 对比与选型:口袋里要有四张地图
  9. 工程落地路径:从绘图室到正式发行
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示特征选择与降维四大方法:PCA线性降维(协方差特征分解PC1/PC2主成分投影方差解释85%)、t-SNE/UMAP非线性(kNN邻域图局部聚类保持3簇2D嵌入)、四方法对比(PCA全局/t-SNE局部/UMAP均衡/PHATE轨迹在线性-局部-成本三维权衡),三模式切换理解降维选型全貌。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+C1+'

维度灾难:高维迷宫的陷阱

你被空投到一座陌生的巨型城市,手里只有一张巴掌大的白纸,却要在上面画出全城的布局。更糟的是,这座城市有成百上千条街道,每条街道都长得差不多——你知道自己要去哪个街区,却完全分不清哪条路通向哪里。这就是高维数据带给分析者的第一道难题:特征太多,多到人脑根本无法直接理解。

在生物信息学场景中,一次基因表达检测会给每个样本带来两万多个特征,而样本量常常只有几百例。这种“特征多、样本少”的数据进入任何机器学习模型,都会引发严重的过拟合风险。更重要的是,高维空间中样本之间的欧氏距离趋于一致——就像每条街道的招牌都写着“距目的地差不多远”,距离这个最基础的度量失去了区分能力。这种现象被称为“维度灾难”。

维度灾难有三个具体表现:数据在高维空间中变得极度稀疏,需要指数级样本才能填满空间;任意两点的距离差异趋于消失,最近邻与最远邻几乎同样远;计算复杂度随维度快速增长,存储和可视化的代价迅速变得不可承受。

回到城市比喻:每条街道的招牌都写着“距目标 500 米”,但不管往哪走数字都差不多——你失去了用距离判断方向的任何线索。因此,制图师必须先做一件事:用数量更少、信息更密集的地标来绘制地图,这就是特征选择和降维登场的理由。

lim⁡d→∞max⁡i,j∥xi−xj∥min⁡i,j∥xi−xj∥→1\displaystyle \lim_{d \to \infty} \frac{\max_{i,j} \|x_i - x_j\|}{\min_{i,j} \|x_i - x_j\|} \to 1
这个极限公式是说:维度越高,所有点之间的距离越趋于相等——距离信息彻底失效。
  1. 距离比值取数据中任意两点之间的最大距离和最小距离,求它们的比值——这个比值描述了点之间距离的区分度,比值越接近 1,说明所有点看起来几乎一样远。
    max⁡i,j∥xi−xj∥min⁡i,j∥xi−xj∥\frac{\max_{i,j} \|x_i - x_j\|}{\min_{i,j} \|x_i - x_j\|}
  2. 取极限当特征维度 d 趋向无穷大时,这个比值的极限趋近于 1,直观含义是“在高维空间中,最近邻和最远邻的距离差异可以忽略不计”。
    lim⁡d→∞\lim_{d \to \infty}

特征选择基础:先扔掉冗余路标

制图师拿到一麻袋街道资料,不会直接开始画——因为里面大量资料是重复的:同一条大道的不同叫法、几十条几乎没有行人走过的小巷、还有早已废弃的断头路。他需要一个“筛子”,把真正影响城市格局的路标挑出来。特征选择就是这个筛子。

特征选择有三种主流策略。过滤法(Filter)就像按“街道人流量”给每条路打分——先计算每个特征与目标变量的统计关联(如卡方检验、相关系数、方差阈值),筛掉分数低的路标,整个过程不依赖具体模型。包装法(Wrapper)则像试穿衣服——每次选一个特征子集去训练模型,根据模型表现决定留下还是删掉特征,反复尝试直到找到最优组合。嵌入法(Embedding)更聪明,它把筛选过程融入模型训练,比如 L1 正则化在拟合时自动把不重要的特征权重压到零,一次训练就完成了“边训练边筛选”。

在组学数据中,两万多个基因里真正对病理分型有区分力的可能只有几百个。特征选择能显著降低维度、提升模型可解释性,同时缩小过拟合风险。但它有一个天然局限:它只是“删除”冗余或无关特征,并不改变保留特征本身的结构——如果真正的信息藏在多个特征的组合里,单一特征删除就可能误伤有效信息,这时就需要 PCA 这类“特征变换”手段。

这个筛子就像制图师先把重复路牌和死胡同清理干净——后续的降维算法(PCA、t-SNE)在干净的数据上才能画出更可靠的地图。特征选择和降维不是竞争关系,而是制图流水线上先后两道工序。

min⁡w∑i=1n(yi−w⊤xi)2+λ∑j=1p∣wj∣\displaystyle \min_{w} \sum_{i=1}^{n} \left( y_i - w^\top x_i \right)^2 + \lambda \sum_{j=1}^{p} |w_j|
这个公式是 L1 正则化回归的损失函数:前半部分衡量预测误差,后半部分中绝对值惩罚项会把不重要的特征权重挤向零,产生“稀疏解”。
  1. 预测误差对于第 i 个样本,模型预测值 w⊤x_i 与真实标签 y_i 之间的平方误差,所有样本求和后代表模型整体拟合程度。
    ∑i=1n(yi−w⊤xi)2\sum_{i=1}^{n} (y_i - w^\top x_i)^2
  2. L1 惩罚项对每个特征的权重 w_j 取绝对值并求和,再乘以调节参数 λ。λ 越大,惩罚越重,越多的权重被精确压缩到零。
    λ∑j=1p∣wj∣\lambda \sum_{j=1}^{p} |w_j|

PCA 原理:直升机俯瞰主干道

清理完冗余路标后,制图师跳到直升机上,从高空俯瞰整座城市。他发现:虽然地面有几千条街道,但车流高度集中在少数几条主干道上——只要画出这些主干道,城市的基本格局就八九不离十了。PCA(主成分分析)做的就是这件事。

PCA 寻找数据中“方差最大的方向”作为第一主成分——也就是车流最密集的那条大道;然后在与此方向正交的平面上寻找方差次大的方向作为第二主成分——相当于与第一条主干道垂直的另外大道。每个主成分都是原始特征的线性组合,主成分之间彼此不相关(正交),这样就避免了冗余信息。

数学上,PCA 的流程是:先把所有样本中心化(减去均值),然后计算特征的协方差矩阵,再对该矩阵做特征值分解。特征向量代表投影方向,特征值大小代表这个方向能够保留的方差量——特征值越大,说明该方向上的“信息量”越丰富。保留前 k 个最大特征值对应的特征向量,就能把数据从 d 维压缩到 k 维。

直升机俯瞰图完美解决了“距离失真”问题,因为 PCA 用线性投影把最关键的方向保留下来,计算高效、结果可解释。但它的软肋也在此:如果城市的主路是弯曲的——也就是数据结构高度非线性——用一条直线主干道去代表它,就会把曲路拉直,造成严重变形。这也是为什么 PCA 常被戏称为“只画直线地图的直升机”。

Σ=1nX⊤X,Σv=λv\displaystyle \Sigma = \frac{1}{n} X^\top X, \qquad \Sigma \mathbf{v} = \lambda \mathbf{v}
Σ 是协方差矩阵,描述特征之间的线性关系;特征向量 v 就是“主干道方向”,特征值 λ 是这条主干道能保留的信息量(方差)。
  1. 协方差矩阵X 是中心化后的数据矩阵(每列一个特征),X⊤X 再除以样本数 n,得到各特征之间的协方差矩阵 Σ——相当于“街道之间的交通流量关系表”。
    Σ=1nX⊤X\Sigma = \frac{1}{n} X^\top X
  2. 特征值方程求解 Σ 的特征向量 v 和特征值 λ。特征向量表示一个不变方向,特征值表示数据沿该方向展开的方差大小。最大特征值对应的特征向量就是第一主成分。
    Σv=λv\Sigma \mathbf{v} = \lambda \mathbf{v}

t-SNE 原理:钻进街区走访邻居

直升机俯瞰有死角——城市里布满蜿蜒曲折的小巷,直线主干道根本无法表达真实的邻里关系。于是制图师换了一种思路:不再俯视,而是走进每个街区,挨家挨户问“你的邻居是谁、你和谁走得最近”。这就是 t-SNE 的精髓:用邻里关系而非全局距离来还原结构。

t-SNE(t-Distributed Stochastic Neighbor Embedding)的做法分两步。第一步,在高维空间中,把每对样本 i 和 j 之间的相似度转化成一个条件概率 p_{j|i}——它表示“从点 i 的视角看,j 成为其邻居的概率”。第二步,在低维空间中,用 t 分布定义类似的条件概率 q_{ij},然后通过梯度下降不断调整低维点的坐标,让 q 矩阵尽量逼近 p 矩阵。如果高维空间里 i 和 j 是邻居,低维空间里它们也会被拉到一起。

t-SNE 有一个“魔法数字”——困惑度(perplexity),它大致决定了每个点把多少个其他点当作“有效邻居”。困惑度太小,地图会碎裂成一小块一小块的孤立社区;困惑度太大,所有社区又会糊成一团分不清边界。实践中,困惑度通常设置在 5 到 50 之间,且对结果影响显著。

t-SNE 画出来的地图就像“小区亲密度地图”:左邻右舍关系清清楚楚,谁和谁是铁哥们一目了然。但代价是小区与小区之间的真实距离被严重扭曲——你看得出哪些点是一伙的,却看不出这群点和那群点之间到底隔了几条街。所以 t-SNE 擅长度量局部关系,却不适合回答“簇与簇之间的远近距离”这类全局问题。

pj∣i=exp⁡(−∥xi−xj∥2/2σi2)∑k≠iexp⁡(−∥xi−xk∥2/2σi2)\displaystyle p_{j|i} = \frac{\exp\left(-\|x_i - x_j\|^2 / 2\sigma_i^2\right)}{\sum_{k \neq i} \exp\left(-\|x_i - x_k\|^2 / 2\sigma_i^2\right)}
这个公式计算的是:给定参考点 x_i,x_j 在它周围“邻居圈”(高斯分布)中的相对概率。σ_i 根据困惑度自动调整——邻居多时宽松,邻居少时收紧。
  1. 高斯相似度核分子用指数函数量化点 j 离点 i 的远近,距离越小指数值越大,相似度越高;其中 σ_i 是高斯带宽,控制“多远算邻居”。
    exp⁡(−∥xi−xj∥2/2σi2)\exp\left(-\|x_i - x_j\|^2 / 2\sigma_i^2\right)
  2. 归一化分母对所有不等于 i 的点 k 求和,确保所有概率加起来等于 1,形成合法的概率分布。
    ∑k≠iexp⁡(−∥xi−xk∥2/2σi2)\sum_{k \neq i} \exp\left(-\|x_i - x_k\|^2 / 2\sigma_i^2\right)

UMAP 原理:智能路网铺开

制图师对 t-SNE 的毛病心知肚明:只谈邻居不谈全局,这地图还是不够用。他想要一种方法——既能像 t-SNE 那样保真局部邻里,又能保留社区之间的相对方位。UMAP(Uniform Manifold Approximation and Projection)从拓扑学和黎曼几何中获得灵感,实现了这个目标。

UMAP 的第一步是“建路网”:在每个点的周围,找到最近的 k 个邻居,把它们连成带权重的图——权重越高,表示两个点在原始空间中越接近。这张图就像城市真实的道路网络,既包含密集的小巷(局部结构),也包含连接各个社区的大路(全局结构)。第二步是“铺开”:在低维空间中对这张图做布局优化,目标是让低维图中的边权重分布尽可能接近高维图。

这个“铺开”过程由一个交叉熵损失函数驱动。交叉熵的第一项捕获局部结构:高维空间中靠近的点,低维空间中必须靠近;第二项捕获全局结构:高维空间中距离远或不相连的点,低维空间中保持远离。两项平衡,UMAP 才能在全局与局部之间找到恰当的折中。

UMAP 就像那个既画得出小区亲密度、又画得出小区之间方位的“全能制图师”。它比 t-SNE 速度更快、可复现性更好,尤其适合百万级单细胞数据的可视化。不过它也有代价:建图时 k 的取值、布局时 min_dist 参数都会显著影响结果,需要经验调参。

CE(X,Y)=∑i≠j[pijlog⁡pijqij+(1−pij)log⁡1−pij1−qij]\displaystyle \text{CE}(X, Y) = \sum_{i \neq j} \left[ p_{ij} \log \frac{p_{ij}}{q_{ij}} + (1-p_{ij}) \log \frac{1-p_{ij}}{1-q_{ij}} \right]
交叉熵衡量高维图(p)与低维图(q)之间的差异:第一项处罚“该近的没拉近”的失误,第二项处罚“该远的没推远”的偏差。
  1. 高维图权重 p点 i 和点 j 在高维空间中成为邻居的边概率,来自 k 近邻图,p 越大表示越接近。
    pij∈[0,1]p_{ij} \in [0,1]
  2. 低维图权重 q点 i 和点 j 在低维嵌入中对应的相似度概率,q 随两点在低维空间的距离变化。
    qij∈[0,1]q_{ij} \in [0,1]
  3. 第一项吸引当 p 大、q 小时,第一项产生大惩罚,促使低维空间把原本靠近的点拉近——这就是“本地保真”。
    pijlog⁡pijqijp_{ij} \log \frac{p_{ij}}{q_{ij}}
  4. 第二项排斥当 p 小、q 大时,第二项产生大惩罚,促使低维空间把原本不相连的点推开——这就是“全局保真”。
    (1−pij)log⁡1−pij1−qij(1-p_{ij}) \log \frac{1-p_{ij}}{1-q_{ij}}

PHATE 原理:追踪河流与轨迹

有些城市不是靠街道连接起来的,而是靠一条大河——所有村庄、集市、渡口都沿着河流分布,人流和物资顺着河道流动。要画这样一种城市,你不能只盯着街道和邻居,而要画出“河流的干流和支流”。PHATE 就是为这类轨迹型数据而生的制图师。

PHATE(Potential of Heat-diffusion for Affinity-based Transition Embedding)用扩散几何来理解数据。想象数据点之间的信息像热量一样在图上扩散:从点 A 出发,随机游走 t 步,能到达哪些点、概率是多少?通过比较不同点在整个图上的“扩散概率分布”,PHATE 定义了点和点之间的扩散距离——它衡量的是“要沿着数据流走多少步才能从 A 到 B”,而不是直线距离。

PHATE 特别擅长处理连续过渡的数据。最典型的案例是细胞发育:干细胞逐渐分化成多种成熟细胞类型,中间的每一个状态都是连续的,像一条河流不断分出支流。t-SNE 会把这种连续的轨迹扯成几个不相连的碎片,而 PHATE 会清晰画出“从源头到各条支流”的完整干道,保留发育轨迹的长度和分支结构。

PHATE 的地图就像“河流流域图”,是一条条连续的干流和支流,非常适合展示细胞分化、疾病进展等连续生物过程。但它的短板也明显:计算扩散过程需要构建大规模图并做多次矩阵运算,计算成本远高于 UMAP,且对 t 参数(扩散步数)较为敏感——画清一条河,比画一张街区图要“贵”得多。

Dt(xi,xj)=∑k(Pikt−Pjkt)2ϕ(k)\displaystyle D_t(x_i, x_j) = \sqrt{\sum_k \frac{\left(P^t_{ik} - P^t_{jk}\right)^2}{\phi(k)}}
扩散距离 D_t 的定义:从点 i 和点 j 出发,分别做 t 步随机游走后,到达各个中间点 k 的概率分布差异有多大——差异越大,说明两个点在数据流上的位置越远。
  1. 转移矩阵 P 的 t 次幂P 是马尔可夫转移矩阵,P 的 t 次幂表示从每个点出发随机游走 t 步后的到达概率分布——t 越大,扩散范围越广,体现的是更宏观的流形结构。
    PiktP^t_{ik}
  2. 概率分布差将点 i 和点 j 各自的 t 步扩散概率做差,逐点刻画它们在扩散意义上的差异。
    Pikt−PjktP^t_{ik} - P^t_{jk}
  3. 标准化求和以 φ(k) 为权重对差异平方求和再开方,消除局部密度不均带来的偏差,得到最终的扩散距离。
    ∑k(⋅)2ϕ(k)\sqrt{\sum_k \frac{\left(\cdot\right)^2}{\phi(k)}}

对比与选型:口袋里要有四张地图

四种制图工具各有所长:PCA 是直升机俯瞰,t-SNE 是街区走访,UMAP 是智能路网铺开,PHATE 是河流追踪。作为数据科学家,你的背包里不能只有一把锤子——要学会根据任务目标,从工具包里挑选最合适的一张地图。

第一看数据结构是否线性。如果数据大体线性(如某些光谱数据),PCA 高效且可解释,一条直路就够用;如果数据高度非线性(如基因表达、图像特征),PCA 会把弯曲的路径拉直,必须动用后三种方法。第二看你关心全局还是局部。想看清“谁和谁是一伙的”这种局部关系,t-SNE 是利器;想同时了解“这群点和那群点的相对方位”,选 UMAP;想看清“这群点如何一步步演变成那群点”的连续轨迹,PHATE 是唯一选择。第三看计算预算。PCA 几乎零成本;UMAP 性价比高,百万级样本也能快速完成;t-SNE 需要多次迭代,速度中等偏慢;PHATE 的扩散计算最昂贵,适合中小规模数据。第四看样本量。几十万到百万级的单细胞图谱,业界标配是 UMAP;小规模探索性分析则常用 PCA 快筛、t-SNE 细看。

实践中有一个稳妥的组合拳策略:先用 PCA 快速降维到几十维(去噪、加速),再做 UMAP 看全局结构;发现连续轨迹再用 PHATE 复核;t-SNE 作为展示局部聚类细节的最终补充。需要强调的是,降维本质上是一个探索性工具,它帮助你“看见”数据,但不能替代严谨的统计假设检验。

聪明制图师的秘诀在于“根据要画的地貌选工具”:平原地带一架直升机足够,山区却需要一张精细的等高线图。这四种方法不是替代关系,而是互补武器库——真正的专家会在同一个项目中灵活调用它们,互相印证,避免单一方法带来的偏见。

method={PCA线性数据 / 大规模快筛t-SNE强调局部聚类UMAP全局 + 局部平衡 / 大规模PHATE连续轨迹 / 发育过程\displaystyle \text{method} = \begin{cases} \text{PCA} & \text{线性数据 / 大规模快筛} \\ \text{t-SNE} & \text{强调局部聚类} \\ \text{UMAP} & \text{全局 + 局部平衡 / 大规模} \\ \text{PHATE} & \text{连续轨迹 / 发育过程} \end{cases}
选型口诀:线性俯瞰用 PCA,局部精细用 t-SNE,平衡高效用 UMAP,轨迹刻画用 PHATE。
  1. 线性快筛数据大体线性、需要快速预览时,用 PCA 做第一步降维,几乎零成本。
    PCA\text{PCA}
  2. 局部聚类需要放大局部社区细节时,t-SNE 的邻居概率建模最优,但注意其全局距离失真。
    t-SNE\text{t-SNE}
  3. 规模与平衡当样本量达十万级以上且需要兼顾全局局部时,UMAP 是默认主力。
    UMAP\text{UMAP}
  4. 连续性数据处理细胞分化、疾病进程等连续过渡数据时,PHATE 的扩散距离最忠实。
    PHATE\text{PHATE}

工程落地路径:从绘图室到正式发行

一张再精美的手绘地图,如果不能印制发行、不标注使用指南,就只是挂在墙上的装饰品。降维模型同样如此——从 Jupyter Notebook 里的可视化探索,到生产环境中的稳定服务,中间有一条完整的工程化路径要走。

第一步是概念验证(POC)。用小规模子集快速对比 PCA、t-SNE、UMAP、PHATE 各自的可视化效果,并邀请领域专家(如生物学教授)确认:“这些聚类是否符合已知的细胞类型?这条轨迹是否对应发育阶段?”这一步的目标不是追求完美,而是快速排除不合适的工具。第二步是超参调优。t-SNE 的困惑度、UMAP 的 n_neighbors 和 min_dist、PHATE 的扩散步数 t,都要通过多次实验和稳定性检验来确定——同一组参数跑多次,如果每次画出来的地图结构都大相径庭,说明结果不可靠。第三步是生产部署。将选定的降维模型连同数据标准化步骤一起封装进 Pipeline,保存训练参数(如 PCA 的特征向量矩阵、数据均值),提供批量推理接口。第四步是监控更新。数据分布发生漂移时及时重新拟合降维模型,定期检查低维结构是否依旧能分离目标类别。

工程落地有三个常见“坑”需要避开。第一,t-SNE 没有对新样本的标准嵌入接口——它每次都要重新优化所有点的位置,不适合在线推理;UMAP 虽有 transform 方法,但新样本嵌入的质量依赖于训练集的覆盖程度;PCA 则可以直接用保存的特征向量矩阵做变换。第二,降维前必须统一特征尺度,否则量纲大的特征会主导距离计算。第三,生产环境要保存完整的预处理参数(均值、标准差、特征向量),方便推理时无缝对齐。

回到城市比喻:一张靠谱的地图必须在绘图室里反复校准,经过小范围试用(POC),再决定批量印刷(部署),并每隔一段时间根据城市变迁重新修订(监控更新)。降维的工程化,本质上就是把“画地图的手艺”固化成一门“可重复、可维护、可扩展的流水线”。

AI 应用场景

单细胞 RNA-seq 细胞类型注释

阶段:数据预处理与可视化探索

解决的问题:一次单细胞实验产生数万个细胞 × 数万个基因的表达矩阵,人工逐个标注细胞类型完全不现实。传统做法是挑选几十个 marker 基因手动分群,但 marker 选择存在主观偏差,容易漏掉稀有细胞亚群。

具体案例:取某癌症患者外周血 PBMC 单细胞数据,先做标准化,筛选高变基因,再用 PCA 压缩到 50 维,接着用 UMAP 嵌入到二维空间,配合 Leiden 聚类算法自动识别出 T 细胞、B 细胞、NK 细胞、单核细胞等多个亚群。随后用 marker 基因(如 CD3D、CD79A)验证每个簇的生物学身份,整个过程从数周人工标注缩短到数小时。

多组学整合中的一致性评估

阶段:特征选择与多视图融合

解决的问题:同一批患者样本同时有转录组、蛋白组、甲基化组三套高维数据,量纲和特征数量差异巨大,直接在原始空间拼接会被量纲最大的组学主导,无法真实评估“多组学之间是否一致”。

具体案例:对每个组学分别做 PCA 提取前 20 个主成分(相当于每张地图先画出各自主干道),拼接成一个 60 维的综合表示,再用 UMAP 投影到二维。如果同一个患者在三套组学中的表征在图上彼此靠近,说明多组学信号一致;反之则提示某个组学可能存在批次效应或生物学异质性,需要进一步排查。

Python 演示

python46 行
import numpy as npfrom sklearn.datasets import load_digitsfrom sklearn.decomposition import PCAfrom sklearn.manifold import TSNEimport matplotlib.pyplot as plt  def pca_transform(X, n_components=2):    # 中心化    X_centered = X - X.mean(axis=0)    # 协方差矩阵    cov = np.cov(X_centered, rowvar=False)    # 特征值分解(用 eigh 保证对称矩阵稳定分解,特征值升序返回)    eigvals, eigvecs = np.linalg.eigh(cov)    # 取最大的 n_components 个特征值对应的特征向量    idx = np.argsort(eigvals)[::-1][:n_components]    W = eigvecs[:, idx]    return X_centered.dot(W), eigvals[idx]  def main():    # 手写数字数据集:8x8 像素,共 64 维    digits = load_digits()    X = digits.data[:1200]    y = digits.target[:1200]     # PCA 降维到 2D    X_pca, _ = pca_transform(X, 2)     # t-SNE 降维到 2D    tsne = TSNE(n_components=2, perplexity=30, random_state=42)    X_tsne = tsne.fit_transform(X)     fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))    sc1 = ax1.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap="tab10", s=8)    ax1.set_title("PCA (linear)")    sc2 = ax2.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap="tab10", s=8)    ax2.set_title("t-SNE (nonlinear)")    fig.colorbar(sc2, ax=ax2)    plt.tight_layout()    plt.savefig("dim_reduction.png", dpi=150)    print("降维对比图已保存为 dim_reduction.png")  if __name__ == "__main__":    main()
目的:对手写数字数据集(64 维)分别用自实现的 PCA 和 sklearn 的 t-SNE 降到二维,直观展示线性与非线性降维在实际数据上的差异。
  1. X_centered = X - X.mean(axis=0)中心化,让数据围绕原点分布,这是 PCA 正确计算协方差的前提。
  2. cov = np.cov(X_centered, rowvar=False)计算特征之间的协方差矩阵,也就是“街道交通流量关系表”。
  3. eigvals, eigvecs = np.linalg.eigh(cov)对称矩阵的特征值分解,得到各方向的信息量(特征值)和方向本身(特征向量)。
  4. idx = np.argsort(eigvals)[::-1][:n_components]取特征值最大的前 2 个方向,即信息保留最多的两条“主干道”。
  5. tsne = TSNE(n_components=2, perplexity=30, random_state=42)配置 t-SNE 的邻居感知范围(困惑度)和随机种子,保证结果可复现。
  6. sc1 = ax1.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap="tab10", s=8)用颜色映射每个数字类别,比较 PCA 与 t-SNE 对类别分离效果的差异。

常见误区

误区在 t-SNE 图上,两个簇隔得很远,说明它们在原始高维空间中也真的隔得很远;簇之间的空隙大小可以解释为差异程度。

正解t-SNE 只保留了局部邻居结构,它的目标函数并不关心(甚至刻意忽略)全局距离。簇与簇之间的空隙大小、相对位置都可能被严重扭曲。如果你需要解读“类别之间的距离”或“群组之间的相互关系”,应该使用 UMAP 或 PHATE,它们的全局结构更有意义。

为何常见:人眼对空间远近极其敏感,看到图上明显的空隙就忍不住解读为“差异很大”。再加上不少教程图片里 t-SNE 恰好把类别分得很开,更加深了这种错觉。

误区只要做完 PCA,数据中的不同类别就会被自动分到不同区域,像魔术一样“显现”出来。

正解PCA 是完全无监督的方法,它根本不看标签,只最大化投影后的总体方差。如果不同类别之间的差异恰好落在方差较小的方向上,PCA 很可能会把它们压在一起。真正让类别“自动分开”的是数据本身的结构,而不是 PCA 的魔法。需要利用标签信息时,可以考虑 LDA(线性判别分析)等有监督方法。

为何常见:网上的 PCA 教程配图为了视觉效果,通常挑选的是那些类间差异远大于类内差异的数据,让人误以为 PCA 天生自带分类能力。

误区降维画出来的图就是高维数据的“缩小版”,图上两点之间的距离可以直接解读为原始空间中的距离。

正解只有 PCA 这类线性方法,投影距离才与原始距离保持近似线性关系。t-SNE、UMAP、PHATE 都是非线性方法,它们的距离是在概率、图或扩散结构上定义的,与原始欧氏距离没有量化关系。地图上相距两厘米的两个点,在原始空间中可能非常远,也可能非常近。

为何常见:日常生活中地图就是实景的等比缩小,这个根深蒂固的类比让很多人默认“降维图 = 数据的缩放版”,忽略了非线性变换对距离的扭曲。

误区PCA 或 UMAP 降维后信息更“干净”,把它们作为分类模型的输入,效果一定比用原始特征好。

正解降维是探索性工具,它追求的是“尽可能保留主要结构”,但会丢弃细节。对分类有用的信息有时恰恰藏在那些细微差异里——比如区分两个相似亚型,可能只靠那几个被 PCA 丢弃的低方差基因。正确做法是将“原始特征 + 分类器”与“降维特征 + 分类器”做交叉验证对比,用数据说话。

为何常见:降维图看起来结构分明、类别清晰,这种视觉上的“清晰感”很容易迁移为“这个特征一定更好”的信心,忽略了可视化效果与分类性能是两回事。

误区UMAP 速度和全局结构都更好,以后统一用 UMAP 就行,t-SNE 可以淘汰了。

正解UMAP 的优势是有条件的。它的全局结构保留依赖于 n_neighbors 的取值,取小了跟 t-SNE 一样只见局部,取大了细节会丢失;而且在某些高维小样本数据上,t-SNE 对局部边界的刻画更精细。PHATE 在轨迹型数据上又比两者都更合适。工具选型永远取决于数据和任务。

为何常见:UMAP 在单细胞领域近些年大放异彩,造成“万能工具”的错觉。但单细胞数据的特点(数十万样本、流形结构清晰)并不能代表所有高维场景。

面试题

Q1. PCA 中“方差最大化方向”指的是什么?

单选题 · easy

  • A.特征之间共线性最大的方向
  • B.样本分布散度最大的方向← 正确答案
  • C.分类边界最清晰的方向
  • D.距离坐标系原点最远的方向

答案:B。PCA 是无监督方法,它的目标是在投影后保留尽可能多的信息,量化指标就是投影方差(散度)。它不关心分类边界,所以 C 错;共线性是特征间的关系,与方差最大化无关;到原点的距离是另一套度量。

Q2. 在 t-SNE 中,参数困惑度(perplexity)直接控制的是什么?

单选题 · mid

  • A.低维空间中点之间的距离单位
  • B.每个点在高维空间中的有效邻居数量← 正确答案
  • C.梯度下降的迭代学习率
  • D.降维输出空间的维度数量

答案:B。困惑度可以理解为“每个点把多少个其他点视为邻居”。它通过自适应调节高斯带宽 σ_i 来影响条件概率 p_{j|i} 的计算,进而决定局部结构的分辨尺度。学习率是另一回事,输出维度由 n_components 指定。

Q3. 以下哪些属于非线性降维方法?

多选题 · mid

  • A.PCA
  • B.t-SNE← 正确答案
  • C.LDA
  • D.UMAP← 正确答案

答案:BD。t-SNE 和 UMAP 通过概率建模、图嵌入等方式捕捉非线性流形结构。PCA 是线性投影(协方差特征分解),LDA 是带标签的线性判别投影,两者对数据的假设都是线性的。

Q4. PHATE 相比 t-SNE 的核心优势是?

单选题 · mid

  • A.计算速度更快
  • B.能保留全局连续轨迹结构← 正确答案
  • C.不需要设置任何超参数
  • D.天然支持百万级以上样本

答案:B。PHATE 用扩散距离描述数据流上的位置远近,能保留连续轨迹和分支结构(如细胞分化路径),这正是 t-SNE 的短板。单细胞百万级场景通常用 UMAP,因为 PHATE 计算成本更高;PHATE 也需要调参(如扩散步数 t)。

Q5. UMAP 的交叉熵损失中,第二项 (1-p)log((1-p)/(1-q)) 的主要作用是什么?

单选题 · hard

  • A.提高随机梯度下降的收敛速度
  • B.惩罚高维中不相连的点在低维中被过度拉近← 正确答案
  • C.确保低维嵌入结果的唯一性
  • D.将高维图中所有边的权重归一化

答案:B。当高维中 p 很小(两条边本不该相连)而低维中 q 较大(两点被错误拉近)时,这一项产生巨大惩罚,从而把不相干的点推开。它保护了全局结构,但不负责收敛速度和唯一性。

Q6. 特征选择中的过滤法(Filter)最突出的特点是什么?

单选题 · easy

  • A.依赖分类器反馈来评估特征子集
  • B.先用统计指标打分,不依赖任何模型← 正确答案
  • C.在模型训练过程中自动把权重压成零
  • D.需要反复交叉验证选择最优子集

答案:B。过滤法用方差、相关系数、卡方检验等统计指标给每个特征独立打分,与后续模型完全解耦,计算效率高。依赖分类器反馈的是包装法(Wrapper),训练中自动稀疏化的是嵌入法(Embedding)。

Q7. 关于降维方法在生产环境中的部署,以下说法正确的有?

多选题 · hard

  • A.t-SNE 没有标准的新样本嵌入接口← 正确答案
  • B.PCA 可以用保存的特征向量矩阵直接投影新样本← 正确答案
  • C.UMAP 提供 transform 方法嵌入新样本← 正确答案
  • D.PHATE 可以毫秒级处理在线推理请求

答案:ABC。PCA 是线性变换,保存特征向量后新样本直接做矩阵乘法即可;UMAP 的 transform 接口可将新样本映射到已有低维空间;t-SNE 每次都要全局重算,没有标准嵌入新样本的接口。PHATE 需要构建扩散图并做大规模矩阵运算,在线推理速度很慢。

Q8. 高维数据中“距离失真”最直接的表现是什么?

单选题 · mid

  • A.所有样本点完全重叠在一起
  • B.最大距离与最小距离之比趋近于 1← 正确答案
  • C.特征之间的协方差全部变为零
  • D.数据总量自动变得稀疏

答案:B。当维度升高,任意两点间距离的绝对差异占比逐渐缩小,最大距离与最小距离之比趋向 1,意味着最近邻与最远邻几乎同样远,距离失去区分能力。这正是维度灾难的核心数学特征。

Q9. 下列关于 PCA 的说法正确的有?

多选题 · easy

  • A.主成分之间相互正交← 正确答案
  • B.主成分是原始特征的线性组合← 正确答案
  • C.特征值大小代表该方向保留的方差量← 正确答案
  • D.PCA 需要样本标签才能确定投影方向

答案:ABC。PCA 是线性、无监督方法,主成分来自协方差矩阵的特征向量,彼此正交,且都是原始特征的线性组合;特征值越大,该方向保留的方差越多。它完全不需要样本标签即可计算投影方向。

Q10. 单细胞 RNA-seq 分析中,先做 PCA 再做 UMAP 的主要原因是什么?

单选题 · hard

  • A.PCA 能自动过滤所有批次效应
  • B.PCA 可以快速压缩维度,加速 UMAP 的邻居搜索← 正确答案
  • C.UMAP 不能直接接受原始基因表达矩阵
  • D.PCA 是唯一能处理缺失值的降维方法

答案:B。单细胞数据有数万个基因,UMAP 直接在原始高维空间构建 k 近邻图的计算量极大。先用 PCA 压缩到 50 维左右,保留主变异并去掉噪声,UMAP 的最近邻搜索大幅加速,同时聚类结构几乎不损失。PCA 不能过滤批次效应,UMAP 也可以接受原始矩阵输入。