12种机器学习模型+交叉验证+Pipeline+网格搜索调参:胰腺癌生存状态预测

发布时间:2026/7/11 17:11:27

12种机器学习模型+交叉验证+Pipeline+网格搜索调参:胰腺癌生存状态预测
12 种机器学习模型 交叉验证 Pipeline 网格搜索调参用 Python 做胰腺癌生存状态预测这篇文章用一份 50000 行的胰腺癌预测数据集从数据理解、EDA 可视化、预处理 Pipeline、多模型横向比较、GridSearchCV 超参数调优、交叉验证到特征重要性完整走一遍医学表格数据的机器学习流程。本文不是医学诊断建议而是一次以第一性原理和费曼学习法来拆解机器学习建模的实战教程。本期摘要第一性原理预测不是“套模型”而是把病人的结构化信息 X 映射到生存状态 y。每一步都要服务于这个映射清洗字段、统一尺度、编码类别、控制数据泄漏、用交叉验证估计泛化能力。数据集50000 条样本24 个字段目标变量是Survival_Status。其中 0 类有 43578 条1 类有 6422 条类别明显不均衡。核心流程先 EDA 看数据脾气再用ColumnTransformer Pipeline把数值标准化、类别 One-Hot 和模型训练绑成一条可复现流水线。模型比较随机森林、梯度提升、SVM、KNN、决策树、朴素贝叶斯、逻辑回归、XGBoost、LightGBM、CatBoost、LDA、QDA 共 12 种模型横向比较。关键提醒很多模型 Accuracy 都在 0.873 左右看似不错但多数类基线本身就是 43578 / 50000 0.87156。医学预测里只看 Accuracy 很危险必须继续看 Recall、Precision、F1、ROC-AUC、PR-AUC 和混淆矩阵。引子把模型讲给没学过机器学习的人听费曼学习法要求我们把复杂概念讲到像日常语言一样直观。这里可以这样理解每个病人是一张表格化病历卡里面有年龄、性别、分期、症状、治疗方式、生活方式和医疗可及性等信息。模型要做的事是看过很多历史病历卡之后学习“哪些组合更可能对应某个生存状态”。第一性原理再往下拆机器学习不神秘它只做三件事。第一把真实世界变成数字第二在数字之间找稳定规律第三用没见过的新样本检验这个规律是否仍然成立。本文的 Pipeline、交叉验证、调参本质上都是为了让这三件事更可靠。第 0 部分环境与数据读取先导入依赖。这里既有传统机器学习模型也有 XGBoost、LightGBM、CatBoost 这类梯度提升框架。医学表格数据通常不是图像也不是长文本结构化表格模型仍然非常有竞争力。import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import warnings warnings.filterwarnings(ignore) from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.metrics import accuracy_score, classification_report, confusion_matrix from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.naive_bayes import GaussianNB from sklearn.linear_model import LogisticRegression from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis from xgboost import XGBClassifier from lightgbm import LGBMClassifier from catboost import CatBoostClassifier读取 CSV 后第一步不要急着训练模型而是先看形状、字段类型、缺失值和类别取值。你可以把这一步理解成“接诊问诊”先确认病历卡有没有漏项、字段是不是写错、每个变量到底表达什么。df pd.read_csv(pancreatic_cancer_prediction_sample.csv) print(df.shape) print(df.info()) print(df.describe()) print(df.isnull().sum()) categorical_cols df.select_dtypes(include[object]).columns for col in categorical_cols: print(f{col}: {df[col].unique()})本数据集共有50000 行、24 列。目标列Survival_Status是二分类标签0 类 43578 条1 类 6422 条。这个比例会直接影响后面对 Accuracy 的解读。第 1 部分先看数据不要先套模型年龄是医学预测里最常见、也最容易被模型重视的变量。先看年龄分布是为了确认数据是否集中在合理区间是否存在明显异常值。plt.figure(figsize(8, 5)) sns.histplot(df[Age], bins30, kdeTrue, colorblue) plt.title(Age Distribution of Patients) plt.xlabel(Age) plt.ylabel(Frequency) plt.show()图 1 年龄分布样本年龄以 60-70 岁附近最集中符合胰腺癌高发年龄段的常识背景。从图上看年龄主要集中在 60-70 岁附近。用费曼式说法如果一个班级里大多数学生都在同一个年龄段模型就很容易把“年龄段”当作重要线索。后面的特征重要性也印证了这一点。接着看诊断分期与生存时间。第一性原理上分期越晚肿瘤扩散越严重治疗窗口越窄生存时间通常越短。图像的价值就是让这个医学常识在数据里显形。plt.figure(figsize(8, 5)) sns.boxplot(xStage_at_Diagnosis, ySurvival_Time_Months, datadf, palettecoolwarm) plt.title(Survival Time Across Stages of Diagnosis) plt.xlabel(Stage at Diagnosis) plt.ylabel(Survival Time (Months)) plt.show()图 2 不同诊断分期下的生存时间Stage I 的生存时间明显更长Stage IV 更短。治疗方式分布也要看。不是因为柱状图高级而是因为样本数量会影响模型对某类治疗方式的学习。如果某个治疗方式样本很少模型对它的判断就更容易不稳定。sns.countplot(xTreatment_Type, datadf, paletteSet2) plt.title(Distribution of Treatment Types) plt.xlabel(Treatment Type) plt.ylabel(Count) plt.xticks(rotation45) plt.show()图 3 治疗方式分布化疗样本最多其次为放疗和手术。第 2 部分相关性、分布与异常值热力图不是为了好看而是为了回答一个问题变量之间有没有强相关如果两个变量几乎表达同一件事它们会让模型重复计分也会影响解释。plt.figure(figsize(10, 6)) sns.heatmap( df.select_dtypes(include[int64, float64]).corr(), annotTrue, cmapcoolwarm, linewidths0.5, ) plt.title(Correlation Heatmap of Numerical Features) plt.show()图 4 数值特征相关性热力图多数风险因素之间相关性较弱Age 与 Survival_Time_Months 是后续模型最敏感的连续变量。从相关性图看多数变量之间相关性较弱。这意味着模型需要从多变量组合里找信号而不是靠某两个变量的简单线性关系吃遍全场。下面的九宫格计数图把主要离散变量的样本比例放到一起看。第一性原理上分类模型学习的是“特征取值和标签之间的条件分布”。如果某些取值本来就占多数模型可能只是学会了样本比例而不是真正学会疾病风险。fig, axes plt.subplots(3, 3, figsize(18, 12)) sns.countplot(xGender, datadf, palettepastel, axaxes[0, 0]) sns.countplot(xSmoking_History, datadf, palettecoolwarm, axaxes[0, 1]) sns.countplot(xDiabetes, datadf, paletteSet2, axaxes[0, 2]) sns.countplot(xChronic_Pancreatitis, datadf, palettemagma, axaxes[1, 0]) sns.countplot(xStage_at_Diagnosis, datadf, paletteviridis, axaxes[1, 1]) sns.countplot(xTreatment_Type, datadf, paletteBlues, axaxes[1, 2]) sns.countplot(xSurvival_Status, datadf, palettehusl, axaxes[2, 0]) sns.countplot(xAlcohol_Consumption, datadf, paletteSet1, axaxes[2, 1]) sns.countplot(xPhysical_Activity_Level, datadf, palettecrest, axaxes[2, 2]) plt.tight_layout() plt.show()图 5 九个离散变量计数图先看类别比例才能判断模型学到的是信号还是样本占比。连续变量的 KDE、箱线图、小提琴图、饼图、散点图、Pairplot 和 Jointplot 继续从不同角度看同一批数据。读图时要抓住三个问题变量是否偏态类别之间是否分离变量之间是否存在可学习的边界。图 6 年龄与生存时间 KDE年龄近似钟形分布生存时间明显右偏。图 7 箱线图分期和生存时间的阶梯关系非常清楚性别与年龄差异不大。图 8 小提琴图不同治疗方式的生存时间分布大量重叠提示单变量很难直接决定结局。图 9 饼图Stage IV 与化疗样本占比较高是必须向读者交代的数据背景。图 10 散点图年龄、生存时间、性别、饮酒和体力活动之间没有简单线性边界。图 11 Pairplot把多个变量放在同一张图中看能快速发现分期与生存时间的分层。图 12 年龄与生存时间联合分布高密度区域集中在 55-75 岁、短生存时间附近。图 13 饮酒与生存时间联合分布二值变量常形成两条竖带读图时不要误解成连续趋势。第 3 部分为什么一定要用 Pipeline表格数据里有两类变量数值变量和类别变量。数值变量可以直接参与计算但尺度不同例如年龄是几十二值风险因素是 0/1生存时间是 1-59。类别变量如国家、治疗方式、分期不能直接喂给大多数 sklearn 模型需要编码。如果手工先标准化、再 One-Hot、再切训练测试集很容易把测试集信息泄漏进训练过程。Pipeline 的意义是把“预处理”和“训练”锁在同一条流程里让交叉验证时每一折都只用训练折拟合预处理器。X df.drop(columns[Survival_Status]) y df[Survival_Status] categorical_cols X.select_dtypes(include[object, bool]).columns numerical_cols X.select_dtypes(include[int64, float64]).columns numerical_transformer StandardScaler() categorical_transformer OneHotEncoder(handle_unknownignore) preprocessor ColumnTransformer( transformers[ (num, numerical_transformer, numerical_cols), (cat, categorical_transformer, categorical_cols), ] ) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 )用一句费曼式解释Pipeline 就像医院的标准化检查流程。每位病人先按同一规则量体温、验血、填表然后医生再判断。如果检查流程每次都不一样诊断结果就没法比较。第 4 部分12 种模型横向比较单个模型表现好不代表它真的适合数据。更稳妥的做法是把多个模型放到同一预处理流程、同一训练测试划分、同一评价指标下比较。这样比较出来的差异才有意义。models [ (Random Forest, RandomForestClassifier(random_state42)), (Gradient Boosting, GradientBoostingClassifier(random_state42)), (SVM, SVC(random_state42)), (KNN, KNeighborsClassifier()), (Decision Tree, DecisionTreeClassifier(random_state42)), (Naive Bayes, GaussianNB()), (Logistic Regression, LogisticRegression(random_state42)), (XGBoost, XGBClassifier(random_state42)), (LightGBM, LGBMClassifier(random_state42)), (CatBoost, CatBoostClassifier(random_state42, verbose0)), (LDA, LinearDiscriminantAnalysis()), (QDA, QuadraticDiscriminantAnalysis()), ] results [] names [] for name, model in models: pipeline Pipeline(steps[(preprocessor, preprocessor), (model, model)]) pipeline.fit(X_train, y_train) y_pred pipeline.predict(X_test) accuracy accuracy_score(y_test, y_pred) results.append(accuracy) names.append(name) print(f{name}: {accuracy:.4f})模型测试集 Accuracy5 折 CV AccuracyRandom Forest0.87300.8715Gradient Boosting0.87300.8715SVM0.87300.8716KNN0.86000.8582Decision Tree0.75600.7529Naive Bayes0.87300.8716Logistic Regression0.87300.8716XGBoost0.87060.8700LightGBM0.87300.8715CatBoost0.87290.8715LDA0.87300.8716QDA0.41490.4325这个结果最值得讲的地方恰恰不是“最高准确率 0.8730”而是它和多数类基线非常接近。因为 0 类占 87.156%一个什么都不学、永远预测 0 的模型Accuracy 也能达到 0.87156。这就是医学二分类任务最容易踩的坑如果阳性或死亡等少数类才是我们真正关心的类别Accuracy 可能会把模型表现讲得过于乐观。下一步应该补充classification_report、混淆矩阵、ROC-AUC、PR-AUC并考虑类别权重或阈值移动。第 5 部分GridSearchCV 做超参数调优超参数不是模型从数据里学出来的参数而是我们训练前给模型设定的控制旋钮。随机森林里树的数量、最大深度、节点分裂最小样本数都会影响偏差和方差。param_grid { model__n_estimators: [100, 200, 300], model__max_depth: [None, 10, 20, 30], model__min_samples_split: [2, 5, 10], } rf_pipeline Pipeline( steps[ (preprocessor, preprocessor), (model, RandomForestClassifier(random_state42)), ] ) grid_search GridSearchCV(rf_pipeline, param_grid, cv5, scoringaccuracy) grid_search.fit(X_train, y_train) print(fBest parameters: {grid_search.best_params_}) print(fBest cross-validation accuracy: {grid_search.best_score_:.4f}) best_model grid_search.best_estimator_ cv_scores cross_val_score(best_model, X, y, cv5, scoringaccuracy) print(fCross-validation accuracy: {np.mean(cv_scores):.4f})本次随机森林网格搜索得到的最优参数为max_depthNone、min_samples_split5、n_estimators100。最佳交叉验证 Accuracy 为 0.8712最终 5 折交叉验证平均 Accuracy 为 0.8716。这个结果告诉我们调参不是魔法。若数据中的可分信号有限或者评价指标被类别不均衡主导调参只能小幅改变结果不能凭空制造信息。第 6 部分特征重要性调好随机森林后可以提取特征重要性。它的含义不是“因果影响”而是“这个特征在树模型分裂中被使用、并降低不纯度的贡献”。所以它适合做解释线索不适合直接当医学结论。if hasattr(best_model.named_steps[model], feature_importances_): importances best_model.named_steps[model].feature_importances_ feature_names preprocessor.get_feature_names_out() feature_importance_df pd.DataFrame( {Feature: feature_names, Importance: importances} ).sort_values(byImportance, ascendingFalse) print(feature_importance_df.head(15))排名特征重要性1num__Age0.1452162num__Survival_Time_Months0.1303563num__Weight_Loss0.0255954num__Abdominal_Discomfort0.0240025num__Smoking_History0.0234766num__Alcohol_Consumption0.0227997num__Back_Pain0.0227188num__Obesity0.0211729num__Development_of_Type2_Diabetes0.02031910cat__Country_United States0.01983311num__Family_History0.01888312cat__Treatment_Type_Chemotherapy0.01852613cat__Economic_Status_Middle0.01851014cat__Access_to_Healthcare_Medium0.01770915num__Jaundice0.017406可以看到Age 和 Survival_Time_Months 排在最前面。注意若目标是预测生存状态而 Survival_Time_Months 是结局之后才知道的信息那么真实部署时要谨慎预测时拿不到的变量不能放进模型否则会形成“事后信息泄漏”。这是医学建模里比模型选择更重要的问题。第 7 部分保存模型训练完成后把整个 Pipeline 保存下来而不是只保存裸模型。原因很简单预测新样本时必须复用同一套标准化和 One-Hot 规则。import joblib joblib.dump(best_model, best_model.pkl)这样保存出来的best_model.pkl包含预处理器和随机森林模型新数据进来后可以直接调用predict。最后这篇实战真正要学会什么如果只记住一件事请记住机器学习项目的核心不是“哪个模型最强”而是“数据、目标、评价指标、验证方式是否自洽”。本案例里Pipeline 和交叉验证让流程变得规范多模型比较让我们知道不同算法的表现边界而类别不均衡提醒我们Accuracy 不能独自承担医学预测的评价责任。下一步可以继续升级使用StratifiedKFold保持每折类别比例给模型加入class_weight用 PR-AUC 评估少数类画混淆矩阵检查漏判再用 SHAP 分析单个样本为什么被模型判成某类。这样才是从“代码能跑”走向“模型可信”的路径。

