Python+XGBoost二分类实战:Pima糖尿病数据从跑通到调优
发布时间:2026/9/25 4:01:45来源:尧图网络
简介这份资源面向机器学习入门与进阶学习者聚焦用Python与XGBoost完成二分类任务帮助读者理解从数据预处理到模型评估的完整流程。压缩包共3个文件包含2个py脚本与1个csv数据集整体约13KB脚本分别承担XGBoost建模与决策树相关实现csv则提供可直接加载的样本数据便于快速跑通代码。资源围绕梯度提升决策树展开涉及缺失值处理、特征工程、训练验证测试集划分、n_estimators与learning_rate等参数配置以及准确率、召回率、F1与AUC-ROC等评估指标适合作为课程作业或项目练手的参考实现。目前已有1581人学习下载读者可借助现成脚本与数据复现二分类建模过程对照调整参数、观察模型表现并在此基础上迁移到垃圾邮件识别、疾病预测等实际场景逐步建立对XGBoost调参和过拟合控制的直观认识。1. 从一份 Pima 印第安人糖尿病数据说起Python XGBoost 二分类到底能跑出什么手上这份基于python与XGBoost实现二分类.rar解压后结构很朴素xgboost.py、tree.py、source目录外加一份pima indians.csv。没有花哨的工程封装也没有 Dockerfile 和 requirements 锁版本就是一份能直接读、直接改、直接跑的脚本级资源。它瞄准的是机器学习里最经典也最容易被讲虚的任务——二分类给定若干特征判断样本属于 0 还是 1。Pima 数据集正好是这类任务的入门标尺8 个数值型特征标签是是否患糖尿病样本量不到 800跑一次训练在普通笔记本上几秒钟就能出结果。这份资源的价值不在于算法有多新而在于它把「数据读进来 → 特征处理 → 训练 → 评估」这条链路用两个脚本讲清楚了。xgboost.py负责主流程tree.py大概率是决策树对照实现source目录里可能放着数据加载或工具函数。适合谁适合刚学完 Python 基础语法、想找一个能跑通的二分类项目练手的人也适合已经会用 sklearn 但没认真调过 XGBoost 参数、想看看原生接口怎么写的从业者。下面按「先跑通、再调优、最后避坑」的顺序拆。2. 把环境搭起来并跑通第一个 XGBoost 二分类脚本2.1 依赖安装与版本选择这份资源没有附带 requirements.txt所以依赖得自己装。XGBoost 的 Python 包在 1.6 之后对 sklearn 接口做了不少调整如果你直接pip install xgboost拿到最新版脚本里如果用的是旧版fit参数名可能会报unexpected keyword argument。常见做法是锁一个稳定版本比如 1.7.6 或 2.0.x先保证能跑通再谈升级。# 建议先建虚拟环境避免污染全局 python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate # 安装核心依赖锁一个经过验证的版本 pip install xgboost1.7.6 pip install pandas scikit-learn numpy逻辑说明虚拟环境是为了隔离XGBoost 依赖 numpy 和 scipypandas 用来读 csvscikit-learn 用来做数据集划分和评估指标。参数上xgboost1.7.6是一个在 Windows 和 Linux 上都比较稳的版本原生接口和 sklearn 接口都完整。如果你用的是 Python 3.11 以上建议直接上 2.0.x否则 1.7.6 的 wheel 可能找不到。2.2 读数据与看数据先别急着训练拿到pima indians.csv第一件事不是model.fit而是把数据形状、缺失值、标签分布看清楚。Pima 数据集有个特点部分特征的 0 值其实是缺失值比如血糖、血压、皮褶厚度生理上不可能是 0。如果直接当数值喂进去模型会学到错误的分布。import pandas as pd import numpy as np # 读数据注意这份 csv 可能没有表头先看前几行 df pd.read_csv(pima indians.csv) print(df.shape) print(df.head()) print(df.isnull().sum()) print(df[Outcome].value_counts() if Outcome in df.columns else df.iloc[:, -1].value_counts())逻辑说明shape看样本量和特征数Pima 一般是 768 行 9 列8 特征 1 标签。isnull().sum()看显式缺失但 Pima 的坑在于隐式缺失——0 值。value_counts()看标签是否均衡Pima 里阳性样本大约占 35%属于轻度不均衡评估时不能只看准确率。参数上如果 csv 没有表头需要加headerNone并手动指定列名否则第一行数据会被当成列名吃掉。2.3 用 XGBoost 原生接口跑通训练xgboost.py里大概率用的是原生DMatrix接口这也是 XGBoost 区别于 sklearn 的地方它有自己的数据容器能更细地控制权重和缺失值处理。下面这段是常见写法和资源里的脚本结构基本一致。import xgboost as xgb from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, roc_auc_score # 假设 df 已经读入最后一列是标签 X df.iloc[:, :-1].values y df.iloc[:, -1].values # 把 0 值当缺失处理XGBoost 原生支持缺失值不用填充 X[X 0] np.nan X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) # 构建 DMatrix缺失值会被自动处理 dtrain xgb.DMatrix(X_train, labely_train) dtest xgb.DMatrix(X_test, labely_test) # 二分类核心参数 params { objective: binary:logistic, # 二分类逻辑回归目标 eval_metric: auc, # 评估指标用 AUC max_depth: 4, # 树深Pima 这种小数据别超过 6 eta: 0.1, # 学习率等价于 learning_rate subsample: 0.8, # 行采样防过拟合 colsample_bytree: 0.8, # 列采样 seed: 42 } num_round 200 bst xgb.train( params, dtrain, num_round, evals[(dtest, test)], early_stopping_rounds20, verbose_eval50 ) # 预测 pred_prob bst.predict(dtest, iteration_range(0, bst.best_iteration 1)) pred_label (pred_prob 0.5).astype(int) print(AUC:, roc_auc_score(y_test, pred_prob)) print(Accuracy:, accuracy_score(y_test, pred_label))逻辑说明objectivebinary:logistic是二分类的标准目标函数输出概率。eval_metricauc比 accuracy 更适合不均衡数据。max_depth4是 Pima 这种小数据集的保守选择树太深必过拟合。eta0.1配合num_round200和early_stopping_rounds20是常见的「小步慢跑 早停」组合。X[X 0] np.nan这一步是关键XGBoost 会把 NaN 自动分到最优分支比手动填均值更稳。iteration_range是为了只用早停后的最佳轮数做预测避免用满 200 轮导致过拟合。3. 参数怎么调从默认值到能打的二分类模型3.1 三个必须理解的参数max_depth、eta、n_estimatorsXGBoost 参数多但二分类小数据集上真正影响结果的就那几个。max_depth控制单棵树复杂度Pima 上 3 到 5 之间最稳超过 6 训练集 AUC 能到 0.99 但测试集掉到 0.75 以下这是血泪经验。eta是学习率越小需要越多轮但泛化通常更好0.05 到 0.1 是常用区间。n_estimators原生接口里是num_round配合早停用不要手动定死。# 用 sklearn 接口做网格搜索比手写循环省事 from xgboost import XGBClassifier from sklearn.model_selection import GridSearchCV clf XGBClassifier( objectivebinary:logistic, eval_metricauc, use_label_encoderFalse, random_state42 ) param_grid { max_depth: [3, 4, 5], learning_rate: [0.05, 0.1, 0.2], n_estimators: [100, 200, 300], subsample: [0.7, 0.8, 1.0] } grid GridSearchCV(clf, param_grid, cv5, scoringroc_auc, n_jobs-1) grid.fit(X_train, y_train) print(grid.best_params_) print(grid.best_score_)逻辑说明GridSearchCV用 5 折交叉验证scoringroc_auc保证选出的参数对不均衡数据友好。n_jobs-1用满 CPU。注意 sklearn 接口里use_label_encoderFalse在新版里已经默认但旧版不加会警告。参数组合 3×3×3×381 组Pima 数据量小几分钟能跑完。如果资源里的tree.py是单棵决策树对照可以把它和 XGBoost 的 AUC 放一起比通常 XGBoost 能高出 5 到 8 个百分点。3.2 特征重要性与tree.py的对照价值tree.py这个文件值得单独看。如果它是用 sklearn 的DecisionTreeClassifier做基线那它的意义是给你一个「下限」单棵树在 Pima 上 AUC 大概 0.68 到 0.72XGBoost 调好后能到 0.82 到 0.85。差距来自 boosting 的残差迭代和正则化。另外XGBoost 训练完可以直接画特征重要性Pima 里Glucose、BMI、Age通常排前三这和医学常识一致能帮你判断模型有没有学歪。import matplotlib.pyplot as plt from xgboost import plot_importance plot_importance(bst, max_num_features8) plt.show() # 或者直接打印分数 score bst.get_score(importance_typegain) for k, v in sorted(score.items(), keylambda x: -x[1]): print(k, round(v, 2))逻辑说明importance_typegain比默认的weight更有参考价值它衡量特征在分裂时带来的平均增益。如果发现某个无关特征排很高比如SkinThickness这种缺失严重的列说明缺失值处理可能有问题需要回头检查X[X 0] np.nan有没有漏掉某些列。3.3 评估不能只看准确率Pima 阳性样本少如果模型全预测为阴性准确率也有 65%但 AUC 只有 0.5。所以评估必须看 AUC、召回率和 F1。资源里如果只打印了 accuracy建议自己补上混淆矩阵。from sklearn.metrics import classification_report, confusion_matrix print(confusion_matrix(y_test, pred_label)) print(classification_report(y_test, pred_label, digits3))逻辑说明classification_report会给出精确率、召回率、F1。医疗场景下召回率更重要漏诊比误诊代价大。如果召回率低于 0.6可以调scale_pos_weight参数把它设成负样本数除以正样本数让模型更关注正类。4. 避坑与排查这份资源跑不起来时先看这几条4.1 现象DMatrix报错label must be in [0,1]原因Pima 标签列如果是 1 和 2 而不是 0 和 1binary:logistic会直接拒绝。有些 csv 版本会把标签写成 1/2。解决读入后先y y - 1或者用LabelEncoder转成 0/1再构建 DMatrix。4.2 现象训练集 AUC 0.99测试集 0.70原因树太深或轮数太多模型把训练集噪声也学进去了。Pima 只有 768 条max_depth8以上必翻车。解决把max_depth降到 3 到 5加subsample0.8、colsample_bytree0.8开早停。如果还不行加lambda1L2 正则和alpha0.1L1 正则。4.3 现象pip install xgboost后 import 报libgomp.so.1找不到原因Linux 上 XGBoost 依赖 OpenMP 运行时最小化安装的系统缺这个库。解决apt-get install libgomp1或yum install libgomp。Windows 上一般不会遇到macOS 用 conda 装更省事。4.4 现象pima indians.csv读进来列数不对原因这份 csv 可能没有表头pd.read_csv默认把第一行当列名导致少一行数据且列名变成数值。解决先pd.read_csv(pima indians.csv, headerNone)看形状如果是 768 行 9 列就手动加列名df.columns [Pregnancies,Glucose,BloodPressure,SkinThickness,Insulin,BMI,DiabetesPedigreeFunction,Age,Outcome]。4.5 现象tree.py和xgboost.py结果对不上原因两个脚本可能用了不同的数据划分随机种子或者一个做了标准化一个没做。XGBoost 对特征尺度不敏感但决策树如果用了max_depth默认值也会过拟合。解决统一random_state统一缺失值处理逻辑再对比。如果tree.py是教学用的手写树那它和 XGBoost 的差距本来就是预期内的不用强行对齐。5. 进阶技巧把这份脚本改成能复用的二分类模板跑通不是终点。这份资源最大的问题是脚本级写法换一份数据就得改一堆路径和列名。我一般会把它重构成一个最小可复用模板数据加载、缺失值处理、训练、评估四段分开参数走配置文件。下面这个train_binary.py是我从类似项目里沉淀下来的骨架你可以直接套。import argparse import pandas as pd import numpy as np import xgboost as xgb from sklearn.model_selection import train_test_split from sklearn.metrics import roc_auc_score, classification_report def load_data(path, label_col, zero_as_nanTrue): df pd.read_csv(path) X df.drop(columns[label_col]).values y df[label_col].values if zero_as_nan: X[X 0] np.nan return X, y def train(X, y, params, num_round300, early_stop30): X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) dtrain xgb.DMatrix(X_train, labely_train) dtest xgb.DMatrix(X_test, labely_test) bst xgb.train( params, dtrain, num_round, evals[(dtest, test)], early_stopping_roundsearly_stop, verbose_evalFalse ) return bst, X_test, y_test if __name__ __main__: parser argparse.ArgumentParser() parser.add_argument(--data, defaultpima indians.csv) parser.add_argument(--label, defaultOutcome) args parser.parse_args() X, y load_data(args.data, args.label) params { objective: binary:logistic, eval_metric: auc, max_depth: 4, eta: 0.1, subsample: 0.8, colsample_bytree: 0.8, seed: 42 } bst, X_test, y_test train(X, y, params) prob bst.predict(xgb.DMatrix(X_test), iteration_range(0, bst.best_iteration 1)) print(AUC:, round(roc_auc_score(y_test, prob), 4)) print(classification_report(y_test, (prob 0.5).astype(int), digits3))逻辑说明argparse让数据路径和标签列名可配换数据集不用改代码。load_data里把 0 转 NaN 做成开关因为不是所有数据集都适用。train函数返回最佳模型和测试集方便后续做 SHAP 解释或阈值调整。参数上num_round300配合early_stop30比固定 200 轮更稳早停会自动找到最佳迭代次数。验证方法很简单换一份 UCI 的二分类数据比如breast-cancer-wisconsin把--data和--label一换如果 AUC 还能在 0.95 以上说明模板是通的。如果掉到 0.8 以下先检查缺失值处理是不是把有效 0 值误杀了。还有一个技巧是阈值调优。默认 0.5 不一定最优尤其是医疗场景。可以画 ROC 曲线找约登指数最大的点from sklearn.metrics import roc_curve fpr, tpr, thresholds roc_curve(y_test, prob) youden tpr - fpr best_threshold thresholds[np.argmax(youden)] print(Best threshold:, round(best_threshold, 3))逻辑说明约登指数最大化真正率减假正率适合正类召回重要的场景。Pima 上最佳阈值常在 0.35 到 0.45 之间比 0.5 能多抓 5% 到 10% 的阳性样本。从那以后我每次拿到这种脚本级资源都强制先跑一遍原始脚本记录基线 AUC再动任何参数。不然调了半天连初始状态是什么样都说不清出了问题连后悔药都没得吃。希望这份拆解能帮你把这份python XGBoost二分类资源真正用起来而不是解压完就放在硬盘里吃灰。本文还有配套的精品资源点击获取
网站建设高端定制企业官网