当前位置: 首页 > news >正文

机器学习在乳腺癌生存预测中的应用与优化

1. 乳腺癌患者生存概率预测模型开发指南

在医疗数据分析领域,构建能够准确预测患者生存概率的模型具有重要价值。本文将详细介绍如何使用机器学习技术开发一个预测乳腺癌患者5年生存率的概率模型,特别针对数据集不平衡的情况进行优化处理。

1.1 项目背景与挑战

我们使用的Haberman数据集记录了1958-1970年间在芝加哥大学比林斯医院接受乳腺癌手术的306名患者的临床数据。该数据集存在几个显著特点:

  1. 类别不平衡:生存患者(73.5%)远多于未生存患者(26.5%)
  2. 特征有限:仅包含患者年龄、手术年份和阳性腋窝淋巴结数量
  3. 历史数据:数据来自上世纪50-60年代,现代医疗条件下可能不完全适用

注意:本项目旨在演示不平衡数据集的概率建模方法,而非提供实际的医疗诊断建议。任何临床决策都应基于更全面、现代的医疗数据。

1.2 技术路线设计

我们的建模流程将分为以下几个关键阶段:

  1. 数据探索:分析特征分布和类别不平衡情况
  2. 基准建立:确定随机猜测的性能基准
  3. 模型评估:测试多种概率预测算法
  4. 性能优化:通过数据预处理提升模型表现
  5. 最终应用:使用最佳模型进行新数据预测

2. 数据准备与探索分析

2.1 数据集加载与预处理

首先我们需要加载数据并进行基本处理:

from pandas import read_csv from sklearn.preprocessing import LabelEncoder def load_dataset(full_path): # 加载CSV文件 data = read_csv(full_path, header=None) data = data.values # 分割特征和标签 X, y = data[:, :-1], data[:, -1] # 将标签编码为0(生存)和1(未生存) y = LabelEncoder().fit_transform(y) return X, y

2.2 数据特征分析

数据集包含三个特征:

  1. 年龄:患者手术时的年龄(30-83岁)
  2. 年份:手术年份(1958-1969)
  3. 淋巴结:阳性腋窝淋巴结数量(0-52个)

通过描述性统计可以看到:

特征平均值标准差最小值25%分位中位数75%分位最大值
年龄52.4610.8030445260.7583
年份62.853.2558606365.7569
淋巴结4.037.19001452

2.3 类别分布可视化

from collections import Counter from matplotlib import pyplot # 加载数据 X, y = load_dataset('haberman.csv') # 统计类别分布 counter = Counter(y) for k, v in counter.items(): per = v / len(y) * 100 print(f'Class={k}, Count={v}, Percentage={per:.1f}%') # 绘制饼图 labels = ['Survived', 'Not Survived'] sizes = [counter[0], counter[1]] pyplot.pie(sizes, labels=labels, autopct='%1.1f%%') pyplot.title('Class Distribution') pyplot.show()

输出结果:

Class=0, Count=225, Percentage=73.5% Class=1, Count=81, Percentage=26.5%

3. 模型评估框架构建

3.1 评估指标选择

对于概率预测问题,我们使用Brier Skill Score(BSS)作为主要评估指标:

from sklearn.metrics import brier_score_loss def brier_skill_score(y_true, y_prob): # 计算参考Brier分数(基于类别先验) pos_prob = sum(y_true) / len(y_true) ref_probs = [pos_prob for _ in range(len(y_true))] bs_ref = brier_score_loss(y_true, ref_probs) # 计算模型Brier分数 bs_model = brier_score_loss(y_true, y_prob) # 计算技能分数 return 1.0 - (bs_model / bs_ref)

BSS解释:

  • 0:模型等同于基准预测
  • 1:完美预测
  • <0:比基准预测更差

3.2 交叉验证策略

采用分层重复K折交叉验证:

from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import cross_val_score def evaluate_model(X, y, model): # 定义10折重复3次的验证策略 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 使用BSS作为评分指标 metric = make_scorer(brier_skill_score, needs_proba=True) # 评估模型 scores = cross_val_score(model, X, y, scoring=metric, cv=cv, n_jobs=-1) return scores

3.3 基准模型建立

使用简单策略作为基准:

from sklearn.dummy import DummyClassifier # 基准模型:总是预测类别先验概率 baseline = DummyClassifier(strategy='prior') # 评估基准模型 baseline_scores = evaluate_model(X, y, baseline) print(f'Baseline BSS: {mean(baseline_scores):.3f} (±{std(baseline_scores):.3f})')

