Python数据挖掘项目:基于三种肝癌样本数据的PCA分析以及神经网络分类模型的

1.项目说明及流程概要:
项目说明
本文项目是我本科毕设项目其中的数据挖掘部分,包括对三种类型的肝癌基因表达数据的PCA分析以及构建神经网络分类模型 。
以下是在本文的数据挖掘工作开始之前所做的准备工作:
在TCGA数据库中检索并下载41位肝细胞癌患者的基因表达数据以及相应的癌旁组织的基因表达数据共82个样本数据,数据结构是82行× \times × 6万列(6万列对应6万种基因表达产物的表达水平),样本包含三种不同类型(3个巴塞罗那病理学分期,1期、2期、3期),使用对数据进行预处理,借助R相关软件包分析不同组样本间的差异表达基因,提取其中部分基因进行 GO富集分析(细胞成分和生物学过程的分析),根据结果总结其中的生物学意义,筛选出20个关键基因,最终,以41个肝癌样本数据为行,20个关键基因为列,原始数据的结构被降维到41× \times × 20 。
样本数据集
使用上述已经处理好的41例肝癌患者的基因表达数据,如下图,每行是一个样本数据(除去首行共41行),前20列是20个关键基因以及它们的基因表达数据,最后一列是每个样本的类别标签(共3种类别)
链接:样本数据集下载
项目流程(全流程通过代码实现)
1). 对数据进行标准化预处理,包括均值标准化和方差标准化 。
2). 对标准化后的数据进行PCA分析,将数据降维并将结果可视化 。
3). 对数据集绘制曲线,观察各类别之间的差异性
4). 对数据集划分训练集(80%)和测试集(20%),使用训练集构建神经网络分类模型并做5折交叉验证 。
5). 调整模型参数:最大迭代次数,并绘制模型得分图像 。
6). 调整模型参数:隐藏层层数,并绘制模型得分图像 。
7). 最终使用调整好的最优参数构建神经网络模型,并用测试集评估模型效果 , 同时绘制学习曲线 , 观察模型训练过程的运行情况 。
关于PCA算法和神经网络的算法原理,可以参阅我另一篇博文:
链接:机器学习算法归详细纳整理
2.对数据集进行主成分分析(PCA)和可视化
流程概要
先对数据进行标准化预处理,包括均值标准化和方差标准化(特征缩放);再对标准化后的数据进行PCA分析,将数据降维到10维,提取其中最大主成分的前2个维度,并可视化绘图;最后再对整个数据集绘制曲线(曲线是一种用来对多维数据降维可视化的工具),从整个维度上观察各类别之间的差异性 。
主要用到的库:numpy、、、(.、.)
完整代码(附注释)
#!/usr/bin/python3# -*- coding: utf-8 -*-"""Created on Fri Aug 14 17:47:47 2020: 2021/5/7 下午10:30@Author: liudong@Software: PyCharm"""import numpy as npimport pandas as pdfrom sklearn.decomposition import PCAfrom sklearn.preprocessing import scaleimport matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['Heiti TC']# 指定默认字体:解决plot不能显示中文问题plt.rcParams['axes.unicode_minus'] = False# 解决保存图像是负号'-'显示为方块的问题def Normalization(data):# 先对数据进行标准化处理data = http://www.kingceram.com/post/scale(data, axis=0, with_mean=True, with_std=True)# with_mean:均值标准化;with_std:方差标准化;axis=0:标准化每个特征(列) , 如果取1则标准化每个观测样本(行)mean = round(data.mean(), 1)std = round(data.std(), 1)print("已完成均值标准化:均值 =",mean)print("已完成特征缩放:方差 =", std)return datadef my_PCA(data, k):# 把数据data降到k维pca = PCA(n_components = k)# 创建PCA对象 , 声明主成分个数,也就是要降到的维度res = pca.fit_transform(data)# 用data来训练PCA模型,同时返回降维后的数据print("原始数据结构: ", data.shape)print("降维后数据结构: ", res.shape)var_ratio = pca.explained_variance_ratio_# pca的这个属性用来获取各个主成分对原始数据的差异性(方差)保留比率 。num = 1for var in var_ratio:print("第{}个主成分保留的差异性:{:.2f}%".format(num,var * 100))num += 1print("总保留的差异性:{:.2f}%".format(np.sum(var_ratio * 100)))return resdef Visualization(res):# 将PCA结果可视化df = pd.DataFrame(res)df1 = df.iloc[:19]df2 = df.iloc[18:30]df3 = df.iloc[30:]fig = plt.figure(figsize=(12,9),dpi= 200)ax = fig.add_axes([0.1,0.1,0.8,0.8])x1 = list(df1.iloc[:,0])y1 = list(df1.iloc[:,1])x2 = list(df2.iloc[:,0])y2 = list(df2.iloc[:,1])x3 = list(df3.iloc[:,0])y3 = list(df3.iloc[:,1])ax.scatter(x1, y1, alpha = 0.5, color = 'r')ax.scatter(x2, y2, alpha = 0.5, color = 'b')ax.scatter(x3, y3, alpha = 0.5, color = 'g')ax.set_xlim(-2, 2)ax.set_ylim(-4, 4)ax.set_title('三种肝癌类型的基因表达数据PCA',fontsize=30)ax.set_xlabel('第一个主成分',fontsize=20)ax.set_ylabel('第二个主成分',fontsize=20)ax.xaxis.set_tick_params(labelsize=15)ax.yaxis.set_tick_params(labelsize=15)ax.legend(labels=['stage1','stage2','stage3'],fontsize=20)plt.savefig('三种肝癌类型的基因表达数据PCA.jpg')plt.show()if __name__ == '__main__':data = http://www.kingceram.com/post/pd.read_csv('data.csv', index_col=False)data.drop(columns=['Stage_Class'])data = Normalization(data)res = my_PCA(data, 10)Visualization(res)# 绘制Andrews曲线df = pd.read_csv('data.csv')plt.figure(figsize=(12,9),dpi= 200)pd.plotting.andrews_curves(df, 'Stage_Class', color=['r','b','g'], linewidth=2)plt.grid(alpha=0.3)plt.title('三种肝癌类型的基因表达数据Andrews曲线', fontsize=30)plt.savefig('三种肝癌类型的基因表达数据Andrews曲线.jpg')plt.show()
结果及分析
1). PCA运行输出结果
可以看出,均值和方差的标准化过程正常,处理后每个样本数据的均值为0 , 方差为1;经过PCA后,数据结构被成功降维到(41,10);此时这10个维度(也就是10个主成分)总共保留了原数据89.24%的差异性 。
2). PCA可视化结果
图像显示,三种类型的肝癌数据样本之间的分开效果比较差,分析其原因,这主要是因为第一个主成分和第二个主成分所保留的样本差异性不够大,总共只有41%左右 , 所以二维可视化之后不足以显示出样本数据之间的类别差异性 。
3). 曲线图像
曲线是一种用来对多维数据降维可视化的工具,能够在整个维度上观察不同类别数据样本的差异性,这里直接对全体数据集作曲线,图像显示 , 三种类别的肝癌样本数据之间有明显的差异性,因此接下来可以放心地去构建神经网络分类模型 。
3.构建神经网络分类模型
流程概要
对数据集划分训练集(80%)和测试集(20%),使用训练集进行5折交叉验证来构建神经网络分类模型;为了寻找到最优的模型参数,首先调整最大迭代次数 , 绘制出模型得分曲线,然后调整隐藏层层数,绘制出模型得分曲线;最终使用调整好的最优参数构建神经网络模型 , 并用测试集评估模型效果,同时绘制学习曲线,观察整个模型训练过程的运行情况 。
主要用到的库:numpy、、、(.、.)
完整代码(附注释)
#!/usr/bin/python3# -*- coding: utf-8 -*-"""Created on Fri Aug 14 17:47:47 2020: 2021/5/6 下午4:19@Author: liudong@Software: PyCharm"""import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib.pyplot import MultipleLocatorfrom sklearn.model_selection import train_test_split, cross_val_score, learning_curvefrom sklearn.neural_network import MLPClassifierplt.rcParams['font.sans-serif'] = ['Heiti TC']# 指定默认字体:解决plot不能显示中文问题plt.rcParams['axes.unicode_minus'] = False# 解决保存图像是负号'-'显示为方块的问题def Data_split():# 预处理:样本数据集划分,训练集80%,测试集20%data = http://www.kingceram.com/post/pd.read_csv('./data.csv')# 读取数据集x_train, x_test, y_train, y_test = train_test_split(data.iloc[:, 0:(data.shape[1]-1)],# 数据集中的自变量集(第一列到倒数第二列)data['Stage_Class'],# 数据集中的因变量集(表示类别标签的最后一列)stratify = data['Stage_Class'],# 按照该列的比例来分层抽样划分训练集和测试集random_state = 8,# 指定随机状态train_size = 0.8)# 训练集比例return x_train, x_test, y_train, y_testdef NN_para_iter(x_train,y_train):# 构建神经网络模型,并调整参数:最大迭代次数,绘制得分图像x = list()y1 = list()y2 = list()for i in np.arange(100, 2000, 100):# 构建神经网络模型mlp = MLPClassifier(solver='sgd',# 反向传播中的优化算法,这里选用随机梯度下降算法activation='tanh',# 激活函数,这里选用tanh双曲函数alpha=0.001,# 正则化惩罚系数hidden_layer_sizes=(50, 50),# 神经网络隐藏层结构:每层神经元数和层数random_state=1,# 指定随机状态max_iter=i,# 最大迭代次数verbose=0)# 是否将进度消息打印输出,取值一般同参数max_iter,0表示不打印输出结果mlp.fit(x_train, y_train)# 用模型拟合数据集scores = cross_val_score(mlp, x_train, y_train, cv=5)# 用数据训练模型,5次交叉验证,得到包含5个得分的列表score = scores.mean()# 求出五次交叉验证得分的平均值x.append(i)y2.append(score)y1.append(mlp.score(x_train, y_train))# 将结果可视化:fig = plt.figure(dpi=200, figsize=(12, 9))ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])ax.plot(x, y1, color='r',marker='o')ax.plot(x, y2, color='b',marker='s')ax.legend(labels=['训练集得分', '交叉验证得分'], loc='upper right',fontsize=20)ax.set_title('神经网络模型得分关于迭代次数的变化曲线',fontsize=30)ax.set_xlabel('迭代次数', fontsize=20)ax.set_ylabel('模型得分', fontsize=20)ax.xaxis.set_tick_params(labelsize=15)ax.yaxis.set_tick_params(labelsize=15)plt.savefig('神经网络模型得分关于迭代次数的变化曲线.jpg')plt.show()def NN_para_layer(x_train,y_train):# 构建神经网络模型,并调整参数:隐藏层层数,绘制得分图像x = list()y1 = list()y2 = list()for i in np.arange(1, 60):# 构建神经网络模型mlp = MLPClassifier(solver='sgd',# 反向传播中的优化算法,这里选用随机梯度下降算法activation='tanh',# 激活函数,这里选用tanh双曲函数alpha=0.001,# 正则化惩罚系数hidden_layer_sizes=(50, i),# 神经网络隐藏层结构:每层神经元数和层数random_state=1,# 指定随机状态max_iter=2000,# 最大迭代次数verbose=0)# 是否将进度消息打印输出,取值一般同参数max_iter,0表示不打印输出结果mlp.fit(x_train, y_train)# 用模型拟合数据集scores = cross_val_score(mlp, x_train, y_train, cv=5)# 用数据训练模型,5次交叉验证,得到包含5个得分的列表score = scores.mean()# 求出五次交叉验证得分的平均值x.append(i)y2.append(score)y1.append(mlp.score(x_train, y_train))# 将结果可视化:fig = plt.figure(dpi=200, figsize=(12, 9))ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])ax.plot(x, y1, color='r',marker='o')ax.plot(x, y2, color='b',marker='s')ax.legend(labels=['训练集得分', '交叉验证得分'], loc='center right',fontsize=20)ax.set_title('神经网络模型得分关于隐藏层层数的变化曲线',fontsize=30)ax.set_xlabel('隐藏层层数', fontsize=20)ax.set_ylabel('模型得分', fontsize=20)ax.xaxis.set_tick_params(labelsize=15)ax.yaxis.set_tick_params(labelsize=15)ax.xaxis.set_major_locator(MultipleLocator(1))# 设置x轴的刻度间隔为1plt.savefig('神经网络模型得分关于隐藏层层数的变化曲线.jpg')plt.show()def draw_learning_curve(x_train, y_train):# 绘制学习曲线,观察模型训练过程是否正常# 调用学习曲线函数,返回三个值:训练样本数递增的一维数组、交叉验证中训练集得分的二维表(包括每次cv)、交叉验证中验证集得分的二维表(包括每次cv)train_sizes, train_scores, validation_scores = learning_curve(MLPClassifier(solver='sgd', activation='tanh', alpha=0.001, hidden_layer_sizes=(50, 7), random_state=1, max_iter=2000, verbose=0),# 用到的机器学习模型x_train,# 样本的自变量集y_train,# 样本的因变量集cv=5,# 交叉验证折叠数train_sizes=np.linspace(0.1,1,10)# 训练样本数量的递增比例情况,默认为np.linspace(0.1,1,5))train_scores_mean = np.mean(train_scores, axis=1)# 求每次训练样本数量对应的训练集得分关于多次cv的均值train_scores_std = np.std(train_scores, axis=1)# 求每次训练样本数量对应的验证集得分关于多次cv的方差validation_scores_mean = np.mean(validation_scores, axis=1)# 求每次训练样本数量对应的验证集得分关于多次cv的均值validation_scores_std = np.std(validation_scores, axis=1)# 求每次训练样本数量对应的验证集得分关于多次cv的方差# 将结果可视化:fig = plt.figure(figsize=(12, 9), dpi=200)ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])ax.plot(train_sizes, train_scores_mean, color='r',marker='o')ax.plot(train_sizes, validation_scores_mean, color='b',marker='s')ax.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.1, color="r")ax.fill_between(train_sizes, validation_scores_mean - validation_scores_std, validation_scores_mean + validation_scores_std, alpha=0.1, color="b")ax.legend(labels=['训练集得分', '交叉验证得分'], loc='best',fontsize=20)ax.set_title('神经网络模型的学习曲线',fontsize=30)ax.grid(True)ax.xaxis.set_tick_params(labelsize=15)ax.yaxis.set_tick_params(labelsize=15)ax.set_xlabel('训练样本数量', fontsize=20)ax.set_ylabel('模型得分', fontsize=20)plt.savefig('神经网络模型的学习曲线.jpg')plt.show()def final_model_evaluate(x_train, x_test, y_train, y_test):# 对最终的神经网络模型评估效果mlp = MLPClassifier(solver='sgd',# 反向传播中的优化算法,这里选用随机梯度下降算法activation='tanh',# 激活函数,这里选用tanh双曲函数alpha=0.001,# 正则化惩罚系数hidden_layer_sizes=(50, 7),# 神经网络隐藏层结构:每层神经元数和层数random_state=1,# 指定随机状态max_iter=2000,# 最大迭代次数verbose=0)# 是否将进度消息打印输出,取值一般同参数max_iter,0表示不打印输出结果mlp.fit(x_train, y_train)# 用模型拟合数据集train_score = mlp.score(x_train, y_train)# 训练集得分scores = cross_val_score(mlp, x_train, y_train, cv=5)# 用数据训练模型,5次交叉验证,得到包含5个得分的列表validation_score = np.mean(scores)# 五次交叉验证得分的平均值validation_max_score = np.amax(scores)# 五次交叉验证得分的最大值test_score = mlp.score(x_test, y_test)print('神经网络模型对于训练集的得分是:{}'.format(round(train_score,2)))print('神经网络模型5次交叉验证的最高得分是:{}'.format((round(validation_max_score,2))))print('神经网络模型5次交叉验证的平均得分是:{}'.format(round(validation_score,2)))print('神经网络模型对于测试集的得分是:{}'.format(round(test_score,2)))if __name__ == '__main__':x_train, x_test, y_train, y_test = Data_split()NN_para_iter(x_train, y_train)NN_para_layer(x_train, y_train)draw_learning_curve(x_train, y_train)final_model_evaluate(x_train, x_test, y_train, y_test)
结果及分析
1). 神经网络模型得分关于迭代次数的变化曲线
图像显示,模型的迭代次数大约1000次左右时训练集的拟合得分和交叉验证的得分开始达到最优,并趋于收敛,因此,神经网络模型中的迭代次数参数应该至少取1000以上的数值,而在中该参数的默认取值是200,远远达不到我们模型的需求 , 故进行调整 。
2). 神经网络模型得分关于隐藏层层数的变化曲线
从图像可以看出,神经网络的隐藏层层数大于2时 , 训练集的拟合效果达到最优,并持续处于最优拟合状态,但是验证集的得分并不稳定 , 这是因为神经网络的结构会影响它对数据的预测效果,应当选择适合该数据集的神经网络结构 。因此,对于该神经网络模型,参数隐藏层层数应该取7,此时它的预测能力达到最优 。
3). 神经网络模型的学习曲线( curve)
学习曲线是一种用来检测算法模型运行情况的有效工具 。观察该模型的学习曲线:
(1). 当训练样本数量很少时 , 训练集得分很高(为满分1),因为此时模型很容易达到完全拟合状态,但是验证集得分很低,因为学习样本太少导致模型预测能力很差 。
(2). 随着样本数的增加,训练集得分逐渐下降 , 因为此时模型不可能对每个样本都完全拟合,样本数很多时,模型对于整个数据集的拟合能力就会下降 , 但是验证集的得分在上升,因为此时学习数据增多,模型的预测能力逐渐增强 。
(3). 最终,理论上训练集和验证集的得分曲线会最趋于水平,且保持一个较近的间隔 , 这在该模型的图像中并不明显,分析其原因,主要是因为样本数据集的数量限制,如果能有更多的样本数据,就能够进一步提升模型的训练效果 。
4). 最终神经网络模型的预测效果
【Python数据挖掘项目:基于三种肝癌样本数据的PCA分析以及神经网络分类模型的】这是最终的模型得分(也就是预测准确率)情况,训练集的拟合度达到84.38%,验证集最高得分是85.71% , 验证集平均得分是71.43%,测试集得分是71.43%,总体来讲模型的预测准确率较高 , 分类效果较为良好 。但是还不够优秀,今后如果有机会可以再进一步进行优化 。