简介本资源面向参加研究生数学建模竞赛、从事机器学习特征工程与生物信息分析的读者围绕2021年D题第一问展开解决从高维分子描述符中筛选关键变量的问题。资源包共14个文件约23.32MB包含xlsx数据集、csv结果表、py与ipynb源码、png可视化图表及doc说明文档覆盖数据读取、方差筛除、随机森林置换特征重要性排序到相关性去冗余的完整流程。代码含详细注释可复现前20个对生物活性影响最显著的分子描述符并附有分子描述符含义解释便于理解变量物理意义。已有265人学习下载适合希望掌握高维特征选择方法、积累抗乳腺癌药物研究案例的读者参考借鉴。1. 分子描述符筛选这道题考的不是建模是判断力很多人第一次拿到 2021 年研究生数学建模 D 题第一题第一反应是打开 Python 直接上随机森林把几千个分子描述符一股脑丢进去跑特征重要性然后挑前二十个交差。如果你也这么想这道题大概率会翻车。这道题真正考的不是你会不会调 sklearn而是你能不能在几千维特征里做出有依据的取舍——它本质上是一道披着机器学习外衣的数据分析题核心考点是描述符筛选逻辑、降维与特征选择的区别、以及可视化论证能力。适合谁适合已经会跑随机森林、但在“为什么选这些特征”上说不清楚的人。拿分关键不在模型精度多高而在你的筛选流程能不能自圆其说先做数据清洗和缺失值处理再做相关性分析和方差过滤最后才轮到随机森林或 LASSO 做重要性排序。顺序错了后面全白搭。2. 考点拆解分子描述符筛选到底考哪几层能力2.1 描述符的三大类与筛选前的预处理分子描述符通常分成三类组成描述符分子量、原子数、环数、拓扑描述符连接性指数、Wiener 指数、几何/量子化学描述符偶极矩、HOMO-LUMO 能隙。题目给的数据表里往往混着这三类而且量纲差异极大——分子量在几百电负性在个位数HOMO-LUMO 能隙可能只有零点几。如果不做标准化就直接丢进模型量纲大的描述符会天然占据更高重要性这是最常见的翻车点。预处理的标准流程是先检查缺失值和异常值缺失比例超过 30% 的描述符直接删列少量缺失用中位数填充然后对每个描述符做方差过滤方差接近零的列说明它在样本间几乎不变对区分分子没有贡献直接剔除最后做标准化用 z-score 或 min-max 都行但要在训练集上拟合 scaler再 transform 测试集不能全量拟合。import pandas as pd from sklearn.preprocessing import StandardScaler # 假设 df 是原始描述符表最后一列是目标值 desc_cols [c for c in df.columns if c ! target] # 1. 删除缺失比例过高的列 threshold 0.3 missing_ratio df[desc_cols].isnull().mean() drop_cols missing_ratio[missing_ratio threshold].index.tolist() df df.drop(columnsdrop_cols) # 2. 剩余缺失用中位数填充 df[desc_cols] df[desc_cols].fillna(df[desc_cols].median()) # 3. 方差过滤剔除方差小于 0.01 的描述符 from sklearn.feature_selection import VarianceThreshold selector VarianceThreshold(threshold0.01) selector.fit(df[desc_cols]) keep_cols [c for c, k in zip(desc_cols, selector.get_support()) if k] df df[keep_cols [target]] # 4. 标准化 scaler StandardScaler() df[keep_cols] scaler.fit_transform(df[keep_cols])这段代码的关键参数是threshold0.01它控制方差过滤的激进程度。阈值太高会误删有用特征太低则起不到过滤效果。实际做题时可以先看方差分布直方图选一个明显低于主体分布的拐点。标准化那一步必须放在方差过滤之后因为标准化会改变方差量级顺序反了方差过滤就失效了。2.2 相关性分析什么时候该删什么时候该留预处理完之后下一步是相关性分析。很多同学一看到两个描述符相关系数 0.95 就立刻删掉一个这其实过于粗暴。正确的做法是分情况如果两个描述符高度相关且属于同一类比如两个拓扑指数保留与目标变量相关性更高的那个如果它们分属不同类比如一个组成描述符和一个量子化学描述符即使数值上相关也可能各自携带独立信息这时候应该保留让后续模型自己判断。画相关性热力图是必须的但不要只画图不解读。答题时要写清楚我以 0.9 为阈值筛出了 X 对高相关描述符其中 Y 对属于同类冗余予以剔除Z 对虽然相关但分属不同类别暂保留进入下一轮。这种有判断的表述才是阅卷人想看到的。import seaborn as sns import matplotlib.pyplot as plt import numpy as np corr_matrix df[keep_cols].corr().abs() upper corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k1).astype(bool)) # 找出相关系数大于 0.9 的描述符对 high_corr_pairs [(col, row) for col in upper.columns for row in upper.index if upper.loc[row, col] 0.9] # 热力图 plt.figure(figsize(12, 10)) sns.heatmap(corr_matrix, cmapcoolwarm, center0) plt.title(Descriptor Correlation Heatmap) plt.show()np.triu的作用是只保留上三角矩阵避免重复计算同一对描述符。k1表示排除对角线自身。热力图的center0让颜色以零为中心对称正负相关一目了然。这一步的输出不只是图还要有一张高相关描述符对的表格标注每对的类别归属和最终取舍决定。2.3 随机森林特征重要性参数怎么调、结果怎么读到了随机森林这一步很多人直接RandomForestRegressor()用默认参数跑然后feature_importances_一排序就完事。这样做有两个问题一是默认树数量 100 可能不够稳定二是没有做交叉验证重要性排序可能只是某一次随机划分的产物。建议的做法是树数量设到 500 以上用cross_val_score看模型在不同折上的表现是否稳定然后用permutation_importance代替默认的feature_importances_。默认重要性基于不纯度减少对高基数特征有偏好排列重要性则直接看打乱某个特征后模型性能下降多少更可靠。from sklearn.ensemble import RandomForestRegressor from sklearn.inspection import permutation_importance from sklearn.model_selection import train_test_split X df[keep_cols] y df[target] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) rf RandomForestRegressor(n_estimators500, max_depthNone, min_samples_leaf2, random_state42, n_jobs-1) rf.fit(X_train, y_train) # 排列重要性 perm_imp permutation_importance(rf, X_test, y_test, n_repeats10, random_state42) imp_df pd.DataFrame({ descriptor: keep_cols, importance_mean: perm_imp.importances_mean, importance_std: perm_imp.importances_std }).sort_values(importance_mean, ascendingFalse) print(imp_df.head(20))n_estimators500是稳定性和计算时间的折中min_samples_leaf2防止过拟合n_repeats10表示每个特征打乱十次取平均。输出里importance_std很重要——如果某个描述符的重要性均值高但标准差也大说明它的贡献不稳定答题时要注明这一点。最终选前 15 到 20 个描述符比较合理太少会丢信息太多则失去筛选意义。3. 真题演练三道高频问法的答题思路3.1 “请说明你筛选描述符的完整流程”这道题几乎是必问的考的是你的逻辑链条是否完整。答题模板按四步走第一步数据清洗说清楚缺失值怎么处理、异常值怎么判断第二步初步过滤说清楚方差过滤和相关性分析的阈值怎么定的第三步模型筛选说清楚用的什么模型、参数怎么设的、重要性怎么算的第四步验证说清楚怎么确认选出来的描述符是有效的比如用选出的特征重新训练模型对比性能。面试官最想听的是每一步的“为什么”而不是“我做了什么”。比如你说“我用 0.9 作为相关性阈值”后面一定要跟一句“因为超过 0.9 的描述符对在化学意义上通常代表同类信息冗余而 0.8 以下可能仍有独立贡献”。这种解释才是加分项。3.2 “随机森林和 LASSO 做特征选择有什么区别你选哪个”这是考察你对方法适用场景的理解。随机森林属于嵌入式方法能捕捉非线性关系对描述符之间的交互作用敏感但重要性排序不如 LASSO 直观LASSO 属于惩罚线性模型会把不重要的特征系数压到零筛选结果更稀疏、更可解释但只能捕捉线性关系。答题思路如果题目要求可解释性强、最终模型是线性的选 LASSO如果目标是预测精度、允许非线性选随机森林。实际做题时可以两个都跑对比选出的描述符交集和各自模型的交叉验证得分取交集作为最终特征集这样既有非线性捕捉能力又有稀疏性保证。3.3 “你怎么证明筛选后的描述符比原始全集更好”这道题考的是验证意识。很多人做完筛选就直接交卷没有做对比实验。正确的答法是用原始全集训练一个基线模型记录交叉验证的 R² 或 RMSE再用筛选后的特征集训练同样的模型对比两个得分。如果筛选后得分持平或更高说明去掉的是冗余特征如果得分下降明显说明筛过头了需要放宽阈值。还要注意一点对比时要用同一套交叉验证划分否则随机性会导致结论不可靠。可以用KFold固定随机种子确保两个模型在相同的折上评估。4. 易错点这五个坑踩一个就丢分4.1 先标准化再方差过滤错在哪标准化会把所有描述符的方差缩放到同一量级原本方差很小的特征标准化后方差变成 1方差过滤完全失效。为什么错没理解标准化的数学含义它改变的就是方差。怎么答对顺序必须是先方差过滤再标准化或者用VarianceThreshold时不标准化等筛选完再统一标准化。4.2 用全量数据拟合 scaler错在哪在训练集和测试集合并后的数据上拟合StandardScaler导致测试集的信息泄漏到训练过程中。为什么错这会让交叉验证得分虚高实际预测时性能下降。怎么答对永远在X_train上fit_transform在X_test上只transform。4.3 只看特征重要性不看稳定性错在哪跑一次随机森林按feature_importances_排序取前二十没有检查这些特征在不同折上是否稳定。为什么错随机森林本身有随机性单次结果可能不可复现。怎么答对用permutation_importance配合n_repeats或者跑多次随机森林取重要性均值标准差大的特征要标注出来。4.4 相关性分析一刀切错在哪所有相关系数超过阈值的描述符对都删掉一个不管它们属于什么类别。为什么错不同类别的描述符即使数值相关也可能携带独立物理化学信息。怎么答对按类别分组做相关性分析同类冗余才删跨类保留并说明理由。4.5 筛选后不做验证直接下结论错在哪选完描述符就写“这些描述符最重要”没有用模型性能对比来支撑。为什么错重要性排序不等于预测能力去掉某些特征后模型可能变差。怎么答对用筛选后的特征重新训练模型和全集基线对比交叉验证得分用数据说话。5. 答题节奏从读题到交卷的时间分配与检查清单这道题在竞赛中的建议时间分配是读题和理清数据 20 分钟预处理和初步筛选 40 分钟模型训练和重要性分析 40 分钟验证和可视化 30 分钟写作和检查 30 分钟。总共约两个半小时留出半小时缓冲。读题阶段重点确认三件事目标变量是什么、描述符有多少列、有没有缺失值。这三件事决定了后面所有步骤的方向。预处理阶段不要追求一步到位先把明显有问题的列处理掉后面可以迭代。模型阶段先跑一个基线再调参不要一上来就追求最优参数。验证阶段一定要做对比实验这是拉开差距的地方。检查清单按这个顺序过一遍缺失值处理了吗、方差过滤和标准化的顺序对吗、相关性分析有没有分类讨论、随机森林的树数量够不够、重要性有没有做稳定性检查、筛选后的特征有没有做性能对比、可视化图有没有标注清楚坐标轴含义、结论有没有数据支撑。这八条每条都对应一个常见失分点交卷前逐条确认。我自己的血泪经验是第一次做这类题时我花了大量时间调随机森林的参数想把 R² 从 0.85 提到 0.87结果最后写作时间不够筛选逻辑写得含糊反而丢了更多分。从那以后我每次做特征筛选类题目都强制先写筛选流程的文字框架再填代码结果确保逻辑链条完整。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?