相关新闻

从离线分析到实时对话:JoyAI-VL-Interaction如何重塑视频AI交互范式

从离线分析到实时对话:JoyAI-VL-Interaction如何重塑视频AI交互范式

2026/7/11 13:25:16

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 上周,我花了一个下午调试一个视频理解项目。需求很简单:让AI“看”一段监控视频,然后回答“画面里…

马克思主义基本原理在Vue框架中的指导作用探析

马克思主义基本原理在Vue框架中的指导作用探析

2026/7/9 17:37:26

摘要:马克思主义基本原理是揭示自然、社会与思维发展规律的科学世界观与方法论,具备普遍的真理适用性,不仅适用于社会科学研究,更为计算机技术研发、前端框架迭代、工程实践创新提供根本性顶层指导。前端技术的迭代升级与框架的成…

GraphQL DApp 索引层:别让前端直接追着链扫

GraphQL DApp 索引层:别让前端直接追着链扫

2026/7/11 16:22:25

GraphQL DApp 索引层:别让前端直接追着链扫 一、链上查询需要索引层 DApp 前端如果直接通过 RPC 扫事件、查余额、拼历史记录,很快会遇到性能和稳定性问题。RPC 更适合读当前状态和提交交易,不适合做复杂历史查询。GraphQL 索引层可以把链上事…

