2021华为杯D题抗乳腺癌药物建模:特征选择与回归分类实战
发布时间:2026/9/26 22:40:42来源:尧图网络
简介本资源为2021年华为杯数学建模竞赛D题「抗乳腺癌候选药物优化建模」的完整解答包面向参加数学建模竞赛的高校学生及对生物信息学、医疗数据分析感兴趣的进阶学习者。内容围绕特征选择、回归预测、二分类建模、最优化求解、模型训练与验证、数据预处理、结果可视化等核心环节展开可帮助读者理解如何将机器学习与统计方法应用于药物研发场景。压缩包共83个文件以32个Python脚本、22个CSV数据文件、14张PNG图表为主另含XLSX表格、XML配置、Markdown说明及DOCX文档整体约31.82MB目录按代码、数据与结果分层组织便于按模块查阅与复现。目前已有3477人学习下载适合需要系统复盘赛题思路、对照代码实现与验证模型效果的读者参考。1. 从一份 2021 华为杯 D 题解答包说起抗乳腺癌候选药物建模到底在算什么如果你正在准备研究生数学建模或者翻往年华为杯真题找练手项目2021 年 D 题「抗乳腺癌候选药物的优化建模」大概率会被反复推到面前。它给出一批化合物分子描述符和对应的生物活性指标要求你从上千维特征里挑出真正有用的那几十个再建立回归和分类模型去预测药物活性、判断候选化合物是否值得继续研发。听起来像生物信息学的活本质却是一道标准的「高维小样本 特征选择 回归/分类 优化」综合题。这份解答包mathematical-modeling-main就是围绕这道题的一整套可运行代码目录里有pycode、Math2021、README.md和.idea配置属于典型的 Python 数学建模工程结构。它适合三类人第一次打华为杯、想看清 D 题完整解题链路的新手做过几场比赛、想对照别人特征工程和调参思路的老手以及需要一份能直接跑通、再改成自己论文代码的从业者。下面我不讲空泛的建模思想只拆这份包怎么用、参数怎么设、哪几步最容易翻车。2. 环境与数据入口把 pycode 跑起来之前先搞清三件事2.1 目录结构与依赖安装拿到压缩包解压后先别急着点运行。mathematical-modeling-main是工程根目录pycode放核心脚本Math2021一般对应赛题数据或中间结果README.md记录运行顺序.idea是 PyCharm 的工程配置删掉不影响运行。常见做法是先建一个干净虚拟环境避免和你机器上已有的 numpy、sklearn 版本打架。# 建议 Python 3.8~3.10太新的 3.12 部分老包轮子不全 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 数学建模常用四件套版本尽量锁在下面区间 pip install numpy1.23.5 pandas1.5.3 scikit-learn1.2.2 matplotlib3.7.1 pip install xgboost1.7.5 lightgbm3.3.5逻辑说明numpy 和 pandas 负责数据读写与矩阵运算scikit-learn 提供特征选择、回归、分类、交叉验证的全套接口xgboost/lightgbm 用于梯度提升回归。参数上numpy 锁 1.23 是因为部分老代码用了已废弃的np.float别名1.24 之后会直接报错sklearn 锁 1.2 是因为RFE、cross_val_score的默认行为在 1.4 有微调老代码结果会对不上。装完先python -c import sklearn; print(sklearn.__version__)确认版本别等跑一半才发现。2.2 数据读取与列名对齐D 题数据通常是「分子描述符 活性标签」的宽表列数上千。读进来第一件事不是建模是确认标签列名和特征列范围。常见做法是把标签列单独抽出来特征矩阵只保留数值列。import pandas as pd import numpy as np # 读原始数据注意编码赛题数据偶尔是 gbk df pd.read_csv(Math2021/train.csv, encodingutf-8) # 标签列一般叫 pIC50 / activity / label按实际列名改 label_col pIC50 y df[label_col].values X df.drop(columns[label_col]) # 只保留数值型特征描述符里混进字符串列会直接让模型报错 X X.select_dtypes(include[np.number]) print(特征维度:, X.shape, 标签范围:, y.min(), y.max())逻辑说明select_dtypes这一步是血泪经验赛题描述符表里常混入分子 ID、SMILES 字符串这类非数值列不剔掉后面标准化和回归都会崩。参数上label_col必须按你实际拿到的数据改别照抄。打印维度是为了确认特征数在合理区间通常几百到两千如果只有几十维多半是读错文件了。2.3 缺失值与常数列的预处理高维描述符里出现 NaN 和方差为 0 的常数列非常普遍。常数列对模型零贡献还会拖慢特征选择。# 缺失值用中位数填充比均值抗异常值 X X.fillna(X.median(numeric_onlyTrue)) # 去掉方差为 0 的常数列 from sklearn.feature_selection import VarianceThreshold vt VarianceThreshold(threshold0.0) X_reduced vt.fit_transform(X) print(去常数列后:, X_reduced.shape)逻辑说明中位数填充是因为描述符分布常有偏态均值会被极端值带偏。VarianceThreshold(threshold0.0)只删完全不变的列阈值设大了会误删弱信号特征这一步保守点。跑完对比前后维度如果一下少了几百列说明原始数据里冗余描述符很多属于正常现象。3. 特征选择与回归建模从上千维描述符里挑出真正有用的那批3.1 用 RFE 做递归特征消除特征选择是这道题的核心得分点。常见做法是先用RandomForestRegressor或GradientBoostingRegressor当基模型配合 RFE 逐步剔除最不重要的特征。RFE 的好处是考虑了特征间的交互比单纯卡方检验、互信息更贴近回归任务。from sklearn.ensemble import RandomForestRegressor from sklearn.feature_selection import RFE from sklearn.model_selection import cross_val_score base RandomForestRegressor(n_estimators200, random_state42, n_jobs-1) # n_features_to_select 先设 50可后续网格搜索 rfe RFE(estimatorbase, n_features_to_select50, step10) rfe.fit(X_reduced, y) X_sel rfe.transform(X_reduced) print(选中特征数:, X_sel.shape[1]) # 用交叉验证看这 50 维的回归表现 scores cross_val_score(base, X_sel, y, cv5, scoringr2) print(R2 均值:, scores.mean())逻辑说明step10表示每轮剔除 10 个最不重要特征步长太小吃计算时间太大可能跳过最优子集。n_features_to_select50是经验起点D 题里 30~80 维通常能兼顾精度和泛化。cross_val_score用 5 折scoringr2看回归拟合优度。参数上random_state固定是为了结果可复现n_jobs-1吃满 CPU。如果 R2 为负说明特征或标签有问题先回去查数据。3.2 回归模型对比岭回归、Lasso 与 XGBoost选完特征后要建回归模型预测活性。岭回归抗共线性Lasso 自带稀疏化XGBoost 拟合能力强但容易过拟合。建议三个都跑一遍做对比。from sklearn.linear_model import Ridge, Lasso from xgboost import XGBRegressor from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline models { Ridge: make_pipeline(StandardScaler(), Ridge(alpha1.0)), Lasso: make_pipeline(StandardScaler(), Lasso(alpha0.01, max_iter5000)), XGBoost: XGBRegressor(n_estimators300, max_depth4, learning_rate0.05, subsample0.8, random_state42) } for name, m in models.items(): s cross_val_score(m, X_sel, y, cv5, scoringr2) print(f{name}: R2{s.mean():.4f} (/- {s.std():.4f}))逻辑说明岭回归和 Lasso 前必须标准化否则正则项会被量纲大的特征主导make_pipeline把标准化和模型绑一起避免数据泄漏。alpha是正则强度Lasso 的 0.01 偏小可网格搜索。XGBoost 的max_depth4控制树深防过拟合subsample0.8增加随机性。对比时看 R2 均值和标准差标准差大说明模型不稳定别只盯均值。3.3 二分类任务判断候选药物是否有效题目后半段通常要求把活性阈值以上的化合物判为「有效」转成二分类。逻辑回归、随机森林、SVM 都能用重点在阈值怎么定和类别是否平衡。from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import roc_auc_score, classification_report # 按活性阈值二值化阈值按赛题要求或数据分布定 threshold np.percentile(y, 70) # 取前 30% 为有效 y_cls (y threshold).astype(int) print(正样本比例:, y_cls.mean()) clf RandomForestClassifier(n_estimators300, random_state42, n_jobs-1) auc cross_val_score(clf, X_sel, y_cls, cv5, scoringroc_auc) print(AUC:, auc.mean())逻辑说明阈值用分位数而不是拍脑袋定能保证正负样本比例可控。roc_auc比准确率更适合类别不平衡场景。如果正样本比例低于 10%要在分类器里加class_weightbalanced。参数上n_estimators300是精度和耗时的折中树再多收益递减。4. 避坑与排查这份解答包最容易翻车的五个地方4.1 现象运行报np.float已废弃原因老代码用了 numpy 1.20 之前的np.float、np.int别名新版本 numpy 直接移除。解决要么把 numpy 降到 1.23要么全局搜索替换成float、int。我一般选降版本改代码容易漏。4.2 现象R2 高得离谱接近 1.0原因特征里混进了标签的衍生列或者标准化时把测试集数据也 fit 进去了典型数据泄漏。解决检查特征矩阵是否误含标签列所有 scaler、特征选择器必须只在训练折上 fit用Pipeline包起来最稳。4.3 现象RFE 跑几个小时不结束原因基模型树太多、step太小、特征维度上千组合起来计算量爆炸。解决先把n_estimators降到 100step提到 20~50或者先用方差阈值和相关性过滤砍掉一半特征再上 RFE。4.4 现象分类结果全预测成负类原因正样本比例太低模型偷懒全判负也能拿高准确率。解决看classification_report的召回率而不是准确率加class_weightbalanced或改用 AUC、F1 评估。4.5 现象换台机器结果对不上原因没固定随机种子或 sklearn 版本不同导致默认参数行为差异。解决所有涉及随机的模型都写死random_state42并在 README 里记录依赖版本团队协作时统一环境。5. 进阶技巧用网格搜索和特征重要性反推模型可信度跑通基础流程后真正拉开差距的是调参和结果解释。我一般先用GridSearchCV在粗粒度上找参数区间再用特征重要性回头看选出来的描述符是否符合化学直觉——如果模型最重要的特征全是些莫名其妙的编号列那多半是数据泄漏或过拟合别急着写进论文。from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [200, 400], max_depth: [3, 5, 7], learning_rate: [0.03, 0.05, 0.1] } gs GridSearchCV( XGBRegressor(random_state42, subsample0.8), param_grid, cv5, scoringr2, n_jobs-1 ) gs.fit(X_sel, y) print(最优参数:, gs.best_params_) print(最优 R2:, gs.best_score_) # 用最优模型看特征重要性反推选出的描述符是否合理 import pandas as pd best gs.best_estimator_ imp pd.Series(best.feature_importances_, indexrange(X_sel.shape[1])) print(Top10 重要特征索引:, imp.nlargest(10).index.tolist())逻辑说明param_grid三个参数组合共 18 种5 折就是 90 次训练n_jobs-1并行能压到可接受时间。scoringr2和前面评估口径一致别这里换 AUC 那里换 R2结果没法比。特征重要性打印出来后对照原始描述符表看这些列代表什么化学性质如果集中在某几类描述符上说明模型学到了真实信号如果分散且无规律警惕过拟合。验证模型可信度还有一招把数据集按分子骨架做分组划分而不是随机划分。同一类骨架的分子同时出现在训练和测试集里会让 R2 虚高。常见做法是用GroupKFold分组列用分子指纹聚类的结果。这一步很多队伍会忽略但评审如果较真随机划分的结果是站不住的。参数搜索的边界也要心里有数max_depth超过 8 基本必过拟合learning_rate低于 0.01 训练慢且收益小n_estimators上千在几百个样本上纯属浪费。我一般先固定learning_rate0.05搜max_depth和n_estimators找到量级后再微调学习率。从那以后我每次拿到高维小样本的建模题都强制先跑一遍方差过滤和相关性检查再上特征选择绝不直接把原始表丢进模型。这份 2021 华为杯 D 题解答包的价值不在于代码多优雅而在于它把「特征选择 → 回归 → 分类 → 优化」这条链路完整走了一遍你可以照着复现再按自己的数据替换标签列和阈值。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网