📋 题目描述
题目描述
NS-2026-04 分子炼金术:小分子性质预测
赛题任务
本题编号为 NS-2026-04。
任务介绍
你是一名分子性质预测员,需要根据小分子的 SMILES 表示预测其物理化学性质或活性指标。参赛者需要从分子字符串中构造描述符、fingerprint 或图结构,并输出每个测试分子的连续预测值。
你的任务是:
- 解析训练集 SMILES 和目标值。
- 构建能跨 scaffold 泛化的分子表示和模型。
- 对测试分子输出连续预测值。
赛题背景
AI for Science 正在成为机器学习的重要方向。小分子性质预测可用于药物发现、材料筛选和实验优先级排序。与普通表格回归不同,分子任务需要处理图结构、官能团、化学骨架和分布外 scaffold。
高分方案通常来自合理的分子表示、scaffold split 验证、特征集成和对异常 SMILES 的稳健处理。
赛题数据
在本页下方“相关资源”处下载数据包,或在 https://modelscope.cn/datasets/SteamedFresh/NS-2026-A-data 处获取。
NS-2026-04/├── train.csv├── test.csv├── scaffold_split.json├── features/│ ├── hashed_smiles_train.npz│ └── hashed_smiles_test.npz├── example_submission/│ └── results.csv└── tools/ ├── check_format.py └── make_features.py数据说明
train.csv 字段:
| 字段 | 类型 | 含义 |
|---|---|---|
id | string | 分子 ID |
smiles | string | 分子 SMILES |
target | float | 目标性质 |
test.csv 不含 target。features/ 提供预提取 hashed SMILES token fingerprint,降低 RDKit 安装门槛。scaffold_split.json 给出推荐本地训练/验证划分。
正式数据规模
| 文件 | 规模 |
|---|---|
train.csv | 8500 条 |
test.csv | 3000 条 |
hashed_smiles_train.npz | 8500 x 2048 |
hashed_smiles_test.npz | 3000 x 2048 |
公开特征使用 2048 维 hashed SMILES token fingerprint,可直接用于线性模型、树模型或其它表格回归模型。选手也可以自行安装 RDKit、构建 Morgan fingerprint、分子图或使用符合规则的公开预训练分子模型。
本题鼓励使用 scaffold-aware validation。公开包中的 scaffold_split.json 提供一个推荐本地验证划分,选手也可以自行构造验证方案。
注意事项
- 使用外部预训练模型或外部数据时,必须说明来源、许可证、是否公开和是否含测试标签风险。
评测说明
提交说明
提交文件必须压缩为 NS-2026-04-answer.zip,压缩包内只包含 results.csv。
提交格式
id,predictionmol_001,0.732格式要求:
- 必须包含且仅包含
id,prediction两列。 - 必须覆盖全部测试分子。
prediction必须为有限数值。- 不允许重复 ID、缺失 ID 或测试集外 ID。
得分计算
本题为单目标回归任务,总分 800。评分采用“连续得分 + gold-band 阈值满分”口径:
- 普通提交按 RMSE、Spearman 和格式合法性连续计分
- 达到 gold-band 的优秀公开边界建模方案直接记为满分
| 指标 | 分值 |
|---|---|
| RMSE 得分 | 500 |
| Spearman 得分 | 250 |
| 格式合法性 | 50 |
评分公式:
raw_score = 500 * max(0, 1 - RMSE / rmse_ref) + 250 * max(0, Spearman) + 50if RMSE <= 0.25 and Spearman >= 0.96: score = 800else: score = raw_score正式题包中 rmse_ref = 0.80。评分脚本保证最终分数范围为 0 到 800。
gold-band 的含义是:选手方法已经在隐藏测试集上同时达到足够低的回归误差和足够稳定的排序质量,可视为本题公开边界下的优秀满分解。该阈值不是要求恢复出隐藏 reference 的逐样本精确生成机制;
示例提交只用于说明格式,不代表合理成绩。建议选手使用 scaffold_split.json 或自行构造 scaffold-aware validation,不建议随机划分作为唯一验证依据。
无效提交情况
以下情况将得到 0 分:
- CSV 无法解析。
- 表头不是且仅不是
id,prediction。 - 测试 ID 缺失、重复或出现测试集之外 ID。
prediction不是有限数值。- 压缩包内缺少
results.csv或包含文件夹/额外文件。
条款
AI 协助规则
本题 AI 协助等级为 A1。
Writeup 补充要求
获奖候选队伍必须按通用 Writeup 公告提交方法概述、任务理解、关键改进、验证与复现、证据截图和代码包,并提供 AI 使用声明。A1 题若让 AI 接触测试输入并生成最终预测,或让 Agent 托管实验并生成提交,原则上视为违反等级规则。
Writeup 必须说明分子表示方式、本地验证方式,优先使用 scaffold split。必须提供特征生成脚本日志或预提取特征版本 hash,展示目标分布、异常 SMILES 处理和至少 3 个预测失败案例。
如果使用外部预训练模型或外部数据,必须说明来源、许可证、是否公开和是否含测试标签风险。
获奖候选队伍必须提交可复现证据,包括特征生成脚本、训练/推理脚本、环境依赖、随机种子、关键运行日志和 AI 使用声明。若使用 RDKit、分子预训练模型或外部分子库,必须列出版本、来源、许可证和是否可能包含本题测试 SMILES 的标签。
Writeup需包含最终提交压缩包文件 SHA256,指平台上传的 NS-2026-04-answer.zip 的 SHA256。
1. 基本信息
-
队长用户名:Ayin
-
队伍名:L.Corp
-
题号:NS-2026-04
-
最终官网提交记录:
- 提交时间:2026-05-28 04:44:35
- 最终有效得分:622.94

