Python数据分类模型处理
pip install pyecharts
## 库导入及其数据读取
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from pyecharts.charts import *
from pyecharts import options as opts
import warnings
warnings.filterwarnings('ignore') #忽略警告信息
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
data = pd.read_csv('Medicaldataset.csv')
data.head()
| Age | Gender | Heart rate | Systolic blood pressure | Diastolic blood pressure | Blood sugar | CK-MB | Troponin | Result | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 64 | 1 | 66 | 160 | 83 | 160.0 | 1.80 | 0.012 | negative |
| 1 | 21 | 1 | 94 | 98 | 46 | 296.0 | 6.75 | 1.060 | positive |
| 2 | 55 | 1 | 64 | 160 | 77 | 270.0 | 1.99 | 0.003 | negative |
| 3 | 64 | 1 | 70 | 120 | 55 | 270.0 | 13.87 | 0.122 | positive |
| 4 | 55 | 1 | 64 | 112 | 65 | 300.0 | 1.08 | 0.003 | negative |
数据预处理
#查看数据信息
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1319 entries, 0 to 1318
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 1319 non-null int64
1 Gender 1319 non-null int64
2 Heart rate 1319 non-null int64
3 Systolic blood pressure 1319 non-null int64
4 Diastolic blood pressure 1319 non-null int64
5 Blood sugar 1319 non-null float64
6 CK-MB 1319 non-null float64
7 Troponin 1319 non-null float64
8 Result 1319 non-null object
dtypes: float64(3), int64(5), object(1)
memory usage: 92.9+ KB
没有空缺数据
#删除重复值
data.duplicated().sum()
0
# 为数据集特征创建映射字典,中文便于理解
feature_map = {
'Age': '年龄',
'Heart rate': '心率',
'Systolic blood pressure': '收缩压',
'Diastolic blood pressure': '舒张压',
'Blood sugar': '血糖',
'CK-MB': '肌酸激酶同工酶',
'Troponin': '肌钙蛋白'
}
#绘制每个特征的统计分布图,查找是否存在离群点(异常值)
plt.figure(figsize=(20, 10))
for i, (col, col_name) in enumerate(feature_map.items(), 1):
plt.subplot(2, 4, i) #创建子图
plt.boxplot(data[col]) #画箱形图
plt.title(f'{col_name}的箱线图', fontsize=14)
plt.ylabel('数值', fontsize=12)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
#### 通过观察发现:心率、收缩压、舒张压存在极端异常值,虽然年龄、血糖、肌酸激酶同工酶、肌钙蛋白也存在离群点,但是这些离群点可能是真实反映,故不处理(急性心肌梗死情况下,肌酸激酶同工酶和肌钙蛋白会特别高),只处理那些极端异常值,删除心率大于1000的那个异常值点,删除收缩压小于50的那个点,删除舒张压大于140的那个点。
# 处理前的数据量
print(f"处理前数据量: {len(data)}")
# 删除心率大于1000的异常值
data = data[data['Heart rate'] <= 1000]
# 删除收缩压小于50的异常值
data = data[data['Systolic blood pressure'] >= 50]
# 删除舒张压大于140的异常值
data = data[data['Diastolic blood pressure'] <= 140]
print(f"处理后数据量: {len(data)}")
处理前数据量: 1319
处理后数据量: 1314
#检查舒张压和收缩压的关系,看看是否存在舒张压大于收缩压的情况。
wrong_bloodpressure = data[data['Diastolic blood pressure'] > data['Systolic blood pressure']]
print(f"发现舒张压大于收缩压的记录数: {len(wrong_bloodpressure)}")
发现舒张压大于收缩压的记录数: 6
考虑到可能是录入时候这6条数据录入反了,所以进行调换处理。
# 获取这些记录的索引
wrong_bloodpressure_index = wrong_bloodpressure.index
# 调换这些记录的收缩压和舒张压值
data.loc[wrong_bloodpressure_index, ['Systolic blood pressure', 'Diastolic blood pressure']] = data.loc[wrong_bloodpressure_index, ['Diastolic blood pressure', 'Systolic blood pressure']].values
#再次画图检查一下分布情况
plt.figure(figsize=(20, 10))
for i, (col, col_name) in enumerate(feature_map.items(), 1):
plt.subplot(2, 4, i)
plt.boxplot(data[col])
plt.title(f'处理后{col_name}的箱线图', fontsize=14)
plt.ylabel('数值', fontsize=12)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()