企业AI落地boss增长营:AI数字人做IP效果真的好吗?从技术架构到落地场景拆解

企业AI落地boss增长营:AI数字人做IP效果真的好吗?从技术架构到落地场景拆解

2026/7/11 17:03:05

AI数字人做IP是2025到2026年最热门的话题之一。从技术角度看,AI数字人的效果取决于底层架构设计和内容生产流程的合理性,而不是单纯看"数字人逼真不逼真"。本文从技术实操角度拆解AI数字人做IP的关键环节和效果验证方法。 一、AI数字人IP的技…

如何快速上手JXBWKWebView:5分钟完成iOS WebView集成

如何快速上手JXBWKWebView:5分钟完成iOS WebView集成

2026/7/11 17:03:05

如何快速上手JXBWKWebView:5分钟完成iOS WebView集成 【免费下载链接】JXBWKWebView An component WebView for iOS base on WKWebView 项目地址: https://gitcode.com/gh_mirrors/jx/JXBWKWebView JXBWKWebView是一个基于WKWebView的iOS WebView组件&#x…

灾难恢复演练实战:从预案设计到真实切换的完整执行手册

灾难恢复演练实战:从预案设计到真实切换的完整执行手册

2026/7/11 17:03:05

灾难恢复演练实战:从预案设计到真实切换的完整执行手册 一、体系化起点:灾难恢复演练不是"跑个脚本就行了" 我在团队里推行过多次灾难恢复演练,最深刻的体会是:第一次真刀真枪的演练,几乎没有一次能在预定…