2. 解题思路
这题要用 SMILES 字符串预测小分子的物化性质,是个单目标回归任务。最麻烦的地方在于测试集里的分子骨架和训练集差得很远,还要能处理极端高值和少数格式有问题的 SMILES。
最终方案:先写规则把训练集和测试集里格式奇怪的 SMILES 修掉,然后把几种计数型分子指纹取 log 之后拼在一起当特征,用骨架分组交叉验证来估计泛化效果,最后用一个带物理描述符的 BayesianRidge 做 Stacking,主要是为了解决树模型在极端值上容易偏保守的问题。最终线上拿到了 622.94 分。
2.1 分子表示
没有用图神经网络,因为 GNN 在骨架分布差异比较大的时候很容易过拟合。最终用的是几类指纹拼在一起:
- 计数型指纹:Morgan (r=2)、Morgan (r=3)、Topological Torsion、Atom Pairs,各 2048 维,频次用
log1p平滑。这类指纹记录的是官能团出现了几次,不只是”有没有”,对回归任务更有用。 - 二值型指纹:MACCS Keys(167维)、RDKit Path-based FP(2048维)、Avalon FP(2048维)。
- RDKit 2D 物化描述符:208 维,用 RobustScaler 标准化后截到
[-5, 5]。
拼完总特征维度是 14,711,局部官能团信息和整体物化性质都覆盖到了。
2.2 验证方式
用的是骨架分组 5 折交叉验证(GroupKFold),不是随机切分。
先用 RDKit 的 MurckoScaffold 给 8500 条训练样本算 Bemis-Murcko 骨架,然后把相同骨架的分子强制分在同一折。这样每折的验证集和训练集里没有同骨架的分子,验证结果能真实反映模型在没见过的骨架上的表现,而不是让模型靠”骨架相似”蒙混过关。
5 折跑完之后能得到覆盖全部 8500 条样本的 Out-Of-Fold 预测,所有消融实验和 Stacking 超参的调整都是看这个 OOF 的 RMSE 和 Spearman 来判断的。
2.3 目标值分布
训练集的 target 均值是 1.21,标准差 0.94,范围 -1.59 到 7.46。分布右偏比较明显,大多数分子集中在 [-1.0, 4.0],超过 4.5 的很少。这导致树模型在高值区域预测比较保守,容易往均值缩,Stacking 里加物理描述符就是为了解这个问题。
3. 主要改进和实验结果
方案迭代过程中,以下三个改动对线上泛化帮助最大:
1 把二值指纹换成计数指纹,频次取 log
- 改了什么:把 Morgan(r=2,3)、Topological Torsion、Atom Pairs 的 bit 指纹换成 count 指纹,频次用
log1p处理。 - 效果:本地 1700 条验证集上,Stacking 的 RMSE 从 0.2800 降到了 0.2707,Spearman 从 0.9399 涨到了 0.9524。官能团出现几次对目标值确实有意义,光知道”有没有”不够用。
2 换成全量骨架 GroupKFold 交叉验证
- 改了什么:不再固定留 1700 条做验证集,改成对全部 8500 条做骨架分组 5 折交叉。
- 效果:线上得分从 623.06 涨到 623.96。全量训练让模型见到了更多种类的骨架,泛化性更好。
3 Stacking 里加入 Top 50 物理描述符
- 改了什么:在基模型的 OOF 预测之外,额外拼接与目标值相关性最强的 50 个 RDKit 2D 描述符,用
BayesianRidge做元回归。 - 效果:本地全量 OOF RMSE 从 0.2886 降到了 0.2794,Spearman 升到 0.9507。元学习器拿到描述符之后有了线性外推的能力,预测超出树模型”历史经验”的极端高值时不再一味往均值靠。
预测失败案例分析
从全量 OOF 预测里找了误差最大的三个样本来看看模型在哪里出了问题:
-
全氟稠环烷烃(
mol_train_07165)- SMILES:
FC1(F)C(F)(F)C(F)(F)C2(F)C(F)(C1(F)F)C(F)(F)C(F)(F)C1(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C12F - 真实值:
7.4558| 预测值:4.4005| 误差:3.0553 - 分析:这是训练集里目标值最高的分子(7.46),所有氢都被氟替换的稠环结构。这类高氟稠环在训练集里几乎没有,属于极端长尾。树模型没法做特征外推,Stacking 加了描述符也还是低估了不少。
- SMILES:
-
全氟直链烷烃(
mol_train_01309)- SMILES:
FC(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)F - 真实值:
5.6748| 预测值:3.7534| 误差:1.9214 - 分析:全氟癸烷,长链氟碳。和上面一样,这类结构太少见,模型没学好,预测偏低。
- SMILES:
-
放射性同位素标记分子(
mol_train_01998)- SMILES:
c1c2c(c(c(c1[131I])[O-])[131I])Oc3c(cc(c(c3[131I])[O-])[131I])C24c5c(c(c(c(c5Cl)Cl)Cl)Cl)C(=O)O4 - 真实值:
4.8691| 预测值:3.1998| 误差:1.6693 - 分析:含放射性同位素
[131I](碘-131)的高氯代染料衍生物。Morgan 指纹会把[131I]识别成和普通碘完全不同的子结构,但这种原子在训练集里几乎没出现过,对应的指纹位基本是空的,模型把它当噪声处理了。
- SMILES:
4. 复现说明
运行环境
| 项目 | 信息 |
|---|---|
| 操作系统 | Windows 11 |
| Python 版本 | 3.12.11 |
| PyTorch 版本 | 2.7.1+cu128 |
| RDKit 版本 | 2026.3.2 |
| LightGBM 版本 | 4.6.0 |
| XGBoost 版本 | 3.2.0 |
| CatBoost 版本 | 1.2.10 |
| scikit-learn 版本 | 1.7.0 |
| CPU 型号 | AMD Ryzen 7 9800X3D 8-Core Processor |
| GPU 型号 | NVIDIA RTX 5090 |
| 内存 (RAM) | 48 GB |
| CUDA 版本 | 13.2 |
随机种子与核心超参数
- 随机种子:全程固定
SEED=42 - 交叉验证:5 折 GroupKFold(按 Murcko Scaffold 分组)
- LightGBM:
num_leaves=63,max_depth=8,learning_rate=0.02 - XGBoost:
max_depth=6,learning_rate=0.015 - CatBoost:
depth=6,learning_rate=0.025 - MLP:
hidden_dims=(1024, 512, 256),dropout=0.4 - Stacking 描述符:与目标值相关性排名前 50 的 RDKit 2D 描述符
- Stacking 元回归器:
BayesianRidge()
预计运行时间
- 特征提取:约 2 分钟,纯 CPU
- 5 折基模型训练:约 15–20 分钟,GPU 显存约 6GB
- Stacking 元回归与推理:几秒,内存占用很小
数据预处理
训练集和测试集里有少量格式有问题的 SMILES,由 fix_smiles.py 自动分级修复。主要有三类问题:
- 铝原子价超限:SMILES 里出现
[AlH3]这种非标准价态,RDKit 解析会报错。用正则替换成[Al]即可。 - 氮原子显式 H 导致价超限:脒/胍基等结构中显式写了
[NH2]或[NH]导致价态不合法,去掉显式 H 让 RDKit 自动填充。 - 重过渡金属配位价报错:含铂
[Pt]的配合物有时会让 RDKit 报错,用sanitize=False宽松模式加载能正常通过,不影响指纹计算。
复现步骤
# 1. 安装依赖pip install rdkit lightgbm xgboost catboost scikit-learn pandas torch tqdm
# 2. 特征提取(修复 SMILES,计算 log1p 计数指纹与 RobustScaler 描述符)python src/build_features_v2.py
# 3. 基模型训练(骨架 GroupKFold 5 折,生成全量 OOF)python src/train_model_full.py
# 4. Stacking(拼接 OOF + Top 50 描述符,训练 BayesianRidge,输出测试集预测)python src/train_stacking_v2.py
# 5. 打包提交(生成 results.csv,格式检查,打包)python src/predict_and_submit_full_opt.py外部数据与开源库声明
- 外部预训练模型或外部数据:无。没用任何外部分子预训练模型或第三方数据。
- 化学库:用了 RDKit(版本 2026.3.2),BSD 开源许可。所有特征都是从 SMILES 本地算出来的,不存在测试标签泄露的风险。
5. AI 使用声明
全局说明
- 本队使用的 AI 工具:Gemini、Claude
- 主要用途:资料查询 / 代码辅助
逐题声明
NS-2026-04
- 官方等级:A1
- 实际使用:资料查询 / 代码辅助
- AI 是否接触完整题面:是
- AI 是否接触测试输入:否
- AI 是否接触提交反馈或排行榜反馈:否
- AI 是否生成或修改最终提交:否
- 是否使用商业 API、闭源远程模型或托管式 Agent:是
- 详细说明:使用了 Gemini 和 Claude 两个闭源远程模型,主要用于资料查询和代码辅助,还有相关专业化学知识解答和业界常用处理方式
Writeup 写作辅助声明
- 是否使用 AI 辅助撰写或润色:是
- 使用工具:Gemini
- 使用范围:语言润色 / Markdown 排版 / 根据本队实验记录整理段落
- AI 接触材料:代码片段 / Writeup 要求
- AI 是否生成新的实验结果、验证分数或复现命令:否
- 人工核对方式:队伍成员核对事实、代码、日志、分数和复现命令
6. 最终提交与 SHA256
-
平台提交文件名称:NS-2026-04-answer.zip
-
平台提交时间:2026-05-28 04:44:35
-
最终有效得分:622.94
-
答案 ZIP SHA256(提交文件 SHA256):1adb4d3fd451f9d35781c81dd0232a166a1dfa8ca42ffb096f70c2f56967b754
-
内部关键文件 SHA256(提交包内部 SHA256):
results.csv:67855e087039573bb9d3ce0abb14e534328a2503d39ba68518acae0dbc1469d7
-
模型文件清单:./models/stack_models_opt.pkl
-
补充说明:夜里想冲一下榜,但是忘了备份旧版,只能交最终版本,比之前最高分低一点。
7. 证据截图



部分日志因为编码问题显示乱码(GBK 和 UTF-8 的问题),但评估指标等关键数据都是正常的。



8. 代码包
代码包包含以下文件:
Ayin-NS-04/├── README.md # 本文件,含复现步骤├── requirements.txt # Python 依赖├── evidence/ # 证据截图│ ├── submission.png│ ├── log_train.png│ ├── log_predict.png│ └── sha256.png├── submission/│ └── NS-2026-04-answer.zip├── models/ # 训练好的核心模型│ └── stack_models_opt.pkl└── src/ # 源码 ├── fix_smiles.py ├── build_features_v2.py ├── train_model_full.py ├── train_stacking_v2.py └── predict_and_submit_full_opt.py如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时


















