文章目录
- 一、UMAP的核心思想
- 二、降维的动机与UMAP的优势
- 三、PCA与UMAP的核心区别
- 算法本质对比
- 何时选择哪种算法
- 四、UMAP降维的步骤
- 1. 构建加权k-近邻图
- 2. 构建模糊拓扑表示
- 3. 初始化低维嵌入
- 4. 优化嵌入
- 五、使用scikit-learn实现UMAP
- 安装
- 基础用法:可视化
- 在机器学习流水线中使用UMAP
- 六、UMAP的核心参数详解
- `n_neighbors`参数对结果的影响
- 选择`n_components`的一般原则
- 七、理解UMAP的嵌入结果
- 提取UMAP特征用于下游任务
- 八、UMAP降维后效果评估
- 评估方法
- 何时UMAP效果最佳
- 准确性可能降低的原因
- 九、3D UMAP可视化
- 十、技巧:预计算k-近邻加速
- 十一、结论
- 十二、 相关文章
UMAP,全称Uniform Manifold Approximation and Projection(均匀流形近似与投影),是一种基于流形学习理论的非线性降维算法。与传统的线性降维方法PCA相比,UMAP在保留数据的拓扑结构和局部邻域关系方面具有独特优势,尤其适用于单细胞测序、图像分析、自然语言处理等领域。本文将从原理、与PCA的关键区别、实现步骤、代码示例到参数调优,来介绍UMAP的使用方法与适用场景。
一、UMAP的核心思想
UMAP假设高维数据采样自一个低维流形,且该流形上的数据分布在局部是均匀的(通过自适应距离归一化实现),而不是整个流形上均匀分布。
- 流形学习:认为高维数据实际上分布在低维流形上,降维的目标是发掘这种潜在的流形结构。
- 保局部结构:UMAP优先保留数据的局部邻域关系,让原始空间中邻近的点在降维后依然靠近。
- 兼顾全局:UMAP相比 t-SNE能更好地避免将全局结构撕裂成多个孤立的簇,从而在可视化中呈现出更连贯的全局布局。
UMAP通过构建一个加权的k-近邻图来表示高维数据的拓扑结构,然后通过优化过程在低维空间中学习一个相似的图结构,最终得到降维后的表示。
二、降维的动机与UMAP的优势
在对比之前,先明确降维的通用动机:
维度灾难:高维数据中样本稀疏,模型需要更多样本才能有效训练。
可视化需求:人类无法直观理解超过3维的数据分布。
去冗余:许多特征间存在高度相关性。
在PCA的好处基础上,UMAP提供了额外的优势:
| 优势 | 说明 |
|---|---|
| 处理非线性关系 | PCA只能捕捉线性变化(如直线趋势),UMAP能发现弯曲、环形等复杂结构 |
| 保留局部拓扑 | 优先保证相似样本在降维后依然相近,适合发现子类别 |
| 计算效率高 | 相比t-SNE,UMAP速度更快,能处理百万级样本 |
| 可扩展性强 | 支持监督降维、预计算k-近邻图等高级功能 |
三、PCA与UMAP的核心区别
算法本质对比
| 方面 | PCA | UMAP |
|---|---|---|
| 数学原理 | 线性投影,最大化方差 | 流形学习,保留拓扑结构 |
| 保留关系 | 全局方差结构 | 局部邻域关系 + 部分全局结构 |
| 数据假设 | 线性关系、无强离群点 | 局部均匀分布在低维流形上 |
| 输出解释 | 各主成分是原始特征的线性组合 | 坐标无直接物理解释 |
| 可重复性 | 确定性算法,结果稳定 | 随机初始化,需设随机种子确保稳定 |
何时选择哪种算法
| 场景 | 推荐算法 | 原因 |
|---|---|---|
| 数据呈线性结构(如经济指标) | PCA | 简单高效,解释性强 |
| 需要保留全局方差结构 | PCA | 主成分贡献率明确 |
| 特征工程/预处理 | PCA | 降维后可逆,可用于重构 |
| 可视化高维聚类(如单细胞) | UMAP | 保留局部关系,簇间分离效果好 |
| 探索非线性结构 | UMAP | 发现流形结构 |
| 大规模数据(>10万样本) | UMAP | 计算效率高 |
四、UMAP降维的步骤
UMAP的核心流程分为四个阶段:
1. 构建加权k-近邻图
在高维空间中为每个点找到k个最近邻(k由n_neighbors参数指定),边的权重基于局部距离自适应调整。
2. 构建模糊拓扑表示
将k-近邻图转换为模糊单纯形集,形成对数据拓扑结构的数学表示。
3. 初始化低维嵌入
通常使用谱嵌入对低维坐标进行初始化(也可选择随机初始化或PCA初始化)。
谱嵌入是一种利用图论和线性代数(特征值分解)来寻找数据最佳低维表示的方法。
4. 优化嵌入
采用随机梯度下降(SGD)优化低维嵌入,使其模糊拓扑结构与高维表示尽可能相似。
五、使用scikit-learn实现UMAP
安装
pipinstallumap-learn基础用法:可视化
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportload_digitsfromsklearn.preprocessingimportStandardScalerimportumap# 1. 加载数据(使用 scikit-learn 自带的 digits 数据集)print("加载 digits 数据集...")digits=load_digits()X=digits.data# (1797, 64) - 8x8 图像展平y=digits.target# (1797,) - 0-9 的数字标签print(f"原始数据形状:{X.shape}")# (1797, 64)print(f"样本数量:{X.shape[0]}")print(f"特征维度:{X.shape[1]}")print(f"类别数量:{len(np.unique(y))}")# 2. 标准化(UMAP 对尺度敏感,建议标准化)scaler=StandardScaler()X_scaled=scaler.fit_transform(X)# 3. 执行 UMAP 降维print("执行 UMAP 降维...")reducer=umap.UMAP(n_neighbors=15,# 局部邻域大小n_components=2,# 降维目标维度min_dist=0.1,# 嵌入点间最小距离random_state=42# 确保可重复性)X_umap=reducer.fit_transform(X_scaled)print(f"降维后形状:{X_umap.shape}")# (1797, 2)# 4. 可视化结果plt.figure(figsize=(12,10))scatter=plt.scatter(X_umap[:,0],X_umap[:,1],c=y,cmap='tab10',s=15,alpha=0.7)plt.colorbar(scatter,ticks=range(10))plt.title('UMAP visualization of Digits dataset (1,797 samples, 64-dim)',fontsize=14)plt.xlabel('UMAP Component 1')plt.ylabel('UMAP Component 2')plt.tight_layout()plt.show()# 5. 打印一些统计信息print(f"降维完成!")print(f"原始维度:{X.shape[1]}→ 降维后维度:{X_umap.shape[1]}")print(f"UMAP 运行参数: n_neighbors={reducer.n_neighbors}, min_dist={reducer.min_dist}")UMAP 建议进行标准化(尤其是使用欧氏距离时),除非所有特征已在可比尺度上。
在机器学习流水线中使用UMAP
与PCA类似,UMAP也可以无缝集成到scikit-learn的Pipeline中:
importnumpyasnpfromsklearn.pipelineimportPipelinefromsklearn.svmimportSVCfromsklearn.model_selectionimporttrain_test_split,GridSearchCVfromsklearn.preprocessingimportStandardScalerfromsklearn.datasetsimportmake_swiss_rollimportumap# 1. 构造非线性数据集(瑞士卷)加上随机噪声np.random.seed(42)n_samples=500X,t=make_swiss_roll(n_samples=n_samples,noise=0.5,random_state=42)# 添加大量随机噪声特征(100个无用特征)X_noise=np.random.randn(n_samples,100)*2X=np.hstack([X,X_noise])# 3维结构 + 100维噪声 = 103维# 二分类标签:基于瑞士卷位置y=(t>np.median(t)).astype(int)X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=42)# 标准化(重要)scaler=StandardScaler()X_train_scaled=scaler.fit_transform(X_train)X_test_scaled=scaler.transform(X_test)# 2. 不使用UMAP(在高维噪声数据上训练)svc=SVC(kernel='rbf',random_state=42,C=1.0)svc.fit(X_train_scaled,y_train)print(f"原始数据准确率:{svc.score(X_test_scaled,y_test):.3f}")# 3. 使用UMAP降维pipeline=Pipeline([('scaler',StandardScaler()),('umap',umap.UMAP(random_state=42,n_neighbors=15)),('svc',SVC(kernel='rbf',random_state=42))])param_grid={'umap__n_components':[2,5,10,20],'svc__C':[0.1,1,10]}grid_search=GridSearchCV(pipeline,param_grid,cv=5,scoring='accuracy')grid_search.fit(X_train,y_train)print(f"UMAP降维后最佳交叉验证准确率:{grid_search.best_score_:.3f}")print(f"最佳参数:{grid_search.best_params_}")# 在测试集上评估test_score=grid_search.best_estimator_.score(X_test,y_test)print(f"测试集准确率:{test_score:.3f}")在高维(103维)但样本量有限(500个)的场景下,UMAP可以作为流水线中的特征提取步骤,通过网格搜索自动选择最优的降维维度和分类器参数。
六、UMAP的核心参数详解
| 参数 | 含义 | 典型值范围 | 效果 |
|---|---|---|---|
n_neighbors | 局部邻域大小 | 5-100 | 越小越关注局部细节;越大越保留全局结构 |
n_components | 降维维度 | 2(可视化)至100 | 目标嵌入维度 |
min_dist | 嵌入点间最小距离 | 0.0-0.5 | min_dist 越小:局部结构更紧凑,但全局结构可能被拉长;min_dist 越大:嵌入更紧凑,但可能模糊簇边界。 |
metric | 距离度量 | ‘euclidean’, ‘cosine’, ‘manhattan’ | 根据数据类型选择 |
random_state | 随机种子 | 任意整数 | 关键:确保结果可重复 |
n_neighbors参数对结果的影响
n_components 定义了数据经由 UMAP 算法映射后的目标低维特征空间的维度数。其选择原则主要取决于下游任务的需求与数据内在流形的复杂度。
在该数据集上的实验表明:
- n_neighbors=2:嵌入完全失效,点散落成松散圆云,无法识别簇
- n_neighbors=15:形成稳定、分离良好的簇,全局结构清晰(推荐起点)
选择n_components的一般原则
| 目标 | 推荐n_components | 说明 |
|---|---|---|
| 可视化(2D散点图) | 2 | 便于直接观察 |
| 可视化(3D交互图) | 3 | 可用plotly等库旋转查看 |
| 特征提取(替代PCA) | 10-100 | 根据下游任务交叉验证选择 |
| 保留局部结构 | 较低(2-5) | 强制压入低维 |
| 保留更多信息 | 较高(30-100) | 减少信息损失 |
七、理解UMAP的嵌入结果
与PCA不同,UMAP的低维坐标没有直接的物理解释。PCA的每个主成分是原始特征的线性组合,可以通过载荷(loadings)解释;而UMAP的坐标仅是嵌入空间中点的位置,用于显示相似性关系。
解读方式:
- 相对距离有意义:点越接近,表示原始空间中越相似
- 簇结构有意义:不同颜色的簇表示不同类型的样本
- 距离没有绝对尺度:UMAP的
min_dist参数会压缩或分散点云
提取UMAP特征用于下游任务
# 将UMAP作为特征提取器umap_featurizer=umap.UMAP(n_components=50,random_state=42)X_umap_features=umap_featurizer.fit_transform(X_train)# 现在X_umap_features可以替换X_train用于任何分类器clf=RandomForestClassifier()clf.fit(X_umap_features,y_train)这种"UMAP + 分类器"的两步法在单细胞RNA测序数据分析中尤为常见。
八、UMAP降维后效果评估
评估方法
| 方法 | 说明 |
|---|---|
| 可视化检查 | 观察簇是否分离、是否有意义 |
| k-近邻保留率 | 检查原始空间中的邻居在嵌入空间中是否仍是邻居 |
| 下游任务性能 | 用降维后的数据训练模型,比较准确率 |
| 轮廓系数 | 评估聚类分离程度 |
何时UMAP效果最佳
推荐使用UMAP的场景:
- 单细胞RNA测序数据(非线性、高噪声)
- 图像数据(像素间存在复杂非线性关系)
- 探索性数据分析,需发现非线性结构
- 样本量较大(>5000),t-SNE速度太慢
推荐使用PCA的场景:
- 需要特征解释性(理解每个主成分的含义)
- 数据确实接近线性结构(如某些物理测量)
- 降维后需要重构原始数据
- 作为线性模型的预处理步骤
准确性可能降低的原因
| 原因 | 说明 |
|---|---|
| 随机性 | UMAP的随机初始化可能导致次优嵌入,需设置random_state |
| 参数不当 | n_neighbors过小导致局部过拟合,过大则模糊簇边界 |
| 维度选择过低 | 强行压入2维可能丢失信息 |
| 数据不适合流形学习 | 如果数据完全随机分布、不构成低维流形结构,UMAP会失效 |
九、3D UMAP可视化
对于更精细的可视化需求,UMAP支持将数据降到3维,配合交互式绘图库(如plotly)可以获得更好的探索体验。
importplotly.expressaspximportpandasaspdfromsklearn.datasetsimportmake_classificationimportumap# 1. 构造高维分类数据集(300维,1000个样本)X,y=make_classification(n_samples=1000,n_features=300,n_informative=250,n_classes=2,random_state=42)# 1. 降维到3维reducer_3d=umap.UMAP(n_components=3,n_neighbors=15,random_state=42)X_umap_3d=reducer_3d.fit_transform(X)# 2. 构建DataFrame用于绘图df_plot=pd.DataFrame({'UMAP1':X_umap_3d[:,0],'UMAP2':X_umap_3d[:,1],'UMAP3':X_umap_3d[:,2],'Label':y# 将标签转换为字符串以便显示})# 3. 生成交互式3D图fig=px.scatter_3d(df_plot,x='UMAP1',y='UMAP2',z='UMAP3',color='Label',opacity=0.7,title='3D UMAP Visualization')fig.update_traces(marker=dict(size=2))fig.show()这种方式会生成的HTML文件支持鼠标拖拽旋转、缩放。
十、技巧:预计算k-近邻加速
对于需要多次尝试不同n_neighbors和min_dist参数的场景,可以预计算k-近邻图以避免重复计算:
fromsklearn.datasetsimportmake_classificationimportumapfromumap.umap_importnearest_neighbors# 生成示例数据X,y=make_classification(n_samples=2000,n_features=50,n_informative=40,random_state=42)print(f"原始数据形状:{X.shape}")max_neighbors=250# 计算 k-近邻(返回索引和距离)knn_indices,knn_dists,knn_search_params=nearest_neighbors(X=X,n_neighbors=max_neighbors,metric='euclidean',metric_kwds=None,angular=False,random_state=42,verbose=False)# 使用预计算的 k-近邻图进行 UMAP 降维umap_model=umap.UMAP(n_neighbors=50,n_components=2,min_dist=0.1,random_state=42,precomputed_knn=(knn_indices,knn_dists))X_umap=umap_model.fit_transform(X)print(f"降维后形状:{X_umap.shape}")这种方法可以减少重复计算 k-近邻图的开销,尤其当需要多次调整 n_neighbors 参数时。
十一、结论
UMAP是目前最强大的非线性降维工具之一,在可视化质量和计算效率之间达到了优秀的平衡。
| 对比维度 | PCA | UMAP |
|---|---|---|
| 适合数据类型 | 线性 | 非线性流形 |
| 可解释性 | 高(主成分载荷) | 低 |
| 可视化质量 | 一般 | 优秀 |
| 计算效率 | 非常快 | 快(比t-SNE快) |
| 随机性 | 无 | 有(设种子可重复) |
选择建议:
- 做数据探索/可视化:UMAP(尤其单细胞、图像、文本嵌入)
- 做标准化的特征工程:PCA(更快、可解释、无随机性)
- 用完整流水线:两者都可集成,用交叉验证对比
UMAP使用最佳实践:
- 始终设置
random_state以确保结果可重复 - 从
n_neighbors=15开始,根据可视化效果和下游任务调整 - 对于可视化,优先用2维;对于特征提取,用交叉验证选择
n_components - 大规模数据(>10万)建议使用预计算k-近邻加速
- 如果簇边界模糊,尝试增大
min_dist降低点之间的挤压
十二、 相关文章
PCA降维介绍