1. 数据准备

# 导入包
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from scipy.stats import ttest_ind, levene
from sklearn.linear_model import LassoCV
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import seaborn as sns # 作图包
import matplotlib.pyplot as plt # 作图包
from sklearn.metrics import roc_curve, roc_auc_score, classification_report # ROC 曲线 AUC 分类报告

# 导入数据
xlsx_a = 'data/featureTable/aa.xlsx'
xlsx_b = 'data/featureTable/bb.xlsx'
data_a = pd.read_excel(xlsx_a)
data_b = pd.read_excel(xlsx_b)
print(data_a.shape,data_b.shape)
# (212, 30) (357, 30)

# 数据预处理(加分组标签后合并)
rows_a,cols_a = data_a.shape
rows_b,cols_b = data_b.shape
labels_a = np.zeros(rows_a)
labels_b = np.ones(rows_b)
data_a.insert(0, 'label', labels_a)
data_b.insert(0, 'label', labels_b)
data = pd.concat([data_a,data_b])

# 数据集划分
data_train, data_test = train_test_split(data,test_size=0.3, random_state = 15)
data_train_a = data_train[:][data_train['label'] == 0]
data_train_b = data_train[:][data_train['label'] == 1]
data_test_a = data_test[:][data_test['label'] == 0]
data_test_b = data_test[:][data_test['label'] == 1]
print(data_train_a.shape)
print(data_train_b.shape)
print(data_test_a.shape)
print(data_test_b.shape)
# (150, 31)
# (248, 31)
# (62, 31)
# (109, 31)

# T 检验特征筛选(训练集)
index = []
for colName in data.columns[:]:
    if levene(data_train_a[colName], data_train_b[colName])[1] > 0.05: 
        if ttest_ind(data_train_a[colName], data_train_b[colName])[1] < 0.05: 
            index.append(colName)
    else: 
        if ttest_ind(data_train_a[colName], data_train_b[colName],equal_var=False)[1] < 0.05: 
            index.append(colName)
print(len(index))
print(index)

# T 检验后训练集数据整理
data_train_a = data_train_a[index]
data_train_b = data_train_b[index]
data_train = pd.concat([data_train_a, data_train_b])
data_train = shuffle(data_train)
data_train.index = range(len(data_train))
X_train = data_train[data_train.columns[1:]]
# 注意下面两行在训练集与测试集上的区别
scaler = StandardScaler()  # 数据标准化
scaler.fit(X_train)
X_train = scaler.transform(X_train) 
X_train = pd.DataFrame(X_train)
X_train.columns = index[1:]
y_train = data_train['label']

# T 检验后测试集数据整理
data_test_a = data_test_a[index]
data_test_b = data_test_b[index]
data_test = pd.concat([data_test_a, data_test_b])
data_test = shuffle(data_test)
data_test.index = range(len(data_test))
X_test = data_test[data_test.columns[1:]]
X_test = scaler.transform(X_test) # 按照训练集的标准化方式进行标准化
X_test = pd.DataFrame(X_test)
X_test.columns = index[1:]
y_test = data_test['label']

# LASSO 特征筛选
alphas = np.logspace(-4,1,50)
model_lassoCV = LassoCV(alphas = alphas, max_iter = 100000).fit(X_train,y_train)
coef = pd.Series(model_lassoCV.coef_, index = X_train.columns)
print('%s %d'%('Lasso picked',sum(coef != 0)))  # Lasso picked 19
index = coef[coef != 0].index
X_train_raw = X_train  
# LASSO 后特征数变化,X_train 发生变化,这里保存一下 LASSO 变换前的训练集数据方便后续作图
X_train = X_train[index]  # LASSO 后的训练集
X_test = X_test[index] # LASSO 后的测试集

2. 特征权重图

plt.figure()
x_values = np.arange(len(index))  # X 值的范围(0-特征数长度)
y_values = coef[coef != 0]        # Y 值 LASSO 筛选后系数不为零的值

# 纵向的柱状图 bar()
plt.bar(x_values, y_values        #横向柱状图使用:barh()
        , color = 'lightblue'     #设置 bar 的颜色
        , edgecolor = 'black'     #设置 bar 边框颜色
        , alpha = 0.8             #设置不透明度
       )
# X 轴的特征名称设置
plt.xticks(x_values               # X 值
           , index                # 特征名
           , rotation='45'        # 旋转 xticks 旋转 45°
           , ha = 'right'         # xticks 的水平对齐方式
           , va = 'top'           # xticks 的垂直对齐方式
          )
plt.xlabel("feature")             # 横轴名称
plt.ylabel("weight")              # 纵轴名称
plt.show()

在这里插入图片描述

3. 特征相关性热度图 heatmap

