2. 聚类算法基础概念归纳总结

让我先问一个问题:为什么空间转录组数据需要聚类?

说白了,组织切片上的每个 spot 都测到了几百到几千个基因的表达量。你想知道哪些 spot 属于同一个细胞类型或功能区域。聚类就是帮我们做这件事的——把相似的 spot 归到一堆,不相似的隔开。

我刚开始接触 Visium 数据时,天真地以为随便拿个 K-means 就能搞定。结果一跑出来,组织形态完全不对——同一个解剖区域的 spots 被分到了不同簇,空间连续性全丢了。嗯,后来才意识到,在空间转录组里,聚类不仅要看基因表达,还得考虑空间位置。所以这一章,我们先打基础,把聚类算法的核心概念理清楚。

2.1 聚类到底是什么?

聚类是一种无监督学习。我们不给算法提供任何标签,只给它数据点(每个 spot 的特征向量)。算法自己决定哪些点应该分到一起。

  • 目标:让同一簇内的点尽可能相似,不同簇的点尽可能不同。
  • 输入:一个 N×M 的矩阵,N 个 spot,M 个特征(基因表达量 + 可选空间坐标)。
  • 输出:每个 spot 的簇标签(0,1,2,...)。

啊对了——在 Visium 场景下,我们通常会把 空间坐标 (x,y) 作为额外特征拼进表达矩阵,也可以单独构建 空间邻近图 作为约束。这个后面会细讲。

2.2 核心要素:距离度量

所有聚类算法都依赖“相似度”或“距离”。选哪个距离,直接影响结果。我个人习惯先看数据分布:

距离类型公式适用场景
欧氏距离√∑(xᵢ-yᵢ)²连续型数值,最常用
曼哈顿距离∑|xᵢ-yᵢ|高维稀疏,或特征量纲差异大
余弦相似度(x·y)/(||x||·||y||)表达谱方向(如归一化后的基因表达)
相关性距离1 - Pearson r想要忽略绝对表达水平,只看表达模式
图距离(最短路径)节点间最短边权之和基于空间邻接图时

我在一个项目中遇到基因表达量跨度很大(从 0 到几万),直接用欧氏距离让高表达基因主导了聚类。后来做了 log1p 归一化,再用余弦相似度,才把组织区域分开。所以——数据预处理跟距离选择是一起考虑的。

2.3 主流聚类算法家族

别看算法名字一堆,其实可以分成几个家族。我画了张图,你一看就明白:

聚类算法家族树 聚类算法 划分式 (K-means) 层次聚类 密度聚类 (DBSCAN) 图/谱聚类 K-medoids / Bisecting 凝聚 / 分裂 OPTICS / HDBSCAN 谱聚类 + Louvain Visium 场景偏好 K-means 快但不考虑空间;DBSCAN 能识别噪声但需调参; 图聚类(Louvain/Leiden)结合空间邻接图,最常用

2.4 各算法核心特点速览

这张表我平时做选型时经常翻,给你参考:

算法是否需要预设 K对噪声容忍度能否发现任意形状空间先验支持典型复杂度
K-means是低否(球形假设)通过特征拼接O(N·K·d)
层次聚类否(切割后需确定)中等依赖链接准则通过距离矩阵O(N²·logN)
DBSCAN否高(可标噪声)是通过 eps 和空间距离O(N·logN) 平均
谱聚类是中等是(图割视角)自然支持(基于邻接矩阵)O(N³) 构建谱
Louvain/Leiden否中等(会聚小簇)是(图结构)必须提供邻接图O(N·logN)

我曾经踩过的坑:在 Visium 数据上直接用 K-means 聚类基因表达量,结果总是把组织边缘的 spot 分配到和中心一样。后来才发现,K-means 对离群点和空间尺度极其敏感。如果你非要用 K-means,至少把空间坐标做 Z-score 标准化再加进去。

2.5 如何评价聚类质量?

无监督学习最头疼的就是:没有 ground truth 标签,怎么知道聚类好不好?这里有几个常用指标:

  • 轮廓系数 (Silhouette Score):综合簇内紧密度和簇间分离度。范围 [-1,1],越高越好。但注意它对非凸簇表现不佳。
  • Davies-Bouldin Index (DBI):簇内平均距离 / 簇间中心距离。越小越好。容易计算,但只考虑中心点。
  • Calinski-Harabasz 指数:簇间方差 / 簇内方差。越大越好。适合球形簇。
  • 空间连续性:Visium 特有。看同一簇的 spots 在组织切片上是否形成连贯区域。可以用 邻域一致性分数(比如 spot 的邻居中属于同一簇的比例)。

我个人经验:空间转录组的聚类千万别只靠纯数学指标。你跑出一个高轮廓系数的结果,结果一看图,组织边界完全不对——那就白搭。一定要配合组织学图像或 H&E 染色来验证。

2.6 一个关键洞察:距离选择 × 空间权重

你想想看,Visium 数据天生有双重结构:基因表达相似性 + 空间邻近性。怎么融合?

通常做法有两种:

  1. 特征拼接:把归一化的表达向量和归一化的空间坐标拼成一个长向量,然后跑常规聚类。简单,但空间权重很难调。
  2. 图约束:先根据空间坐标构建 Delaunay 三角网或 kNN 邻接图,然后在图上跑谱聚类或 Louvain。这样能天然保证空间连续性。

我的建议:优先尝试第二种。用 Scanpy 或 Squidpy 建图,然后跑 Leiden 聚类。因为它不仅考虑了表达相似性,还通过“图上的模块度”天然整合了空间邻接关系。这也是当前 Visium 社区的主流做法。

2.7 避坑指南(来自现场)

最后,我把这些年踩过的雷总结成几条:

  • 不要迷信默认参数:scikit-learn 的 K-means 默认用欧氏距离,但在空间转录组里,维度灾难会让距离失效。先做 PCA 降维再聚类。
  • 注意簇数不稳定:很多算法需要预设 K,但生物学上你预先不知道有多少种细胞类型。建议跑多个 K,结合生物学先验或肘部法则选。
  • 空间噪声跟技术性 dropout 混合:Visium 每个 spot 可能是多种细胞的混合,小簇太多容易变成“假团”。最好用 HDBSCAN 这种能自动丢弃噪声的算法先过滤。
  • 可重复性问题:K-means 和谱聚类受随机初始化影响大,务必设 random_state 并多次重启选最优。

好了,基础概念就讲到这里。下一块内容我们会直接上手跑一个真实 Visium 数据集,从数据加载到聚类结果可视化,一步一步看怎么选参数。