4. 聚类分析基础概念归纳总结

说到批次效应检测,我个人最常用的先手招就是聚类分析。你想想看,如果数据里藏着批次效应,那不同批次的样本在降维空间里往往会自然抱团——这不就是个天然的聚类问题吗?

不过很多人一上来就调包跑K-Means,结果可视化出来一堆乱糟糟的点,完全看不出批次在哪儿。为什么?因为连聚类的基本假设都没搞明白。今天我们就把这些基础概念捋一遍。

4.1 什么是聚类?它跟分类有什么区别?

用一句话说:分类是有标签的,聚类是没标签的。分类像考试——老师给了标准答案,你只需把新样本对号入座。聚类像拼图——你只有一堆散件,得靠形状、颜色把它们分成几堆,至于每堆代表什么,得分析完才知道。

维度分类 (Classification)聚类 (Clustering)
训练数据有标签无标签
学习方式监督学习无监督学习
目标预测类别发现结构
批次效应检测不适用(哪有批次标签让你训练)天然匹配:自动暴露样本间的隐藏分组

所以在我们这个场景里,聚类是识别批次效应的主力。我记得刚入行时有个项目,样本按收集年份自然分成了三群,PCA一看全错开。当时我还以为是生物学差异,后来才发现是实验试剂批次不同——这就是聚类暴露的问题。

4.2 核心概念:距离、簇与内聚

所有聚类算法都绕不开三件事:距离怎么算?簇长什么样?多紧才算一簇?

4.2.1 距离度量

说白了,距离越近越可能是一家人。最常用的有这几种:

  • 欧氏距离:最直观,高维空间里容易“维度灾难”,但在PCA降维后的低维空间里挺好用。
  • 曼哈顿距离:对异常值更鲁棒,我在处理基因表达数据时偶尔会用它。
  • 余弦相似度:只看方向不看长度,适合比较表达谱的形状而非强度。嗯,批次效应常体现在整体偏移上,用余弦有时反而能绕过这个坑。
# 在Python里计算欧氏距离和余弦距离
from scipy.spatial.distance import euclidean, cosine

vec1 = [2.1, 3.5, 1.2]
vec2 = [2.3, 3.7, 1.5]

print("欧氏距离:", euclidean(vec1, vec2))
print("余弦距离:", cosine(vec1, vec2))   # 0表示完全相同
我的小技巧:做批次效应检测时,我会先把数据用PCA降到2~5维,然后用欧氏距离。因为PCA本身已经正交化了,欧氏距离就能很好地反映空间位置差异。

4.2.2 簇与簇内相似度

一簇样本在特征空间里应该紧密抱团。衡量簇的“紧密程度”有两个常用指标:

  • 簇内平方和 (WCSS):所有样本到簇中心的距离平方和,越小越紧凑。
  • 轮廓系数 (Silhouette Score):既考虑簇内紧密度,又考虑簇间分离度,值在[-1,1]之间,越接近1越好。
from sklearn.metrics import silhouette_score
import numpy as np

# 假设我们已经用KMeans得到了labels
X = np.random.rand(100, 3)
labels = np.random.randint(0, 3, 100)

score = silhouette_score(X, labels)
print("轮廓系数:", score)
我曾经踩过的坑:轮廓系数对不规则形状的簇不太友好。比如一条长条形簇被批次效应扭曲了,轮廓系数可能很低,但其实聚类分组是正确的。所以不要只依赖一个指标,多结合可视化判断。

4.3 常见聚类算法概览

不同算法适合不同形状和规模的数据。处理批次效应时,我根据数据特点来选:

算法核心思想适合批次效应的场景
K-Means基于中心点的硬聚类批次效应导致椭球形簇,快速初筛
层次聚类自底向上合并或自顶向下分裂想看出批次之间的层次关系(如批次内还有亚批次)
DBSCAN基于密度的聚类,可识别噪声批次效应让数据形成任意形状的簇,且含有离群样本
GMM(高斯混合模型)软聚类,每个样本属于某簇的概率批次边界模糊,样本可能“半在A批半在B批”

我个人习惯先跑K-Means快速看个大概,如果簇的形状奇怪(比如长条、环状),就换成DBSCAN。有一次在单细胞RNA-seq数据里,批次效应让细胞聚成一条弧线,K-Means完全分不开,换成DBSCAN一下就识别出三个密度中心——每个中心对应一个实验批次。

4.4 如何评价聚类结果?

聚类没有标准答案,但有几个经验法则:

  1. 肘部法则:K-Means里,画WCSS随K变化的曲线,找到拐点。不过批次效应检测时K往往不大(2~5个批次),所以先猜K等于已知批次数的试试。
  2. 轮廓分析:计算所有样本的轮廓系数,如果多数样本在0.5以上,说明簇分得还可以。
  3. 稳定性检验:对数据加一点随机噪声或重采样,看聚类结果是否稳定。如果换个种子就全变了,那说明聚类结构不可靠。
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 肘部法则示意代码
wcss = []
for k in range(2, 10):
    km = KMeans(n_clusters=k, random_state=42)
    km.fit(X)
    wcss.append(km.inertia_)

# 然后绘制wcss随k的变化(此处省略绘图代码)

关键点:在批次效应检测中,我们不是要追求“完美的簇”,而是要看聚类结果是否能对应到批次标签。如果聚类出来的簇与已知批次完全吻合,那批次效应就很明显了。反过来,如果簇内混合了不同批次,说明数据整合得不错。

4.5 聚类与批次效应检测的关系:一张图说清楚

下面这张图是我经验里最常用的流程:从原始数据到最终判断批次效应是否显著。

聚类分析在批次效应检测中的流程 聚类分析辅助批次效应检测流程 原始表达矩阵 PCA降维 (2~10维) 聚类 (K-Means/DBSCAN等) 评估 (轮廓系数 + 可视化) 簇与批次标签是否对应? ✅ 批次效应显著 ✅ 整合良好 注:实际项目中常需要 在聚类后调整参数重试几次

我的习惯做法:每次做完聚类我都会标上真实批次颜色看一眼,如果两个簇界限分明且颜色基本不混,那批次效应基本实锤了。如果簇内五颜六色,那可以放心往下做差异分析。

4.6 小结:你该记住的

  • 聚类是无监督方法,天然适合发现未知的批次分组。
  • 距离度量要跟数据特点匹配:PCA降维后欧氏距离最省心。
  • 算法不要死磕一个:先K-Means试探,不行再DBSCAN或层次聚类。
  • 评估时别忘了可视化,光看指标容易漏掉“形状奇怪”的批次簇。
  • 最终判断是看聚类结果能否对应到批次标签,而不是追求聚类指标完美。

嗯,基础概念就说到这儿。下一轮我们会实际动手,用真实数据跑一遍K-Means聚类检测批次效应——到时候这些概念全能用上。