数据清洗——利用机器学习方法进行健康智能诊断
| 1.数据预处理与质量控制: 目的:确保数据的完整性和准确性,为后续的分析和建模提供可靠的基础。 具体操作:通过识别并填补缺失值,解决数据不完整的问题,减少因数据缺失导致的偏差。 2.探索性数据分析(EDA): 目的:理解数据的分布特性、趋势以及不同特征之间的关系,为后续建模提供洞察。 具体操作:通过分组对比不同年龄、性别的人群中患病占比,揭示潜在的患病风险因素,为模型特征选择提供依据。 3.分类建模与评估: 目的:构建并评估能够有效预测肝病患者状态的机器学习模型。 具体操作: 使用逻辑回归、决策树、随机森林三种不同的分类算法进行建模,通过比较这些模型的Recall(召回率)、Precision(精确率)和F1值(两者的调和平均),评估各模型的性能。 4.选择表现最优的模型(在本例中是随机森林模型)作为后续优化的基础。 模型优化与效率提升: 目的:通过数据降维技术减少模型复杂度,提高模型的预测准确性和运行效率。 具体操作: 应用主成分分析(PCA)对数据进行降维处理,以去除数据中的冗余信息,同时保留最重要的特征。 将降维后的数据重新用于随机森林模型进行分类,验证降维是否有助于提升模型性能。 5.综合评估与应用前景: 目的:评估优化后模型的实际应用价值,并探索其在医疗诊断领域的潜在应用。 具体操作: 分析优化后模型在特定数据集上的表现,如准确率、泛化能力等。 探讨将模型应用于实际医疗场景的可能性,如辅助医生进行快速、准确的诊断决策。 | 
|---|
【实验原理】
||
||
一、数据预处理
目的:提高数据质量,确保后续分析的有效性。 步骤与方法: 查看数据描述信息:通过统计描述(如均值、标准差、最小值、最大值等)了解数据的整体情况。 缺失值处理: 识别:通过数据描述信息或可视化方法(如直方图、箱线图)识别缺失值。 填补:根据数据的特性选择合适的填补方法,如均值填补、中位数填补、众数填补或使用机器学习算法(如K近邻、随机森林等)进行预测填补。
二、数据探索性分析(EDA)
目的:深入理解数据,发现数据中的模式和趋势,为后续建模提供洞见。 步骤与方法: 分组对比: 按年龄分组:分析不同年龄段的患病占比,了解年龄与肝病发病率的关系。 按性别分组:对比男性和女性中的患病占比,探讨性别差异对肝病的影响。 可视化分析:使用图表(如柱状图、饼图、折线图等)直观展示分析结果。
三、分类建模
目的:构建能够准确预测肝病的机器学习模型。 步骤与方法: 模型选择: 逻辑回归:适用于二分类问题,通过Sigmoid函数将线性预测值转化为概率值。 决策树:通过递归地划分数据空间,形成一系列if-then规则进行分类。 随机森林:集成多个决策树的结果,通过投票或平均策略提高分类性能。 模型训练:使用训练集数据训练上述三种模型。 模型评估: Recall(召回率):衡量模型找到所有正例的能力。 Precision(精确率):衡量模型预测为正例的样本中实际为正例的比例。 F1值:Recall和Precision的调和平均数,用于综合评估模型的性能。 模型选择:根据Recall、Precision和F1值选择表现最好的模型,即随机森林模型。
四、模型优化
目的:进一步提高模型的准确率和效率。 步骤与方法: 主成分分析(PCA): 降维:通过PCA将数据从高维空间映射到低维空间,保留主要信息的同时减少计算量。 去噪:PCA可以去除数据中的噪声和冗余信息,提高模型的泛化能力。 使用降维后的数据重新训练随机森林模型:利用PCA降维后的数据进行模型训练,观察模型性能是否有所提升。 实验原理总结 本实验通过数据预处理提高数据质量,通过数据探索性分析发现数据中的模式和趋势,进而选择合适的机器学习模型进行预测。在模型选择过程中,通过对比不同模型的性能指标(Recall、Precision、F1值)选择最优模型。为了进一步提高模型性能,采用主成分分析对数据进行降维处理,并重新训练模型。这一过程体现了机器学习在医疗诊断领域的应用潜力和价值。 |
| 【实验环境】 | 
|---|
【实验步骤】
||
||
一.数据预处理
1.2 导入数据 import pandas as pd _#_读取数据集
data =pd.read_csv('ILPD(印度肝病患者数据集)数据集.csv', encoding="utf-8")
print(data.head())
_#_查看数据信息
data.info() 
 _#_查看数据信息
