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

作者CSDN:进击的西西弗斯
本文链接:https://blog.csdn.net/qq_42216093/article/details/116994199
版权声明:本文为作者原创文章,未经作者同意禁止转载或盗用



1.项目说明及流程概要:



项目说明


本文项目是我本科毕设项目其中的数据挖掘部分,包括对三种类型的肝癌基因表达数据的PCA分析以及构建神经网络分类模型。


以下是在本文的数据挖掘工作开始之前所做的准备工作:

在TCGA数据库中检索并下载41位肝细胞癌患者的基因表达数据以及相应的癌旁组织的基因表达数据共82个样本数据,数据结构是82行 × \times × 6万列(6万列对应6万种基因表达产物的表达水平),样本包含三种不同类型(3个巴塞罗那病理学分期,1期、2期、3期),使用Python对数据进行预处理,借助R相关软件包分析不同组样本间的差异表达基因,提取其中部分基因进行 GO富集分析(细胞成分和生物学过程的分析),根据结果总结其中的生物学意义, 筛选出20个关键基因,最终,以41个肝癌样本数据为行,20个关键基因为列,原始数据的结构被降维到41 × \times × 20。



样本数据集


使用上述已经处理好的41例肝癌患者的基因表达数据,如下图,每行是一个样本数据(除去首行共41行),前20列是20个关键基因以及它们的基因表达数据,最后一列是每个样本的类别标签(共3种类别)

链接:样本数据集下载



项目流程(全流程通过Python代码实现)


1). 对数据进行标准化预处理,包括均值标准化和方差标准化。

2). 对标准化后的数据进行PCA分析,将数据降维并将结果可视化。

3). 对数据集绘制Andrews曲线,观察各类别之间的差异性

4). 对数据集划分训练集(80%)和测试集(20%),使用训练集构建神经网络分类模型并做5折交叉验证。

5). 调整模型参数:最大迭代次数,并绘制模型得分图像。

6). 调整模型参数:隐藏层层数,并绘制模型得分图像。

7). 最终使用调整好的最优参数构建神经网络模型,并用测试集评估模型效果,同时绘制学习曲线,观察模型训练过程的运行情况。



关于PCA算法和神经网络的算法原理,可以参阅我另一篇博文:


链接:机器学习算法归详细纳整理




2.对数据集进行主成分分析(PCA)和可视化



流程概要


先对数据进行标准化预处理,包括均值标准化和方差标准化(特征缩放);再对标准化后的数据进行PCA分析,将数据降维到10维,提取其中最大主成分的前2个维度,并可视化绘图;最后再对整个数据集绘制Andrews曲线(Andrews曲线是一种用来对多维数据降维可视化的工具),从整个维度上观察各类别之间的差异性。


主要用到的Python库:numpypandasmatplotlibsklearnsklearn.decompositionsklearn.preprocessing



完整代码(附注释)


#!/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 np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.preprocessing import scale
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Heiti TC']    # 指定默认字体:解决plot不能显示中文问题
plt.rcParams['axes.unicode_minus'] = False           # 解决保存图像是负号'-'显示为方块的问题


def Normalization(data):        # 先对数据进行标准化处理

    data = 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 data


def 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 = 1
    for var in var_ratio:
        print("第{}个主成分保留的差异性:{:.2f}%".format(num,var * 100))
        num += 1
    print("总保留的差异性:{:.2f}%".format(np.sum(var_ratio * 100)))

    return res


def 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 = 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). Andrews曲线图像

三种肝癌类型的基因表达数据Andrews曲线

Andrews曲线是一种用来对多维数据降维可视化的工具,能够在整个维度上观察不同类别数据样本的差异性,这里直接对全体数据集作Andrews曲线,图像显示,三种类别的肝癌样本数据之间有明显的差异性,因此接下来可以放心地去构建神经网络分类模型。




3.构建神经网络分类模型



流程概要


对数据集划分训练集(80%)和测试集(20%),使用训练集进行5折交叉验证来构建神经网络分类模型;为了寻找到最优的模型参数,首先调整最大迭代次数,绘制出模型得分曲线,然后调整隐藏层层数,绘制出模型得分曲线;最终使用调整好的最优参数构建神经网络模型,并用测试集评估模型效果,同时绘制学习曲线,观察整个模型训练过程的运行情况。


主要用到的Python库:numpypandasmatplotlibsklearnsklearn.model_selectionsklearn.neural_network



完整代码(附注释)


