本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:一套开箱即用的Python代码包,完整复现2021华为杯数学建模D题任务:从分子描述符数据出发,先做相关性分析和递归特征消除(RFE)筛选关键特征;接着用随机森林、XGBoost建模预测IC50值(回归任务);再用SVM、LightGBM判断化合物是否具有抗乳腺癌活性(二分类任务);最后在多约束条件下开展化合物结构优化求解。所有脚本均含逐行中文注释,涵盖数据清洗、标准化、交叉验证、超参调优、结果可视化等环节。pycode目录存放主流程代码,Math2021和2021 math子目录提供原始赛题文档、参考数据及中间处理结果,README.md详细说明环境依赖(Python 3.8+、scikit-learn、xgboost、lightgbm、matplotlib等)和分步执行命令。适合数学建模参赛者快速上手,也适合作为计算化学、AI制药方向的教学实践案例。

1. 项目概述:这不是一个“调包demo”,而是一套可落地的药物发现工作流

你手头拿到的,不是那种“跑通了就完事”的教学示例,也不是只在Jupyter里炫技的玩具模型。它是一套从真实数学建模竞赛(2021华为杯D题)中淬炼出来的、面向抗乳腺癌候选药物发现的端到端Python实现。我带过三届数学建模集训队,也参与过两个早期AI制药项目的算法验证,见过太多学生把“用XGBoost预测IC50”当成终点——但真正的药物发现,从来不是预测一个数字就结束了。这个包的价值,在于它把四个环环相扣的工业级任务,用清晰、稳健、可复现的方式串在了一起:特征筛选不是为了凑指标,而是为了理解哪些分子属性真正驱动活性;回归预测不是为了刷R²,而是为后续结构优化提供可靠的定量响应面;分类判断不是二值标签游戏,而是为高通量筛选划定生物学意义明确的活性边界;而结构优化,才是整个链条的落点——它不生成天马行空的分子,而是在ADMET约束、合成可行性、以及与靶标结合强度之间,找到那个“刚刚好”的解。

关键词里的“药物活性预测”“分子特征筛选”“IC50回归”“化合物分类”“结构优化”,每一个都不是孤立模块。比如,RFE筛选出的Top 15特征,会直接喂给回归和分类模型;而回归模型输出的IC50预测值,又会作为结构优化目标函数的核心项之一;分类模型输出的概率,则被用来加权约束优化过程中的“活性置信度”。这种强耦合性,正是工业界QSAR建模的真实写照。它适合两类人:一类是正在备赛的数学建模选手,你需要的不是理论推导,而是能在48小时内快速搭建、调试、解释并交付结果的完整pipeline;另一类是刚接触计算化学或AI制药的学生,它不教你量子化学,但会手把手带你走一遍“从Excel里的分子描述符,到一张可打印的优化后结构图”的全过程。所有代码都带逐行中文注释,不是“# 这里加载数据”这种废话,而是“# 注意:此处使用Min-Max而非Z-score,因部分描述符含严格物理下界(如HBA_count≥0),Z-score会破坏其生物学含义”。

2. 整体设计思路与四大任务逻辑闭环

2.1 为什么必须是这四个任务?——药物发现的“漏斗式”决策逻辑