data.info() 
 _#_对总体数据进行统计,查看常见的数据的统计学特征
a1=data.describe(include='all')
print(a1) 
 #1.3 数字编码
from sklearn.preprocessing import LabelEncoder
le= LabelEncoder()
#0 为男性, 1 为女性
data["Gender"] = le.fit_transform(data["Gender"][:])
print(data) 
 _#1.4._缺失值填补
from sklearn.impute import SimpleImputer
_#_采用均值填补法
imp=SimpleImputer(strategy='mean')
data['A/G'] = imp.fit_transform(data['A/G'].to_frame())
a2=data.describe()
print(a2) 
 _#1.5._数据列的数值转化
#定义Selector列
calculate_col ="Selector"
calculate_value = 2
_#_将Selector值从{1,2},转化为{1,0}并更名为Selector_cal
data[calculate_col +'_cal']= calculate_value - data[calculate_col]
_#_删除Selector列
data = data.drop(labels='Selector',axis=1)
_#_查看转化后的数据集
print(data)
_#_保存数据
data.to_csv("ILPD(印度肝病患者数据集)数据集_clearn.csv",index=False,encoding="utf-8") 
 
二.数据相关型探索
#2.1 年龄分布直方图、性别数量柱状图
import matplotlib.pyplot as plt
import seaborn as sns
_#_读取数据集
data =pd.read_csv('ILPD(印度肝病患者数据集)数据集_clearn.csv', encoding="utf-8")
_#_确保 genders 与数据中的实际值匹配
genders = ['女性', '男性']
_#_设置图形显示参数
plt.rcParams['font.sans-serif'] = ['simHei'] _#_用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False _#_用来正常显示负号
fig, [ax1, ax2] = plt.subplots(1, 2, figsize=(12, 5))
_#_画出年龄分布直方图
sns.histplot(data['Age'], kde=False, palette="Set2", ax=ax1)
ax1.set(xlabel='年龄', ylabel='数量', title='年龄分布')
_#_画出性别分布柱状图
sns.countplot(x='Gender', data=data, palette="Set2", ax=ax2)
ax2.set(xlabel='性别', ylabel='数量', title='性别分布')
ax2.set_xticklabels(genders)
_#_显示图形
plt.tight_layout() _#_自动调整子图参数 _,_使之填充整个图像区域
plt.show()   
 #2.2 年龄、性别与患病的分布情况
fig, [ax1, ax2] = plt.subplots(1, 2, figsize=(12, 5))
_#_绘制年龄箱线图
sns.boxplot(x='Selector_cal', y='Age', hue='Selector_cal', data=data, palette="Set2", ax=ax1)
ax1.set_title('年龄与患病情况的分布', fontsize=13)
ax1.set(ylabel='年龄', xlabel='') _#_通常箱线图的 x 轴标签不太重要,因为它只是区分不同类别的
#如果需要移除图例
if ax1.legend is not None:
ax1.legend.remove()
_#_绘制性别柱状图
sns.countplot(x='Gender', hue='Selector_cal', data=data, palette="Set2", ax=ax2)
ax2.set_title('性别与患病情况的分布', fontsize=13)
ax2.set(xlabel='性别', ylabel='数量')
ax2.set_xticklabels(['女性', '男性']) _#_确保这里与数据中的性别值匹配
ax2.legend(title='是否患病', labels=['不患病', '患病'])
plt.show() 
 #2.3 _各指标间的相关性
