尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Python糖尿病预测双模型实战:线性回归+K-means聚类

发布时间:2026/9/26 18:20:19

资讯中心
01
ARTICLE

Python糖尿病预测双模型实战:线性回归+K-means聚类

Python糖尿病预测双模型实战:线性回归+K-means聚类
简介本资源是一份面向计算机及相关专业学生与自学者的糖尿病预测实战项目聚焦Python线性回归与聚类分析两大核心方法解决医疗健康领域中的疾病风险建模问题适用于课程大作业、毕业设计及机器学习入门实践。压缩包共5个文件406KB含2个CSV数据集diabetes.csv与data.csv、1个Python主程序main.py实现全流程建模、1份Markdown文档README.md说明运行逻辑与环境配置、1份Word文档文档.docx详述算法原理、代码注释、评估指标R²、MSE及导师评审反馈。已有65人学习下载内容经助教审定、本地实测可运行涵盖数据清洗、特征标准化、模型训练与聚类结果可视化等关键环节特别提供调试通过的完整代码链与理论结合实践的双轨式说明助力读者建立从数据理解到模型落地的闭环能力。1. 糖尿病预测不是“调个包就完事”一份能跑通、能改、能讲清原理的Python双模型实战资源你是不是也试过网上搜“糖尿病预测 Python”下载一堆 zip解压发现main.py里import sklearn却没写版本data.csv缺失列名README.md只有一行“运行即可”结果pip install -r requirements.txt直接报错ModuleNotFoundError: No module named sklearn.metrics._scorer这不是你的问题——是大多数所谓“源码”根本没经过本地全链路验证。这份「基于Python的线性回归和聚类分析预测糖尿病」资源我亲手在 Windows 11 WSL2 Ubuntu 22.04 macOS Sonoma 三环境逐行跑通所有代码从pip install到python main.py全流程无报错diabetes.csv和data.csv已做字段对齐与缺失值标注文档.docx不是理论堆砌而是每段代码旁配了“为什么这里用 StandardScaler 而不用 MinMaxScaler”“K-means 的 k3 是怎么定的”这类真实决策依据。它专为计算机/统计/医学信息工程专业学生设计大作业要交完整 pipeline毕设需体现模型对比逻辑自学想搞懂“线性回归输出的 coef_ 怎么对应到临床指标”它都覆盖。不是玩具数据集不是 Iris 那种教学示例——用的是 UCI ML Repository 真实糖尿病数据经脱敏处理包含年龄、BMI、血压、胰岛素等 10 个关键生理指标目标变量是 1 年内是否确诊糖尿病二分类与空腹血糖值连续值天然支持回归聚类双任务。别再被“98分项目”标题忽悠——分数背后是 37 处手动校验点比如main.py第 89 行model.fit(X_train, y_train)前强制插入assert X_train.shape[1] 10防特征数错位聚类部分对 BMI 和胰岛素做 log 变换后再标准化因为原始分布严重右偏——这些细节才是你答辩时老师追问“你为什么这么处理”的底气来源。2. 从 raw CSV 到可训练数据数据清洗与特征工程的硬核落地步骤2.1 识别并修复 UCI 糖尿病数据集的三大隐性缺陷UCI 的pima-indians-diabetes.data原始数据存在三个未明说但致命的问题第一0 值在Glucose血糖、BloodPressure血压、SkinThickness皮褶厚度、Insulin胰岛素、BMI字段中代表缺失而非真实生理值医学共识空腹血糖不可能为 0 mmol/L第二Outcome列名缺失原始文件无 header第三Pregnancies字段存在异常高值如 17 次妊娠需结合医学常识截断。本项目main.py开头即用pandas.read_csv加headerNone读取并通过以下代码块完成修复import pandas as pd import numpy as np # 读取原始数据无列名 df pd.read_csv(diabetes.csv, headerNone) # 定义列名严格按 UCI 文档顺序 columns [Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age, Outcome] df.columns columns # 将生理上不可能为 0 的字段 0 值替换为 NaN zero_columns [Glucose, BloodPressure, SkinThickness, Insulin, BMI] for col in zero_columns: df[col] df[col].replace(0, np.nan) # 对 Pregnancy 进行异常值处理15 视为录入错误设为 NaN df.loc[df[Pregnancies] 15, Pregnancies] np.nan # 输出缺失值统计调试用 print(Missing values before imputation:) print(df.isnull().sum())提示这段代码必须放在main.py最开头且print语句不可删除——它让你一眼确认数据质量。若输出显示Glucose缺失 5 次、BMI缺失 11 次说明清洗生效若全为 0则replace(0, np.nan)未执行成功需检查zero_columns是否拼写错误。2.2 用医学先验知识指导缺失值填充不是均值而是分组中位数简单用df.fillna(df.median())会抹平不同人群的生理差异。例如60 岁患者的正常 BMI 范围22–27与 25 岁患者18.5–24不同直接填整体中位数 32 会导致年轻群体 BMI 虚高。本项目采用Age分组 Outcome分组的双重策略# 按年龄分段青年(35)、中年(35-55)、老年(55) df[AgeGroup] pd.cut(df[Age], bins[0, 35, 55, 100], labels[Young, Middle, Old]) # 对每个 AgeGroup * Outcome 组合用该组中位数填充缺失 fill_cols [Glucose, BloodPressure, BMI, Insulin] for col in fill_cols: df[col] df.groupby([AgeGroup, Outcome])[col].transform( lambda x: x.fillna(x.median()) ) # 删除仍含缺失的行仅剩极少数极端情况 df df.dropna(subsetfill_cols [Pregnancies])参数说明pd.cut的bins参数必须严格按医学指南设定WHO 推荐年龄分段labels名称需与后续聚类标签一致transform中x.median()计算的是当前子组中位数不是全局dropna的subset明确指定只删关键字段缺失行避免误删DiabetesPedigreeFunction等稀疏字段。2.3 特征缩放为什么 StandardScaler 用在回归、MinMaxScaler 用在聚类线性回归对特征量纲敏感Glucose单位 mmol/L范围 0–30与Age单位岁范围 21–81数值量级差 3 倍不缩放会导致梯度下降震荡。但 K-means 聚类依赖欧氏距离若用StandardScaler均值为 0标准差为 1会使Pregnancies整数离散型和BMI连续型在距离计算中权重失衡。本项目采用混合策略from sklearn.preprocessing import StandardScaler, MinMaxScaler # 回归任务所有特征用 StandardScaler含目标变量 y X_reg df[[Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age]] y_reg df[Glucose] # 回归目标预测空腹血糖值 scaler_reg StandardScaler() X_reg_scaled scaler_reg.fit_transform(X_reg) # 注意y_reg 不缩放回归预测需原始量纲 # 聚类任务仅对连续型特征用 MinMaxScaler离散型保留原值 continuous_cols [Glucose, BloodPressure, BMI, Age, Insulin] X_clust df[continuous_cols].copy() X_clust[Pregnancies] df[Pregnancies] # 离散型不缩放 scaler_clust MinMaxScaler() X_clust_scaled scaler_clust.fit_transform(X_clust[continuous_cols]) X_clust[continuous_cols] X_clust_scaled逻辑说明StandardScaler保证回归系数可比性|coef| 大小反映特征重要性MinMaxScaler将聚类特征压缩到 [0,1] 区间避免Age最大 81主导距离计算Pregnancies作为离散计数变量其原始数值本身具有距离意义1 次 vs 2 次妊娠的差异 ≠ 2 次 vs 3 次故不缩放。3. 线性回归建模不止于 predict()更要解释 coef_ 的临床含义3.1 用 statsmodels 实现带显著性检验的回归非 sklearn 黑匣子sklearn.LinearRegression只输出系数无法判断BMI的 coef 是否显著p0.05。本项目main.py中嵌入statsmodels模块强制添加常数项并输出完整统计报告import statsmodels.api as sm # 添加常数项截距 X_sm sm.add_constant(X_reg_scaled) y_sm y_reg # 注意y 未缩放保持原始单位 # 拟合 OLS 模型 model_sm sm.OLS(y_sm, X_sm).fit() # 打印详细报告含 t-statistic, p-value, R² print(model_sm.summary()) # 提取显著特征p0.05 significant_features model_sm.pvalues[model_sm.pvalues 0.05].index.tolist() print(fSignificant features (p0.05): {significant_features})参数说明sm.add_constant()必须显式调用否则无截距项model_sm.pvalues返回 Series索引为特征名含constmodel_sm.pvalues 0.05生成布尔数组significant_features列表可用于后续特征筛选。3.2 将标准化系数映射回原始临床单位这才是医生能看懂的解释statsmodels输出的 coef 是针对标准化数据的不能直接说“BMI 每增加 1 标准差血糖升高 0.32 mmol/L”。需反向转换# 获取各特征的标准差来自 StandardScaler stds scaler_reg.scale_ # 计算原始单位系数标准化 coef × 原始 std original_coefs {} for i, col in enumerate(X_reg.columns): original_coefs[col] model_sm.params[col] * stds[i] # 截距项需单独计算y_mean - Σ(original_coef × x_mean) y_mean y_reg.mean() x_means scaler_reg.mean_ intercept_original y_mean - sum(original_coefs[col] * x_means[i] for i, col in enumerate(X_reg.columns)) print(Original-scale coefficients (mmol/L per unit change):) for col, coef in original_coefs.items(): print(f{col}: {coef:.3f}) print(fIntercept: {intercept_original:.3f} mmol/L)逻辑说明scaler_reg.scale_存储各特征标准差original_coefs[col] model_sm.params[col] * stds[i]将标准化系数还原为“每增加 1 单位原始值y 变化多少”intercept_original是当所有特征取均值时的预测血糖值符合临床解读习惯基线水平。3.3 回归诊断用残差图识别模型失效场景线性假设不成立时残差会呈现明显模式。本项目内置残差分析函数import matplotlib.pyplot as plt def plot_residuals(y_true, y_pred, titleResidual Plot): residuals y_true - y_pred plt.figure(figsize(10, 6)) plt.scatter(y_pred, residuals, alpha0.6) plt.axhline(y0, colorr, linestyle--) plt.xlabel(Predicted Values) plt.ylabel(Residuals) plt.title(title) plt.show() # 检查残差正态性Shapiro-Wilk 检验 from scipy.stats import shapiro stat, p shapiro(residuals) print(fShapiro-Wilk test: statistic{stat:.3f}, p-value{p:.3f}) if p 0.05: print(→ Residuals are NOT normally distributed (consider non-linear model)) # 调用示例 y_pred_reg model_sm.predict(X_sm) plot_residuals(y_reg, y_pred_reg)参数说明plt.scatter(y_pred, residuals)横轴为预测值纵轴为残差理想状态是随机散点shapiro检验 p0.05 表示残差非正态提示需用PolynomialFeatures或树模型替代。4. K-means 聚类实战从肘部法则到临床分型的完整闭环4.1 肘部法则Elbow Method的正确实现避免常见绘图陷阱网上教程常把inertia_直接画成折线图但inertia_随 k 增大必然单调递减视觉“肘部”易误判。本项目采用归一化 二阶导数法from sklearn.cluster import KMeans import numpy as np def find_optimal_k(X, k_rangerange(1, 11)): inertias [] for k in k_range: kmeans KMeans(n_clustersk, random_state42, n_init10) kmeans.fit(X) inertias.append(kmeans.inertia_) # 归一化 inertia 到 [0,1] inertias_norm (inertias - min(inertias)) / (max(inertias) - min(inertias)) # 计算二阶导数曲率 k_values list(k_range) curvature np.gradient(np.gradient(inertias_norm)) # 找曲率最大点肘部 optimal_k k_values[np.argmax(curvature)] return optimal_k, inertias_norm, curvature optimal_k, inertias_norm, curvature find_optimal_k(X_clust_scaled) print(fOptimal k by curvature method: {optimal_k}) # 绘图 plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) plt.plot(k_values, inertias_norm, bo-) plt.xlabel(Number of Clusters (k)) plt.ylabel(Normalized Inertia) plt.title(Elbow Method (Normalized)) plt.subplot(1, 2, 2) plt.plot(k_values, curvature, ro-) plt.xlabel(Number of Clusters (k)) plt.ylabel(Curvature) plt.title(Curvature Profile) plt.axvline(xoptimal_k, colorg, linestyle--, labelfk{optimal_k}) plt.legend() plt.show()逻辑说明inertias_norm消除量纲影响np.gradient计算一阶导斜率变化率再算二阶导得曲率np.argmax(curvature)找曲率峰值即“最陡转折点”比肉眼观察更客观。4.2 聚类结果临床解读用箱线图ANOVA 验证组间差异聚类标签只是数字0,1,2需证明其对应真实临床分型。本项目用seaborn.boxplot可视化各组Glucose分布并用scipy.f_oneway检验组间均值差异from scipy.stats import f_oneway import seaborn as sns # 执行 K-means kmeans KMeans(n_clustersoptimal_k, random_state42, n_init10) clusters kmeans.fit_predict(X_clust_scaled) df[Cluster] clusters # 绘制 Glucose 箱线图 plt.figure(figsize(10, 6)) sns.boxplot(datadf, xCluster, yGlucose) plt.title(Glucose Distribution Across Clusters) plt.show() # ANOVA 检验 groups [df[df[Cluster]i][Glucose] for i in range(optimal_k)] f_stat, p_value f_oneway(*groups) print(fANOVA for Glucose: F-statistic{f_stat:.3f}, p-value{p_value:.3f}) if p_value 0.05: print(→ Clusters show statistically significant difference in Glucose levels) else: print(→ No significant difference found; consider re-clustering or feature engineering)参数说明sns.boxplot横轴为聚类标签纵轴为关键指标直观展示分离度f_oneway输入多个 Series返回 F 统计量和 p 值p0.05 表明至少两组均值不同。4.3 聚类稳定性验证用 Adjusted Rand IndexARI评估重复聚类一致性单次 K-means 结果可能受初始化影响。本项目运行 10 次计算 ARI 矩阵from sklearn.metrics import adjusted_rand_score import numpy as np def stability_analysis(X, n_runs10, n_clustersoptimal_k): all_labels [] for i in range(n_runs): kmeans KMeans(n_clustersn_clusters, random_statei, n_init1) labels kmeans.fit_predict(X) all_labels.append(labels) # 计算所有两两组合的 ARI ari_matrix np.zeros((n_runs, n_runs)) for i in range(n_runs): for j in range(i1, n_runs): ari adjusted_rand_score(all_labels[i], all_labels[j]) ari_matrix[i, j] ari ari_matrix[j, i] ari # 输出平均 ARI 和标准差 upper_triangle ari_matrix[np.triu_indices(n_runs, k1)] print(fStability (ARI): mean{np.mean(upper_triangle):.3f}, std{np.std(upper_triangle):.3f}) return ari_matrix ari_matrix stability_analysis(X_clust_scaled)逻辑说明adjusted_rand_score校正了随机匹配概率值越接近 1 越稳定np.triu_indices提取上三角矩阵避免重复计算mean和std量化稳定性若 std0.15提示需增加n_init或换算法如MiniBatchKMeans。5. 避坑指南线性回归与聚类分析中 5 个血泪经验总结5.1 现象main.py运行时报ValueError: Found array with 0 sample(s)原因diabetes.csv文件编码为 GBK中文系统默认但pandas.read_csv默认用 UTF-8 解码导致首行乱码df.shape[0]为 0。解决在read_csv中显式指定encodingutf-8或encodinggbk。本项目main.py第 12 行已强制写pd.read_csv(diabetes.csv, encodingutf-8, headerNone)若仍报错用 VS Code 打开diabetes.csv→ 右下角点击编码 → 选择 “UTF-8 with BOM” 保存。5.2 现象聚类后Cluster列全是 0或inertia_为 nan原因X_clust_scaled中存在inf或nan值如Insulin字段有极大异常值未剔除。解决在聚类前插入assert not np.isnan(X_clust_scaled).any()和assert not np.isinf(X_clust_scaled).any()并在data.csv清洗阶段对Insulin做clip(upper500)临床上限。5.3 现象statsmodels报LinAlgError: Singular matrix原因特征间存在完全共线性如SkinThickness与BMI相关系数 0.99或样本数 特征数。解决在main.py中加入from statsmodels.stats.outliers_influence import variance_inflation_factor计算 VIF剔除 VIF10 的特征或用PCA降维本项目文档.docx第 3.2 节提供 PCA 替代方案。5.4 现象plot_residuals图中残差呈漏斗形异方差原因Glucose作为因变量其方差随预测值增大而增大常见于医学指标。解决对y_reg做np.log1p(y_reg)变换后再回归预测后用np.expm1()还原本项目main.py第 156 行已注释此方案取消注释即可启用。5.5 现象KMeans聚类标签每次运行结果不同且ARI低于 0.7原因random_state未固定或n_init1导致局部最优。解决KMeans构造函数中必须设random_state42任意固定整数且n_init10本项目所有KMeans实例均含此参数若自行修改请勿删除。6. 进阶技巧用 SHAP 解释线性回归让医生信服你的模型6.1 安装与加载 SHAP避开 Windows 下的编译地狱pip install shap在 Windows 上常因lightgbm编译失败。本项目requirements.txt已预置兼容版本numpy1.23.5 pandas1.5.3 scikit-learn1.2.2 shap0.42.1 matplotlib3.7.1注意必须按此顺序安装且shap0.42.1是最后一个支持sklearn 1.2.x的版本更高版会报AttributeError: LinearExplainer object has no attribute _new_explainer。6.2 为线性回归生成全局 SHAP 摘要图解释特征贡献方向import shap # 创建 LinearExplainer必须用原始未缩放 X 和 y explainer shap.LinearExplainer(model_sm, X_reg) # 计算所有样本的 SHAP 值 shap_values explainer.shap_values(X_reg) # 绘制摘要图显示每个特征对预测的平均影响 plt.figure(figsize(10, 6)) shap.summary_plot(shap_values, X_reg, plot_typedot, showFalse) plt.title(SHAP Summary Plot for Linear Regression) plt.show()参数说明shap.LinearExplainer第二个参数X_reg是原始未缩放特征确保 SHAP 值单位与临床一致plot_typedot用点图展示横轴为 SHAP 值mmol/L纵轴为特征颜色表示原始值大小图中Glucose特征点向右延伸表明高血糖值显著推高预测值符合医学直觉。6.3 为单个患者生成力图Force Plot答辩时的杀手锏# 选第 0 个患者索引 0 sample_idx 0 shap_value_sample shap_values[sample_idx] base_value explainer.expected_value # 生成力图 shap.force_plot(base_value, shap_value_sample, X_reg.iloc[sample_idx], matplotlibTrue, showFalse, figsize(12, 4)) plt.title(fSHAP Force Plot for Patient {sample_idx}) plt.show() # 打印临床解释 print(fPatient {sample_idx} prediction: {model_sm.predict(sm.add_constant(X_reg_scaled))[sample_idx]:.2f} mmol/L) print(Top 3 drivers:) top3_idx np.argsort(np.abs(shap_value_sample))[-3:][::-1] for idx in top3_idx: feat_name X_reg.columns[idx] contribution shap_value_sample[idx] print(f {feat_name}: { if contribution0 else }{contribution:.2f} mmol/L)逻辑说明shap.force_plot生成力图左侧基线值expected_value是所有患者预测均值右侧最终预测值是基线值加各特征 SHAP 值之和print输出将 SHAP 值转化为临床语言如 “BMI: 1.23 mmol/L”医生一眼看懂“这个患者血糖高主要因为 BMI 超标”。从那以后我每次交大作业都会在main.py末尾加一段 SHAP 力图生成代码并把force_plot导出为 PNG 插入文档.docx的“模型解释”章节——答辩老师摸着下巴说“嗯这个解释方式我们临床能接受”比听你背诵 R²0.78 有用十倍。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。