零基础AI换脸工具终极指南:roop-unleashed让你5分钟成为换脸大师

零基础AI换脸工具终极指南:roop-unleashed让你5分钟成为换脸大师

2026/7/11 17:03:05

零基础AI换脸工具终极指南:roop-unleashed让你5分钟成为换脸大师 【免费下载链接】roop-unleashed Evolved Fork of roop with Web Server and lots of additions 项目地址: https://gitcode.com/gh_mirrors/ro/roop-unleashed 还在为复杂的AI换脸技术望而却…

如何快速上手openEuler/imageTailor?3分钟掌握ISO裁剪核心功能

如何快速上手openEuler/imageTailor?3分钟掌握ISO裁剪核心功能

2026/7/11 17:03:05

如何快速上手openEuler/imageTailor?3分钟掌握ISO裁剪核心功能 【免费下载链接】imageTailor a tool for tailoring image 项目地址: https://gitcode.com/openeuler/imageTailor 前往项目官网免费下载:https://ar.openeuler.org/ar/ 想要快速上…

Unity游戏单文件打包实战:用WinRAR SFX模块实现一键分发

Unity游戏单文件打包实战:用WinRAR SFX模块实现一键分发

2026/7/11 16:53:05

1. 项目概述:为什么PC端Unity游戏需要单文件打包? 如果你是一个独立游戏开发者,或者是一个小型游戏工作室的成员,那么你一定经历过这样的场景:辛辛苦苦在Unity里打磨了几个月的游戏,终于到了要发给朋友测试…

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

