DAY 15 复习日

article/2025/7/19 2:57:33

        尝试找到一个kaggle或者其他地方的结构化数据集,用之前的内容完成一个全新的项目,这样你也是独立完成了一个专属于自己的项目。

数据来源:糖尿病分类数据集Kaggle

一、数据预处理

1、读取并查看数据

# 忽略警告
import warnings
warnings.simplefilter('ignore')# 数据处理
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler# 数据可视化
import matplotlib.pyplot as plt
import seaborn as sns# 划分数据集
from sklearn.model_selection import train_test_split# SMOTE过采样
from imblearn.over_sampling import SMOTE# 模型和评估指标
from sklearn.ensemble import RandomForestClassifier  # 随机森林模型
import xgboost as xgb  # XGBoost模型
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import classification_report, confusion_matrix# 时间
import time# 绘制shap图
import shap

dt = pd.read_csv(r'C:\Users\acstdm\Desktop\python60-days-challenge-master\项目 5-糖尿病分类问题\Diabetes .csv')
print('数据基本信息:')
print(dt.info())

输出:

数据基本信息:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 14 columns):#   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  0   ID         1000 non-null   int64  1   No_Pation  1000 non-null   int64  2   Gender     1000 non-null   object 3   AGE        1000 non-null   int64  4   Urea       1000 non-null   float645   Cr         1000 non-null   int64  6   HbA1c      1000 non-null   float647   Chol       1000 non-null   float648   TG         1000 non-null   float649   HDL        1000 non-null   float6410  LDL        1000 non-null   float6411  VLDL       1000 non-null   float6412  BMI        1000 non-null   float6413  CLASS      1000 non-null   object 
dtypes: float64(8), int64(4), object(2)
memory usage: 109.5+ KB
None

有1000个样本,无缺失值。

其中Gender(性别)和CLASS(类型)是字符型。

2、特征解释:

  1. ID:唯一标识符
  2. No_Pation:患者的另一个标识符。它可能是患者编号或记录 ID。
  3. Gender:性别
  4. AGE:年龄
  5. Urea:血液中的尿素水平(可能以 mg/dL 或 mmol/L 为单位)。尿素是蛋白质代谢的废物,可以指示肾功能。
  6. Cr:血液中的肌酐水平(可能以 mg/dL 或 μmol/L 为单位)。肌酐是另一种表明肾功能的废物。
  7. HbA1c:糖化血红蛋白,衡量过去 2-3 个月平均血糖水平的指标(以百分比表示)。
  8. Chol:血液中的胆固醇水平(可能以 mg/dL 或 mmol/L 为单位)。这通常是指总胆固醇。
  9. TG:血液中的甘油三酯水平(可能以 mg/dL 或 mmol/L 为单位)。甘油三酯是血液中的一种脂肪。
  10. HDL:高密度脂蛋白胆固醇水平(通常称为“好”胆固醇,以 mg/dL 或 mmol/L 为单位)。
  11. LDL:低密度脂蛋白胆固醇水平(通常称为“坏”胆固醇,以 mg/dL 或 mmol/L 为单位)。
  12. VLDL:极低密度脂蛋白胆固醇水平(以 mg/dL 或 mmol/L 为单位)。
  13. BMI:体重指数,基于身高和体重的体脂量度指标(计算方法是体重(公斤)除以身高(米)的平方)。
  14. CLASS:指示患者糖尿病状态的类标签。可能的值似乎是:
  • N:非糖尿病
  • P:糖尿病前期
  • Y:糖尿病

print('\n前五行信息预览')
print(dt.head())

输出:
 

前五行信息预览ID  No_Pation Gender  AGE  Urea  Cr  HbA1c  Chol   TG  HDL  LDL  VLDL  \
0  502      17975      F   50   4.7  46    4.9   4.2  0.9  2.4  1.4   0.5   
1  735      34221      M   26   4.5  62    4.9   3.7  1.4  1.1  2.1   0.6   
2  420      47975      F   50   4.7  46    4.9   4.2  0.9  2.4  1.4   0.5   
3  680      87656      F   50   4.7  46    4.9   4.2  0.9  2.4  1.4   0.5   
4  504      34223      M   33   7.1  46    4.9   4.9  1.0  0.8  2.0   0.4   BMI CLASS  
0  24.0     N  
1  23.0     N  
2  24.0     N  
3  24.0     N  
4  21.0     N

3、数据清洗

在后续的编码过程中,发现编码后反而出现了缺失值,故在此添加一系列代码进行查看。