plt.figure(figsize=(12,10), dpi= 80)  # figsize 图片宽高,dpi 分辨率
sns.heatmap(X_train.corr()            # 计算特征间的相关性
            , xticklabels=X_train.corr().columns
            , yticklabels=X_train.corr().columns
            , cmap='RdYlGn'   # 配色方案
            , center=0.5      # 颜色分布的中间值
            , annot=True)     # 是否标出相关性系数,默认 False
plt.title('Correlogram of features', fontsize=22) 
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.show()

在这里插入图片描述

4. LASSO 模型中 Lambda 选值图

MSEs = model_lassoCV.mse_path_  # 读出在所有 lambda 交叉验证情况下的均分误差 MSE
"""
# 等价于下面两行
MSEs_mean, MSEs_std = [], []
for i in range(len(MSEs)):
    MSEs_mean.append(MSEs[i].mean())
    MSEs_std.append(MSEs[i].std())
"""
MSEs_mean = np.apply_along_axis(np.mean,1,MSEs) # 对均分误差 MSE 每行求均值 mean (0=列,1=行)
MSEs_std = np.apply_along_axis(np.std,1,MSEs) # 对均分误差 MSE 每行求标准差 std

plt.figure()
plt.errorbar(model_lassoCV.alphas_,MSEs_mean    #x, y 数据,一一对应
             , yerr=MSEs_std                    #y 误差范围(误差棒)
             , fmt="o"                          #数据点标记(o=圆点)
             , ms=3                             #数据点大小
             , mfc="r"                          #数据点颜色 r=红色
             , mec="r"                          #数据点边缘颜色
             , ecolor="lightblue"               #误差棒颜色
             , elinewidth=2                     #误差棒线宽
             , capsize=4                        #误差棒边界线长度
             , capthick=1)                      #误差棒边界线厚度
plt.semilogx()    # 用 x 的对数作为横坐标
plt.axvline(model_lassoCV.alpha_,color = 'black',ls="--") # 选出的 lambda 值用虚线标出
print(model_lassoCV.alpha_)  # 选出的 lambda 值 0.0006551285568595509
plt.xlabel('Lambda')
plt.ylabel('MSE')
plt.show()

在这里插入图片描述

5. 特征系数随 Lambda 变化曲线

coefs = model_lassoCV.path(X_train_raw,y_train,alphas = alphas, max_iter = 100000)[1].T
# 取第一个 array(coef)并转置

plt.figure()
plt.semilogx(model_lassoCV.alphas_,coefs, '-')  # lambda 的对数画 x 轴,coefs 画 y 轴,线型'-'连续的曲线
plt.axvline(model_lassoCV.alpha_,color = 'black',ls="--") # 选出的 lambda 值用虚线标出
plt.xlabel('Lambda')
plt.ylabel('Coefficients')
plt.show()

在这里插入图片描述

6. 随机森林分类器

model_rf = RandomForestClassifier(n_estimators = 200
                                  , criterion = 'entropy'
                                  , random_state = 20
                                  , class_weight = 'balanced'
                                 )
model_rf.fit(X_train,y_train)   # 训练集拟合模型
print(model_rf.score(X_test,y_test))  #测试集准确率  0.9532163742690059

7. ROC 曲线

y_test_probs = model_rf.predict_proba(X_test)  # 获取测试集预测结果的预测概率

# 阈值 thresholds=1 时的 FPR、TPR
fpr, tpr, thresholds = roc_curve(y_test, y_test_probs[:,1], pos_label = 1) 
# y_test 测试集的 y 值
# y_test_probs[:,1] 测试集预测结果为 1 的概率
# pos_label = 1  预测结果=1 的为阳性

plt.figure()
plt.plot(fpr, tpr, marker = 'o')
plt.xlabel("1 - Specificity")  # 特异度 FPR 假阳性率
plt.ylabel("Sensitivity")  # 灵敏度 TPR 真阳性率
plt.show()

# 通过测试集的实际值 y_test 和预测值计算 AUC
auc_score = roc_auc_score(y_test,model_rf.predict(X_test)) 
print(auc_score)  
# 0.9389612311334714

在这里插入图片描述

8. 精确度(Precision),敏感度(Sensitivity),特异度(Specificity)等输出

y_test_pred = model_rf.predict(X_test) # y_test 的预测值
print(classification_report(y_test, y_test_pred)) 
#               precision    recall  f1-score   support

#          0.0       0.98      0.89      0.93        62
#          1.0       0.94      0.99      0.96       109

#     accuracy                           0.95       171
#    macro avg       0.96      0.94      0.95       171
# weighted avg       0.95      0.95      0.95       171
# 如果将“1”类作为“阳性”,“1”类对应的 recall 就是 Sensitivity,“0”类的 recall 即为 Specificity
# 例如上述结果,1 类为阳性时,Precision=0.94,Sensitivity=0.99,Specificity=0.98
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