Datawhale AI 夏令营 | 物质科学赛道Task1

目录

背景知识

比赛任务

赛事数据

数据集

Baseline

评价指标

补充知识

分子指纹

决策树(Decision Trees)

随机森林模型(Random Forest)

baseline解析

准备工作

step1 配置环境

pickle

pandas

tqdm

rdkit

numpy

step2 读取数据并使用Morgan分子指纹建模SMILES

定义mfgen()函数

定义vec_cpd_lst()函数

读取数据并向量化(vectorization)

step3 随机森林模型拟合和保存(训练过程)

step4 answer generation答案生成

思考


本次夏令营以题带练,题目为第二届世界科学智能大赛物质科学赛道:催化反应产率预测。利用历史催化反应数据,并结合AI技术,可以预测新催化反应的产率,从而有效地帮助科研人员和产业界加快高活性反应条件的筛选速度,减少资源与人力的消耗,促进新物质的创造与合成。

背景知识

反应底物和反应条件是决定其产率的关键因素。因此,我们可以利用AI模型来捕捉底物、条件与产率之间的内在联系。借助产率预测AI模型,仅需输入底物和条件的信息,我们就能够预测该反应组合下的产率,从而有效提升催化反应的条件筛选效率。

比赛任务

本次比赛提供在药物合成中常见的多种催化反应实验数据,其中包括反应的底物、包括催化剂在内的反应添加剂、反应溶剂以及反应产物,期待选手通过分析反应数据,利用机器学习、深度学习算法或者大语言模型,建立产率预测模型,从而辅助未知新反应的反应条件筛选。

任务:构建一个能够准确预测碳氮成键反应产率的预测模型

  • 通过对反应中所包含的反应底物、添加剂、溶剂以及产物进行合理的特征化,运用机器学习模型或者深度学习模型拟合预测反应的产率。或者利用训练集数据对开源大语言模型进行微调以预测反应的产率。

赛事数据

数据集

初赛数据集仅包含碳氮成键类型反应数据,其中训练集中包含23538条反应数据,测试集中包含2616条反应数据。训练集与测试集的比例接近9:1。每条训练数据包含 rxnid, Reactant1, Reactant2 , Product , Additive , Solvent , Yield字段。其中 Reactant1 , Reactant2 , Product , Additive , Solvent 字段中为对应物质的SMILES字符串,Yield字段为目标字段,是经过归一化的浮点数。

Baseline

我们提供一个基础的baseline,利用分子指纹对化合物进行编码,并且使用随机森林模型来预测反应的产率。

评价指标

实验真实结果与预测结果R^{2}决定系数来进行评测:

补充知识

本次学习活动的赛题是一个典型的回归问题,机器学习一般分为两种类型的问题:回归问题和分类问题。

回归问题:即预测的结果是连续的值。

分类问题:预测的结果是离散的值。

赛题要求就是建模SMILES式子,然后模型输出到0-1之间的连续值。

分子指纹

分子指纹将分子结构转化为一系列数字或位向量,以此表示分子的结构信息。这些特征通常包括原子和分子的电荷、大小、极性等,旨在刻画分子所具备的一些重要化学特征。

较为常见的输入格式是SMILES化学式表示,使用一些化学信息学软件/库(如RDKit、ChemAxon等)计算分子指纹。

在本项目,采用Morgan指纹表示。关于不同的化学指纹表示方法及其特点可以看Rdkit|化学指纹(fingerprint)

决策树(Decision Trees)

决策树作为机器学习算法中较为简单和常见的算法之一,可以用于解决分类和回归两类问题。

决策树用于分类问题:对于一个数据(数值、图片、视频),对于该数据节点做是非题,判断该数据节点应当向树的哪个方向走,直至叶子节点,得到该数据对应的标号。

决策树用于回归问题:叶节点不再是上述的分类,而是一个具体的实数值。

决策树的优点:①可解释性,可看到数据处理的过程【常用于银行业保险业】;②处理数值型和类别型的特征。

决策树的缺点:①不稳定性(对于数据的噪音不同,树的构建将会不同),可以属于集成学习解决该问题;②数据过于复杂会生成复杂的树,导致过拟合,针对过拟合问题可以把决策树的枝剪掉一些;③大量的判断语句(可能是if else)不容易并行,性能差。

