简介Diabetes-Predictor 是一份面向数据科学初学者与医疗健康分析爱好者的机器学习实战资源围绕 Pima Indians 糖尿病数据集完整演示从数据预处理、探索性分析到建模评估的预测流程帮助读者理解如何用分类模型评估疾病风险。压缩包共 4 个文件约 322KB包含 1 个 ipynb 交互式笔记本、1 个 py 脚本、1 个 joblib 训练模型和 1 个 md 说明文档覆盖代码复现、脚本调用与模型加载等用途。目前已有 236 人学习下载。资源价值在于提供可直接运行的端到端案例笔记本中呈现缺失值处理、特征工程、多模型对比与交叉验证等关键环节py 脚本便于快速执行joblib 文件省去重新训练成本md 文档则梳理项目结构与思路适合作为课程作业、入门练手或医疗预测类项目的参考模板。1. 一个糖尿病预测项目为什么值得你花半小时跑一遍Diabetes-Predictor 这个名字听起来像医学课题实际上它是一份用 Jupyter Notebook 写成的二分类机器学习实战代码。数据集是经典的 Pima Indians Diabetes 结构8 个特征、1 个标签任务是根据血糖、血压、BMI 等指标判断是否患病。它适合两类人刚学完 sklearn 想找一个完整流程练手的新手以及需要快速搭一个基线模型再迭代的开发者。整个项目没有花哨的深度学习逻辑回归、随机森林、XGBoost 挨个上配合混淆矩阵和 ROC 曲线做评估。你拿到手就能在本地跑通改几行参数就能看到指标变化这种即时反馈对建立工程直觉特别有用。2. 项目结构与技术选型Notebook 里到底装了什么2.1 目录布局与文件职责拿到源码包第一件事是看目录。Diabetes-Predictor 的结构很典型没有过度工程化Diabetes-Predictor/ ├── data/ │ └── diabetes.csv # 原始数据集8特征1标签 ├── notebooks/ │ └── diabetes_predictor.ipynb # 主分析流程 ├── models/ │ └── best_model.pkl # 训练后持久化的模型 ├── requirements.txt # 依赖清单 └── README.mddata/放原始 CSVnotebooks/是核心工作区models/存训练好的模型文件。这种布局的好处是数据和代码分离你换一份同结构的 CSV 就能复用整个流程。常见做法是把特征工程和模型训练拆成两个 Notebook但这个项目合在一起对初学者更友好从上到下执行一遍就能看到完整链路。2.2 技术栈与依赖版本核心依赖就四个pandas做数据加载和清洗scikit-learn负责预处理、模型训练和评估matplotlibseaborn画图xgboost作为集成模型的补充。requirements.txt里通常锁定版本避免因为 sklearn 版本差异导致train_test_split的stratify参数行为不一致。# 建议用虚拟环境隔离避免和系统包冲突 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt这里有个细节如果你用的是 Apple Silicon 芯片xgboost 的安装可能需要额外指定pip install xgboost --no-binary :all:否则会报架构不匹配。这不是项目本身的问题是环境差异提前知道能省半小时排查。2.3 数据加载与探索性分析Notebook 的前几个 cell 做的是标准 EDA。先读数据再看分布最后检查缺失值。Pima 数据集有个坑很多字段用 0 表示缺失比如血糖为 0 在生理上不可能。项目里通常会把这类 0 值替换成 NaN 再填充。import pandas as pd import numpy as np # 加载数据列名按数据集惯例命名 columns [Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age, Outcome] df pd.read_csv(data/diabetes.csv, namescolumns) # 这些字段的 0 值在医学上无意义视为缺失 zero_as_missing [Glucose, BloodPressure, SkinThickness, Insulin, BMI] df[zero_as_missing] df[zero_as_missing].replace(0, np.nan) # 用中位数填充比均值更抗异常值 df.fillna(df.median(), inplaceTrue) print(df.describe())这段代码的关键在replace(0, np.nan)和fillna(median)。参数inplaceTrue表示原地修改省内存。中位数填充是常见做法因为血糖和胰岛素分布右偏均值会被极端值拉高。如果你换成均值模型召回率可能掉两三个百分点这是实际跑一遍就能观察到的差异。3. 核心模块拆解从特征工程到模型评估的完整链路3.1 特征标准化与数据划分原始特征的量纲差异很大Age最大 81DiabetesPedigreeFunction最大 2.42。逻辑回归和 KNN 对尺度敏感必须标准化。项目里用StandardScaler做 Z-score 归一化然后按 8:2 划分训练集和测试集。from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split X df.drop(Outcome, axis1) y df[Outcome] # 先划分再标准化避免数据泄露 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 注意测试集用 transform 而非 fit_transform这里最容易翻车的地方是数据泄露如果在划分前就对全量数据做fit_transform测试集的统计信息会渗入训练过程评估指标虚高。stratifyy保证训练集和测试集的标签比例一致对不平衡数据尤其重要。random_state42固定随机种子保证你每次跑的结果可复现。3.2 多模型对比与交叉验证项目不会只跑一个模型就下结论。Notebook 里通常定义一个模型字典循环训练并输出交叉验证分数from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score from xgboost import XGBClassifier models { LogisticRegression: LogisticRegression(max_iter1000), RandomForest: RandomForestClassifier(n_estimators100, random_state42), XGBoost: XGBClassifier(use_label_encoderFalse, eval_metriclogloss) } for name, model in models.items(): scores cross_val_score(model, X_train_scaled, y_train, cv5, scoringroc_auc) print(f{name}: AUC{scores.mean():.4f} (/- {scores.std():.4f}))cross_val_score的cv5表示 5 折交叉验证scoringroc_auc用 AUC 而非准确率因为糖尿病数据正负样本比例大约 65:35准确率有欺骗性。max_iter1000是给逻辑回归的迭代上限默认 100 在未标准化数据上经常不收敛。XGBoost 的use_label_encoderFalse是较新版本的参数老版本不需要报错时删掉即可。3.3 模型评估与可视化训练完不是看一个数字就结束。项目会输出混淆矩阵、分类报告和 ROC 曲线from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc import matplotlib.pyplot as plt best_model models[RandomForest].fit(X_train_scaled, y_train) y_pred best_model.predict(X_test_scaled) y_prob best_model.predict_proba(X_test_scaled)[:, 1] print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred)) fpr, tpr, _ roc_curve(y_test, y_prob) plt.plot(fpr, tpr, labelfAUC {auc(fpr, tpr):.3f}) plt.plot([0, 1], [0, 1], k--) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate) plt.legend() plt.show()predict_proba返回的是概率取第二列作为正类概率。混淆矩阵让你看到假阳性和假阴性各有多少——在医疗场景里假阴性漏诊比假阳性更严重所以召回率比精确率更值得关注。ROC 曲线的对角线是随机猜测的基线曲线越靠左上越好。这些图在 Notebook 里直接渲染改一个模型名字就能重新出图迭代成本极低。3.4 模型持久化与复用训练完的模型用joblib存到models/目录下次直接加载不用重新训练import joblib joblib.dump(best_model, models/best_model.pkl) joblib.dump(scaler, models/scaler.pkl) # 标准化器也要存推理时保持一致 # 加载时 loaded_model joblib.load(models/best_model.pkl) loaded_scaler joblib.load(models/scaler.pkl)注意标准化器必须和模型一起保存。很多人只存模型推理时忘了对新数据做同样的标准化结果预测全错。这是血泪经验别问我是怎么知道的。4. 避坑与常见问题跑不起来时先看这几条4.1 缺失值处理不当导致模型偏差现象模型准确率看着不错但混淆矩阵里假阴性特别多。原因直接用 0 值训练模型把“血糖为 0”当成一个有效特征学进去了。解决在 EDA 阶段就把生理上不可能的 0 值替换为 NaN再用中位数或 KNN 填充。检查方法是df[df[Glucose] 0].shape[0]如果大于 0 就说明没处理干净。4.2 标准化顺序错误引发数据泄露现象交叉验证分数很高但换一批新数据预测效果骤降。原因在train_test_split之前就做了fit_transform测试集信息泄露到训练过程。解决严格遵循“先划分、再 fit 训练集、最后 transform 测试集”的顺序。记住fit_transform只能出现在训练集上测试集永远只用transform。4.3 版本不兼容导致 XGBoost 报错现象XGBClassifier初始化时报TypeError: __init__() got an unexpected keyword argument use_label_encoder。原因xgboost 2.0 之后移除了这个参数。解决删掉use_label_encoderFalse只保留eval_metriclogloss。或者用pip install xgboost1.7.6降级到兼容版本。这类报错信息很明确顺着改就行不用慌。4.4 随机种子未固定导致结果不可复现现象每次重新运行 NotebookAUC 都在变没法对比模型优劣。原因train_test_split和模型初始化都没设random_state。解决在所有涉及随机性的地方统一加random_state42包括train_test_split、RandomForestClassifier、cross_val_score的cv参数用StratifiedKFold时也要设。固定种子后同一份代码跑一百遍结果都一样调参才有意义。4.5 Notebook 执行顺序混乱导致变量未定义现象单独运行某个 cell 报NameError: name X_train_scaled is not defined。原因跳过了前面的 cell或者改了代码后没按顺序重跑。解决改完代码后点Kernel - Restart Run All从头到尾执行一遍。Notebook 的隐式状态是双刃剑方便探索但容易埋雷。养成改完就全量重跑的习惯能避免很多玄学问题。5. 二次开发与改造思路从 Demo 到可用工具的几步5.1 特征工程升级当前项目只做了中位数填充和标准化。想提升效果可以加特征交叉比如Glucose * BMI作为新特征或者用PolynomialFeatures生成二次项。另一个方向是分箱把Age按 10 岁一段离散化有时能捕捉非线性关系。改完后用同一套交叉验证对比AUC 提升超过 0.01 才值得保留否则容易过拟合。5.2 模型调参与集成随机森林的n_estimators、max_depth、min_samples_split都可以用GridSearchCV搜。但别一上来就大网格先粗后细from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [50, 100, 200], max_depth: [None, 5, 10], min_samples_split: [2, 5] } grid GridSearchCV(RandomForestClassifier(random_state42), param_grid, cv5, scoringroc_auc, n_jobs-1) grid.fit(X_train_scaled, y_train) print(grid.best_params_, grid.best_score_)n_jobs-1用满所有 CPU 核心但注意内存占用。搜完把最优参数写回模型字典再跑一次评估。如果多个模型 AUC 接近可以用VotingClassifier做软投票集成通常比单模型稳。5.3 封装成可调用的预测函数Notebook 适合探索但真要给别人用得封装成函数或脚本def predict_diabetes(features: dict) - dict: 输入原始特征字典返回预测标签和概率 model joblib.load(models/best_model.pkl) scaler joblib.load(models/scaler.pkl) input_df pd.DataFrame([features]) input_scaled scaler.transform(input_df) prob model.predict_proba(input_scaled)[0, 1] return {prediction: int(prob 0.5), probability: round(prob, 4)}这个函数可以直接被 Flask 或 FastAPI 调用变成 HTTP 接口。注意输入特征的顺序必须和训练时一致否则标准化会错位。我一般会在函数里加一个assert list(features.keys()) expected_columns做校验防止调用方传错字段。5.4 验证改造效果的方法每次改完代码别只看一个 AUC 数字。固定测试集对比改造前后的混淆矩阵和分类报告重点看召回率和 F1 的变化。如果召回率提升但精确率下降要判断业务上哪个更重要。医疗筛查场景宁可误报也不能漏诊所以召回率优先。另外用cross_validate返回多个指标一次性看全貌from sklearn.model_selection import cross_validate scoring [accuracy, precision, recall, f1, roc_auc] results cross_validate(best_model, X_train_scaled, y_train, cv5, scoringscoring) for metric in scoring: print(f{metric}: {results[test_ metric].mean():.4f})从那以后我每次改完模型都强制走一遍“固定种子 → 全量重跑 → 多指标对比”的流程再也没出现过“改完反而更差但不知道差在哪”的情况。希望这份拆解能帮你少走点弯路把 Diabetes-Predictor 跑起来、改起来。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?