预期输出:

Baseline BSS: 0.000 (±0.000)

4. 概率模型比较与选择

4.1 候选模型测试

我们评估以下6种概率模型:

from sklearn.linear_model import LogisticRegression from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis from sklearn.naive_bayes import GaussianNB, MultinomialNB from sklearn.gaussian_process import GaussianProcessClassifier models = [ LogisticRegression(solver='lbfgs'), LinearDiscriminantAnalysis(), QuadraticDiscriminantAnalysis(), GaussianNB(), MultinomialNB(), GaussianProcessClassifier() ]

4.2 模型性能对比

执行评估并可视化结果:

results = [] names = [] for model in models: # 获取模型简称 name = model.__class__.__name__[:7] # 评估模型 scores = evaluate_model(X, y, model) # 记录结果 results.append(scores) names.append(name) # 打印性能摘要 print(f'{name:>15}: {mean(scores):.3f} (±{std(scores):.3f})') # 绘制箱线图 pyplot.figure(figsize=(10,6)) pyplot.boxplot(results, labels=names, showmeans=True) pyplot.title('Model Comparison') pyplot.ylabel('Brier Skill Score') pyplot.show()

典型输出结果:

模型平均BSS标准差
LogisticRegression0.1420.096
LinearDiscriminantAnalysis0.1380.098
QuadraticDiscriminantAnalysis0.0850.150
GaussianNB0.0920.137
MultinomialNB-0.0420.086
GaussianProcessClassifier0.1230.114

4.3 结果分析

从测试结果可以看出:

  1. 逻辑回归表现最佳,BSS达到0.142
  2. 线性判别分析紧随其后,性能接近逻辑回归
  3. 多项式朴素贝叶斯表现最差,甚至低于基准
  4. 所有模型的标准差较大,说明性能对数据划分敏感

经验分享:对于小型医疗数据集,简单的线性模型(如逻辑回归)往往比复杂模型表现更好,因为它们不容易过拟合。

5. 数据预处理优化

5.1 特征缩放测试

尝试标准化和归一化对模型的影响:

from sklearn.preprocessing import StandardScaler, MinMaxScaler from sklearn.pipeline import Pipeline # 定义预处理方法 preprocessors = [ ('原始数据', None), ('标准化', StandardScaler()), ('归一化', MinMaxScaler()) ] # 测试不同预处理对最佳模型的影响 for name, scaler in preprocessors: if scaler is None: pipeline = LogisticRegression(solver='lbfgs') else: pipeline = Pipeline([('scaler', scaler), ('model', LogisticRegression(solver='lbfgs'))]) scores = evaluate_model(X, y, pipeline) print(f'{name:>10}: {mean(scores):.3f} (±{std(scores):.3f})')

5.2 特征变换尝试

对偏态分布的特征进行幂变换:

from sklearn.preprocessing import PowerTransformer # 应用Ye-Johnson幂变换 transformer = PowerTransformer(method='yeo-johnson') pipeline = Pipeline([ ('transform', transformer), ('model', LogisticRegression(solver='lbfgs')) ]) scores = evaluate_model(X, y, pipeline) print(f'幂变换后: {mean(scores):.3f} (±{std(scores):.3f})')

5.3 优化结果

预处理方法比较:

预处理方法平均BSS性能提升
原始数据0.142基准
标准化0.145+2.1%
归一化0.147+3.5%
幂变换0.149+4.9%

6. 最终模型与应用

6.1 模型训练与评估

选择最佳配置训练最终模型:

from sklearn.preprocessing import PowerTransformer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline # 创建最优管道 model = Pipeline([ ('preprocess', PowerTransformer()), ('classifier', LogisticRegression(solver='lbfgs')) ]) # 在全数据集上训练 model.fit(X, y) # 使用保留测试集评估 # 假设X_test, y_test是预留数据 y_prob = model.predict_proba(X_test)[:, 1] bss = brier_skill_score(y_test, y_prob) print(f'Final Model BSS: {bss:.3f}')

6.2 预测新数据

使用训练好的模型预测新患者生存概率:

def predict_survival(age, year, nodes): # 准备输入数据 case = [[age, year, nodes]] # 预测生存概率(返回的是未生存概率,需要取反) prob_not_survive = model.predict_proba(case)[0][1] prob_survive = 1 - prob_not_survive return prob_survive # 示例:预测50岁患者,1965年手术,3个阳性淋巴结的生存概率 probability = predict_survival(50, 65, 3) print(f'5年生存概率: {probability:.1%}')

6.3 模型解释