查看不同分类及其数量:

# 查看不同分类及其数量
print(dt['Gender'].value_counts())
print(dt['CLASS'].value_counts())

输出:

Gender
M    565
F    434
f      1
Name: count, dtype: int64
CLASS
Y     840
N     102
P      53
Y       4
N       1
Name: count, dtype: int64

查看特征下的不同类别:

dt['CLASS'].unique()

输出:

array(['N', 'N ', 'P', 'Y', 'Y '], dtype=object)

分析:

Gender有未知分类f,推测是大小写问题,实际为应为F。

CLASS有重名分类Y、N,由上行输出可知是数据集中多打了空格。

添加数据清洗步骤:

将Gender下的类别统一成大写,将CLASS下的类别去除空格

# 数据清洗
dt['Gender'] = dt['Gender'].str.upper()  # 统一性别为大写
dt['CLASS'] = dt['CLASS'].str.strip()  # 去除类别空格
# 检查一下 处理好了
print(dt['CLASS'].unique())
print(dt['Gender'].unique())

输出:解决了!!

['N' 'P' 'Y']
['F' 'M']

4、对离散特征进行编码

# 定义映射矩阵
mapping = {'Gender':{'M':1,'F':0},'CLASS':{'N':0,'P':1,'Y':2}
}
# 进行编码
dt['Gender'] = dt['Gender'].map(mapping['Gender'])
dt['CLASS'] = dt['CLASS'].map(mapping['CLASS'])

这样就编码好了。

dt.isnull().sum() # 检查缺失值 无缺失值

输出:都没有缺失值,说明前面数据清洗没白做

ID           0
No_Pation    0
Gender       0
AGE          0
Urea         0
Cr           0
HbA1c        0
Chol         0
TG           0
HDL          0
LDL          0
VLDL         0
BMI          0
CLASS        0
dtype: int64

5、连续特征进行归一化

# 连续特征
continuous_features = ['ID', 'No_Pation', 'Cr', 'BMI']
# 借助sklearn库进行归一化 
min_max_scaler = MinMaxScaler()  # 实例化
for feature in continuous_features:dt[feature] = min_max_scaler.fit_transform(dt[[feature]])
dt.head()
IDNo_PationGenderAGEUreaCrHbA1cCholTGHDLLDLVLDLBMICLASS
00.6270340.0002370504.70.0503784.94.20.92.41.40.50.1739130
10.9186480.0004521264.50.0705294.93.71.41.12.10.60.1391300
20.5244060.0006340504.70.0503784.94.20.92.41.40.50.1739130
30.8498120.0011600504.70.0503784.94.20.92.41.40.50.1739130
40.6295370.0004521337.10.0503784.94.91.00.82.00.40.0695650

二、绘制热力图

continuous_features = ['ID', 'No_Pation', 'AGE', 'Urea', 'Cr', 'HbA1c', 'Chol', 'TG', 'HDL', 'LDL', 'VLDL', 'BMI']# 计算相关系数矩阵 corr()
correlation_matrix = dt[continuous_features].corr()# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300# 绘制热力图
plt.figure(figsize=(12, 10))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlation Heatmap of Continuous Features')
plt.show()

三、连续特征箱线图

# 定义要绘制的特征
features = ['AGE', 'Urea', 'HbA1c', 'Chol', 'TG', 'LDL']"""
创建一个2*3的子图
fig:代表整个2*3的大画布
axes:是一个2*3数组, 通过axes[i][j]访问每个子图
"""
fig, axes = plt.subplots(2, 3, figsize=(12, 8))# 设置分辨率
plt.rcParams['figure.dpi'] = 300# 遍历特征并绘制箱线图 enumerate
for i, feature in enumerate(features):x = i // 3  # 计算当前子图的行索引y = i % 3   # 计算当前子图的列索引# 绘制箱线图 boxplot()axes[x][y].boxplot(dt[feature].dropna())axes[x][y].set_title(f"boxplot of {feature}")axes[x][y].set_ylabel(feature)# 调整布局 tight_layout()
plt.tight_layout()# 显示图形 show()
plt.show()

四、模型训练

1、划分数据集

X = dt.drop(['CLASS'], axis=1)   # 特征
y = dt['CLASS']   # 标签
# 8:2划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

2、基准模型

(1)默认随机森林模型