预处理数据:删除不需要的列_
df = data.drop(['Gender', 'Selector_cal'], axis=1)
_#_定义绘制热力图的函数
#热力图(heatmap)对连续型对象之间计算线性相关系数,对其相关性进行可视化呈现。
def correlation_heatmap(df):
plt.figure(figsize=(12, 8))
sns.heatmap(
df.corr(),
cmap='Blues',
square=True,
cbar_kws={'shrink': .9},
annot=True,
linewidths=0.1,
vmax=1.0,
linecolor='white',
annot_kws={'fontsize': 12}
)
plt.title('连续型对象间的皮尔森相关系数', y=1.05, size=15)
plt.show()
_#_调用函数
correlation_heatmap(df)
'''
针对两个离散型变量Gender和Selector,
我们使用卡方检验来观测其相关性,
使用的方法是sklearn.feature_selection中的chi2方法
'''
import pandas as pd
from scipy.stats import chi2_contingency
_#_创建一个交叉表
contingency_table = pd.crosstab(data['Gender'], data['Selector_cal'])
_#_进行卡方检验
chi2_stat, p_value, dof, expected = chi2_contingency(contingency_table)
_#_打印结果
print('性别变量与是否得病变量之间的卡方统计量为:%.4f' % chi2_stat)
print('性别变量与是否得病变量之间的p-value为:%.4f' % p_value)
_#_如果 p-value 小于显著性水平,则两个变量显著相关
if p_value < 0.05:
print("性别与是否得病变量之间存在显著的相关性。")
else:
print("性别与是否得病变量之间不存在显著的相关性。")
"""
计算与Selector其他连续型变量之间的关系,
使用的方法为sklearn.feature_selection中的f_classif方法
"""
import pandas as pd
from sklearn.feature_selection import f_classif
fdata = pd.DataFrame(data.drop(['Gender'], axis=1)) _#_只删除 Gender 列
selector = data['Selector_cal'].values _#__直接获取 Selector 列的值作为数组
使用 f_classif 计算 Selector 与其他连续型变量间的关系_
F, p_val = f_classif(fdata, selector)
_#_输出结果
print('各连续型变量的名称:')
print(fdata.columns.tolist())
print('各连续型变量与是否得病之间的F值为:')
print(F)
print('各连续型变量与是否得病之间的pvalue为:')
print(p_val)
_#__通常,我们会根据 p-value 来筛选重要的特征
例如,选择 p-value 小于 0.05 的特征_
significant_features = fdata.columns[p_val < 0.05]
print('p-value 小于 0.05 的显著特征为:')
print(significant_features) 
 
三.构建分类模型
#3.1 训练集测试集划分
'''
我们根据计算出的label_cal来对数据集进行划分。划分比例设置为测试集:训练集 = 20%:80%。
'''
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
x = data.drop(['Selector_cal'], axis=1) # x 为删除Selector_cal的数据集
y = data['Selector_cal'] # y _为Selector_cal列
划分数据集_
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=2, stratify=data['Selector_cal']) #3.2 逻辑回归
from sklearn.linear_model import LogisticRegression
_#_为权重赋值
weights = {0: 1, 1: 1.3}
_#_进行logistic回归
lr = LogisticRegression(penalty='l2', random_state=8, class_weight=weights)
lr.fit(x_train, y_train)
_#_对y进行预测
y_predprb = lr.predict_proba(x_test)[:, 1]
y_pred = lr.predict(x_test)
from sklearn import metrics
from sklearn.metrics import auc
_#_计算fpr,tpr及thresholds的值
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_predprb)
_#_计算gmean的值
gmean = np.sqrt(tpr*(1-fpr))
_#_计算最大的gmean值对应的thresholds值
dictionary = dict(zip(thresholds,gmean))
max_thresholds = max(dictionary, key=dictionary.get)
print("最大的GMean值为:%.4f"%(max(gmean)))
print("最大的GMean对应的thresholds为:%.4f"%(max_thresholds))
'''
计算AUC值,打印分类预测报告并画出混淆矩阵:
'''
from sklearn.metrics import roc_auc_score
_#_计算AUC值
test_roc_auc = roc_auc_score(y_test, y_predprb)
print(test_roc_auc)
_#_打印模型分类预测报告
print(classification_report(y_test, y_pred))
_#_画出混淆矩阵热力图
cm1 = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm1, annot=True, linewidths=.5, square=True, cmap='Blues')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
all_sample_title = 'ROC AUC Score: {0}'.format(round(test_roc_auc,2))
plt.title(all_sample_title, size=15)
plt.show() 
 
 #3.3 决策树
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
建立决策树模型
model = DecisionTreeClassifier(random_state=5, class_weight=weights)
model = model.fit(x_train, y_train)
对y进行预测
y_predict = model.predict(x_test)
y_predprb = model.predict_proba(x_test)[:, 1]
计算AUC值
test_roc_auc = roc_auc_score(y_test, y_predprb)
print(test_roc_auc)
打印模型分类预测报告
print(classification_report(y_test, y_predict))
绘制混淆矩阵热力图
cm2 = confusion_matrix(y_test, y_predict)
plt.figure(figsize=(9, 9))
sns.heatmap(cm2, annot=True, linewidths=.5, square=True, cmap='Blues')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
all_sample_title = 'ROC AUC score: {0}'.format(round(test_roc_auc,2))
plt.title(all_sample_title, size=15)
plt.show() 
  
 # 3.4 随机森林