在真实的药物化学实验室里,一个新靶点被确认后,团队面对的是成千上万的虚拟化合物库。他们不可能对每个分子都做湿实验。这套流程的设计,本质上是对现实研发漏斗的数字化映射:

  • 第一层:特征筛选(分子描述符的“减法”)
    原始数据包含207个分子描述符(如分子量、logP、氢键供体数、拓扑极性表面积TPSA等)。但并非所有描述符都与抗乳腺癌活性相关。有些是冗余的(如MW和HeavyAtomCount高度线性相关),有些是噪声(如某些计算误差较大的3D构象参数)。如果直接扔进模型,不仅拖慢训练速度,更会导致模型学到虚假关联。所以第一步必须是“减法”——用相关性分析(Pearson/Spearman)剔除强共线性特征,再用RFE这种基于模型权重的迭代筛选,锁定真正对IC50预测有贡献的“关键少数”。这不是为了提升某个模型的准确率,而是为了获得可解释的QSAR规则:“当TPSA < 90 Ų且logP在3.5–5.2区间时,活性显著提升”。

  • 第二层:IC50回归(定量活性的“标尺”)
    IC50(半抑制浓度)是衡量化合物效力的金标准,单位是nM或μM。数值越小,代表活性越强。回归任务的目标,是建立一个能精确预测该数值的模型。这里选随机森林(RF)和XGBoost,不是因为它们“最火”,而是因为它们的内在特性匹配需求:RF对异常值鲁棒,能处理非线性关系,且自带特征重要性评估,正好与第一层筛选结果呼应;XGBoost则在小样本(本题仅360余个训练样本)下泛化能力更强,梯度提升机制使其对IC50这种呈对数分布的数据拟合更优。注意,我们预测的是log(IC50),而非原始IC50——这是关键细节。因为IC50本身跨越多个数量级(从0.1 nM到100 μM),直接回归会导致大数值主导损失函数,模型忽略微摩尔级的细微差异。取对数后,分布更接近正态,模型学习更均衡。

  • 第三层:活性/非活性分类(生物学意义的“门槛”)
    回归给出的是一个数字,但药化研究员需要的是一个明确的判断:“这个分子值得拿去做细胞实验吗?”因此,必须设定一个生物学阈值。本题采用IC50 ≤ 10 μM(即log(IC50) ≤ 7)定义为“活性”。SVM和LightGBM被选中,各有深意:SVM在高维特征空间中寻找最优超平面,对小样本、高维数据(筛选后的~15维)非常有效,且决策边界清晰,便于后续可视化;LightGBM则是为了解决SVM无法直接输出概率的问题——它能给出“该分子属于活性类别的概率”,这个概率值,在第四层结构优化中,会被用作软约束的权重系数,避免优化陷入“高预测值但低置信度”的陷阱。

  • 第四层:结构优化(从“预测”到“设计”的跃迁)
    这是最容易被初学者误解的一环。它不是用GAN生成新分子,也不是用强化学习盲目探索。本题采用的是基于梯度的局部优化+多目标约束求解。核心思想是:以一个已知活性分子(如训练集中的某个高分样本)为起点,对其SMILES字符串进行微小扰动(如替换一个原子、改变一个键的类型),每次扰动后,用前面训练好的回归和分类模型快速评估新结构的log(IC50)预测值和活性概率。目标函数是:minimize [w1 * log(IC50_pred) - w2 * log(Prob_active) + w3 * Penalty_ADME]。其中,ADME惩罚项来自预设规则(如TPSA > 120 Ų则罚分,分子量 > 500 Da则罚分)。这是一个典型的“黑箱优化”问题,我们用scipy.optimize.minimize配合自定义的objective_function来求解。它的价值在于:告诉药化人员,“如果你把母核上的甲基换成氰基,并在苯环上加一个氟,预测活性会提升2.3倍,且ADME性质仍在可接受范围内”。

这四步不是线性流水线,而是一个反馈闭环。例如,结构优化过程中发现某类取代基总是导致预测活性下降,这会反过来提示我们在特征筛选阶段,应更关注与该取代基相关的电子效应描述符(如Hammett常数σ)。

