想象你空降到一座从未有人绘制过地图的陌生城市。这座城市有几千条街道、几万个路口,而你手里只有每个路口的 GPS 坐标——纬度、经度、海拔、车流量、人口密度……每一个指标都是一维特征,合起来就是高维数据。数据维度一多,人脑就完全失去直觉:你明明握着海量信息,却看不清这座城长什么样。你真正需要的,是一张地铁线路图:把关键地点画在一张纸上,近的挨得近,远的隔得开,线路清清楚楚。UMAP(Uniform Manifold Approximation and Projection,均匀流形近似与投影)就是这样一位手艺高超的制图师。它先实地走访,摸清每个路口和哪些邻居挨得近(构建模糊近邻图),再精心布置,画出一张既保留邻里关系、又尽量不扭曲城市整体格局的二维地图(低维坐标优化)。相比另一位著名制图师 t-SNE,UMAP 画得更快,还不会为了照顾局部而把整座城市的距离关系彻底扭曲。这篇文章,就带你打开这位城市制图师的工具箱,看看里面的原理、参数和实战用法。
学会 UMAP,你就能把高维数据“画成图”,在可视化探索、特征工程、聚类分析中快速发现数据内在结构,是数据科学家与算法工程师必备的降维利器。
可视化演示
交互展示UMAP算法的模糊图构建、交叉熵优化过程和与t-SNE的降维对比效果,理解流形学习核心机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
模糊单纯复集构建 k近邻图确定局部邻域结构 模糊隶属度衡量点对连接强度 w_ij = exp(-d/d_i) 构建高维模糊拓扑图
降维概述
想象你空降一座陌生大城市,手里只有每个地点的上千条 GPS 坐标——海拔、车流、人口密度、空气质量……这叫高维数据。维度太多,反而让人没法真正“看清”这座城,就像捧着一本厚词典,却想一眼掌握城市全貌。人也一样,眼见为实的前提是信息能被摊平在二维平面上。
高维空间的第一个反直觉事实叫“高维灾难”。当维度不断升高时,样本点会像被吹气球一样全部贴到“表面”上,任意两点之间的距离都趋于相等——“近邻”这个概念彻底失效。这就是为什么不能直接拿高维特征去画图、聚类:数字依然在,但“远近”已经没有了意义。
更幸运的是,绝大多数高维数据并非稀稀拉拉散落在整个空间,而是贴在一张低维的“流形”上。打个比方:一张写着字的纸被揉成纸团,它在三维空间里占体积、看着乱,但摊开之后仍是一张二维的纸,纸上的字迹相对位置不变。流形假设说的正是这件事:高维数据的内在结构,往往就是一张被“揉皱”的低维表面。
回到制图师比喻:城市太大、路况信息太杂,只有把地理信息浓缩到一张纸上,你才能一眼看出哪里是市中心、哪里是卫星城。降维不是丢信息,而是把揉皱的纸摊平,把冗余和噪音去掉,让结构重新可见。PCA、t-SNE、UMAP 都是摊纸的方法,区别只在于“摊开时优先保住什么”。
- 最近的距离分子是所有样本点对中最短的那段距离,相当于城市里“两个挨得最近的路口”。
- 最远的距离分母是所有点对中最长的距离,相当于这座城市里隔得最远的两个路口。
- 维度趋于无穷当特征维度 \(d\) 不断增大,每个样本的坐标轴越来越多。
- 比值等于 1最近与最远几乎相同,意味着“近”这个概念被抹平,这正是必须降维的根本原因。
UMAP原理
UMAP 这位制图师的工作分两步。第一步是实地走访:对每个路口,只询问最近的若干位邻居,记录“谁和谁挨得近、亲密度有多高”,据此画出一张模糊的城市邻里关系网。这张网在算法里叫“模糊近邻图”,“模糊”二字的意思是每条边都带一个 0 到 1 的亲密度,而不只是简单的连或不连。
第一步背后是局部尺度的智慧。每个路口 \(i\) 到它最近邻居的距离记为 \(\rho_i\),其他点到 \(i\) 的距离减去 \(\rho_i\),再除以一个尺度因子 \(\sigma_i\),最后取指数,就得到亲密度 \(w_{ij}\)。越近越接近 1,略远就快速衰减到 0。这就精确捕捉了流形的局部几何:邻居的定义只和“身边几条街”有关,和城市整体大小无关。
第二步是绘制地铁图:先在二维平面上随机摆上所有点,然后用一个叫“交叉熵”的评分函数来打分——高维里该近的没近、不该近的却挤在一起,都要扣分。制图师沿着得分下降最快的方向,一点点微调每个点的位置,直到分数降到最低。最终地图上的远亲近邻,基本还原了高维空间里的邻里关系。
用比喻总结:UMAP 就是“先摸清街坊关系,再照着关系网画地铁图”。它不怕城市有多复杂,因为画图时只依赖“亲密度”而不是死抠欧氏距离,所以既能留得住街坊邻里,也放得开整座城市的格局。
- 高维亲密度 \(w_{ij}\)代表高维空间里点 \(i\) 和点 \(j\) 的邻居亲密度,由近邻图按局部尺度计算,近则接近 1,远则接近 0。
- 低维亲密度 \(q_{ij}\)两点在二维地图上的亲密度,地图上离得越近,越接近 1。
- 第一项惩罚当高维里是邻居、低维却被分开时,\(w_{ij}\approx 1\) 而 \(q_{ij}\approx 0\),这一项变得很大,相当于“把邻居画远了”要挨重罚。
- 第二项惩罚当高维里不是邻居、低维却挤到一起时,这一项变得很大,相当于“把陌生人画太近”也要挨罚。
- 对所有点对求和把每一对点的两项损失累加起来,制图师就在这两种力量之间反复拉扯,最终画面是邻里关系最接近真实城市的地铁图。
对比t-SNE
t-SNE 是比 UMAP 更有名的老牌制图师。它非常擅长保住“街坊邻居”关系,却对城市整体格局漠不关心:远景、近景会被画得一样密,簇与簇之间的真实距离完全失真。它的地图上,你只能知道谁挨着谁,却不知道两个街区到底隔了多远。
技术根源在于损失函数。t-SNE 把所有点对的距离做了全局归一化求和,不同簇之间“该离多远”失去约束;而 UMAP 的交叉熵是逐点独立、带非邻居斥力的,既管邻居也管“非邻居”,因此全局结构保留得更好。视觉上最直观的差异是:t-SNE 常常把同一大类画成几个互不相连的小岛,UMAP 则更倾向于把整个类保持成一块完整大陆。
速度上差距更为悬殊。t-SNE 每步迭代都要计算所有 \(O(n^2)\) 个点对间的相似度,而 UMAP 借助随机投影树等近似近邻搜索,复杂度降到接近线性的 \(O(n^{1.14})\),并且用负采样进一步加速。同样是十万个点,t-SNE 可能跑数小时,UMAP 往往几分钟就画完了。
可以这样记:t-SNE 是“只管邻居对、不管全城”的老派画师,UMAP 是“邻居与全局兼顾”的新派制图师。日常使用中两者各有绝活,但当你要看图快、又在意整体布局时,UMAP 通常是更顺手的那支笔。
- 样本数量 \(n\)地图上要摆放的路口数量,也就是数据量大小。
- t-SNE 的复杂度每步要比较所有点对,样本翻倍,耗时约翻 4 倍,一万个点就已经很吃力。
- UMAP 的复杂度借助近似近邻搜索,样本翻倍时耗时只多一点点,增长接近线性。
- 差值的意义点越多差距越大,这也是大规模数据上 UMAP 成为标配的核心原因之一。
参数调优
制图师的工作台上摆着两件核心工具:n_neighbors(走访半径)和 min_dist(地图最小间距)。这两件工具决定了地图长什么样,也决定了你想在图上看见什么。
n_neighbors 决定每个路口向多少个邻居打听布局。设小了,视野只覆盖小组团,地图容易被画成无数碎片,只见树木不见森林;设大了,视野放到全城,整体轮廓清晰,但小街巷的细节会被抹平。经验上,小数据集可以从 5 附近起步,大数据集从 30 到 50 尝试,关键看你想强调局部还是全局。
min_dist 控制地图上两点之间允许的最小空隙。它不直接参与高维构图,而是在低维优化时发挥作用:min_dist 越小,点与点可以贴得极近,类簇紧凑密集;min_dist 越大,点与点必须保持距离,整体松散开阔,簇间空隙更明显。UMAP 会依据 min_dist 去拟合低维亲密度曲线中的参数 \(a\)、\(b\),从而改变“多近才算近”的标尺。
其他参数也不容忽视:n_components 决定投影到几维(通常 2 或 3);metric 决定用哪种距离度量(欧氏、余弦等);random_state 固定随机种子,保证实验可复现。用一句比喻收尾:n_neighbors 是“走访半径”——决定你看街巷还是全城;min_dist 是“图上站间距”——决定地图画得密还是疏。没有绝对最佳,只有“你想在图上看见什么”。
- 地图坐标 \(y_i, y_j\)两个点在低维地图上的位置,是我们要优化的变量。
- 地图距离两点在地图上的直线距离,画得越近,亲密度越高。
- 拟合参数 \(a, b\)由
min_dist拟合得到,决定曲线的陡峭程度。 - 曲线越陡
min_dist小,只有挨得极近才算邻居,结果就是类簇密集紧凑。 - 曲线越平缓
min_dist大,稍远一点仍有一定亲密度,结果就是整体松散开阔。
实战应用
有了制图师,我们终于能“看懂”城市了。最常见的用途是数据可视化:把基因表达、用户向量、图像特征等高维数据降到二维,用颜色标出不同类别,肉眼直接扫出数据中的簇、离群点和异常模式。这一步往往是一个项目里最先做、也最有洞察力的动作。
第二个用途是特征工程。上千维的稀疏特征直接喂给模型,不仅慢,还容易过拟合。把高维特征压缩成几十维的 UMAP 嵌入,可以作为下游模型的输入特征,相当于先请制图师画一张干净的简图,再让模型在简图上做决策。注意一定要在验证集上对比压缩前后的效果,不能想当然地认为压缩必然更好。
第三个用途是聚类的“前置化简”:先 UMAP 降维,再跑 K-Means,比在高维空间直接算距离更稳定、更抗噪声。评估聚类效果常用轮廓系数——它同时考察“同簇是否凝聚”和“异簇是否分离”。轮廓系数接近 1,说明画出来的类簇干净利落。
说到底,地图终究是给人看的。UMAP 让高维数据“可视化地说话”:不管是用在探索性分析、给模型喂特征,还是给聚类算法搭桥,它都在帮你把头脑里那座抽象的城市,缩小成一眼能看完的图纸。
- 簇内距离 \(a(i)\)点 \(i\) 到同簇其他点的平均距离,越小说明这一簇越凝聚。
- 簇间距离 \(b(i)\)点 \(i\) 到最近其他簇所有点的平均距离,越大说明簇与簇分得越开。
- 分子 \(b(i) - a(i)\)簇间距离减簇内距离,正值越大,说明“离别人远、离自己人近”。
- 归一化到 \([-1, 1]\)除以最大值后,接近 1 表示聚类质量优秀,接近 -1 表示样本被分错了窝。
局限与选型
地图终究不是城市本身。UMAP 的第一大局限是结果随机性:不固定随机种子,两次运行画出的地图会略有不同,尤其是簇边界和局部细节。做研究、写报告时,务必固定 random_state,并在论文里写清楚参数,否则读者无法复现你的图。
第二大局限是超参数敏感。n_neighbors 和 min_dist 稍一变化,画面就可能大不相同。一个被忽视的问题是:嵌入坐标的距离只是相对关系,跨区域的绝对距离没有原始空间含义。你可以在 UMAP 图上看“谁比谁更近”,却不能直接拿两点的坐标算相似度去做严格检索。
选型上可以把问题分成三档:数据以线性结构为主,优先 PCA——更快、可解释、无随机性;只关心局部邻居关系,t-SNE 勉强可用;要全局结构、要大图、要速度,选 UMAP。评估嵌入质量时,可以计算高维距离与低维距离的 Pearson 相关,相关越高说明远近关系保存得越好。
最后提醒一句:任何地图都是简化,UMAP 也不例外。把它当探索工具而不是真理源头,让降维结论回到原始特征和业务场景中去验证,才不会在一张漂亮的图上迷了路。
- 高维距离 \(d_{ij}\)原始空间里两点之间的距离,代表“城市里的远近”。
- 低维距离 \(\hat d_{ij}\)地图上两点之间的距离,代表“图纸上的远近”。
- 同向偏差相乘高维里远、低维里也远,两个偏差同号,贡献正分,说明地图画得准。
- 归一化到 \([-1, 1]\)接近 1 表示远近关系保存完好,接近 0 说明嵌入严重失真。
AI 应用场景
单细胞转录组测序可视化
阶段:数据可视化与探索性分析
解决的问题:单细胞测序中每个细胞有几万个基因表达特征,传统 PCA 只能看全局线性结构,t-SNE 在大规模数据上又慢又容易把相似细胞亚型画散。UMAP 能在几分钟内完成数万个高维样本的投影,并保留细胞亚型间的真实远近关系,是当前生信领域的标配工具。
具体案例:对 5 万个免疫细胞做 scRNA-seq 后,用 UMAP(n_neighbors=30, min_dist=0.3) 降成二维,不同细胞亚型形成清晰分开的类簇。研究者根据类簇边界和间距快速圈出疑似新的稀有亚群,再回到基因表达矩阵验证标志基因,大幅缩短探索周期。
推荐系统 Embedding 质量检查
阶段:特征监控与质量评估
解决的问题:推荐系统训练出的用户向量、物品向量高达百维以上,团队难以判断这些向量是否真的学到了语义相似性。用 UMAP 把 Embedding 投影到二维,可以直观检查“相似用户/物品是否聚在一起”。
具体案例:电商推荐团队把 128 维的物品向量用 UMAP 可视化,发现某品类的向量散落成多个碎片簇,无法成团。排查后定位到该品类训练数据存在缺失和标注噪声,修复数据后重新训练,Embedding 聚类质量显著改善。
风控高维特征探索与衍生特征提炼
阶段:特征工程与探索性数据分析
解决的问题:交易反欺诈场景有成百上千维特征,业务专家很难直观理解哪些特征让欺诈和正常交易产生差异。UMAP 可视化能帮助挖掘特征组合的判别模式。
具体案例:反欺诈团队将 800 维交易特征用 UMAP 降维后叠加欺诈标签着色,发现欺诈样本在图上呈一条清晰带状分布。受此启发,团队构造了“设备指纹集中度”和“行为时间熵”两个衍生特征,加入模型后 AUC 提升约 3 个百分点。
Python 演示
"""简化版 UMAP:从零实现 kNN 模糊构图 + 交叉熵低维优化(教学用)"""import numpy as npfrom math import exp def build_graph(X, k=10): """第一步:高维空间构建模糊近邻图""" n = len(X) w = np.zeros((n, n)) for i in range(n): dists = np.sqrt(((X - X[i]) ** 2).sum(axis=1)) nbr = np.argsort(dists)[1:k + 1] # 取最近 k 个邻居,排除自己 rho = dists[nbr[0]] # 到最近邻的距离 sigma = (dists[nbr[-1]] - rho) / 2.0 # 简化归一化因子 for j in nbr: w[i, j] = exp(-(dists[j] - rho) / sigma) return (w + w.T) * 0.5 def optimize(Y, w, steps=300, lr=0.1): """第二步:优化低维坐标,让低维连接强度逼近高维图""" n = Y.shape[0] for _ in range(steps): diff = Y[:, None, :] - Y[None, :, :] # 任意两点之差 (n,n,2) d2 = (diff ** 2).sum(-1) + 1e-8 # 低维距离平方 q = 1.0 / (1.0 + d2) # 低维连接强度 weight = (w - q) / (1.0 + d2) # 交叉熵梯度系数 np.fill_diagonal(weight, 0.0) grad = 4.0 * (weight[:, :, None] * diff).sum(axis=1) gmax = np.abs(grad).max() Y -= lr * grad / (gmax + 1e-12) # 归一化梯度下降 return Y def umap(X, k=12, steps=300, seed=42): w = build_graph(X, k) w /= w.sum() # 归一化成概率形式 rng = np.random.default_rng(seed) Y = rng.normal(0.0, 0.1, size=(len(X), 2)) # 随机初始化低维坐标 return optimize(Y, w, steps, lr=0.1) if __name__ == "__main__": rng = np.random.default_rng(0) n = 250 t = rng.uniform(0, 3.0, n) # 瑞士卷角度 h = rng.uniform(0, 1, n) # 瑞士卷高度 X = np.c_[t * np.cos(t), t * np.sin(t), h] # 三维瑞士卷 Y = umap(X, k=12, steps=300) print("高维形状:", X.shape, "-> 低维形状:", Y.shape) print("前三个点的二维坐标:\n", np.round(Y[:3], 2))
w[i, j] = exp(-(dists[j] - rho) / sigma)把“距离”翻译成 0 到 1 的邻居亲密度,这是近邻构图的灵魂。return (w + w.T) * 0.5把亲密度矩阵对称化,让点 i 对 j 的亲近和 j 对 i 的亲近一致。q = 1.0 / (1.0 + d2)计算低维地图上两点的亲密度,对应正文里的 q 曲线。weight = (w - q) / (1.0 + d2)高维亲密度与低维亲密度差异越大,调整力量越强。grad = 4.0 * (weight[:, :, None] * diff).sum(axis=1)把所有邻居的“拉力/推力”合成一个合力方向。Y -= lr * grad / (gmax + 1e-12)沿合力方向迈一小步,防止震荡,对应“制图师反复微调点位”。rng.normal(0.0, 0.1, size=(len(X), 2))低维坐标随机初始化,相当于先把点随机撒在图纸上。X = np.c_[t * np.cos(t), t * np.sin(t), h]构造瑞士卷形状的高维样例,验证算法能把它摊平。
常见误区
误区听说 UMAP 就是 t-SNE 的加速版,两者画出来的图差不多,直接抄 t-SNE 的调参经验就行。
正解两者底层损失不同。t-SNE 只保证“高维邻居在低维还是邻居”,不同簇之间该离多远完全没人管;UMAP 的交叉熵对“高维非邻居却在低维靠近”同样惩罚,因此能保留更多全局结构。速度差异来自工程优化(近似近邻搜索、负采样),不能简单当成同一个算法的快慢版本。
为何常见:两者都输出二维散点图、长得像,加上 t-SNE 名气在前,很容易把 UMAP 误认为"t-SNE 2.0"。
误区既然 UMAP 能保留距离信息,那我直接拿嵌入坐标算欧氏距离做相似度检索,应该没问题吧?
正解地图上的距离不等于城市里的真实距离。UMAP 保留的是“相对远近关系”,跨区域的绝对距离没有原始空间含义。想保留可解释的距离,应该考虑 PCA 或度量学习;UMAP 适合看结构、找类簇,不适合做严格相似度匹配。
为何常见:坐标是数值,数值就能算距离,这个直觉让人很容易把嵌入坐标当正式特征使用。
误区官方默认 n_neighbors=15、min_dist=0.1,示例图都挺正常,我应该也不需要改吧?
正解默认值只适合中等规模数据的初步可视化。样本量小、关注局部细节时可调小 n_neighbors;想看清大类结构就调大;数据点很密很挤时,调小 min_dist 能让类簇更紧凑。参数是制图师手里的工具,应该按“你想在图上看见什么”来选,而不是永远用默认。
为何常见:教程和文档展示的图都是调好参数后的结果,默认参数恰好能跑,容易让人形成“不用管参数”的思维定势。
误区我跑完 UMAP,两个类别还是叠在一起,是不是代码写错了或者参数没调好?
正解如果两个类在高维流形上本来就相邻或重叠,UMAP 不会强行切开。粗暴调小 n_neighbors 可能制造看似分离的假象,却牺牲了真实结构。图上的分离度应当反映数据本身的可分性,而不是算法的执念。
为何常见:公开分享的可视化大多是“分得漂亮”的精选结果,幸存者偏差让人误以为 UMAP 天然能把所有类分开。
面试题
Q1. UMAP 属于哪一类机器学习方法?
- A.监督分类算法
- B.无监督降维算法← 正确答案
- C.强化学习算法
- D.深度生成模型
答案:B。UMAP 训练时不需要标签,只根据数据本身的结构把高维样本投影到低维,属于无监督降维,与 PCA、t-SNE 同类,而不是分类或生成模型。
Q2. 相比 t-SNE,UMAP 最突出的优势是?
- A.计算更快且保留全局结构← 正确答案
- B.只能处理小规模数据
- C.完全不需要调整参数
- D.保留了高维绝对距离
答案:A。UMAP 用近似近邻搜索把复杂度降到接近线性,远快于 t-SNE 的 O(n²);同时交叉熵让非邻居也有斥力,因此全局结构保留更好。B、C、D 都是错误描述。
Q3. UMAP 算法的第一步是什么?
- A.计算样本主成分方向
- B.构建模糊近邻图← 正确答案
- C.训练一个分类器
- D.做特征选择降维
答案:B。UMAP 分两步:先在高维空间为每个点找最近邻居并计算 0 到 1 的亲密度,构建模糊近邻图;再在低维优化坐标,让地图亲密度逼近高维图。PCA 和特征选择都不是 UMAP 的第一步。
Q4. 调大 n_neighbors 参数,通常会导致什么?
- A.只能看到极小局部
- B.更关注全局结构← 正确答案
- C.结果完全不会变化
- D.训练时间必然缩短
答案:B。n_neighbors 决定每个点向多少个邻居学习布局,调大后视野覆盖更大范围,地图更侧重全局,但局部小街巷细节会被抹平。A 是 n_neighbors 过小的表现,C、D 明显错误。
Q5. min_dist 参数的主要作用是什么?
- A.控制高维采样数量
- B.控制低维最小点距← 正确答案
- C.决定近邻搜索算法
- D.调整损失学习速率
答案:B。min_dist 规定低维地图上两点允许的最小间距,越小点越密集、类簇越紧凑,越大整体越松散开阔。它不参与高维采样、不改变近邻搜索和优化步长。
Q6. 关于 UMAP,下列说法正确的有?
- A.基于流形假设降维← 正确答案
- B.比 t-SNE 计算更快← 正确答案
- C.结果完全可复现
- D.保留更多全局结构← 正确答案
答案:ABD。UMAP 假设高维数据落在低维流形上并据此降维;借助近似近邻搜索所以更快;交叉熵对非邻居同样惩罚,全局结构更好。C 错误:不固定随机种子时结果有随机性,并非完全可复现。
Q7. 高维灾难中的“距离浓度”现象是指什么?
- A.点间距离保持差异明显
- B.近邻远近失去区分度← 正确答案
- C.高维球体体积不变大
- D.降维后信息不损失
答案:B。维度升高后,任意两点最短距离与最长距离之比趋近 1,远近没有差别,“最近邻居”和“最远邻居”几乎一样远,近邻概念失效。A 说反了,C、D 与现象无关。
Q8. UMAP 交叉熵损失的第一项 w·ln(w/q) 的含义是什么?
- A.高维邻居低维分离惩罚← 正确答案
- B.高维非邻居低维靠近惩罚
- C.近邻被拉开时损失增大← 正确答案
- D.远点被拉近时损失增大
答案:AC。w 接近 1 表示高维里是邻居,q 接近 0 表示低维里被分开,此时 w·ln(w/q) 很大,所以第一项惩罚“该近的不近”,A、C 同义。B、D 对应第二项 (1-w)·ln((1-w)/(1-q)),即“不该近的近了”的惩罚。
Q9. 把 UMAP 嵌入用于下游聚类分析时,正确的做法是?
- A.嵌入距离等于原始距
- B.应多次运行看稳定性← 正确答案
- C.参数对结果影响极小
- D.嵌入结果优等原特征
答案:B。UMAP 结果有随机性且对超参数敏感,下游分析前应固定随机种子并多次运行,确认聚类结构是否稳定。嵌入距离不能当原始距离用(A 错),参数影响很大(C 错),降维会丢信息、并非始终优于原特征(D 错)。
Q10. 以下属于 UMAP 的局限性的有?
- A.结果受随机种子影响← 正确答案
- B.对超参数比较敏感← 正确答案
- C.嵌入距离不是原始距← 正确答案
- D.对线性结构处理更好
答案:ABC。UMAP 需要固定随机种子才可复现,n_neighbors 与 min_dist 稍变就会影响细节,且嵌入坐标是相对布局,绝对距离无原始空间含义。D 说反了:线性数据用 PCA 更合适,UMAP 的优势恰恰在非线性结构。