'''
随机森林是一种集成模型,通过使用随机的方式从数据中抽取样本和特征,
训练多个不同的决策树,形成“森林”。每个树都给出自己的分类意见,称“投票”。
'''
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
_#_建立随机森林模型
ran_for = RandomForestClassifier(n_estimators=80, random_state=0, class_weight=weights)
ran_for.fit(x_train, y_train)
_#_对 y 进行预测
y_pred_ran = ran_for.predict(x_test)
y_predprb = ran_for.predict_proba(x_test)[:, 1]
_#_计算 AUC 值
test_roc_auc = roc_auc_score(y_test, y_predprb)
print("==================================================")
print("AUC值:")
print(test_roc_auc)
_#_打印模型分类预测报告
print('==================================================')
print('预测报告')
print(classification_report(y_test, y_pred_ran, digits=2))
_#_绘制混淆矩阵热力图
cm3 = confusion_matrix(y_test, y_pred_ran)
plt.figure(figsize=(9, 9))
sns.heatmap(cm3, annot=True, linewidths=.5, square=True, cmap='Blues')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
all_sample_title = 'ROC AUC score: {0}'.format(round(test_roc_auc,2))
plt.title(all_sample_title, size=15)
plt.show()  
 
 #3.5 主成分分析
'''
PCA降维是一种常见的数据降维方法,其目的是在“信息”损失较小的前提下,将高维的数据转换到低维,从而减小计算量。
PCA通常用于高维数据集的探索与可视化,还可以用于数据压缩,数据预处理等。
'''
from sklearn import preprocessing
X = data.iloc[:, :-1] _#_除了 label_cal 列
y = data['Selector_cal']
np.random.seed(123)
perm = np.random.permutation(len(X)) #_将数组随机生成一个新的序列
X = X.loc[perm]
y = y[perm]
X = preprocessing.scale(X)#_进行标准化处理
from sklearn.decomposition import PCA
_#_使用 PCA 进行降维
pca = PCA(copy=True, n_components=6, whiten=False, random_state=1)
X_new = pca.fit_transform(X)
print(u'所保留的6个主成分的方差贡献率为:')
print(pca.explained_variance_ratio_)
print(u'排名前2的主成分特征向量为:')
print(pca.components_[0:1])
print(u'累计方差贡献率为:')
print(sum(pca.explained_variance_ratio_))
_#_对数据集进行划分
x_train, x_test, y_train, y_test = train_test_split(X_new, y, test_size=0.2, random_state=2, stratify=data['Selector_cal'])
_#_建立随机森林模型
ran_for = RandomForestClassifier(n_estimators=80, random_state=0, class_weight=weights)
_#_训练模型
ran_for.fit(x_train, y_train)
_#_对 y 进行预测
y_pred_ran = ran_for.predict(x_test)
y_predprb = ran_for.predict_proba(x_test)[:, 1]
_#_计算 AUC 值
test_roc_auc = roc_auc_score(y_test, y_predprb)
print("==================================================")
print("AUC值:")
print(test_roc_auc)
_#_打印模型分类预测报告
print('==================================================')
print('预测报告')
print(classification_report(y_test, y_pred_ran, digits=2))
_#_绘制混淆矩阵热力图
cm4 = confusion_matrix(y_test, y_pred_ran)
plt.figure(figsize=(9, 9))
sns.heatmap(cm4, annot=True, linewidths=.5, square=True, cmap='Blues')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
all_sample_title = 'ROC AUC score: {0}'.format(round(test_roc_auc,2))
plt.title(all_sample_title, size=15)
plt.show() 
 
  |