随机森林模型(Random Forest)

随机森林是让决策树稳定的方法。

针对决策树的不稳定性缺点,随机森林模型将训练多个决策树综合得到结果,提升稳定性。

随机森林的随机性(randomness)来自于:①bagging,在训练集随机采样一些样本出来(放回导致可重复性);②在bagging出来的数值中,随机采样一些特征,而并不是全部特征。

baseline解析

准备工作

继续使用魔搭GPU环境,在对应的文件夹添加dataset压缩包。

新建终端并执行下面操作,以解压数据集。

unzip dataset.zip

step1 配置环境

!pip install pandas
!pip install -U scikit-learn
!pip install rdkit

需要安装三个库:pandas(用于数据处理和分析),scikit-learn(机器学习库),rdkit(化学信息工具)。

import pickle
import pandas as pd
from tqdm import tqdm
from sklearn.ensemble import RandomForestRegressor
from rdkit.Chem import rdMolDescriptors
from rdkit import RDLogger,Chem
import numpy as np
RDLogger.DisableLog('rdApp.*') #表示禁用 RDKit 生成的日志消息
pickle

picklePython 库中的一个模块,用于将 Python对象序列化和反序列化。pickle 可以将对象序列化为字符串或字节序列,以便在网络上传输或保存到文件中。

在Saving model to file和Load model from file步骤时,使用了pickle模块的dump方法保存为文件,load方法从文件中加载出来。

pandas

Pandas 库是一个免费、开源的第三方 Python 库,是数据分析常见工具。Datawhale开源教程项目叫 Joyful Pandas 可以学习pandas

tqdm

监测程序运行的进度,估计运行的时长,协助debug。

详细用法可见这篇博客【python第三方库】tqdm——超详细解读

rdkit

化学信息学中主要的工具,开源。网址:http://www.rdkit.org

详细用法可见博客RDkit入门

numpy

官方文档:numpy.org ,这里结合baseline中出现的语句进行介绍。

numpy的核心:ndarray ,数组对象表示固定大小项的多维、同构数组。

生成ndarray的方法有二:numpy.array() 和 numpy.zeros() ,baseline中均有体现

# 返回给定形状和类型的新数组。
numpy.array ( object , dtype = None , * , copy = True , order = 'K', subok = False , ndmin = 0 , like = None )

# 返回给定形状和类型的新数组,并用零填充。
numpy.zeros ( shape, dtype = float, order = 'C', *, like =None ) 

在向量化时用到concatenate方法,具体参数及解释如下

numpy.concatenate ( (a1, a2, ...), axis=0 ,out=None,dtype =None, casting="same_kind" )

表示沿现有轴连接一系列数组。

step2 读取数据并使用Morgan分子指纹建模SMILES

定义mfgen()函数
def mfgen(mol,nBits=2048, radius=2):
    '''
    Parameters
    ----------
    mol : mol
        RDKit mol object.
    nBits : int
        Number of bits for the fingerprint.
    radius : int
        Radius of the Morgan fingerprint.
    Returns
    -------
    mf_desc_map : ndarray
        ndarray of molecular fingerprint descriptors.
    '''
    fp = rdMolDescriptors.GetMorganFingerprintAsBitVect(mol,radius=radius,nBits=nBits)
    return np.array(list(map(eval,list(fp.ToBitString()))))

由三个参数(摩尔值、指纹的位数、指纹的半径)-->返回的是分子指纹描述符阵列

这里使用的是

fp = rdMolDescriptors.GetMorganFingerprintAsBitVect(mol,radius=radius,nBits=nBits)

生成为Morgan指纹,可用于描述分子的结构和相似性,它基于分子的拓扑结构和半径参数生成。

指纹的长度和半径参数可以根据需要进行调整,以平衡指纹的信息量和计算效率。