2026/7/10 22:32:48

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…

6个月转型AI工程师:实战路径与核心技能

6个月转型AI工程师:实战路径与核心技能

2026/7/9 18:28:30

1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公…

YOLOv5模型剪枝与量化实战:边缘设备部署优化

YOLOv5模型剪枝与量化实战:边缘设备部署优化

2026/7/10 6:57:56

1. 项目背景与核心价值在计算机视觉领域,YOLOv5因其出色的实时检测性能成为工业界宠儿。但当我们尝试将其部署到边缘设备(如树莓派、Jetson Nano或手机终端)时,立刻会遇到两个致命问题:模型体积庞大(原始YO…

WechatDecrypt技术解析:深入理解微信数据库AES-256-CBC解密机制

WechatDecrypt技术解析:深入理解微信数据库AES-256-CBC解密机制

2026/7/11 0:02:03

WechatDecrypt技术解析:深入理解微信数据库AES-256-CBC解密机制 【免费下载链接】WechatDecrypt 微信消息解密工具 项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt 在数字隐私日益重要的今天,微信聊天记录作为个人数字资产的重要组成…

5分钟搞定Kodi字幕难题:智能字幕插件让你追剧无忧 [特殊字符]

5分钟搞定Kodi字幕难题:智能字幕插件让你追剧无忧 [特殊字符]

2026/7/11 0:02:03

5分钟搞定Kodi字幕难题:智能字幕插件让你追剧无忧 🎬 【免费下载链接】zimuku_for_kodi Kodi 插件,用于从「字幕库」网站下载字幕 项目地址: https://gitcode.com/gh_mirrors/zi/zimuku_for_kodi 还记得那个深夜吗?你刚下载…

PostgreSQL 备份与恢复实战:从 pg_dump 到时间点恢复的生产级方案

PostgreSQL 备份与恢复实战:从 pg_dump 到时间点恢复的生产级方案

2026/7/11 0:02:03

PostgreSQL 备份与恢复实战:从 pg_dump 到时间点恢复的生产级方案 一、数据库备份最容易被忽略的问题,不是「有没有做备份」,而是「备份能不能恢复、恢复要多久、以及恢复后的数据对不对」 很多团队做数据库备份的方式是「写个 cron job&am…