# --- 1.默认参数随机森林模型 ---
print("--- 1.默认参数随机森林模型 ---")
start_time = time.time()
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)
rf_pred = rf_model.predict(X_test)
end_time = time.time()
print(f"随机森林模型训练时间:{end_time - start_time:.4f}, 秒")
print(f"默认随机森林模型准确率:", accuracy_score(y_test, rf_pred))
# !!!该项目是三分类问题,需要修改average参数
print(f"默认随机森林模型f1分数:{f1_score(y_test, rf_pred, average='weighted'):.4f}")
print(f"默认随机森林模型召回率:{recall_score(y_test, rf_pred, average='weighted'):.4f}")
print(f"默认随机森林分类报告:\n", classification_report(y_test, rf_pred))
print(f"默认随机森林混淆矩阵:\n", confusion_matrix(y_test, rf_pred))
print('*' * 55)

输出:

--- 1.默认参数随机森林模型 ---
随机森林模型训练时间:0.1872, 秒
默认随机森林模型准确率: 0.995
默认随机森林模型f1分数:0.9951
默认随机森林模型召回率:0.9950
默认随机森林分类报告:precision    recall  f1-score   support0       0.95      1.00      0.98        211       1.00      1.00      1.00         62       1.00      0.99      1.00       173accuracy                           0.99       200macro avg       0.98      1.00      0.99       200
weighted avg       1.00      0.99      1.00       200默认随机森林混淆矩阵:[[ 21   0   0][  0   6   0][  1   0 172]]
*******************************************************

!!!该项目是三分类问题,需要修改average参数

f1_score参数说明(根据需求选择):

  • average='micro' :全局统计TP/FP/FN计算
  • average='macro' :各类别平等权重
  • average='weighted' :按样本数量加权平均
  • average=None :返回每个类别的单独分数

建议使用macro或weighted参数。

(2)默认XGBoost模型

# --- 2.默认参数xgbboost模型 ---
print("--- 2.默认参数xgbboost模型 ---")
start_time = time.time()
xgb_model = xgb.XGBClassifier(random_state=42)
xgb_model.fit(X_train, y_train)
xgb_pred = xgb_model.predict(X_test)
end_time = time.time()
print(f"xgbboost模型训练时间:{end_time - start_time:.4f}, 秒")
print(f"默认xgbboost模型准确率:", accuracy_score(y_test, xgb_pred))
# !!!该项目是三分类问题,需要修改average参数
print(f"默认xgbboost模型f1分数:{f1_score(y_test, xgb_pred, average='weighted'):.4f}")
print(f"默认xgbboost模型召回率:{recall_score(y_test, xgb_pred, average='weighted'):.4f}")
print(f"默认xgbboost分类报告:\n", classification_report(y_test, xgb_pred))
print(f"默认xgbboost混淆矩阵:\n", confusion_matrix(y_test, xgb_pred))
print('*' * 55)

输出:

--- 2.默认参数xgbboost模型 ---
xgbboost模型训练时间:0.2230, 秒
默认xgbboost模型准确率: 0.99
默认xgbboost模型f1分数:0.9900
默认xgbboost模型召回率:0.9900
默认xgbboost分类报告:precision    recall  f1-score   support0       0.95      0.95      0.95        211       1.00      1.00      1.00         62       0.99      0.99      0.99       173accuracy                           0.99       200macro avg       0.98      0.98      0.98       200
weighted avg       0.99      0.99      0.99       200默认xgbboost混淆矩阵:[[ 20   0   1][  0   6   0][  1   0 172]]
*******************************************************

3、处理不平衡数据后的模型

使用smote进行过采样,然后使用随机森林进行分类。

smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print("SMOTE过采样后训练集的形状:", X_train_smote.shape, y_train_smote.shape)
print("训练集的形状:", X_train.shape, y_train.shape)print("\n--- 3.SMOTE过采样的随机森林模型 ---")
start_time = time.time()
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train_smote, y_train_smote)
rf_pred = rf_model.predict(X_test)
end_time = time.time()print(f"随机森林模型训练时间:{end_time - start_time:.4f}, 秒")
print(f"默认随机森林分类报告:\n", classification_report(y_test, rf_pred))
print(f"默认随机森林混淆矩阵:\n", confusion_matrix(y_test, rf_pred))
print('*' * 55)

输出:

SMOTE过采样后训练集的形状: (2013, 13) (2013,)
训练集的形状: (800, 13) (800,)--- 3.SMOTE过采样的随机森林模型 ---
随机森林模型训练时间:0.3746, 秒
默认随机森林分类报告:precision    recall  f1-score   support0       0.95      1.00      0.98        211       1.00      1.00      1.00         62       1.00      0.99      1.00       173accuracy                           0.99       200macro avg       0.98      1.00      0.99       200
weighted avg       1.00      0.99      1.00       200默认随机森林混淆矩阵:[[ 21   0   0][  0   6   0][  1   0 172]]
*******************************************************

