实验报告:单细胞测序数据分析
实验目的
本实验的目的是通过支持向量机(SVM)模型对单细胞测序数据进行分类。将使用两组数据:基因表达数据和对应的标签数据。通过训练SVM模型,期望能够准确地分类细胞类型。
数据描述
-
基因表达数据(expression_data):
-
数据集包含1102个样本。
-
每个样本包含234个基因的表达值。
-
表达值范围从0到不同的正数。
-
-
标签数据(labels_data):
-
数据集包含1102个标签,分别对应基因表达数据中的样本。
-
标签包括"BC_CML","CP_CML","k562","normal"和pre_BC"。
-
实验步骤
-
导入必要的库: 使用Pandas进行数据操作,NumPy进行数值计算,Scikit-learn进行数据标准化、标签编码、模型训练和评估,Seaborn和Matplotlib进行可视化。
-
读取数据: 从Excel文件中读取基因表达数据和标签数据。
-
数据对齐和预处理: 确保基因表达数据和标签数据具有相同的索引,以保证每个样本的标签对应正确的基因表达值。 将基因表达数据进行标准化处理,使每个基因的表达值在同一范围内。 对标签数据进行编码,将字符串标签转换为数值标签。
-
划分训练集和测试集: 将数据集按8:2的比例划分为训练集和测试集。
-
训练SVM模型: 使用线性核函数的SVM模型对训练集数据进行训练。
-
模型评估: 使用测试集数据进行预测,并计算模型的准确率、混淆矩阵和分类报告。
-
结果可视化: 绘制混淆矩阵图以直观展示模型的分类性能。
算法描述
本实验使用了支持向量机(SVM)算法进行分类。以下是该算法的详细描述:
支持向量机(SVM)
支持向量机(SVM)是一种监督学习算法,常用于分类和回归分析。SVM通过在特征空间中找到一个最佳的超平面(或多维空间中的决策边界)来区分不同类别的数据点。其核心思想是最大化数据点到决策边界的距离,以保证分类的稳健性。
算法步骤
-
选择超平面: 在特征空间中找到一个超平面将数据点分成不同的类。对于线性可分的数据,存在无数个超平面可以分割数据,SVM选择那个最大化边界的超平面。
-
最大化间隔: 确定使得正负样本之间的间隔最大的超平面。这个间隔是指离超平面最近的数据点(称为支持向量)到超平面的距离。
-
优化问题: 将问题转化为一个凸优化问题,通过求解拉格朗日乘子来找到最优解。
-
核函数: 对于非线性可分的数据,SVM使用核函数将数据映射到高维空间,在高维空间中数据可能是线性可分的。常见的核函数包括线性核、径向基函数(RBF)核、多项式核等。本实验中,我们使用了线性核。
公式
对于线性可分的情形,SVM的决策函数可以表示为:
f(x) = \text{sign}(w \cdot x + b)
其中,w 是权重向量,x 是输入特征向量,b 是偏置项。
对于非线性可分的情形,引入核函数 K(x_i, x_j):
f(x) = \text{sign}\left( \sum_{i=1}^{N} \alpha_i y_i K(x_i, x) + b \right)
其中,\alpha_i 是拉格朗日乘子,y_i 是训练样本的标签,K(x_i, x_j) 是核函数。
评价指标
-
准确率(Accuracy): 准确率是分类器正确分类的样本数量占总样本数量的比例。
-
精确度(Precision): 精确度是正确预测的正样本数量占所有预测为正样本数量的比例。
-
召回率(Recall): 召回率是正确预测的正样本数量占所有实际为正样本数量的比例。
-
F1得分(F1-score): F1得分是精确度和召回率的调和平均数。
实验代码
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler, LabelEncoder from sklearn.metrics import accuracy_score, confusion_matrix, classification_report from sklearn.svm import SVC import seaborn as sns import matplotlib.pyplot as plt # 导入数据 expression_data = pd.read_excel('/Users/heng/Downloads/单细胞测序数据.xlsx', index_col=0) labels_data = pd.read_excel('/Users/heng/Downloads/单细胞测序数据Labels.xlsx', header=None) # 打印数据框的前几行以检查数据格式 print("Expression Data Head:\n", expression_data.head()) print("Labels Data Head:\n", labels_data.head()) # 确保样本的顺序一致 print("Expression Data Index:\n", expression_data.index) print("Labels Data Index:\n", labels_data.index) # 将labels_data的索引设置为expression_data的索引 labels_data.index = expression_data.index # 检查是否对齐 print("Labels Data Index after setting:\n", labels_data.index) # 确保索引长度一致 print(f"Length of Expression Data: {len(expression_data)}") print(f"Length of Labels Data: {len(labels_data)}") # 检查对齐后是否为空 if expression_data.empty or labels_data.empty: raise ValueError("Aligned data is empty. Please check the input files and indices.") # 确保所有列名都是字符串 expression_data.columns = expression_data.columns.astype(str) # 数据标准化 scaler = MinMaxScaler() expression_data_scaled = scaler.fit_transform(expression_data) # 标签编码 label_encoder = LabelEncoder() labels_encoded = label_encoder.fit_transform(labels_data.iloc[:, 0].values.ravel()) # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(expression_data_scaled, labels_encoded, test_size=0.2, random_state=42) # 训练SVM模型 svm_model = SVC(kernel='linear') svm_model.fit(X_train, y_train) # 预测并评估 y_pred = svm_model.predict(X_test) # 计算准确率和其他指标 accuracy = accuracy_score(y_test, y_pred) conf_matrix = confusion_matrix(y_test, y_pred) class_report = classification_report(y_test, y_pred, target_names=label_encoder.classes_) print("Accuracy:", accuracy) print("Confusion Matrix:\n", conf_matrix) print("Classification Report:\n", class_report) # 绘制混淆矩阵 plt.figure(figsize=(10, 7)) sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=label_encoder.classes_, yticklabels=label_encoder.classes_) plt.xlabel('Predicted Label') plt.ylabel('True Label') plt.title('Confusion Matrix') plt.show()
终端输出
heng@zhangxiaohengdeMacBook-Air 代码.py % /usr/bin/python3 /Users/heng/Documents/代码.py/single_cell_analysis.py Expression Data Head: ABCC4 ABL1 ADAM19 AFG3L2 ANXA2 ANXA2P2 APOC1 ... YIF1B YKT6 ZC3H12C ZFP36L2 ZKSCAN1 ZNF200 ZNF317 OX2046H9 0.0 0.0 0.00000 0.0 1.127670 0.000000 0.0 ... 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 OX2046E1 0.0 0.0 8.58976 0.0 0.000000 0.000000 0.0 ... 0.0 1.553472 0.0 0.000000 0.000000 0.0 0.0 OX2046H3 0.0 0.0 0.00000 0.0 2.132528 0.000000 0.0 ... 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 OX2046F11 0.0 0.0 0.00000 0.0 2.760942 0.000000 0.0 ... 0.0 0.000000 0.0 9.446053 8.431234 0.0 0.0 OX2046F4 0.0 0.0 0.00000 0.0 10.403728 7.755902 0.0 ... 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 [5 rows x 234 columns] Labels Data Head: 0 0 BC_CML 1 BC_CML 2 BC_CML 3 BC_CML 4 BC_CML Expression Data Index: Index(['OX2046H9', 'OX2046E1', 'OX2046H3', 'OX2046F11', 'OX2046F4', 'OX2046E4', 'OX2046C4', 'OX2046E2', 'OX2046H7', 'OX2046C11', ... 'CML1266_DIAG_PL3F3', 'CML1266_DIAG_PL3F11', 'CML1266_DIAG_PL3E5', 'CML1266_DIAG_PL1A1', 'CML1266_DIAG_PL1B3', 'CML1266_DIAG_PL3A1', 'CML1266_DIAG_PL3A9', 'CML1266_DIAG_PL3F12', 'CML1266_DIAG_PL3A11', 'CML1266_DIAG_PL3A2'], dtype='object', length=1102) Labels Data Index: RangeIndex(start=0, stop=1102, step=1) Labels Data Index after setting: Index(['OX2046H9', 'OX2046E1', 'OX2046H3', 'OX2046F11', 'OX2046F4', 'OX2046E4', 'OX2046C4', 'OX2046E2', 'OX2046H7', 'OX2046C11', ... 'CML1266_DIAG_PL3F3', 'CML1266_DIAG_PL3F11', 'CML1266_DIAG_PL3E5', 'CML1266_DIAG_PL1A1', 'CML1266_DIAG_PL1B3', 'CML1266_DIAG_PL3A1', 'CML1266_DIAG_PL3A9', 'CML1266_DIAG_PL3F12', 'CML1266_DIAG_PL3A11', 'CML1266_DIAG_PL3A2'], dtype='object', length=1102) Length of Expression Data: 1102 Length of Labels Data: 1102 Accuracy: 0.8959276018099548 Confusion Matrix: [[ 27 1 0 0 6] [ 0 100 0 3 1] [ 0 0 4 0 0] [ 0 3 0 43 0] [ 3 6 0 0 24]] Classification Report: precision recall f1-score support BC_CML 0.90 0.79 0.84 34 CP_CML 0.91 0.96 0.93 104 k562 1.00 1.00 1.00 4 normal 0.93 0.93 0.93 46 pre_BC 0.77 0.73 0.75 33 accuracy 0.90 221 macro avg 0.90 0.88 0.89 221 weighted avg 0.89 0.90 0.89 221
混淆矩阵可视化:
-
使用热力图展示混淆矩阵,直观展示分类结果。
实验结果
数据预处理
在数据预处理阶段,对表达数据和标签数据进行了对齐。具体步骤如下:
-
表达数据(Expression Data):包含1102个样本,每个样本有234个特征基因。
-
标签数据(Labels Data):包含1102个样本的对应标签。
-
对齐步骤:将标签数据的索引设置为与表达数据一致,确保数据对齐。
支持向量机模型(SVM)训练与测试
使用支持向量机(SVM)模型对单细胞测序数据进行了分类。模型的训练和测试分为以下几个步骤:
-
数据划分:
-
使用
train_test_split
将数据集划分为训练集和测试集,比例为80:20。
-
-
标准化处理:
-
使用
MinMaxScaler
对表达数据进行了归一化处理,将数据缩放到[0, 1]区间。
-
-
模型训练:
-
使用支持向量机(SVM)模型对训练集数据进行了训练。
-
-
模型评估:
-
在测试集上对模型进行了评估,计算了模型的准确率、混淆矩阵和分类报告。
-
模型性能评估
模型的性能评估结果如下:
-
准确率(Accuracy):
-
模型在测试集上的准确率为89.59%。
-
-
混淆矩阵(Confusion Matrix):
BC_CML CP_CML k562 normal pre_BC BC_CML 27 1 0 0 6 CP_CML 0 100 0 3 1 k562 0 0 4 0 0 normal 0 3 0 43 0 pre_BC 3 6 0 0 24 -
分类报告(Classification Report):
precision recall f1-score support BC_CML 0.90 0.79 0.84 34 CP_CML 0.91 0.96 0.93 104 k562 1.00 1.00 1.00 4 normal 0.93 0.93 0.93 46 pre_BC 0.77 0.73 0.75 33 accuracy 0.90 221 macro avg 0.90 0.88 0.89 221 weighted avg 0.89 0.90 0.89 221
结论
通过本实验,成功地使用支持向量机(SVM)对单细胞测序数据进行了分类。模型的准确率和分类报告显示了模型的性能,混淆矩阵图直观展示了分类结果。以下是主要结论:
-
模型准确率较高:模型在测试集上的准确率为89.59%,表明SVM在处理该数据集时具有较好的性能。
-
分类精确度和召回率较好:大多数类别的精确度和召回率较高,特别是CP_CML和normal类别,说明模型在这些类别上表现较好。
-
少数类别的表现:对于样本较少的k562类别,尽管样本数少但模型依然能够正确分类。对于pre_BC类别,模型的召回率和精确度相对较低,可能需要进一步优化。