一、程序代码简介
1.1. 文献:
1.2. 代码:gitee仓库(大陆推荐)、github仓库
1.3. 功能:
集成急性经口全身毒性二元/多元分类回归模型的层次H-QSAR建模方法的实现
1.4. 数据集
本研究中使用的大鼠急性经口毒性数据由国家毒理学计划机构间替代毒理学方法评价中心(NICEATM)和美国环保署国家计算毒理学中心(NCCT)从许多公共可用数据集和资源中收集。完整的描述和实际的数据集可以在这里找到。整个数据集由11992个化合物组成,被半随机分成一个训练集(75%)和一个外部测试集(25%),项目组织者对LD50分布的覆盖率相当。
训练集和测试数据在train_test_sets文件夹中。
1.5. 建模策略
上图显示了构建层次QSAR模型的总体工作流程。利用机器学习算法和化学描述符/指纹的不同组合,建立了基本回归模型、二元模型和多类模型(共60个模型)。通过10次交叉验证生成基础模型的偏离预测。折叠外的预测被连接在一起,并作为输入(元特征)用于构建分层回归、二元和多类模型。
1.6. Jupyter Notebook代码本使用流程
1.6.1 准备标签:
- (1)labels.ipynb
1.6.2 基础模型:
- (2)计算基本模型的化学描述符/指纹:descriptors.ipynb
- (3)描述符选择:descriptors_selections.ipynb
- (4)基础模型的超参数搜索:Base_models_selection.ipynb
- (5)用最优超参数建立基础模型:Base_models.ipynb
1.6.3 分层模型
- (6)元特征:Hierarchical_features.ipynb
- (7)层次模型的超参数调整:Hierarchical_models_selection.ipynb
- (8)用最优超参数建立层次模型:Hierarchical_models.ipynb
1.6.4 模型评价
- (9)评估交叉验证和测试集性能:Model_evaluation.ipynb
二、代码运行与理解
2.1. labels.ipynb
- (1)导入库或模块
# 导入库/模块
import pandas as pd
import numpy as np
import math
import joblib
from rdkit import Chem
from rdkit.Chem import PandasTools
from rdkit.Chem import Descriptors
from sklearn.preprocessing import LabelEncoder
- (2)导入训练集和测试集
train = pd.read_csv('../data/train_test_sets/train.csv', index_col = 'CASRN') # 训练集
test = pd.read_csv('../data/train_test_sets/test.csv', index_col = 'CASRN') # 测试集
# 探索数据
train # 或者用下述语句中的任一条
train.head(1)
train.head()
train.shape
- (3)添加RoMol列
# 利用PandasTools中AddMoleculeColumnToFrame方法添加分子结构图列
PandasTools.AddMoleculeColumnToFrame(train,smilesCol='SMILES')
PandasTools.AddMoleculeColumnToFrame(test,smilesCol='SMILES')
- (4)添加Mw描述符列
train['MW'] = train.apply(lambda x: Descriptors.MolWt(x['ROMol']), axis=1)
test['MW'] = test.apply(lambda x: Descriptors.MolWt(x['ROMol']), axis=1)
- (5)定义logLD50转换函数(单位由mgkg转换为mmolkg)
def logLD50(df):
logLD50_mmolkg = []
for i in range(df.shape[0]):
if pd.isna(df['LD50_mgkg'][i]):
logLD50_mmolkg.append(df['LD50_mgkg'][i])
else:
logLD50_mmolkg.append(math.log10(float(df['LD50_mgkg'][i])/float(df['MW'][i])))
return logLD50_mmolkg
- (6)转换logLD50,并新增1列
train['logLD50_mmolkg'] = logLD50(train)
test['logLD50_mmolkg'] = logLD50(test)
- (7)定义二元毒性和二元剧毒函数
def binary_toxic(df):
toxic = []
for i in range(df.shape[0]):
if pd.isna(df['nontoxic'][i]):
toxic.append(df['nontoxic'][i])
else:
toxic.append(1 if df['nontoxic'][i] is False else 0)
return toxic
def binary_verytoxic(df):
verytoxic = []
for i in range(df.shape[0]):
if pd.isna(df['very_toxic'][i]):
verytoxic.append(df['very_toxic'][i])
else:
verytoxic.append(0 if df['very_toxic'][i] is False else 1)
return verytoxic
- (8)将化合毒性和剧毒性质转换为0/1值,并新增两列
train['toxic'] = binary_toxic(train)
test['toxic'] = binary_toxic(test)
train['verytoxic'] = binary_verytoxic(train)
test['verytoxic'] = binary_verytoxic(test)
- (9)删除不需要的列
train = train.drop(['nontoxic', 'very_toxic', 'ROMol', 'MW', 'LD50_mgkg'], axis=1)
test = test.drop(['nontoxic', 'very_toxic', 'ROMol', 'MW', 'LD50_mgkg'], axis=1)
- (10)数据集的列重排
columnsTitles = ['SMILES', 'logLD50_mmolkg', 'verytoxic', 'toxic', 'EPA_category', 'GHS_category'] #新列顺序
train = train.reindex(columns=columnsTitles)
test = test.reindex(columns=columnsTitles)
- (11)保存数据(csv格式)
train.to_csv('../data/train_test_sets/train_labels.csv')
test.to_csv('../data/train_test_sets/test_labels.csv')
- (12)定义编码函数
def get_labelencoder(df_labels):
encoder_verytoxic = LabelEncoder().fit(df_labels[~df_labels['verytoxic'].isnull()]['verytoxic'].values)
encoder_toxic = LabelEncoder().fit(df_labels[~df_labels['toxic'].isnull()]['toxic'].values)
encoder_epa = LabelEncoder().fit(df_labels[~df_labels['EPA_category'].isnull()]['EPA_category'].values)
encoder_ghs = LabelEncoder().fit(df_labels[~df_labels['GHS_category'].isnull()]['GHS_category'].values)
return encoder_verytoxic, encoder_toxic, encoder_epa, encoder_ghs
- (13)编码