4、修改权重的随机森林模型

# 关键 定义带权重的模型
rf_model_weighted = RandomForestClassifier(random_state=42,class_weight='balanced'
)

五、可解释性分析 shap图

初始化 SHAP 解释器

# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(rf_model)
shap_values = explainer.shap_values(X_test)

找和测试集形状一样的shap_values输出值

# 找和测试集形状一样的shap_values输出值
print(shap_values[:, :, 0].shape)
print(X_test.shape)

输出:

(200, 13)
(200, 13)

1、SHAP 特征重要性条形图

# --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) ---
plt.figure(figsize=(10, 6))
shap.summary_plot(shap_values[:, :, 0], X_test, plot_type="bar",show=False) # 只显示第一个类别(0)的条形图

2、特征重要性蜂巢图

shap.summary_plot(shap_values[:, :, 0], X_test, plot_type="violin", show=False)
plt.title("SHAP Feature Importance")
plt.show()

3、SHAP 依赖性图

shap.dependence_plot("BMI", shap_values[:, :, 0], X_test, interaction_index="AGE")
shap.dependence_plot("HbA1c", shap_values[:, :, 0], X_test, interaction_index="AGE")

@ 浙大疏锦行


http://www.hkcw.cn/article/LCjNtRQCVX.shtml

相关文章

JAVA 常用 API 正则表达式

1 正则表达式作用 作用一&#xff1a;校验字符串是否满足规则作用二&#xff1a;在一段文本中查找满足要求的内容 2 正则表达式规则 2.1 字符类 package com.bjpowernode.test14;public class RegexDemo1 {public static void main(String[] args) {//public boolean matche…

【ArcGIS微课1000例】0147:Geographic Imager6.2下载安装教程

文章目录 一、软件功能二、下载地址三、安装教程Geographic Imager地图工具使Adobe Photoshop空间图像可以快速高效地工作。它增加了导入,编辑,操作和导出地理空间图像的工具,例如航空和卫星图像。Geographic Imager Mac功能非常强大,拥有栅格数据输出、投影信息修改、基于…

cf每日刷题c++

目录 Square Year&#xff08;800&#xff09; Not Quite a Palindromic String&#xff08;900&#xff09; Down with Brackets&#xff08;900&#xff09; Square Year&#xff08;800&#xff09; https://codeforces.com/problemset/problem/2114/A #include <iost…

天拓四方工业互联网平台赋能:地铁电力配电室综合监控与无人巡检,实现效益与影响的双重显著提升

随着城市化进程的不断加快&#xff0c;城市轨道交通作为缓解交通压力、提升出行效率的重要方式&#xff0c;在全国各大城市中得到了迅猛发展。地铁电力配电室作为核心供电设施&#xff0c;其基础设施的安全性、稳定性和智能化水平也面临更高要求。 本文将围绕“工业物联网平台…

直线模组在手术机器人中有哪些技术挑战?

手术机器人在现代医疗领域发挥着越来越重要的作用&#xff0c;直线模组作为其关键部件&#xff0c;对手术机器人的性能有着至关重要的影响。然而&#xff0c;在手术机器人中使用直线模组面临着诸多技术挑战&#xff0c;具体如下&#xff1a; 1、‌高精度要求‌&#xff1a;手术…

shell脚本的两种循环及状态返回值的区别及对比

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权并注明出处。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 一、shell中的两种循环命令 1. 两种循环的区别 shell循环中有两种循环&#xff1a;break、continue。break和contin…

【CATIA的二次开发15】根对象Application涉及基础控制与进程管理相关方法

在CATIA VBA开发中,对根对象Application涉及撤销和重做事务管理相关方法进行详细总结,并且用不同形式展示出来。供大家后续开发全面了解Application对象的方法,以便在开发过程中快速查找和使用: 一、Application常用方法分类 1、基础控制与进程管理(3个方法) 方法名功能…

CNEX防爆连接器Exe型3芯4芯5芯

CNEX防爆连接器Exe型作为工业安全领域的关键组件&#xff0c;其3芯、4芯、5芯等多规格设计满足了复杂工况下的电气连接需求。这类产品严格遵循GB3836.1-2010和IEC60079标准&#xff0c;适用于石油、化工、煤矿等存在爆炸性气体环境的场所。本文将深入解析其技术特性、选型要点及…

