跟着Theis Lab学单细胞: 特征并非“生而平等”

· 8 min read · Tutorials

跟着Theis Lab学单细胞: 特征并非“生而平等”

跟着Theis Lab学单细胞: 特征并非“生而平等”

单细胞最佳实践

特征选择

本章导读 SECTION PREVIEW

1. 了解特征选择的必要性以及目标

2. 理解传统方法的局限性和基于偏差的新方法

3. 实战:使用scry包进行特征选择

本节对应原书 8 Feature Selection

在单细胞RNA测序数据分析中,我们通常会面临一个问题:测序得到的基因数量可能高达3万个,但其中很多基因的表达量为零或接近零,对后续分析贡献不大。今天我们来学习如何通过特征选择(Feature Selection)来筛选出真正有生物学意义的基因,提高分析效率。

01

为什么需要特征选择?

在完成了数据标准化之后,我们的数据虽然消除了技术噪音,保留了生物学差异,但仍然面临一个问题:单细胞RNA测序通常能检测到多达30,000个基因,而其中很多基因的表达量要么为零,要么极低,对我们理解细胞状态和类型贡献不大。

就像在茫茫人海中寻找关键人物一样,我们需要从这3万个基因中筛选出真正能反映细胞生物学特征的"明星基因"。这就是特征选择的目的所在。

feature_selection.jpeg (3292×1040)

特征选择的本质

特征选择(Feature Selection)的核心目标是从所有基因中筛选出一个子集,这个子集应该:

  • • 信息量大:  能够反映细胞间的主要差异
  • • 变异性高:  在不同细胞类型或状态间有明显变化
  • • 噪音低:  不是由技术因素造成的随机波动

通常情况下,单细胞实验聚焦于特定组织,因此只有一小部分基因具有生物学意义上的表达变异。大多数基因要么在所有细胞中都不表达(管家基因之外的组织特异性基因),要么表达水平恒定(管家基因)。

传统方法的局限

传统的特征选择方法主要有两种思路:

  1. 1. 高变异基因(Highly Variable Genes, HVG)
  • • 计算每个基因的变异系数(coefficient of variation)
  • • 选择变异最大的500-2000个基因
  • (大家常用的Seurat包,FindVariableFeatures就是这个思路)
  1. 2. 高表达基因(Highly Expressed Genes)
  • • 根据平均表达水平排序
  • • 选择表达最高的基因

但这些方法存在一个致命缺陷:还记得上一章我们提到的log1p变换吗?由于不能对零值取对数,我们需要加一个伪计数(通常是1)。这个看似无害的操作实际上会严重影响后续的变异计算。

补课:  伪计数的选择是任意的。选择0.1、1或10会得到完全不同的变异估计,特别是对低表达基因来说。研究表明,小的伪计数值会人为地增加零计数基因的方差。

02

基于偏差(Deviance)的特征选择

偏差方法的原理

Germain等人提出了一种巧妙的解决方案:使用偏差(deviance)进行特征选择 。这种方法的优势在于(术语警告⚠️):

  1. 1. 直接作用于原始计数:  不需要标准化,避免了伪计数问题
  2. 2. 有明确的统计学含义:  偏差衡量的是数据与零模型(null model)的拟合程度
  3. 3. 计算简单:  可以用闭式解(closed-form solution)直接计算

什么是偏差?

简单来说,偏差量化了一个基因是否在所有细胞中都有恒定的表达模式 。如果一个基因在所有细胞中的表达都差不多(符合零模型null model),那么它的偏差值就低;反之,如果一个基因在不同细胞中的表达差异很大(不符合零模型),它的偏差值就高。

高偏差值 = 高信息量 = 值得关注的基因

03

实战:使用scry进行特征选择

首先导入必要的包:

import logging
import anndata2ri
import matplotlib.pyplot as plt
import numpy as np
import rpy2.rinterface_lib.callbacks as rcb
import rpy2.robjects as ro
import scanpy as sc
import seaborn as sns

# 设置环境
sc.settings.verbosity = 0
sc.settings.set_figure_params(
    dpi=80,
    facecolor="white",
    frameon=False,
)

# 配置R接口
rcb.logger.setLevel(logging.ERROR)
ro.pandas2ri.activate()
anndata2ri.activate()

%load_ext rpy2.ipython

本教程适合在jupyter notebook里运行。在R中运行(比如R markdown)可以参考跟着Theis Lab学单细胞: 格式转换,你需要知道底层逻辑(下)实现python部分。

加载R包:

%%R
library(scry)

加载标准化后的数据(也就是上节课跟着Theis Lab学单细胞: “标准化”的数学原理保存的数据。想直接运行的小伙伴也可见文末获取):

# 加载上一章保存的数据
adata = sc.read(
    filename="s4d8_normalization.h5ad",
    backup_url="https://figshare.com/ndownloader/files/40015741",
)

# 将数据传递到R环境
ro.globalenv["adata"] = adata

注意:  偏差方法使用原始计数(存储在adata.X中),不需要任何标准化。

计算偏差并选择特征:

%%R
# 使用scry计算二项偏差
sce = devianceFeatureSelection(adata, assay="X")

将偏差值导出到Python:

# 提取偏差值
binomial_deviance = ro.r("rowData(sce)$binomial_deviance").T

选择偏差值最高的4000个基因:

# 对偏差值排序,选择top 4000
idx = binomial_deviance.argsort()[-4000:]
mask = np.zeros(adata.var_names.shape, dtype=bool)
mask[idx] = True

# 保存结果到adata对象
adata.var["highly_deviant"] = mask
adata.var["binomial_deviance"] = binomial_deviance

为了可视化特征选择的效果,让我们画个基因的平均表达vs离散度散点图:

# 使用scanpy计算每个基因的统计量
sc.pp.highly_variable_genes(adata, layer="scran_normalization")

# 绘制散点图
ax = sns.scatterplot(
    data=adata.var, x="means", y="dispersions", hue="highly_deviant", s=5
)
ax.set_xlim(None, 1.5)
ax.set_ylim(None, 3)
plt.show()

高偏差基因高偏差基因

从图中可以观察到,高平均表达的基因被选为高偏差基因。在实际数据中,高表达基因往往也是生物学上最有意义的基因。

最后保存结果:

adata.write("s4d8_feature_selection.h5ad")

06

后记

使用偏差法时,通常选择2000-5000个高偏差基因较合适。太少可能丢失重要信息,太多则包含过多噪音。当然,不同组织、不同实验条件下,合适的基因数量可能不同。如果后续要做精细的亚群分析,可以适当增加基因数量。也可以在后续评估聚类质量时再修改。

大家觉得使用偏差法和传统方法,哪个效果更好呢?欢迎在评论区交流讨论。本章英文原文及完整代码,可以在后台回复scbp08获取。

----------

单细胞领域大牛编写的最强硬核单细胞教程来啦!想要追更学习笔记,请给我们加个✨,不错过最新推送:

Single Cell Tutorial