数据分析
data.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| Age | 1314.0 | 56.198630 | 13.645583 | 14.000 | 47.000 | 58.000 | 65.0000 | 103.0 |
| Gender | 1314.0 | 0.659817 | 0.473951 | 0.000 | 0.000 | 1.000 | 1.0000 | 1.0 |
| Heart rate | 1314.0 | 75.987823 | 15.286893 | 20.000 | 64.000 | 74.000 | 85.0000 | 135.0 |
| Systolic blood pressure | 1314.0 | 127.316591 | 25.881832 | 65.000 | 110.000 | 124.000 | 143.0000 | 223.0 |
| Diastolic blood pressure | 1314.0 | 72.087519 | 13.797991 | 38.000 | 62.000 | 71.000 | 80.0000 | 128.0 |
| Blood sugar | 1314.0 | 146.790487 | 75.013659 | 35.000 | 98.000 | 116.000 | 170.0000 | 541.0 |
| CK-MB | 1314.0 | 15.322877 | 46.408436 | 0.321 | 1.660 | 2.850 | 5.8175 | 300.0 |
| Troponin | 1314.0 | 0.361174 | 1.156510 | 0.001 | 0.006 | 0.014 | 0.0850 | 10.3 |
#可视化分析
#1.患者年龄分布
plt.figure(figsize=(20,15))
plt.subplot(3,3,1)
data['Age'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['Age'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图,,secondary_y=True添加第二个y轴显示人数
#plt.hist(data['Age'],bins=12)
plt.title('患者年龄分布')
plt.xlabel('年龄(岁)')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#2.患者性别分布(饼图)
gender_counts=data['Gender'].value_counts() #数据统计
plt.subplot(3,3,2)
plt.pie(gender_counts,labels=['男','女'],autopct="%1.1f%%",startangle=75,colors=['#66b3ff','#ff9999'])
plt.title('患者性别分布')
plt.axis('equal') #使得饼图为圆形
#3.绘制患者心率分布
plt.subplot(3,3,3)
data['Heart rate'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['Heart rate'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
#plt.hist(data['Heart rate'],bins=12)
plt.title('患者心率分布')
plt.xlabel('心率(次/分钟)')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#4.绘制患者收缩压分布
plt.subplot(3,3,4)
data['Systolic blood pressure'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['Systolic blood pressure'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
#plt.hist(data['Systolic blood pressure'],bins=12)
plt.title('患者收缩压分布')
plt.xlabel('收缩压(mmHg)')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#5.绘制患者舒张压分布
plt.subplot(3,3,5)
data['Diastolic blood pressure'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['Diastolic blood pressure'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
#plt.hist(data['Diastolic blood pressure'],bins=12)
plt.title('患者舒张压分布')
plt.xlabel('舒张压(mmHg)')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#6.患者血糖分布
plt.subplot(3,3,6)
data['Blood sugar'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
data['Blood sugar'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
#plt.hist(data['Blood sugar'],bins=12,density=True)
plt.title('患者血糖分布')
plt.xlabel('血糖(mg/dl)')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#7.患者肌酸激酶同工酶水平
plt.subplot(3,3,7)
data['CK-MB'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['CK-MB'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
#plt.hist(data['Systolic blood pressure'],bins=12)
plt.title('患者肌酸激酶同工酶水平')
plt.xlabel('肌酸激酶同工酶')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#8.患者肌钙蛋白水平
plt.subplot(3,3,8)
data['Troponin'].plot(kind='kde',color='red',label='核密度图')#绘制核密度图
data['Troponin'].plot(kind='hist',bins=12,secondary_y=True)#绘制直方图
plt.title('患者肌钙蛋白水平')
plt.xlabel('肌钙蛋白')
plt.ylabel('人数')
plt.grid(axis='y',linestyle='--')
#9.患者患心脏病比例(饼图)
Result_counts=data['Result'].value_counts() #数据统计
plt.subplot(3,3,9)
plt.pie(Result_counts,labels=['患病','未患病'],autopct="%1.1f%%",startangle=75,colors=['#66b3ff','#ff9999'])
plt.title('患者患心脏病比例')
plt.axis('equal') #使得饼图为圆形
(-1.0999995255527086,
1.0999989954709557,
-1.0999999092452373,
1.0999984088108516)

患者基础人口特征:\ 性别分布:男性(1)共870人,女性(0)共449人\ 年龄分布:年龄范围14-103岁,平均56.2岁,集中在55-65岁区间
患者生理指标:\ 心率:平均76次/分钟,主要分布在65-85次/分钟\ 血压:收缩压平均127.3mmHg,舒张压平均72.1mmHg\ 血糖:平均146.8mg/dl,呈右偏分布
患者心脏指标:\ CK-MB(肌酸激酶同工酶):平均15.3,大多数患者值较低\ 肌钙蛋白:平均0.36,大部分患者值集中在较低区间
诊断结果:\ 阳性(positive)患者807例,阴性(negative)患者507例
心脏病影响因素分析
#可视化分析
fig=plt.figure(figsize=(20,16))
plt.subplots_adjust(wspace=0.3,hspace=0.4)#调整子图的间隔
#1.年龄与诊断结果关系
ax1=plt.subplot(3,3,1)
positive_ages = data[data['Result'] == 'positive']['Age']
negative_ages = data[data['Result'] == 'negative']['Age']
plt.boxplot([positive_ages, negative_ages], labels=['Positive', 'Negative'])
#data.boxplot(column='Age',by='Result',ax=ax1)#这种API需要data为DF格式,通过指定列column和by分组
plt.title('年龄与心脏病诊断结果的关系')
plt.xlabel('诊断结果')
plt.ylabel('年龄')
# 2.性别与诊断结果关系
positive_data=data.loc[data['Result']=='positive']
gender_positive_counts=positive_data['Gender'].value_counts()
plt.subplot(3, 3, 2)
plt.pie(gender_positive_counts,labels=['男','女'],autopct="%1.1f%%",startangle=75,colors=['#66b3ff','#ff9999'])
plt.title('性别与心脏病诊断结果的关系')
# 3. 心率与诊断结果关系
ax3 = plt.subplot(3, 3, 3)
positive_Heartrate = data[data['Result'] == 'positive']['Heart rate']
negative_Heartrate = data[data['Result'] == 'negative']['Heart rate']
plt.boxplot([positive_Heartrate, negative_Heartrate], labels=['Positive', 'Negative'])
ax3.set_title('心率与心脏病诊断结果的关系', fontsize=14)
ax3.set_xlabel('诊断结果', fontsize=12)
ax3.set_ylabel('心率 (次/分钟)', fontsize=12)
# 4. 收缩压与诊断结果关系
ax4 = plt.subplot(3, 3, 4)
data.boxplot(column='Systolic blood pressure',by='Result',ax=ax4)
ax4.set_title('收缩压与心脏病诊断结果的关系', fontsize=14)
ax4.set_xlabel('诊断结果', fontsize=12)
ax4.set_ylabel('收缩压 (mmHg)', fontsize=12)
# 5. 舒张压与诊断结果关系
ax5 = plt.subplot(3, 3, 5)
data.boxplot(column='Diastolic blood pressure',by='Result',ax=ax5)
ax5.set_title('舒张压与心脏病诊断结果的关系', fontsize=14)
ax5.set_xlabel('诊断结果', fontsize=12)
ax5.set_ylabel('舒张压 (mmHg)', fontsize=12)
# 6. 血糖与诊断结果关系
ax6 = plt.subplot(3, 3, 6)
data.boxplot(column='Blood sugar',by='Result',ax=ax6)
ax6.set_title('血糖与心脏病诊断结果的关系', fontsize=14)
ax6.set_xlabel('诊断结果', fontsize=12)
ax6.set_ylabel('血糖 (mg/dl)', fontsize=12)
# 7. CK-MB与诊断结果关系
ax7 = plt.subplot(3, 3, 7)
positive_CKMB = data[data['Result'] == 'positive']['CK-MB']
negative_CKMB = data[data['Result'] == 'negative']['CK-MB']
plt.boxplot([positive_CKMB, negative_CKMB], labels=['Positive', 'Negative'])
#data.boxplot(column='CK-MB',by='Result',ax=ax7)
ax7.set_title('CK-MB与心脏病诊断结果的关系', fontsize=14)
ax7.set_xlabel('诊断结果', fontsize=12)
ax7.set_ylabel('CK-MB', fontsize=12)
# 8. 肌钙蛋白与诊断结果关系
ax8 = plt.subplot(3, 3, 8)
data.boxplot(column='Troponin',by='Result',ax=ax8)
ax8.set_title('肌钙蛋白与心脏病诊断结果的关系', fontsize=14)
ax8.set_xlabel('诊断结果', fontsize=12)
ax8.set_ylabel('肌钙蛋白', fontsize=12)
plt.tight_layout()
plt.show()

心脏病患者的肌酸激酶同工酶和肌钙蛋白显著高于未患心脏病的人,而且高龄可能也会导致心脏病,男性患心脏病的比例高于女性,其他特征差异不是非常明显。
分类模型构建与预测
数据预处理
将目标变量转为01变量,并且把连续变量进行标准化处理,由于目标变量的不平衡程度相对温和(阳性61.4%,阴性38.6%),未达到需要强制平衡的临界水平(差异在60%以上才考虑平衡样本),将处理后的数据进行划分
# 将"positive"/"negative"转换为1/0
data['Result_Binary'] = (data['Result'] == 'positive').astype(int)
features = ['Gender','Age', 'CK-MB', 'Troponin']
# 定义特征和目标变量
x = data[features].copy()
y = data['Result_Binary']
# 只对连续变量标准化
continuous_vars = ['Age', 'CK-MB', 'Troponin']
# 先把连续变量列转为float类型
x[continuous_vars] = x[continuous_vars].astype(float)
scaler = StandardScaler()#创建标准化模型
x.loc[:, continuous_vars] = scaler.fit_transform(x[continuous_vars])#进行标准化处理
# 划分训练集和测试集(80%/20%)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=15, stratify=y)
逻辑回归模型
模型预测基本步骤:\ 1.创建模型:模型= 模型函数(参数配置)\ 2.训练模型:模型.fit(x训练集,y训练集)\ 3.模型预测:模型.predict(x测试集)\ 4.模型评估:\ 模型报告:classification_report(y_test, y_pred)\ 混淆矩阵:confusion_matrix(y_test, y_pred))\ ROC曲线:roc_curve(y_test, y_prob)\
由于所有模型的训练、预测、评估都是一样的,古可以定义成一个函数
def evaluate_model(model, model_name, X_train, X_test, y_train, y_test): #模型对象、模型名称,x训练集,y训练集,x测试集
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印分类报告
print(f"=== {model_name} 模型评估 ===")
print(classification_report(y_test, y_pred))#包含准确率、召回率、f1测度、支持率
# 绘制混淆矩阵
cm = confusion_matrix(y_test, y_pred) #返回混淆矩阵
plt.figure(figsize=(8, 6))
plt.imshow(cm,cmap='hot',interpolation='nearest')#热力图
plt.colorbar()#视觉映射
#添加标签
for i in range(2):
for j in range(2):
plt.text(j, i, f'{cm[i, j]:.2f}', ha='center', va='center', color='black')
plt.title(f'{model_name}模型混淆矩阵')
plt.show()
# 绘制ROC曲线
if hasattr(model, "predict_proba"):#hasattr用于检查对象是否具有指定的属性
y_prob = model.predict_proba(X_test)[:, 1]
else: # 对于SVM等没有predict_proba方法的模型
y_prob = model.decision_function(X_test) if hasattr(model, "decision_function") else y_pred
fpr, tpr, _ = roc_curve(y_test, y_prob) #roc曲线
roc_auc = auc(fpr, tpr) #auc面积
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC曲线(面积 = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('假阳率')
plt.ylabel('真阳率')
plt.title(f'{model_name}模型ROC曲线')
plt.legend(loc="lower right")
plt.show()
return model, roc_auc
结论
本项目基于对心脏病发作数据集的系统分析,得出以下主要结论:
人群特征:患者年龄分布广泛,平均年龄56.2岁,男性比例高于女性,且男性患心脏病的风险显著高于女性。\ 生理与生化指标:心脏病患者的肌酸激酶同工酶(CK-MB)和肌钙蛋白(Troponin)水平均显著高于未患病者,年龄也是影响心脏病的重要因素。心率、血压、血糖等常规生理指标在两组间差异不显著。
模型预测:多种机器学习模型均能较好地区分心脏病患者与非患者,其中树模型(决策树、随机森林、XGBoost)表现优于逻辑回归和SVM,具有较高的预测准确性。\ 实际意义:本研究结果为心脏病的早期筛查和风险评估提供了数据支持,提示临床在关注传统生理指标的同时,应重视心脏生化指标的检测与分析。
一、分类模型概述
分类模型的目标是基于特征变量预测样本的类别标签。常见的分类算法包括:
传统算法:逻辑回归、决策树、随机森林、支持向量机 (SVM)、K 近邻 (KNN)等。
集成学习:AdaBoost、Gradient Boosting (XGBoost、LightGBM、CatBoost) 等。
神经网络:多层感知机 (MLP)、卷积神经网络 (CNN)、循环神经网络 (RNN) 等。
二、分类模型构建流程
- 数据准备
首先需要准备训练数据,包括特征矩阵X和标签向量y。 - 模型选择与训练
根据数据特点和任务需求选择合适的模型。 - 模型评估
使用多种评估指标全面评估模型性能。 - 超参数调优
使用网格搜索或随机搜索找到最优参数组合。
三、预测流程
训练好模型后,可对新数据进行预测。
四、处理不平衡数据
当类别分布不均时,需采取特殊策略。
五、集成多个分类器
通过投票或堆叠策略集成多个模型,提高预测性能。
1.逻辑回归:
逻辑回归模型的核心是Sigmoid函数,它将线性回归模型的输出映射到(0,1)区间内,表示为概率。这个概率可以用来预测样本属于某个类别的可能性。逻辑回归虽然名字中有“回归”二字,但它实际上是用于分类的,特别是二分类问题

2.决策树:
决策树模型通过一系列规则对数据进行分类。它包括根节点、内部节点和叶节点。根节点是决策树的起始点,内部节点表示特征属性,叶节点代表决策结果。构建决策树时,需要考虑如何选择最佳特征和如何进行树的剪枝以避免过拟合。

3.随机森林:
随机森林是一种流行的机器学习算法,它通过构建多个决策树并输出分类的模式或者回归的平均预测值。在Python中,可以使用sklearn.ensemble模块中的RandomForestClassifier或RandomForestRegressor类来实现随机森林模型的训练和预测。

4.支持向量机:
SVM的目标是在特征空间中找到一个最优的超平面,以最大化不同类别数据点之间的间隔。这个超平面是由支持向量定义的,即距离超平面最近的数据点。SVM通过最大化这个间隔来构建分类器,从而提高模型的泛化能力。

5.K 近邻 (KNN):
邻近算法,或者说K最邻近(KNN,K-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)