兰卫课堂
单细胞转录组分析中的痛点:海量数据、高维特征、复杂关系。传统统计方法往往难以应对这种"数据泥潭"。这恰恰是Lasso和Ridge回归大展身手的舞台!二者究竟有什么不同呢?
其实二者都是基于线性回归的改进方法。最大的不同在于:Lasso回归主要适用于特征选择,即当特征数量很多,但只有少数特征真正重要时,将这些少数特征选出来,更容易解释模型;
Ridge回归则不会排除任何特征,而是会保留所有特征的系数,默认所有的特征都可能对模型预测有用(虽然贡献大小不同)。
因此,如果你的研究目标是寻找最关键的基因标记,Lasso无疑是你的最佳伴侣。它能帮你在海量基因中找到真正的"关键少数"。反之,如果你更看重整体特征的平衡性,Ridge回归会是更好的选择。
下面,用单细胞转录组分析的场景来解释Lasso和Ridge回归的区别。
首先,我们用代码创建一个模拟的单细胞数据分析示例:
# -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltimport matplotlib.font_manager as fmfrom sklearn.linear_model import Lasso, Ridgefrom sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_split# 配置中文字体plt.rcParams['font.family'] = 'sans-serif'plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']plt.rcParams['axes.unicode_minus'] = False# 模拟单细胞测序数据np.random.seed(42)def generate_scRNA_data(n_cells=1000, n_genes=200): # 模拟一些真实的生物学关系 # 假设有一些关键的调控基因及其共表达网络 # 生成一些核心调控基因的表达水平 core_regulators = np.random.exponential(2, size=(n_cells, 5)) # 为这些核心调控基因生成靶基因 target_genes = np.zeros((n_cells, n_genes)) # 添加一些生物学关系 # 前50个基因强烈依赖于第一个核心调控基因 target_genes[:, :50] = np.outer(core_regulators[:, 0], np.random.normal(1, 0.1, 50)) # 接下来的 50 个基因取决于多个调控基因的组合 target_genes[:, 50:100] = np.dot(core_regulators[:, 1:3], np.random.normal(1, 0.1, (2, 50))) # 剩下的基因是随机噪声或者弱表达 target_genes[:, 100:] = np.random.normal(0, 0.1, (n_cells, n_genes - 100)) # 添加技术噪音 technical_noise = np.random.normal(0, 0.05, (n_cells, n_genes)) target_genes += technical_noise # 确认所有表达值非负 target_genes = np.maximum(target_genes, 0) return core_regulators, target_genes# 生成数据core_regulators, target_genes = generate_scRNA_data()# 选择一个靶基因作为响应变量(假定它是一个重要的marker基因)y = target_genes[:, 0] # 使用第一个目标基因作为响应变量X = target_genes[:, 1:] # 所有其他基因作为特征# 标准化数据scaler = StandardScaler()X_scaled = scaler.fit_transform(X)# 划分为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)# 训练Lasso 模型lasso = Lasso(alpha=0.1,max_iter=10000, tol=1e-4)lasso.fit(X_train, y_train)# 训练Ridge模型ridge = Ridge(alpha=0.1,max_iter=10000, tol=1e-4)ridge.fit(X_train, y_train)# 展示分析结果def analyze_results(lasso_model, ridge_model, feature_names=None): if feature_names is None: feature_names = [f"Gene_{i}" for i in range(X.shape[1])] # 得到非零系数 lasso_nonzero = np.nonzero(lasso_model.coef_)[0] ridge_nonzero = np.nonzero(ridge_model.coef_)[0] print("模型比较结果:") print("-" * 50) print(f"Lasso 识别的基因数量: {len(lasso_nonzero)}") print(f"Ridge 保留的基因数量: {len(ridge_nonzero)}") # 绘图比较系数 plt.figure(figsize=(15, 6)) # 仅显示前 50 个基因的系数以进行可视化 n_display = 50 plt.subplot(1, 2, 1) plt.bar(range(n_display), lasso_model.coef_[:n_display]) plt.title('Lasso回归系数\n(稀疏基因选择)') plt.xlabel('基因') plt.ylabel('系数值') plt.subplot(1, 2, 2) plt.bar(range(n_display), ridge_model.coef_[:n_display]) plt.title('Ridge回归系数\n(平滑基因权重)') plt.xlabel('基因') plt.ylabel('系数值') plt.tight_layout() plt.show() plt.savefig('scRNA_regression_comparison.png') # 打印模型得分 print("\n模型性能:") print(f"Lasso测试集 R2 分数: {lasso_model.score(X_test, y_test):.4f}") print(f"Ridge测试集 R2 分数: {ridge_model.score(X_test, y_test):.4f}") # 打印 Lasso 识别的前 10 个重要基因 print("\nLasso 鉴定出的前 10 个重要基因:") lasso_top_idx = np.argsort(np.abs(lasso_model.coef_))[-10:] for idx in lasso_top_idx: print(f"Gene_{idx}: {lasso_model.coef_[idx]:.4f}")analyze_results(lasso, ridge)# 生成简单的共表达网络可视化plt.figure(figsize=(10, 5))plt.subplot(1, 2, 1)plt.imshow(np.corrcoef(target_genes[:, :50].T), cmap='coolwarm', aspect='auto')plt.title('前 50 个基因的共表达相关性\n(Lasso 对于独立基因效果很好)')plt.colorbar()plt.subplot(1, 2, 2)plt.imshow(np.corrcoef(target_genes[:, 50:100].T), cmap='coolwarm', aspect='auto')plt.title('基因共表达相关性50-100\n(Ridge 对于共表达基因效果很好)')plt.colorbar()plt.tight_layout()plt.show()plt.savefig('gene_correlation.png')
然后,运行以上代码,得到如下结果
模型比较结果:
--------------------------------------------------
Lasso 识别的基因数量: 18
Ridge 保留的基因数量: 199
模型性能:
Lasso测试集 R2 分数: 0.9961
Ridge测试集 R2 分数: 0.9990
Lasso 鉴定出的前 10 个重要基因:
Gene_68: -0.0000
Gene_17: 0.0007
Gene_21: 0.0014
Gene_7: 0.0026
Gene_4: 0.0200
Gene_5: 0.1107
Gene_3: 0.1342
Gene_2: 0.2745
Gene_0: 0.4331
Gene_1: 0.7231
从以上模拟的单细胞转录组的分析结果可以看出,Lasso和Ridge在以下方面存在区别:
1. 基因选择效果:
Lasso回归只选择了18个重要基因,而Ridge保留了所有199个基因
这反映了在单细胞分析中的两种不同需求:
Lasso适合寻找标记基因(marker genes)和关键调控因子
Ridge适合研究整个基因调控网络和通路分析
2. 应用场景:
Lasso回归适用于:
寻找细胞类型特异性标记基因
识别关键转录因子
筛选出最重要的信号通路组件
例如:
在肿瘤异质性研究中识别驱动基因
在干细胞分化研究中找出关键调控因子
在免疫细胞分类中确定细胞类型标记物
Ridge回归适用于:
研究基因共表达网络
分析复杂的细胞信号通路
预测基因表达调控关系
例如:
研究基因调控网络中的协同效应
分析细胞分化过程中的基因表达动态变化
预测药物响应相关的基因表达模式
3. 生物学意义:
Lasso的稀疏性反映了生物系统中的"关键节点"现象:
少数几个主要转录因子控制整个基因表达程序
细胞类型往往由少数几个特异性标记基因定义
Ridge的平滑性反映了生物系统的"网络效应":
基因之间存在广泛的相互作用和共表达关系
细胞功能往往需要多个基因的协同作用
4. 实际建议:
如果你的目标是找出细胞类型的标记基因或关键调控因子,使用Lasso
如果你想研究整个基因网络的协同作用,使用Ridge
在许多情况下,可以同时使用两种方法来获得互补的生物学见解
以上的例子,展示了如何在单细胞转录组数据分析中灵活运用这两种回归方法,以回答不同的生物学问题,希望对大家在数据分析有帮助。
本文由 医学事务中心 倪志伟 提供