分布式锁和数据库锁完成接口幂等性

1、分布式锁 唯一主键与乐观锁的本质是使用了数据库的锁&#xff0c;但由于数据库锁的性能不太好&#xff0c;所以我们可使用Redis、Zookeeper等中间件来实现分布式锁的功能&#xff0c;以Redis为例实现幂等&#xff1a;当用户通过浏览器发起请求&#xff0c;服务端接收到请求…

​黑森林实验室推出 FLUX.1Kontext:可通过文本和参考图像对图像进行多次修改

今天我们激动地推出FLUX.1 Kontext——这是一套生成流匹配模型&#xff0c;可让您生成和编辑图像。与现有文生图模型不同&#xff0c;FLUX.1 Kontext系列实现了情境化图像生成功能&#xff0c;支持同时用文本和图像作为提示输入&#xff0c;并能无缝提取修改视觉概念&#xff0…

在React框架中使用Braft Editor集成Table表格的详细教程

简介&#xff1a;Braft Editor是一款基于draft-js开发的React富文本编辑器&#xff0c;支持多媒体、自定义样式和扩展功能。其表格扩展模块允许用户插入、调整表格结构&#xff0c;适合需要数据展示的场景&#xff08;如CMS系统、报表工具&#xff09;。 1.安装依赖 yarn add…

经营分析会,财务该怎么做?

目录 一、业绩洞察&#xff1a;从「现象描述」到「因果分析」 1.分层拆解 2.关联验证 3.根因追溯 二、预算管理&#xff1a;从「刚性控制」到「动态平衡」 1.分类管控 2.滚动校准 3.价值评估 三、客户与市场&#xff1a;从「交易记录」到「价值评估」 1.价值分层 2.…

yum安装nginx后无法通过服务方式启动

背景 在linux系统下&#xff0c;通过yum方式安装nginx后 通过nginx命令 nginx 可以启动nginx 但是作为测试或者生产服务器&#xff0c;我们需要配置开机自启动&#xff0c;这时候需要用服务方式启动 yum安装后的nginx 已经默认生成了服务启动方式的 nginx.service文件 按…

kuboard自带ETCD存储满了处理方案

一、前言 当运行 ETCD 日志报 Erro: mvcc database space exceeded 时&#xff0c;说明 ETCD 存储不足了&#xff08;默认 ETCD 存储是 2G&#xff09;&#xff0c;配额会触发告警&#xff0c;然后 Etcd 系统将进入操作受限的维护模式。 通过下面命令可以查看 ETCD 存储使用情…

『uniapp』添加桌面长按快捷操作 shortcuts(详细图文注释)

目录 手机环境适配说明安卓效果图代码 iOS(暂未实测,没有水果开发者)总结 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 手机环境适配说明 个别手机系统可能需要进行特别的权限设置,否则会无法使用 桌面快捷方式: 已知的有…

【目标检测】【ICCV 2021】条件式DETR实现快速训练收敛

Conditional DETR for Fast Training Convergence 条件式DETR实现快速训练收敛 代码链接 论文链接 摘要 最近提出的DETR方法将Transformer编码器-解码器架构应用于目标检测领域&#xff0c;并取得了显著性能。本文针对其训练收敛速度慢这一关键问题&#xff0c;提出了一种条…

Java线程:线程池详解(ThreadPoolExecutor构造器七个参数、线程池处理Runnable/Callable任务)

认识线程池 什么是线程池&#xff1f; 线程池就是一个可以复用线程的技术 不使用线程池的问题 用户每发起一个请求&#xff0c;后台就需要创建一个新线程来处理&#xff0c;下次新任务来了肯定又要创建新线程处理的&#xff0c;而创建新线程的开销是很大的&#xff0c;并且请求…

华为OD机试真题——开放日活动/取出尽量少的球(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《开放…

day14 leetcode-hot100-25(链表4)

141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 1.哈希集合 思路 将节点一个一个加入HashSet&#xff0c;并用contains判断是否存在之前有存储过的节点&#xff0c;如果有便是环&#xff0c;如果没有便不是环。 具体代码 /*** Definition for singly-linked list.*…

低碳理念在道路工程中的应用-预制路面

一、引子 在上一篇文章里&#xff0c;给大家介绍了预制基层的应用&#xff0c;有人提出&#xff0c;既然基层能够预制&#xff0c;那么&#xff0c;道路面层能不能预制呢&#xff0c;有没有相关的研究成果和应用实例呢&#xff1f;答案是肯定的&#xff0c;在本篇文章中&#x…