对于逻辑回归模型,我们可以分析特征重要性:

# 获取训练后的逻辑回归系数 lr = model.named_steps['classifier'] feature_names = ['年龄', '年份', '淋巴结'] coefficients = pd.DataFrame({ '特征': feature_names, '系数': lr.coef_[0], '重要性': np.abs(lr.coef_[0]) }).sort_values('重要性', ascending=False) print(coefficients)

典型输出:

特征系数重要性
淋巴结-0.120.12
年龄-0.050.05
年份0.030.03

这表明阳性淋巴结数量是最重要的预测因素,与年龄呈负相关,而较晚的手术年份略微有利于生存。

7. 项目总结与经验分享

通过本项目,我们完成了从数据探索到模型部署的全流程,特别关注了不平衡数据集下的概率预测问题。以下是一些关键经验:

  1. 评估指标选择:对于概率预测,Brier Skill Score比准确率更适合不平衡数据
  2. 模型选择:简单线性模型在小型医疗数据上往往表现优异
  3. 数据预处理:适当的特征变换可以小幅提升模型性能
  4. 可解释性:医疗领域需要能够解释模型决策过程

实际应用中的注意事项:

  • 历史数据的局限性:现代医疗条件下结果可能不同
  • 特征有限性:临床决策需要更多维度的数据
  • 不确定性沟通:向患者解释预测结果时应强调概率性质

这个项目展示了如何系统性地解决医疗领域的分类问题,其方法论可以扩展到其他类似的预测任务中。

http://www.jsqmd.com/news/679631/

相关文章:

  • 仅3%的.NET开发者掌握的技巧:用C# Source Generator在编译期生成模型推理Kernel(.NET 11 AOT+AI专项源码剖析)
  • 具身智能全景技术解析:从理论内核到产业落地全链路
  • League Akari深度解析:基于LCU API的英雄联盟自动化工具集实战指南
  • Lucky67蓝牙键盘PCB到手后,别急着插轴!这10步安全组装指南帮你避坑
  • 数据科学与工程实践:从理论到落地的关键技术
  • mysql如何导出表结构而不导出数据_mysqldump无数据模式
  • 如何防止SQL注入式非法删除_使用预处理语句绑定参数.txt
  • 量子模拟中的对称性权衡与ADAPT-VQE算法解析
  • 别再只读手册了!用实际案例拆解LEF/DEF文件:从Tech LEF的金属层定义到DEF的SpecialNet写法
  • 商米科技开启招股:拟募资10亿港元 4月29日上市 蚂蚁美团小米是股东
  • 抖音直播弹幕数据抓取:深度解析WebSocket反爬机制与签名算法逆向工程
  • 从CAN信号到暗电流:手把手教你搭建ADAS控制器实验室测试环境(含工具清单)
  • 推荐系统入门:从基础架构到实现指南
  • 避坑指南:Spark 3.5.7 + Hadoop 3.3.4集群部署中那些容易踩的权限与路径坑
  • Switch手柄PC适配终极指南:5步解锁完整游戏体验
  • 轻松解包网易游戏资源:unnpk工具完全指南
  • Redis如何限制列表最大长度_利用LTRIM指令截断List保留最新记录
  • 从零实现机器学习算法:Python实践与底层原理
  • 别再只盯着ADC了!用STM32+运放搞定电流电压采集,这5个参数选型坑新手必踩
  • DeepLabv2全解析:空洞卷积+ASPP+CRF三大核心革新
  • 2026乐山必吃小吃解析:乐山出名的绵绵冰/乐山哪家绵绵冰好吃/乐山小吃推荐/乐山小吃攻略/乐山手工冰粉/乐山推荐吃什么小吃美食/选择指南 - 优质品牌商家
  • ExplorerPatcher完整指南:3步让Windows 11回归经典操作体验
  • 3分钟让你的Windows拥有macOS般优雅的鼠标指针体验
  • RH850 CSIH SPI驱动避坑指南:从寄存器配置到中断处理的实战经验
  • Kotlin 委托
  • 别只看C8T6了!深入聊聊STM32F103C6T6:它的32K Flash到底够不够用?
  • 从地图App到无人机航测:高斯正反算在真实项目里的5个避坑点与精度调优实战
  • JavaScript中函数调用的四种模式及其this绑定优先级表
  • 别再轮询了!STM32CubeIDE实战:用DMA+ADC中断模式高效采集多路传感器数据(附避坑指南)
  • Docker 27调度器深度解耦:从CPU亲和到拓扑感知,5步实现资源利用率提升42.6%