【影像组学】从特征筛选到分类建模全流程实践及作图
1. 数据准备2. 特征权重图3. 特征相关性热度图 heatmap4. LASSO 模型中 Lambda 选值图5. 特征系数随 Lambda 变化曲线6. 随机森林分类器7. ROC 曲线8. 精确度(Precision),敏感度(Sensitivity),特异度(Specificity)等输出......
·
文章目录
- 应用:入门级影像组学文章解析
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
更多推荐
已为社区贡献4条内容
所有评论(0)