定义vec_cpd_lst()函数
def vec_cpd_lst(smi_lst):
    smi_set = list(set(smi_lst)) #为什么这么操作?
    smi_vec_map = {}
    # 得到了mol值,调用上面的函数,得到对应分子的分子指纹描述符阵列
    #用字典保存{分子smiles表示方式:分子指纹描述符阵列}
    for smi in tqdm(smi_set): 
    # tqdm是进度条模块,tqdm可以让我们在训练过程中看到每个epoch的进度
        mol = Chem.MolFromSmiles(smi)
        smi_vec_map[smi] = mfgen(mol)
    smi_vec_map[''] = np.zeros(2048) 
    
    #保存对应的分子指纹阵列的列表推导式
    vec_lst = [smi_vec_map[smi] for smi in smi_lst]
    return np.array(vec_lst)
读取数据并向量化(vectorization)
dataset_dir = '../dataset'   # Change this to your dataset directory
# 读训练集和测试集
train_df = pd.read_csv(f'{dataset_dir}/round1_train_data.csv') 
test_df = pd.read_csv(f'{dataset_dir}/round1_test_data.csv')
# 打印出训练集和测试集的size
print(f'Training set size: {len(train_df)}, test set size: {len(test_df)}')

# 提取训练集的反应物1/2、催化剂、溶剂的smiles表示方法
train_rct1_smi = train_df['Reactant1'].to_list()
train_rct2_smi = train_df['Reactant2'].to_list()
train_add_smi = train_df['Additive'].to_list()
train_sol_smi = train_df['Solvent'].to_list()

# 得到分子指纹描述符阵列 fingerprint=fp
train_rct1_fp = vec_cpd_lst(train_rct1_smi)
train_rct2_fp = vec_cpd_lst(train_rct2_smi)
train_add_fp = vec_cpd_lst(train_add_smi)
train_sol_fp = vec_cpd_lst(train_sol_smi)
train_x = np.concatenate([train_rct1_fp,train_rct2_fp,train_add_fp,train_sol_fp],axis=1)
train_y = train_df['Yield'].to_numpy() #将数据转换为一个numpy数组

#将测试集的内容提取出来
test_rct1_smi = test_df['Reactant1'].to_list()
test_rct2_smi = test_df['Reactant2'].to_list()
test_add_smi = test_df['Additive'].to_list()
test_sol_smi = test_df['Solvent'].to_list()

test_rct1_fp = vec_cpd_lst(test_rct1_smi)
test_rct2_fp = vec_cpd_lst(test_rct2_smi)
test_add_fp = vec_cpd_lst(test_add_smi)
test_sol_fp = vec_cpd_lst(test_sol_smi)
test_x = np.concatenate([test_rct1_fp,test_rct2_fp,test_add_fp,test_sol_fp],axis=1)

step3 随机森林模型拟合和保存(训练过程)

model fitting and saving,使用随机森林模型【这里可以调参】

# Model fitting模型拟合
model = RandomForestRegressor(n_estimators=100,max_depth=10,min_samples_split=2,min_samples_leaf=1,n_jobs=-1)
model.fit(train_x,train_y)

参数解释:

  • n_estimators=10: 决策树的个数,越多越好;但是越多意味着计算开销越大;

  • max_depth: (default=None)设置树的最大深度,默认为None;

  • min_samples_split: 根据属性划分节点时,最少的样本数;

  • min_samples_leaf: 叶子节点最少的样本数;

  • n_jobs=1: 并行job个数,-1表示使用所有cpu进行并行计算。

# Saving model to file模型保存为文件
with open('./random_forest_model.pkl', 'wb') as file:
    pickle.dump(model, file)
# Load model from file从文件中加载出来模型
with open('random_forest_model.pkl', 'rb') as file:
    loaded_model = pickle.load(file)
# Inference预测/推理
test_pred = loaded_model.predict(test_x)

step4 answer generation答案生成

ans_str_lst = ['rxnid,Yield']
for idx,y in enumerate(test_pred):
    ans_str_lst.append(f'test{idx+1},{y:.4f}')
with open('./submit.txt','w') as fw:
    fw.writelines('\n'.join(ans_str_lst))

格式符合要求。

思考

mfgen()函数:指纹的长度和半径参数可以根据需要进行调整,以平衡指纹的信息量和计算效率。

随机森林模型:决策树的个数和深度可以调参。

参考:datawhale跟李沐学AI

本周还会发布更加深入的分析文章,期待您的点赞、收藏,欢迎讨论交流!

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值