#!/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 pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator
from sklearn.model_selection import train_test_split, cross_val_score, learning_curve
from sklearn.neural_network import MLPClassifier
plt.rcParams['font.sans-serif'] = ['Heiti TC']    # 指定默认字体:解决plot不能显示中文问题
plt.rcParams['axes.unicode_minus'] = False           # 解决保存图像是负号'-'显示为方块的问题


def Data_split():       # 预处理:样本数据集划分,训练集80%,测试集20%

    data = 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_test


def 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轴的刻度间隔为1
    plt.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以上的数值,而在sklearn中该参数的默认取值是200,远远达不到我们模型的需求,故进行调整。


2). 神经网络模型得分关于隐藏层层数的变化曲线

神经网络模型得分关于隐藏层层数的变化曲线

从图像可以看出,神经网络的隐藏层层数大于2时,训练集的拟合效果达到最优,并持续处于最优拟合状态,但是验证集的得分并不稳定,这是因为神经网络的结构会影响它对数据的预测效果,应当选择适合该数据集的神经网络结构。因此,对于该神经网络模型,参数隐藏层层数应该取7,此时它的预测能力达到最优。


3). 神经网络模型的学习曲线(Learning curve)

神经网络模型的学习曲线

学习曲线是一种用来检测算法模型运行情况的有效工具。观察该模型的学习曲线:

(1). 当训练样本数量很少时,训练集得分很高(为满分1),因为此时模型很容易达到完全拟合状态,但是验证集得分很低,因为学习样本太少导致模型预测能力很差。

(2). 随着样本数的增加,训练集得分逐渐下降,因为此时模型不可能对每个样本都完全拟合,样本数很多时,模型对于整个数据集的拟合能力就会下降,但是验证集的得分在上升,因为此时学习数据增多,模型的预测能力逐渐增强。

(3). 最终,理论上训练集和验证集的得分曲线会最趋于水平,且保持一个较近的间隔,这在该模型的图像中并不明显,分析其原因,主要是因为样本数据集的数量限制,如果能有更多的样本数据,就能够进一步提升模型的训练效果。


4). 最终神经网络模型的预测效果

截屏2021-05-16 下午5.02.51

这是最终的模型得分(也就是预测准确率)情况,训练集的拟合度达到84.38%,验证集最高得分是85.71%,验证集平均得分是71.43%,测试集得分是71.43%,总体来讲模型的预测准确率较高,分类效果较为良好。但是还不够优秀,今后如果有机会可以再进一步进行优化。

  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
好的,我可以为您介绍如何使用Python实现基于PCA和FA的心脏病分类模型。首先,我们需要加载数据集并进行预处理。 ```python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 加载数据集 data = pd.read_csv('heart.csv') # 分割特征和标签 X = data.iloc[:, :-1].values y = data.iloc[:, -1].values # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) # 特征标准化 sc = StandardScaler() X_train = sc.fit_transform(X_train) X_test = sc.transform(X_test) ``` 接下来,我们可以使用PCA数据进行降维。 ```python from sklearn.decomposition import PCA # 使用PCA进行降维 pca = PCA(n_components=2) X_train_pca = pca.fit_transform(X_train) X_test_pca = pca.transform(X_test) ``` 然后,我们可以使用降维后的特征训练分类模型。 ```python from sklearn.linear_model import LogisticRegression # 使用PCA降维后的特征训练逻辑回归模型 classifier_pca = LogisticRegression(random_state=0) classifier_pca.fit(X_train_pca, y_train) ``` 接下来,我们可以使用FA对数据进行降维和特征提取。 ```python from sklearn.decomposition import FactorAnalysis # 使用FA进行降维和特征提取 fa = FactorAnalysis(n_components=2) X_train_fa = fa.fit_transform(X_train) X_test_fa = fa.transform(X_test) ``` 然后,我们可以使用提取的潜在因子训练分类模型。 ```python # 使用FA提取的潜在因子训练逻辑回归模型 classifier_fa = LogisticRegression(random_state=0) classifier_fa.fit(X_train_fa, y_train) ``` 最后,我们可以使用测试集评估模型的性能。 ```python from sklearn.metrics import accuracy_score # 使用测试集评估模型性能 y_pred_pca = classifier_pca.predict(X_test_pca) accuracy_pca = accuracy_score(y_test, y_pred_pca) y_pred_fa = classifier_fa.predict(X_test_fa) accuracy_fa = accuracy_score(y_test, y_pred_fa) print('PCA accuracy:', accuracy_pca) print('FA accuracy:', accuracy_fa) ``` 希望这些代码示例能够对您有所帮助。请注意,这只是一个简单的示例,实际应用可能需要进一步优化和调整模型参数以获得更好的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的西西弗斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值