这次我们来看一个数据分析中非常实用的技术组合:PCA + 聚类 + UMAP 可视化。这个组合特别适合处理高维数据,比如基因表达数据、用户画像数据或者任何特征维度超过几十个的数据集。
很多人在面对高维数据时会遇到几个典型问题:特征太多导致计算慢、维度太高难以直观理解、聚类结果无法可视化验证。PCA 负责降维去冗余,聚类算法发现数据内在分组,UMAP 则将高维关系映射到二维平面进行直观展示。这个组合在生物信息学、市场细分、异常检测等领域都有广泛应用。
下面我会用 Python 和 R 两种语言分别演示完整流程,重点放在实际可操作的代码和效果对比上。无论你是数据分析师、算法工程师还是科研人员,这套方法都能直接应用到自己的项目中。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 技术组合 | PCA(线性降维) + 聚类算法(如K-means) + UMAP(非线性可视化) |
| 主要功能 | 高维数据降维、聚类分析、可视化展示 |
| 硬件要求 | 普通CPU即可,大数据集需要足够内存 |
| 内存占用 | 取决于数据量,万级样本通常需要4GB+内存 |
| 编程语言 | Python(sklearn, umap-learn)或 R(stats, umap) |
| 可视化输出 | 二维散点图,支持颜色标注聚类结果 |
| 适合场景 | 基因表达分析、用户分群、异常检测、数据探索 |
2. 适用场景与使用边界
这个技术组合最适合以下场景:
基因表达数据分析:单细胞RNA测序数据通常有上万个基因特征,通过降维聚类可以识别细胞类型。比如在2018年Cell Research的文章中,研究人员用t-SNE对睾丸细胞降维聚类,识别出13个细胞亚群。
用户画像细分:电商平台有数百个用户行为特征,通过PCA降维后聚类,可以实现精准的用户分群,为个性化推荐提供基础。
异常检测:在高维数据中,异常点通常在降维后的可视化图中会偏离主要集群,便于直观发现。
数据质量检查:降维可视化可以快速检查数据是否存在批次效应、离群值等问题。
但是需要注意几个边界:
- PCA是线性降维,对于非线性结构的数据可能效果不佳
- 聚类算法需要预先指定簇数(如K-means的K值),需要配合肘部法则等方选择
- UMAP的参数设置(如n_neighbors)会影响可视化效果,需要调试
- 可视化结果仅供参考,不能完全替代统计检验
3. 环境准备与前置条件
Python 环境准备
# 创建conda环境(可选) conda create -n dim_reduction python=3.9 conda activate dim_reduction # 安装核心包 pip install numpy pandas matplotlib seaborn scikit-learn umap-learn jupyter # 安装额外可视化包 pip install plotly kaleidoR 环境准备
# 安装必要包 install.packages(c("ggplot2", "dplyr", "umap", "cluster", "factoextra")) # 或者一次性安装 install.packages(c("tidyverse", "umap", "cluster", "factoextra", "plotly"))数据准备
我们将使用两个经典数据集进行演示:
- Iris数据集(150个样本,4个特征)
- 模拟的高维数据集(1000个样本,50个特征)
4. Python 完整实现流程
4.1 数据加载与预处理
import numpy as np import pandas as pd from sklearn.datasets import load_iris, make_blobs from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt import seaborn as sns # 加载iris数据集 iris = load_iris() X = iris.data y = iris.target feature_names = iris.feature_names target_names = iris.target_names print(f"数据形状: {X.shape}") print(f"特征名: {feature_names}") print(f"类别名: {target_names}") # 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 创建高维模拟数据 X_high_dim, y_high_dim = make_blobs(n_samples=1000, n_features=50, centers=5, random_state=42) X_high_dim_scaled = StandardScaler().fit_transform(X_high_dim)4.2 PCA 降维实现
from sklearn.decomposition import PCA # PCA降维 pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) print(f"PCA解释方差比例: {pca.explained_variance_ratio_}") print(f"累计解释方差: {np.cumsum(pca.explained_variance_ratio_)}") # 可视化PCA结果 plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) scatter = plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis') plt.colorbar(scatter) plt.xlabel('PC1 ({:.2f}%方差)'.format(pca.explained_variance_ratio_[0]*100)) plt.ylabel('PC2 ({:.2f}%方差)'.format(pca.explained_variance_ratio_[1]*100)) plt.title('PCA降维结果 - Iris数据集') # 高维数据PCA pca_high = PCA(n_components=2) X_high_pca = pca_high.fit_transform(X_high_dim_scaled) plt.subplot(1, 2, 2) scatter_high = plt.scatter(X_high_pca[:, 0], X_high_pca[:, 1], c=y_high_dim, cmap='viridis') plt.colorbar(scatter_high) plt.xlabel('PC1 ({:.2f}%方差)'.format(pca_high.explained_variance_ratio_[0]*100)) plt.ylabel('PC2 ({:.2f}%方差)'.format(pca_high.explained_variance_ratio_[1]*100)) plt.title('PCA降维结果 - 高维模拟数据') plt.tight_layout() plt.show()4.3 聚类分析实现
from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score, adjusted_rand_score # 使用PCA结果进行聚类 kmeans = KMeans(n_clusters=3, random_state=42) y_pred = kmeans.fit_predict(X_pca) # 评估聚类效果 silhouette_avg = silhouette_score(X_pca, y_pred) ari = adjusted_rand_score(y, y_pred) print(f"轮廓系数: {silhouette_avg:.3f}") print(f"调整兰德指数: {ari:.3f}") # 可视化聚类结果 plt.figure(figsize=(15, 5)) plt.subplot(1, 3, 1) plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis') plt.title('真实类别') plt.xlabel('PC1') plt.ylabel('PC2') plt.subplot(1, 3, 2) plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y_pred, cmap='viridis') plt.title('聚类结果') plt.xlabel('PC1') plt.ylabel('PC2') plt.subplot(1, 3, 3) # 标记分类错误的点 incorrect = y != y_pred plt.scatter(X_pca[~incorrect, 0], X_pca[~incorrect, 1], c='green', label='正确') plt.scatter(X_pca[incorrect, 0], X_pca[incorrect, 1], c='red', label='错误') plt.legend() plt.title('分类正确性检查') plt.xlabel('PC1') plt.ylabel('PC2') plt.tight_layout() plt.show()4.4 UMAP 可视化实现
import umap.umap_ as umap # UMAP降维可视化 reducer = umap.UMAP(random_state=42) X_umap = reducer.fit_transform(X_scaled) # 高维数据UMAP reducer_high = umap.UMAP(random_state=42) X_high_umap = reducer_high.fit_transform(X_high_dim_scaled) # 对比可视化 fig, axes = plt.subplots(2, 2, figsize=(15, 12)) # Iris数据集对比 axes[0, 0].scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis') axes[0, 0].set_title('PCA - Iris数据集') axes[0, 0].set_xlabel('PC1') axes[0, 0].set_ylabel('PC2') axes[0, 1].scatter(X_umap[:, 0], X_umap[:, 1], c=y, cmap='viridis') axes[0, 1].set_title('UMAP - Iris数据集') axes[0, 1].set_xlabel('UMAP1') axes[0, 1].set_ylabel('UMAP2') # 高维数据对比 axes[1, 0].scatter(X_high_pca[:, 0], X_high_pca[:, 1], c=y_high_dim, cmap='viridis') axes[1, 0].set_title('PCA - 高维模拟数据') axes[1, 0].set_xlabel('PC1') axes[1, 0].set_ylabel('PC2') axes[1, 1].scatter(X_high_umap[:, 0], X_high_umap[:, 1], c=y_high_dim, cmap='viridis') axes[1, 1].set_title('UMAP - 高维模拟数据') axes[1, 1].set_xlabel('UMAP1') axes[1, 1].set_ylabel('UMAP2') plt.tight_layout() plt.show()4.5 完整流程整合
def complete_analysis_pipeline(X, y=None, n_clusters=3, random_state=42): """ 完整的降维聚类可视化流程 """ # 1. 数据标准化 from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 2. PCA降维 pca = PCA(n_components=2, random_state=random_state) X_pca = pca.fit_transform(X_scaled) # 3. UMAP降维 reducer = umap.UMAP(random_state=random_state) X_umap = reducer.fit_transform(X_scaled) # 4. 聚类分析 kmeans = KMeans(n_clusters=n_clusters, random_state=random_state) y_pred_pca = kmeans.fit_predict(X_pca) y_pred_umap = kmeans.fit_predict(X_umap) # 5. 可视化 fig, axes = plt.subplots(2, 3, figsize=(18, 12)) # PCA相关可视化 axes[0, 0].scatter(X_pca[:, 0], X_pca[:, 1], c=y if y is not None else 'blue') axes[0, 0].set_title('PCA - 真实类别' if y is not None else 'PCA降维') axes[0, 1].scatter(X_pca[:, 0], X_pca[:, 1], c=y_pred_pca, cmap='tab10') axes[0, 1].set_title('PCA - 聚类结果') axes[0, 2].scatter(X_pca[:, 0], X_pca[:, 1], c=(y == y_pred_pca) if y is not None else y_pred_pca, cmap='coolwarm') axes[0, 2].set_title('PCA - 正确性检查' if y is not None else 'PCA - 聚类分布') # UMAP相关可视化 axes[1, 0].scatter(X_umap[:, 0], X_umap[:, 1], c=y if y is not None else 'blue') axes[1, 0].set_title('UMAP - 真实类别' if y is not None else 'UMAP降维') axes[1, 1].scatter(X_umap[:, 0], X_umap[:, 1], c=y_pred_umap, cmap='tab10') axes[1, 1].set_title('UMAP - 聚类结果') axes[1, 2].scatter(X_umap[:, 0], X_umap[:, 1], c=(y == y_pred_umap) if y is not None else y_pred_umap, cmap='coolwarm') axes[1, 2].set_title('UMAP - 正确性检查' if y is not None else 'UMAP - 聚类分布') plt.tight_layout() plt.show() # 返回结果 results = { 'pca': X_pca, 'umap': X_umap, 'clusters_pca': y_pred_pca, 'clusters_umap': y_pred_umap } if y is not None: from sklearn.metrics import silhouette_score, adjusted_rand_score results['silhouette_pca'] = silhouette_score(X_pca, y_pred_pca) results['silhouette_umap'] = silhouette_score(X_umap, y_pred_umap) results['ari_pca'] = adjusted_rand_score(y, y_pred_pca) results['ari_umap'] = adjusted_rand_score(y, y_pred_umap) return results # 应用完整流程 results = complete_analysis_pipeline(X, y, n_clusters=3) print("评估指标:") print(f"PCA轮廓系数: {results.get('silhouette_pca', 'N/A'):.3f}") print(f"UMAP轮廓系数: {results.get('silhouette_umap', 'N/A'):.3f}") print(f"PCA调整兰德指数: {results.get('ari_pca', 'N/A'):.3f}") print(f"UMAP调整兰德指数: {results.get('ari_umap', 'N/A'):.3f}")5. R语言完整实现流程
5.1 数据准备与PCA实现
# 清除环境变量 rm(list=ls()) # 设置工作目录 setwd("D:/RStudio/project/dim_reduction") # 加载包 library(ggplot2) library(dplyr) library(umap) library(cluster) library(factoextra) # 加载iris数据集 data(iris) head(iris) # 提取特征和标签 iris.data <- iris[, 1:4] iris.labels <- iris$Species # 数据标准化 iris.scaled <- scale(iris.data) # PCA分析 iris.pca <- prcomp(iris.scaled, scale. = FALSE) summary(iris.pca) # 提取主成分 iris.pcs <- data.frame(iris.pca$x, Species = iris.labels) head(iris.pcs, 10) # PCA可视化 ggplot(iris.pcs, aes(x = PC1, y = PC2, color = Species)) + geom_point(size = 3) + stat_ellipse(level = 0.95, show.legend = FALSE) + theme_bw() + labs(title = "PCA降维可视化 - Iris数据集", x = paste("PC1 (", round(iris.pca$sdev[1]^2/sum(iris.pca$sdev^2)*100, 2), "%)"), y = paste("PC2 (", round(iris.pca$sdev[2]^2/sum(iris.pca$sdev^2)*100, 2), "%)"))5.2 聚类分析实现
# 使用PCA结果进行聚类 set.seed(42) kmeans_result <- kmeans(iris.pcs[, 1:2], centers = 3, nstart = 25) # 添加聚类结果 iris.pcs$Cluster <- as.factor(kmeans_result$cluster) # 聚类效果评估 silhouette_score <- silhouette(kmeans_result$cluster, dist(iris.pcs[, 1:2])) avg_silhouette <- mean(silhouette_score[, 3]) cat("平均轮廓系数:", round(avg_silhouette, 3), "\n") # 聚类结果可视化 ggplot(iris.pcs, aes(x = PC1, y = PC2, color = Cluster)) + geom_point(size = 3) + theme_bw() + labs(title = paste("K-means聚类结果 (轮廓系数:", round(avg_silhouette, 3), ")"), x = "PC1", y = "PC2") + scale_color_discrete(name = "聚类标签")5.3 UMAP可视化实现
# UMAP降维 set.seed(42) iris.umap <- umap(iris.data) # 查看UMAP结果 head(iris.umap$layout) # 创建UMAP结果数据框 umap_df <- data.frame(UMAP1 = iris.umap$layout[, 1], UMAP2 = iris.umap$layout[, 2], Species = iris.labels) # UMAP可视化 ggplot(umap_df, aes(x = UMAP1, y = UMAP2, color = Species)) + geom_point(size = 3) + theme_bw() + labs(title = "UMAP降维可视化 - Iris数据集", x = "UMAP1", y = "UMAP2") + theme(legend.position = "top") # 对比PCA和UMAP library(gridExtra) p1 <- ggplot(iris.pcs, aes(x = PC1, y = PC2, color = Species)) + geom_point(size = 2) + theme_bw() + labs(title = "PCA", x = "PC1", y = "PC2") p2 <- ggplot(umap_df, aes(x = UMAP1, y = UMAP2, color = Species)) + geom_point(size = 2) + theme_bw() + labs(title = "UMAP", x = "UMAP1", y = "UMAP2") grid.arrange(p1, p2, ncol = 2)5.4 完整R流程函数
complete_analysis_r <- function(data, labels = NULL, n_clusters = 3) { " 完整的降维聚类可视化流程(R版本) " # 数据标准化 data_scaled <- scale(data) # PCA分析 pca_result <- prcomp(data_scaled, scale. = FALSE) pca_df <- as.data.frame(pca_result$x[, 1:2]) # UMAP分析 set.seed(42) umap_result <- umap(data) umap_df <- as.data.frame(umap_result$layout) colnames(umap_df) <- c("UMAP1", "UMAP2") # 聚类分析 set.seed(42) kmeans_pca <- kmeans(pca_df, centers = n_clusters, nstart = 25) kmeans_umap <- kmeans(umap_df, centers = n_clusters, nstart = 25) # 准备可视化数据 if (!is.null(labels)) { pca_df$Species <- labels pca_df$Cluster <- as.factor(kmeans_pca$cluster) umap_df$Species <- labels umap_df$Cluster <- as.factor(kmeans_umap$cluster) } else { pca_df$Cluster <- as.factor(kmeans_pca$cluster) umap_df$Cluster <- as.factor(kmeans_umap$cluster) } # 可视化 if (!is.null(labels)) { p1 <- ggplot(pca_df, aes(x = PC1, y = PC2, color = Species)) + geom_point(size = 2) + theme_bw() + ggtitle("PCA - 真实类别") p2 <- ggplot(pca_df, aes(x = PC1, y = PC2, color = Cluster)) + geom_point(size = 2) + theme_bw() + ggtitle("PCA - 聚类结果") p3 <- ggplot(umap_df, aes(x = UMAP1, y = UMAP2, color = Species)) + geom_point(size = 2) + theme_bw() + ggtitle("UMAP - 真实类别") p4 <- ggplot(umap_df, aes(x = UMAP1, y = UMAP2, color = Cluster)) + geom_point(size = 2) + theme_bw() + ggtitle("UMAP - 聚类结果") } else { p1 <- ggplot(pca_df, aes(x = PC1, y = PC2)) + geom_point(size = 2, color = "blue") + theme_bw() + ggtitle("PCA降维") p2 <- ggplot(pca_df, aes(x = PC1, y = PC2, color = Cluster)) + geom_point(size = 2) + theme_bw() + ggtitle("PCA - 聚类结果") p3 <- ggplot(umap_df, aes(x = UMAP1, y = UMAP2)) + geom_point(size = 2, color = "blue") + theme_bw() + ggtitle("UMAP降维") p4 <- ggplot(umap_df, aes(x = UMAP1, y = UMAP2, color = Cluster)) + geom_point(size = 2) + theme_bw() + ggtitle("UMAP - 聚类结果") } # 组合图形 grid.arrange(p1, p2, p3, p4, ncol = 2, nrow = 2) # 返回结果 results <- list( pca = pca_df, umap = umap_df, clusters_pca = kmeans_pca$cluster, clusters_umap = kmeans_umap$cluster ) return(results) } # 应用完整流程 r_results <- complete_analysis_r(iris.data, iris.labels, n_clusters = 3)6. 性能优化与大数据集处理
当处理大规模数据时,需要考虑性能优化:
# 针对大数据集的优化方案 from sklearn.decomposition import IncrementalPCA from umap.umap_ import UMAP import numpy as np def large_scale_analysis(X, batch_size=1000, n_components=2, n_clusters=5): """ 大规模数据降维聚类优化方案 """ # 增量PCA处理大数据 ipca = IncrementalPCA(n_components=n_components, batch_size=batch_size) X_ipca = ipca.fit_transform(X) # 采样后进行UMAP(大数据集UMAP较慢) n_samples = min(10000, X.shape[0]) indices = np.random.choice(X.shape[0], n_samples, replace=False) X_sample = X[indices] # UMAP参数优化 reducer = UMAP( n_neighbors=15, min_dist=0.1, n_components=2, random_state=42, low_memory=True # 低内存模式 ) X_umap_sample = reducer.fit_transform(X_sample) # 对整个数据集使用近似方法 from sklearn.neighbors import NearestNeighbors knn = NearestNeighbors(n_neighbors=15) knn.fit(X_umap_sample) # 这里可以继续实现大规模数据的近似UMAP映射 # 具体实现取决于具体需求和数据规模 return X_ipca, X_umap_sample # 内存使用监控 import psutil import os def monitor_memory_usage(): process = psutil.Process(os.getpid()) return process.memory_info().rss / 1024 / 1024 # 返回MB print(f"当前内存使用: {monitor_memory_usage():.2f} MB")7. 不同降维方法对比分析
# 多种降维方法对比 from sklearn.manifold import TSNE from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA def compare_dimension_reduction(X, y, methods=['pca', 'tsne', 'umap', 'lda']): """ 对比不同降维方法效果 """ results = {} fig, axes = plt.subplots(2, 2, figsize=(15, 12)) axes = axes.ravel() for i, method in enumerate(methods): if method == 'pca': reducer = PCA(n_components=2, random_state=42) X_reduced = reducer.fit_transform(X) title = 'PCA' elif method == 'tsne': reducer = TSNE(n_components=2, random_state=42, perplexity=30) X_reduced = reducer.fit_transform(X) title = 't-SNE' elif method == 'umap': reducer = umap.UMAP(n_components=2, random_state=42) X_reduced = reducer.fit_transform(X) title = 'UMAP' elif method == 'lda' and y is not None: reducer = LDA(n_components=2) X_reduced = reducer.fit_transform(X, y) title = 'LDA' # 可视化 scatter = axes[i].scatter(X_reduced[:, 0], X_reduced[:, 1], c=y, cmap='viridis') axes[i].set_title(title) axes[i].set_xlabel('Component 1') axes[i].set_ylabel('Component 2') plt.colorbar(scatter, ax=axes[i]) results[method] = X_reduced plt.tight_layout() plt.show() return results # 方法对比 comparison_results = compare_dimension_reduction(X_scaled, y)8. 实际应用案例:用户画像分析
# 模拟用户画像数据 def simulate_user_profiles(n_users=1000, n_features=20): """ 模拟电商用户行为数据 """ np.random.seed(42) # 生成用户特征:购买频率、浏览时长、消费金额等 user_data = np.random.randn(n_users, n_features) # 添加一些聚类结构 user_data[:300] += [2, 2, 1, 0.5] + np.random.randn(300, n_features) * 0.3 # 高价值用户 user_data[300:600] += [0, 0, -1, -0.5] + np.random.randn(300, n_features) * 0.3 # 普通用户 user_data[600:800] += [-2, -2, -2, -1] + np.random.randn(200, n_features) * 0.3 # 低活跃用户 user_data[800:] += [1, -1, 2, -2] + np.random.randn(200, n_features) * 0.3 # 特殊群体 # 创建特征名称 feature_names = [f'feature_{i}' for i in range(n_features)] return user_data, feature_names # 生成模拟数据 user_profiles, feature_names = simulate_user_profiles() # 应用降维聚类流程 user_results = complete_analysis_pipeline(user_profiles, n_clusters=4) print("用户分群分析完成!") print("建议后续步骤:") print("1. 分析每个簇的特征分布") print("2. 为不同用户群制定个性化策略") print("3. 监控用户群演变趋势")9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| PCA解释方差过低 | 数据非线性强或噪声过大 | 检查累计解释方差比例 | 尝试非线性降维(UMAP/t-SNE) |
| 聚类效果差 | 簇数选择不当或数据未标准化 | 使用肘部法则选择K值 | 数据标准化,调整聚类参数 |
| UMAP结果不稳定 | 参数设置敏感或数据分布特殊 | 调整n_neighbors和min_dist | 多次运行取稳定结果,调参 |
| 内存不足 | 数据量过大或特征维度太高 | 监控内存使用情况 | 使用增量PCA,数据采样 |
| 可视化点重叠 | 维度压缩过度或数据本身密集 | 检查点分布和聚类间距 | 调整降维参数,尝试3D可视化 |
内存优化技巧:
# 对于超大数据集,使用采样策略 def smart_sampling(X, y=None, max_samples=10000, strategy='random'): if X.shape[0] <= max_samples: return X, y if strategy == 'random': indices = np.random.choice(X.shape[0], max_samples, replace=False) elif strategy == 'stratified' and y is not None: from sklearn.model_selection import train_test_split _, X_sample, _, y_sample = train_test_split( X, y, train_size=max_samples, stratify=y, random_state=42 ) return X_sample, y_sample X_sample = X[indices] y_sample = y[indices] if y is not None else None return X_sample, y_sample10. 最佳实践与使用建议
参数调优顺序:
- 先进行数据标准化和清洗
- 用PCA探索线性结构,确定大致维度
- 使用肘部法则确定聚类数量
- 用UMAP进行非线性可视化验证
- 根据业务需求调整参数
结果验证方法:
- 使用轮廓系数评估聚类紧密度
- 用调整兰德指数对比真实标签(如果有)
- 多次运行检查结果稳定性
- 结合业务知识验证分群合理性
工程化部署建议:
# 封装成可重用管道 from sklearn.pipeline import Pipeline from sklearn.base import BaseEstimator, TransformerMixin class DimensionReductionCluster(BaseEstimator, TransformerMixin): def __init__(self, n_components=2, n_clusters=3, method='pca'): self.n_components = n_components self.n_clusters = n_clusters self.method = method def fit(self, X, y=None): # 实现拟合逻辑 return self def transform(self, X): # 实现转换逻辑 return X # 创建完整管道 pipeline = Pipeline([ ('scaler', StandardScaler()), ('reducer', DimensionReductionCluster()), ('cluster', KMeans(n_clusters=3)) ])这套PCA + 聚类 + UMAP的技术组合在实际项目中验证过多次,特别适合数据探索阶段的快速分析。关键是要理解每种方法的适用场景:PCA适合线性关系明显的数值数据,UMAP擅长处理复杂的非线性结构,聚类算法则需要根据数据特性选择。
第一次使用时建议从小数据集开始,比如先用Iris数据熟悉整个流程,然后再应用到自己的业务数据中。注意记录每次的参数设置和结果,逐步建立自己的分析模板。