

背景概述
红外光谱特征吸收频率的预测关键在于理解官能团的振动模式与其分子结构之间的复杂关系。科学问题本质上是如何通过定量方法构建映射关系,以便在不同环境条件下预测吸收峰。这涉及到官能团的电子环境、空间构型及其相互作用,从而影响其红外光谱特征的表现。
数据探索与预处理
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting rdkit==2023.9.5 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b1/5d/570131a2ccf83e42efe3d601cf7054cb8b0ec0b390d775813fca76af9d7b/rdkit-2023.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (34.4 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 34.4/34.4 MB 4.4 MB/s eta 0:00:0000:0100:01 Collecting scikit-learn==1.4.0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/3f/61/047b353f0ad550226ef962da182b4a09b689eb6df6bd84a03e44f9ee95bb/scikit_learn-1.4.0-1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.1 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.1/12.1 MB 3.5 MB/s eta 0:00:0000:0100:01 Collecting xgboost==2.0.3 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c3/eb/496aa2f5d356af4185f770bc76055307f8d1870e11016b10fd779b21769c/xgboost-2.0.3-py3-none-manylinux2014_x86_64.whl (297.1 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 297.1/297.1 MB 2.9 MB/s eta 0:00:0000:0100:01 Requirement already satisfied: Pillow in /opt/mamba/lib/python3.10/site-packages (from rdkit==2023.9.5) (10.4.0) Requirement already satisfied: numpy in /opt/mamba/lib/python3.10/site-packages (from rdkit==2023.9.5) (1.24.2) Collecting threadpoolctl>=2.0.0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl (18 kB) Collecting joblib>=1.2.0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl (301 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 301.8/301.8 kB 848.6 kB/s eta 0:00:00a 0:00:01 Requirement already satisfied: scipy>=1.6.0 in /opt/mamba/lib/python3.10/site-packages (from scikit-learn==1.4.0) (1.10.1) Installing collected packages: threadpoolctl, rdkit, joblib, xgboost, scikit-learn Successfully installed joblib-1.4.2 rdkit-2023.9.5 scikit-learn-1.4.0 threadpoolctl-3.5.0 xgboost-2.0.3 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
数据的初步探索
SMILES IR_Characteristic_Peak 0 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=C(C=C1)C 2102.0 1 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=C(C=C1... 2107.0 2 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC(=CC=C1)OC 2106.0 3 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC(=CC=C1... 2107.0 4 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=NC=C1 2114.0
使用 RDKit 对 SMILES 进行去重
在化学数据处理中,SMILES(Simplified Molecular Input Line Entry System)是一种常用的分子结构表示方法。然而,由于分子可能有不同的 SMILES 表达方式(即同一分子可能对应多个不同的 SMILES 字符串),因此直接使用字符串比较的方法可能无法准确地识别重复的分子。为了解决这个问题,我们可以使用 RDKit
提供的分子标准化和哈希方法来进行查重。
核心库介绍
Chem
:RDKit
的核心模块,用于化学分子的读写和操作。MolToSmiles
:将分子对象转换为规范化的 SMILES 字符串。
- 使用
MolFromSmiles
将 SMILES 字符串转换为 RDKit 的分子对象。如果转换失败,返回 None。 - 使用
MolToSmiles
生成规范化的 SMILES 字符串,确保同一分子总是得到相同的 SMILES 表示。
SMILES IR_Characteristic_Peak \ 0 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=C(C=C1)C 2102.0 1 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=C(C=C1... 2107.0 2 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC(=CC=C1)OC 2106.0 3 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC(=CC=C1... 2107.0 4 [N+](=[N-])=C(C(=O)ON1C(CCC1=O)=O)C1=CC=NC=C1 2114.0 Canonical_SMILES 0 Cc1ccc(C(=[N+]=[N-])C(=O)ON2C(=O)CCC2=O)cc1 1 [N-]=[N+]=C(C(=O)ON1C(=O)CCC1=O)c1ccc(C(F)(F)F... 2 COc1cccc(C(=[N+]=[N-])C(=O)ON2C(=O)CCC2=O)c1 3 [N-]=[N+]=C(C(=O)ON1C(=O)CCC1=O)c1cccc(C(F)(F)... 4 [N-]=[N+]=C(C(=O)ON1C(=O)CCC1=O)c1ccncc1
原始数据集大小:1827 去重后数据集大小:1827
为什么要进行 SMILES 查重?
- 数据质量提升:重复的分子可能会导致模型过拟合或偏差,去重可以提高数据质量。
- 准确性:由于 SMILES 表达方式的多样性,直接的字符串比较可能无法识别重复分子。使用 RDKit 规范化 SMILES,可以确保同一分子有一致的表示。
IR 特征峰值的分布与可视化
特征工程
数据集划分
在特征工程完成后,我们需要将数据集划分为训练集和测试集。
定义特征和目标变量
目标变量 y
:我们要预测的值,即红外特征峰值。
特征列表 feature
:手工提取的化学特征,基于领域知识。
摩根指纹特征 Morgan_features
:用于描述分子结构的二进制向量。
特征矩阵 X
:模型的输入数据。
FE Processing complete.
划分训练集和测试集
基于数据的随机划分
使用train_test_split
方法,将数据集随机划分为训练集和测试集。
基于分子骨架的随机划分
数据标准化
为了提高模型的训练效果和稳定性,我们需要对数据进行标准化处理。
初始化标准化器
StandardScaler()
:将特征缩放为均值为 0,标准差为 1。
在训练集上拟合标准化器:确保标准化的均值和标准差基于训练集,避免数据泄漏。
对测试集进行转换:使用在训练集上计算的参数,对测试集进行相同的转换。
对训练集进行标准化(先拟合后转换)
拟合(fit):scaler.fit(X_train_val)
计算训练集的均值和标准差。这些参数将用于后续的数据标准化。
转换(transform):scaler.transform(X_train_val
) 使用计算得到的均值和标准差,将训练集数据标准化。
fit_transform
:是 fit
和 transform
的组合方法,简化了代码。
对测试集进行标准化(直接转换)
直接转换(transform):在测试集上仅使用 transform
方法,而不再调用 fit
。这是因为测试集的标准化必须基于训练集的均值和标准差,以避免信息泄漏。通过这种方式,确保模型在预测时只依赖于训练数据的信息,从而保持模型的泛化能力。
模型训练与评估
在本教程中,我们将使用 XGBoost 回归模型XGBRegressor
进行超参数调优和模型评估。我们将逐步讲解每个步骤,以便更好地理解整个过程。
定义模型和需要调优的超参数
参数说明:
n_estimators
:要训练的决策树的数量。更多的树可能提高模型的性能,但也会增加计算时间。
max_depth
:每棵树的最大深度。较大的深度可能捕获更多的模式,但也可能导致过拟合。
learning_rate
:学习率,控制每棵树对最终模型的贡献。较小的学习率通常需要更多的树。
subsample
:训练每棵树时使用的样本比例。通过取小于 1.0 的值,可以防止过拟合。
设置交叉验证策略
n_splits=10
:将数据分成 10 份,每次使用 9 份训练,1 份验证。
shuffle=True
:在分割之前打乱数据,以确保每个折的数据分布尽可能一致。
random_state
:设置随机种子,保证结果的可重复性。
使用 GridSearchCV 进行超参数调优
步骤解析:
创建 GridSearchCV
对象:
estimator
:指定要训练的模型。
param_grid
:提供要调优的超参数及其取值范围。
scoring
:指定评估指标。由于 GridSearchCV
默认寻找评分最高的模型,因此使用负的均方误差。
cv
:指定交叉验证策略,这里使用之前定义的 kf
。
n_jobs=-1
:使用所有可用的 CPU
核心,加速计算。
进行网格搜索:
fit
方法:在训练数据上搜索最佳超参数组合。GridSearchCV
会尝试每一种参数组合,并使用交叉验证评估性能。
GridSearchCV(cv=KFold(n_splits=10, random_state=42, shuffle=True), estimator=XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, int... max_cat_to_onehot=None, max_delta_step=None, max_depth=None, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=None, n_jobs=None, num_parallel_tree=None, random_state=42, ...), n_jobs=-1, param_grid={'learning_rate': [0.1], 'max_depth': [7], 'n_estimators': [500], 'subsample': [0.8]}, scoring='neg_mean_squared_error')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GridSearchCV(cv=KFold(n_splits=10, random_state=42, shuffle=True), estimator=XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, int... max_cat_to_onehot=None, max_delta_step=None, max_depth=None, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=None, n_jobs=None, num_parallel_tree=None, random_state=42, ...), n_jobs=-1, param_grid={'learning_rate': [0.1], 'max_depth': [7], 'n_estimators': [500], 'subsample': [0.8]}, scoring='neg_mean_squared_error')
XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, interaction_constraints=None, learning_rate=None, max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None, max_delta_step=None, max_depth=None, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=None, n_jobs=None, num_parallel_tree=None, random_state=42, ...)
XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, interaction_constraints=None, learning_rate=None, max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None, max_delta_step=None, max_depth=None, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=None, n_jobs=None, num_parallel_tree=None, random_state=42, ...)
查看最佳超参数组合
找到最佳超参数组合后,我们可以查看结果。
grid_search.best_params_
:返回具有最佳性能的超参数组合。
通过打印该结果,我们可以了解模型的最佳配置。
最佳超参数组合: {'learning_rate': 0.1, 'max_depth': 7, 'n_estimators': 500, 'subsample': 0.8}
使用最佳超参数在整个训练集上训练模型
使用找到的最佳超参数组合,在整个训练集上训练模型。
best_estimator_
:获取使用最佳超参数组合的模型实例。
再次调用 fit
方法:在整个训练集上训练模型,以充分利用所有可用的数据,提高模型的泛化能力。
XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, interaction_constraints=None, learning_rate=0.1, max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None, max_delta_step=None, max_depth=7, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=500, n_jobs=None, num_parallel_tree=None, random_state=42, ...)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
XGBRegressor(base_score=None, booster=None, callbacks=None, colsample_bylevel=None, colsample_bynode=None, colsample_bytree=None, device=None, early_stopping_rounds=None, enable_categorical=False, eval_metric=None, feature_types=None, gamma=None, grow_policy=None, importance_type=None, interaction_constraints=None, learning_rate=0.1, max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None, max_delta_step=None, max_depth=7, max_leaves=None, min_child_weight=None, missing=nan, monotone_constraints=None, multi_strategy=None, n_estimators=500, n_jobs=None, num_parallel_tree=None, random_state=42, ...)
在测试集上评估模型性能
- 决定系数(R²):反映模型解释变量变异的程度,取值范围为 0 到 1。值越接近 1,模型的解释能力越强。
- 均方根误差(RMSE):均方误差(MSE)的平方根,表示预测值与真实值之间的平均偏差。值越小,模型性能越好。
测试集 RMSE: 4.144 测试集 R²: 0.959
结果分析
基于SHAPLEY VALUE的模型可解释性分析
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting shap Downloading https://pypi.tuna.tsinghua.edu.cn/packages/13/a6/b75760a52664dd82d530f9e232918bb74d1d6c39abcf34523c4f75cd4264/shap-0.46.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (540 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 540.1/540.1 kB 13.7 MB/s eta 0:00:00a 0:00:01 Collecting numba Downloading https://pypi.tuna.tsinghua.edu.cn/packages/79/58/cb4ac5b8f7ec64200460aef1fed88258fb872ceef504ab1f989d2ff0f684/numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.7/3.7 MB 36.4 MB/s eta 0:00:00a 0:00:01 Requirement already satisfied: numpy in /opt/mamba/lib/python3.10/site-packages (from shap) (1.24.2) Requirement already satisfied: scikit-learn in /opt/mamba/lib/python3.10/site-packages (from shap) (1.4.0) Requirement already satisfied: tqdm>=4.27.0 in /opt/mamba/lib/python3.10/site-packages (from shap) (4.64.1) Requirement already satisfied: pandas in /opt/mamba/lib/python3.10/site-packages (from shap) (1.5.3) Collecting cloudpickle Downloading https://pypi.tuna.tsinghua.edu.cn/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl (22 kB) Collecting slicer==0.0.8 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/63/81/9ef641ff4e12cbcca30e54e72fb0951a2ba195d0cda0ba4100e532d929db/slicer-0.0.8-py3-none-any.whl (15 kB) Requirement already satisfied: scipy in /opt/mamba/lib/python3.10/site-packages (from shap) (1.10.1) Requirement already satisfied: packaging>20.9 in /opt/mamba/lib/python3.10/site-packages (from shap) (23.0) Collecting llvmlite<0.44,>=0.43.0dev0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c6/21/2ffbab5714e72f2483207b4a1de79b2eecd9debbf666ff4e7067bcc5c134/llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (43.9 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 43.9/43.9 MB 14.1 MB/s eta 0:00:0000:0100:01 Requirement already satisfied: pytz>=2020.1 in /opt/mamba/lib/python3.10/site-packages (from pandas->shap) (2022.7.1) Requirement already satisfied: python-dateutil>=2.8.1 in /opt/mamba/lib/python3.10/site-packages (from pandas->shap) (2.8.2) Requirement already satisfied: joblib>=1.2.0 in /opt/mamba/lib/python3.10/site-packages (from scikit-learn->shap) (1.4.2) Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/mamba/lib/python3.10/site-packages (from scikit-learn->shap) (3.5.0) Requirement already satisfied: six>=1.5 in /opt/mamba/lib/python3.10/site-packages (from python-dateutil>=2.8.1->pandas->shap) (1.16.0) Installing collected packages: slicer, llvmlite, cloudpickle, numba, shap Successfully installed cloudpickle-3.1.0 llvmlite-0.43.0 numba-0.60.0 shap-0.46.0 slicer-0.0.8 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
全局性解释
局部性解释