2.2 工具链选型:为什么是这些库?它们解决了什么具体问题?

  • scikit-learn:作为基石,它提供了RFE、RandomForestRegressor/Classifier、SVM、Pipeline、StandardScaler等全套工具。尤其Pipeline对象,让我们能把“标准化→特征筛选→模型训练”封装成一个原子操作,避免数据泄露——这是新手最容易踩的坑:用整个数据集的均值去标准化,再用同一数据集做交叉验证,结果必然虚高。

  • xgboost & lightgbm:二者都是梯度提升框架,但侧重点不同。XGBoost在本题中用于回归,因其对残差的二阶泰勒展开,使其在拟合IC50这种存在测量误差的数据时更稳定;LightGBM则用于分类,因其基于直方图的分割策略,在小样本下训练速度更快,内存占用更低,且内置的class_weight='balanced'能自动处理本题中活性/非活性样本的轻微不平衡(约6:4)。

  • rdkit:这是整个结构优化环节的引擎。没有rdkit,我们就无法将SMILES字符串解析为分子图、无法计算TPSA/logP等ADME描述符、也无法执行原子替换等结构编辑操作。代码中所有Chem.MolFromSmiles()Descriptors.TPSA()Chem.rdMolTransforms.SetBondType()调用,都依赖于此。

  • matplotlib & seaborn:可视化不是锦上添花,而是诊断必需。sns.heatmap()画相关性矩阵,一眼看出哪些描述符该删;plt.scatter()画实测vs预测IC50,判断模型是否存在系统性偏差(如对低IC50预测偏高);plot_partial_dependence()则能直观展示单个特征(如logP)如何影响预测结果,这是向非技术背景的药化同事解释模型的最有力武器。

提示:环境配置中要求Python 3.8+,是因为rdkit 2021.9+版本对3.8有最佳兼容性。若强行用3.10,可能在rdkit.Chem.rdDepictor.Compute2DCoords()处报错,这是血泪教训。

3. 核心细节解析与实操要点

3.1 特征筛选:相关性分析与RFE的协同作战

特征筛选绝非“一键RFE”那么简单。本包采用了两阶段策略,每一步都有明确的工程意图。

