8. 聚类Clustering
预处理和可视化使我们能够描述我们的scRNA-seq数据集并降低其维度。到目前为止,我们嵌入并可视化了细胞以了解数据集的基础属性。然而,它们的定义仍然相当抽象。单细胞分析的下一个步骤是识别数据集中的细胞结构。
在scRNA-seq数据分析中,我们通过查找与已知细胞状态或细胞周期阶段相关的细胞身份来描述数据集中的细胞结构。这个过程通常称为细胞身份注释。为此,我们将细胞组织成簇,以推断相似细胞的身份。聚类本身是一个常见的无监督机器学习问题。我们可以通过最小化表达空间中的簇内距离来导出簇。在这种情况下,表达空间决定了细胞相对于降维表示的基因表达相似性。例如,这种较低维度的表示是通过主成分分析确定的,然后基于欧几里德距离进行相似性评分。
在k最近邻(KNN)图中,节点反映数据集中的细胞。我们首先在PC(主成分)缩减表达空间上计算所有细胞的欧几里德距离矩阵,然后将每个细胞连接到其K个最相似的细胞。通常,K设置为5到100之间的值,具体取决于数据集的大小。KNN图通过图中的密集连接区域来反映表达数据的基础拓扑结构。KNN图中的密集区域是通过Leiden和Louvain等community检测方法实现。
Leiden算法是Louvain算法的改进版本,在单细胞RNA-seq数据分析方面优于其他聚类方法。由于Louvain算法不再维护,因此首选使用Leiden。
因此,我们建议在单细胞k最近邻(KNN)图上使用Leiden算法来对单细胞数据集进行聚类。
Leiden通过考虑簇中细胞之间的链接数量与数据集中的总体预期链接数量来创建簇。
起点是一个单例分区,其中每个节点都充当自己的社区(a)。下一步,该算法通过将单个节点从一个社区移动到另一个社区来创建分区(b),随后进行细化以增强分区(c)。然后将细化的分区聚合到网络(d)。随后,算法再次移动聚合网络中的各个节点(e),直到细化不再改变分区(f)。 重复所有步骤,直到创建最终的聚类并且分区不再发生变化。
Leiden模块具有分辨率参数,可以确定分区簇的规模,从而确定聚类的粗糙度。更高分辨率的参数会导致更多的簇。该算法还允许通过对KNN图进行子设置来对数据集中的特定聚类进行有效的子聚类。子聚类使用户能够识别聚类内的细胞类型特定状态或更精细的细胞类型标记,但也可能导致仅由于数据中存在的噪声而产生的结果。
前面提到,Leiden算法是在scanpy中实现的。
import scanpy as sc
sc.settings.verbosity = 0
sc.settings.set_figure_params(dpi=80, facecolor="white", frameon=False)
8.1 聚类人类骨髓来源细胞
首先,我们加载数据集。 我们对来自我们已经预处理的NeurIPS人类骨髓数据集的预处理样本site4-donor8
进行聚类。
该数据集使用log1pPF、scran和scTransform 进行标准化。我们将按照预处理章节中的建议重点关注本笔记本中数据集的scran标准化版本,以更好地识别单个细胞的状态。
adata = sc.read("s4d8_subset_gex.h5ad")
我们可以使用scanpy函数sc.pp.neighbors
计算低维基因表达表示的KNN图。我们在前30个主成分上调用此函数,因为它们捕获了数据集中的大部分方差。
可视化聚类可以帮助我们理解结果,因此我们将细胞嵌入到UMAP中。有关UMAP可视化的更多信息可以在可视化部分找到。
sc.pp.neighbors(adata, n_pcs=30)
sc.tl.umap(adata)
输出结果:
/Users/anna.schaar/opt/miniconda3/envs/bp_pp/lib/python3.8/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.
我们现在可以调用Leiden算法。
sc.tl.leiden(adata)
scanpy中默认的分辨率参数是1.0。然而,在许多情况下,分析人员可能希望尝试不同的分辨率参数来控制聚类的粗糙度。因此,我们建议将聚类结果保存。
sc.tl.leiden(adata, key_added="leiden_res0_25", resolution=0.25)
sc.tl.leiden(adata, key_added="leiden_res0_5", resolution=0.5)
sc.tl.leiden(adata, key_added="leiden_res1", resolution=1.0)
我们现在可视化在不同分辨率下使用莱顿算法获得的不同聚类结果。正如我们所看到的,分辨率很大程度上影响了我们的聚类的粗略程度。较高的分辨率参数会导致更多的社区,即更多的识别簇,而较低的分辨率参数会导致更少的社区。因此,分辨率参数控制算法将KNN嵌入中的聚类区域分组在一起的密度。这对于注释集群变得尤其重要。
sc.pl.umap(
adata,
color=["leiden_res0_25", "leiden_res0_5", "leiden_res1"],
legend_loc="on data",
)
我们现在可以清楚地检查不同分辨率对聚类结果的影响。对于0.25的分辨率,聚类更加粗糙,算法检测到的社区也更少。此外,与分辨率为1.0 时获得的聚类相比,聚类区域的密度较低。
我们想再次强调,必须谨慎解释显示的簇之间的距离。由于UMAP嵌入是二维的,因此不一定能很好地捕获所有点之间的距离。我们建议不要解释UMAP嵌入上可视化的簇之间的距离。