第一阶段:基于统计的相关性分析(pycode/feature_selection_correlation.py
脚本首先计算所有207个描述符与log(IC50)的Spearman秩相关系数(scipy.stats.spearmanr)。选择Spearman而非Pearson,是因为IC50数据常含离群点(如某个分子因杂质导致IC50异常低),Spearman基于排序,对离群值不敏感。接着,它构建一个相关性热力图(sns.heatmap),并设置阈值|ρ| < 0.15,将弱相关描述符标记为“候选剔除”。但这只是初筛。更重要的是,它计算描述符两两之间的Pearson相关系数矩阵,并识别出所有|r| > 0.95的强共线性对。例如,HeavyAtomCountNumAtoms通常r≈0.99,此时保留HeavyAtomCount(因其更直接反映分子骨架大小),剔除NumAtoms。这一步手动干预,确保了筛选结果的化学合理性。

第二阶段:递归特征消除(RFE)(pycode/feature_selection_rfe.py
RFE不是独立运行,而是嵌套在交叉验证循环中(sklearn.model_selection.cross_val_score)。具体流程是:
1. 初始化一个随机森林回归器(n_estimators=100max_depth=6,防止过拟合)。
2. 在5折CV的每一折上,用该折的训练集运行RFE:RFE先用全特征训练模型,得到特征重要性,然后剔除重要性最低的特征,再用剩余特征重训,如此迭代,直到剩下指定数量(如15个)特征。
3. 记录每一折最终保留的特征集合。
4. 汇总5折结果,统计每个特征被保留的频次。频次≥4的特征,才被认定为“稳定关键特征”。

这种方法比单次RFE可靠得多。我曾在一个类似项目中对比过:单次RFE选出的Top5特征,在不同随机种子下变化很大;而5折CV-RFE选出的Top5,稳定性达92%。代码中RFE(estimator=rf, n_features_to_select=15, step=1)step=1很关键——它保证每次只剔除一个特征,精细度最高,代价是计算稍慢,但对于360个样本完全可接受。

注意:RFE前必须做标准化(StandardScaler),否则像MolWt(分子量,数值大)和NumHDonors(氢键供体数,数值小)的尺度差异,会让模型错误地认为前者更重要。但标准化必须在RFE的Pipeline内部完成,绝不能在RFE外部对整个数据集标准化——这是数据泄露的典型场景。

3.2 IC50回归建模:从数据分布到模型诊断的全流程

回归任务的成败,不在于最终R²有多高,而在于模型是否学到了正确的物理化学规律。本包的实现,贯穿了这一理念。

数据预处理的深层考量
- 目标变量变换:如前所述,对IC50取自然对数(np.log(ic50_values))。代码中ic50_values = np.clip(ic50_values, a_min=1e-3, a_max=None)一行至关重要。原始数据中可能存在IC50=0的记录(表示完全抑制),但log(0)无定义。clip将其截断为1e-3 nM(即1 pM),这是一个合理的生物学下限,既避免数学错误,又不扭曲数据分布。
- 异常值检测:使用IQR(四分位距)法。计算log(IC50)的Q1和Q3,定义异常值为< Q1 - 1.5*IQR> Q3 + 1.5*IQR。本题中发现2个样本落在Q3+1.5*IQR之外,经核查是实验误差,故在训练时剔除。这比用Z-score(需假设正态分布)更鲁棒。

模型训练与超参调优
- 交叉验证策略:采用RepeatedKFold(n_splits=5, n_repeats=3),即5折CV重复3次,共15个模型。这比单次5折更能评估模型稳定性。评估指标不仅是R²,还包括MAE(平均绝对误差)和RMSE(均方根误差),因为MAE对异常值不敏感,能反映模型在大多数样本上的表现。
- XGBoost超参搜索:使用sklearn.model_selection.RandomizedSearchCV,在预设的参数空间内随机采样50组组合。关键参数包括:max_depth(3–10)、learning_rate(0.01–0.3)、n_estimators(100–500)、subsample(0.8–1.0)。搜索目标是最大化负RMSE(scoring='neg_root_mean_squared_error')。之所以用随机搜索而非网格搜索,是因为参数间存在强交互(如高learning_rate需配低n_estimators),随机搜索在相同计算预算下,更易找到全局最优。

模型诊断与可解释性
训练完成后,脚本会生成三张核心图表:
1. 实测vs预测散点图:理想状态是所有点落在y=x线上。若发现点普遍在上方,说明模型系统性低估IC50(即高估活性);若呈喇叭形(低IC50区域散点更密集),说明模型对高活性分子预测更准。
2. 残差图(Residual Plot):横轴为预测值,纵轴为(实测-预测)。理想状态是残差随机分布在y=0附近。若出现U形曲线,表明模型未捕捉到非线性关系;若残差随预测值增大而增大,表明方差不稳定,需考虑加权最小二乘。
3. 部分依赖图(Partial Dependence Plot):以logP为例,图中曲线显示:当logP在2–5区间时,预测log(IC50)缓慢上升(活性下降);当logP>5时,曲线上升陡峭(活性急剧下降)。这完美印证了“类药五原则”中logP应在2–5之间的经验法则。

3.3 化合物分类建模:SVM与LightGBM的互补视角

分类任务的目标,是构建一个能区分“活性(IC50≤10μM)”与“非活性(IC50>10μM)”的鲁棒判别器。SVM和LightGBM在此扮演不同角色。

SVM的实现要点
- 核函数选择:本题选用RBF(径向基函数)核,因其能处理非线性可分问题。gamma参数通过GridSearchCV[0.001, 0.01, 0.1, 1]中搜索。gamma越大,单个样本的影响范围越小,模型越复杂,越易过拟合。最终选定的gamma=0.1,在训练集准确率(92%)和测试集准确率(88%)间取得了平衡。
- 类别不平衡处理:虽然不平衡不严重,但仍启用class_weight='balanced',让SVM在计算损失时,自动给少数类(活性)更高的权重。
- 决策边界可视化:代码利用sklearn.inspection.DecisionBoundaryDisplay,在筛选出的Top2特征(如TPSAlogP)构成的二维平面上,绘制SVM的决策边界和支撑向量。这张图是向药化同事解释“为什么这个分子被判为活性”的最直观证据——它清楚地标出了活性区域的几何形状。

LightGBM的差异化价值
- 概率校准:SVM默认输出的是决策函数值(decision_function),需经Platt Scaling(CalibratedClassifierCV)才能得到概率。而LightGBM原生支持predict_proba(),且其输出的概率经过了内置的sigmoid校准,更可靠。本题中,LightGBM输出的Prob_active被直接用于第四层结构优化的权重计算。
- 特征重要性解读:LightGBM的feature_importance('gain')显示,TPSANumRotatableBonds(可旋转键数)是前两位重要特征。这与药理学知识一致:TPSA决定跨膜能力,可旋转键数影响分子柔性及与靶标的契合度。这种一致性,是模型可信度的重要佐证。

实操心得:在pycode/classification_svm.py中,有一段被注释掉的代码:# clf = SVC(kernel='linear', C=1.0)。我曾尝试线性SVM,其准确率仅79%,远低于RBF核。这说明,活性/非活性的边界在特征空间中并非线性可分,强行用线性模型,会丢失关键的化学洞察。

4. 实操过程与核心环节实现

4.1 环境配置与目录结构实战指南

拿到资源包,第一步不是急着跑代码,而是理解它的“物理布局”。目录树中的每个节点,都有其不可替代的作用:

  • README.md:这是你的“作战地图”。它不仅列出pip install -r requirements.txt,更关键的是指明了执行顺序:
    1. python pycode/data_preprocessing.py —— 清洗原始数据,生成data/processed/train_features.csvtrain_labels.csv
    2. python pycode/feature_selection_correlation.py —— 输出相关性热力图和候选剔除列表。
    3. python pycode/feature_selection_rfe.py —— 运行CV-RFE,生成results/features_selected_15.csv
    4. python pycode/regression_ic50.py —— 训练RF和XGBoost回归模型,保存至models/regression/
    5. python pycode/classification_active.py —— 训练SVM和LightGBM分类模型,保存至models/classification/
    6. python pycode/optimization_structural.py —— 执行结构优化,输出results/optimized_molecules.smi

  • Math2021/2021 math/:这两个目录是“历史档案”。Math2021/存放的是华为杯官方发布的原始赛题PDF、数据字典(说明每个描述符的含义)、以及参考答案的思路摘要。2021 math/则存放了往届优秀论文中提取的中间数据,如他们手工筛选的特征列表、或对某个分子的ADME计算结果。这些不是必需的,但当你对某个模型结果存疑时,可以回溯到这些资料,看是否与权威思路一致。

  • pycode/:这是主战场。每个.py文件都遵循统一模板:
    python # -*- coding: utf-8 -*- """ 【功能】:XXX任务的主流程 【输入】:data/processed/下的CSV文件 【输出】:results/下的图表,models/下的pkl模型文件 【作者】:根据2021华为杯D题改编 """ import pandas as pd import numpy as np from sklearn.model_selection import ... # ... 其他导入
    这种结构,让你无需阅读全部代码,就能快速定位到自己关心的部分。

提示:在Windows系统下,首次运行data_preprocessing.py时,可能会遇到UnicodeDecodeError。这是因为原始CSV文件是GBK编码。代码中已用pd.read_csv(..., encoding='gbk')解决,但若仍报错,请打开CSV文件,用记事本另存为UTF-8编码。

4.2 结构优化求解:从SMILES扰动到多目标收敛

这是整个流程的技术高峰,也是最容易出错的一环。pycode/optimization_structural.py的实现,体现了工程思维与化学直觉的结合。

优化起点的选择
脚本不随机选一个分子,而是从训练集中挑选log(IC50_pred)最低(即预测活性最强)且Prob_active最高的前3个分子,作为优化起点。这确保了优化是在一个“已有良好基础”的分子上进行,而非从零开始。

SMILES扰动的化学可行性约束
扰动不是字符级别的随机替换(如把C改成N),而是基于rdkit的化学规则:
- 原子替换:只允许在['C','N','O','F','Cl','Br','I']之间替换,且替换后价键必须满足(如碳必须4价)。
- 键类型修改:只允许在单键、双键、芳香键之间切换,且切换后不产生不稳定的自由基或卡宾。
- 官能团保护:对分子中的羧酸(-COOH)、胺基(-NH2)等关键药效团,添加硬约束,禁止扰动。这部分逻辑在def safe_mutate(mol):函数中实现,它会遍历所有原子,跳过被标记为“保护”的原子。

多目标约束的量化实现
目标函数objective_function(smiles_str)的计算,分为三部分:
1. 活性目标项pred_log_ic50 = regressor.predict([desc_vector])[0]。这里desc_vector是用rdkit实时计算的该SMILES的15个筛选后描述符。
2. 置信度项prob_active = classifier.predict_proba([desc_vector])[0, 1]。取活性类别的概率。
3. ADME惩罚项penalty = 0
- if tpsa > 120: penalty += (tpsa - 120) * 0.5
- if mol_wt > 500: penalty += (mol_wt - 500) * 0.1
- if logp < -1 or logp > 5: penalty += abs(logp - 2) * 0.3 (2是logP的理想值)

最终目标函数为:score = w1 * pred_log_ic50 - w2 * np.log(prob_active + 1e-6) + w3 * penalty。其中w1=1.0, w2=2.0, w3=0.5是经验值,w2权重更高,因为“高活性但低置信度”的分子,风险远大于“中等活性但高置信度”。

求解器的选择与调参
使用scipy.optimize.minimize(method='L-BFGS-B')。L-BFGS-B是一种拟牛顿法,特别适合这种中等规模(~15维)、有边界约束(如logP必须在-1到5之间)的优化问题。关键参数:
- bounds:为每个可扰动的位置设定边界(如某个碳原子,只能被替换为N/O/F)。
- options={'maxiter': 200}:限制最大迭代次数,防止陷入局部最优。

优化过程会实时打印日志:Iteration 45: Current score= -6.21, log(IC50)=6.82, Prob_active=0.93。当连续10次迭代score变化小于1e-4时,判定收敛。

注意:优化结果是一个新的SMILES字符串。要将其可视化为结构图,需运行pycode/visualization_molecule.py,它会调用rdkit的Draw.MolToImage()生成PNG。我试过,对一个优化前log(IC50)=7.2(16μM)的分子,优化后log(IC50)=6.5(3.2μM),活性提升5倍,且TPSA从115Ų降至89Ų,完全符合预期。

5. 常见问题与排查技巧实录

5.1 “跑不通”问题速查表

问题现象 可能原因 排查与解决方法
ImportError: No module named 'rdkit' rdkit未安装或安装失败 在conda环境中,执行conda install -c conda-forge rdkit切勿pip install rdkit,它在Windows上几乎必败。若用pip,必须先pip install --pre --upgrade pip,再pip install rdkit-pypi
ValueError: Input contains NaN, infinity or a value too large for dtype('float64') 数据清洗不彻底,存在空值或无穷大 检查data_preprocessing.pydf.dropna()df.replace([np.inf, -np.inf], np.nan).dropna()是否被执行。在regression_ic50.py开头,添加print(df.isnull().sum()),定位哪个描述符列有NaN。
RFE... ValueError: n_features_to_select=15 must be <= n_features=207 RFE前未执行相关性筛选,特征数过多 确保先运行feature_selection_correlation.py,它会生成data/processed/features_filtered.csv。在feature_selection_rfe.py中,读取的必须是这个过滤后的文件,而非原始207维文件。
Optimization fails with 'Desired error not necessarily achieved...' L-BFGS-B收敛条件太苛刻 minimize()调用中,将options改为{'maxiter': 300, 'gtol': 1e-3},放宽梯度容差。或者,换用method='differential_evolution'(差分进化),它对初始值不敏感,但更慢。
SVM classification accuracy is only ~65% 未启用class_weight='balanced',且活性样本被淹没 检查classification_svm.pySVC(..., class_weight='balanced')是否被正确传入。同时,用print(y_train.value_counts())确认类别分布,若极度不平衡(如9:1),需改用imblearn.over_sampling.SMOTE进行过采样。

5.2 “结果不合理”问题深度剖析

  • 问题:回归模型预测的log(IC50)全部集中在6.8–7.2之间,缺乏区分度
    这通常意味着特征工程失败。检查feature_selection_rfe.py的输出:如果RFE选出的15个特征中,有10个是高度相关的(如MolLogP, HeavyAtomMolLogP, LabuteASA),说明相关性分析没做好。回到feature_selection_correlation.py,将共线性阈值|r| > 0.95调低至0.90,强制剔除更多冗余特征。

  • 问题:结构优化后,新分子的SMILES无法被rdkit解析(None
    这表明扰动违反了化学规则。在safe_mutate()函数中,添加调试语句:print("Mutated SMILES:", new_smiles); print("RDKit parse result:", Chem.MolFromSmiles(new_smiles))。常见原因是:在芳香环上添加了一个sp3杂化的氮,破坏了芳香性。解决方案是在扰动后,强制调用Chem.rdmolops.RemoveHs(mol)Chem.rdmolops.AddHs(mol)来重置氢原子,再Chem.rdMolTransforms.Compute2DCoords(mol)

  • 问题:LightGBM的predict_proba()输出概率全为0.5或1.0,毫无区分度
    这是过拟合的典型信号。检查classification_active.py中LightGBM的num_leaves参数,若设为64,则过大。将其改为31,并增加min_data_in_leaf=20,强制每个叶子节点至少有20个样本,提升泛化性。

5.3 赛场与教学场景下的实用技巧

  • 数学建模竞赛技巧:在答辩环节,不要花5分钟讲XGBoost原理。拿出pycode/visualization_pdp.py生成的logP_vs_IC50.png,指着图说:“我们的模型发现,当logP在3.5–4.5时,预测IC50最低,这与文献报道的‘最佳logP窗口’完全吻合,证明了模型的化学合理性。”——这比任何指标都更有说服力。

  • 教学演示技巧:给学生讲结构优化时,不要直接跑完整流程。先用pycode/debug_optimization.py,它会固定一个分子,只扰动一个位置(如苯环上的一个H),并打印出所有可能的取代基及其预测分数。学生能直观看到:“把H换成F,分数+0.3;换成Cl,分数-0.1”,从而理解优化的本质是“试错与评估”。

  • 延伸研究建议:本包是“确定性优化”,下一步可升级为“贝叶斯优化”。用scikit-optimize库,将目标函数包装为@use_named_args(space),定义超参数空间(如space=[Real(0.1, 1.0, prior='log-uniform', name='w1'), ...]),让算法自动寻找最优的权重组合。这能进一步提升优化效率。

我在实际使用中发现,最宝贵的不是最终的优化分子,而是整个流程中生成的所有中间文件:results/correlation_heatmap.png揭示了分子属性间的内在联系;results/rfe_feature_stability.csv给出了每个特征被选中的频率,这是撰写QSAR论文“讨论”部分的直接素材;results/optimization_history.csv记录了每一次扰动的得分,可用于分析优化路径的收敛性。把这些文件打包进你的最终报告,远比堆砌一堆模型指标更有力量。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:一套开箱即用的Python代码包,完整复现2021华为杯数学建模D题任务:从分子描述符数据出发,先做相关性分析和递归特征消除(RFE)筛选关键特征;接着用随机森林、XGBoost建模预测IC50值(回归任务);再用SVM、LightGBM判断化合物是否具有抗乳腺癌活性(二分类任务);最后在多约束条件下开展化合物结构优化求解。所有脚本均含逐行中文注释,涵盖数据清洗、标准化、交叉验证、超参调优、结果可视化等环节。pycode目录存放主流程代码,Math2021和2021 math子目录提供原始赛题文档、参考数据及中间处理结果,README.md详细说明环境依赖(Python 3.8+、scikit-learn、xgboost、lightgbm、matplotlib等)和分步执行命令。适合数学建模参赛者快速上手,也适合作为计算化学、AI制药方向的教学实践案例。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