预训练大模型在新冠药物研发中崭露头角——首届全球AI药物研发算法大赛基线模型详解

赛题背景

首届全球AI药物研发算法大赛,是由清华大学药学院、百度飞桨、百度智能云和临港实验室共同主办,并得到中国药学会等单位大力支持的一项全球性技术创新大赛,旨在借助百度飞桨在生物计算方向上的算法优势,通过AI Studio平台,探索AI+药学领域前沿技术,挖掘和培育优秀人才,诚邀全球范围内生物计算、人工智能等相关专业的高校师生、企业、科研机构及开发者参赛。

这次大赛聚焦于新冠小分子药物等热点议题,旨在鼓励参赛者利用人工智能方法,发掘治疗新冠病毒的潜在药物。 参赛者可以利用深度学习、分子对接等方法,预测和评估小分子与主蛋白酶之间的相互作用,以及小分子在细胞中抑制病毒复制的潜力,挖掘潜在的药物候选物。通过本次大赛,我们希望能够推动药物研发领域的创新,为未来的疾病治疗和防控工作提供有力的支持。

基线模型解析

数据探索和预处理

# 导入数据集
import pandas as pd
train_df = pd.read_csv('data/data220139/train.csv')
print(f'len of train_df is {len(train_df)}')
train_df.head()

 SMILES转3D图

# 使用分子力场将smiles转化为3d分子图,并保存为smiles_to_graph_dict.pkl文件
from threading import Thread, Lock
from pahelix.utils.compound_tools import mol_to_geognn_graph_data_MMFF3d
from rdkit.Chem import AllChem

mutex = Lock()  # 互斥锁,防止多个线程同时修改某一文件或某一全局变量,引发未知错误

def calculate_3D_structure_(smiles_list):
    n = len(smiles_list)
    global p
    index = 0
    while True:
        mutex.acquire()  # 获取锁
        if p >= n:
            mutex.release()
            break
        index = p        # p指针指向的位置为当前线程要处理的smiles
        smiles = smiles_list[index]
        print(index, ':', round(index / n * 100, 2), '%', smiles)
        p += 1           # 修改全局变量p
        mutex.release()  # 释放锁
        try:
            molecule = AllChem.MolFromSmiles(smiles)
            molecule_graph = mol_to_geognn_graph_data_MMFF3d(molecule)  # 根据分子力场生成3d分子图
        except:
            print("Invalid smiles!", smiles)
            mutex.acquire()
            with open('work/invalid_smiles.txt', 'a') as f:
                # 生成失败的smiles写入txt文件保存在该目录下
                f.write(str(smiles) + '\n')
            mutex.release()
            continue

        global smiles_to_graph_dict
        mutex.acquire()   # 获取锁
        smiles_to_graph_dict[smiles] = molecule_graph
        mutex.release()   # 释放锁

for mode in ['train', 'test']:
# for mode in ['test']:
    if mode == 'train':
        smiles_list = train_df["SMILES"].tolist()
    else:
        smiles_list = test_df["SMILES"].tolist()
    global smiles_to_graph_dict
    smiles_to_graph_dict = {}
    global p              # p为全局指针,指向即将要处理的smiles
    p = 0
    thread_count = 12      # 线程数。一般根据当前运行环境下cpu的核数来设定
    threads = []
    for i in range(thread_count):
        threads.append(Thread(target=calculate_3D_structure_, args=(smiles_list, )))
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    pkl.dump(smiles_to_graph_dict, open(f'work/{mode}_smiles_to_graph_dict.pkl', 'wb'))
    print(f'{mode} is Done!')

这段代码是用于将SMILES(Simplified Molecular Input Line Entry System)表示的分子转换为3D分子图,并将结果保存为一个字典文件。SMILES是一种表示分子结构的简单文本字符串。这段代码使用了多线程来加速处理过程。下面是代码的逐行解释:

  1. 导入所需的库和模块。

    • ThreadLock 用于多线程处理。
    • mol_to_geognn_graph_data_MMFF3d 用于将分子转换为3D图。
    • AllChem 来自rdkit.Chem,用于处理化学信息。
  2. 创建一个互斥锁,防止多个线程同时修改文件或全局变量。

  3. 定义一个函数 calculate_3D_structure_,它接受一个SMILES字符串列表,并计算每个SMILES的3D分子图。

    • 使用全局变量 p 作为指针,指向要处理的SMILES。
    • 使用互斥锁来同步对全局变量的访问。
    • 对每个SMILES,尝试将其转换为3D分子图。
    • 如果转换失败,将无效的SMILES写入一个文本文件。
    • 如果转换成功,将结果添加到全局字典 smiles_to_graph_dict 中。
  4. 在主程序中,对训练和测试数据集执行上述转换。

    • 初始化空字典 smiles_to_graph_dict 和指针 p
    • 创建多个线程来并行处理SMILES列表。
    • 启动所有线程,并等待它们完成。
    • 使用pickle库将结果字典保存为文件。

这段代码的主要目的是通过多线程加速将化学分子(以SMILES形式表示)转换为3D图的过程,并将结果保存为字典文件。这可能是在化学或药物研究领域的一个预处理步骤,以便于后续的分析和建模。

模型架构

class ADMET(nn.Layer):
    def __init__(self):
        super(ADMET, self).__init__()
        compound_encoder_config = json.load(open('GEM/model_configs/geognn_l8.json', 'r'))  
        self.encoder = GeoGNNModel(compound_encoder_config) 
        self.encoder.set_state_dict(pdl.load("GEM/weight/class.pdparams")) 
        # GEM编码器输出的图特征为32维向量, 因此mlp的输入维度为32
        self.mlp = nn.Sequential(       
            nn.Linear(32, 32, weight_attr=nn.initializer.KaimingNormal()),  
            nn.ReLU(),
            nn.Linear(32, 32, weight_attr=nn.initializer.KaimingNormal()),
            nn.ReLU(),
            nn.Linear(32, 32, weight_attr=nn.initializer.KaimingNormal()),
            nn.ReLU(),
            nn.Linear(32, 2, weight_attr=nn.initializer.KaimingNormal()),
        )

    def forward(self, atom_bond_graph, bond_angle_graph):
        node_repr, edge_repr, graph_repr = self.encoder(atom_bond_graph.tensor(), bond_angle_graph.tensor())
        return self.mlp(graph_repr)

训练模型

def trial(model_version, model, batch_size, criterion, scheduler, opt):
    # 创建dataloader
    train_data_loader, valid_data_loader = get_data_loader(mode='train', batch_size=batch_size)   

    current_best_metric = -1e10
    max_bearable_epoch = 50    # 设置早停的轮数为50,若连续50轮内验证集的评价指标没有提升,则停止训练
    current_best_epoch = 0

    train_metric_list = []     # 记录训练过程中各指标的变化情况
    valid_metric_list = []

    for epoch in range(800):   # 设置最多训练800轮
        model.train()
        for (atom_bond_graph, bond_angle_graph, label_true_batch) in train_data_loader:
            label_predict_batch = model(atom_bond_graph, bond_angle_graph)
            label_true_batch = pdl.to_tensor(label_true_batch, dtype=pdl.int64, place=pdl.CUDAPlace(0))
            loss = criterion(label_predict_batch, label_true_batch)
            loss.backward()   # 反向传播
            opt.step()   # 更新参数
            opt.clear_grad()
        scheduler.step()   # 更新学习率

        # 评估模型在训练集、验证集的表现
        metric_train = evaluate(model, train_data_loader)
        metric_valid = evaluate(model, valid_data_loader)

        train_metric_list.append(metric_train)
        valid_metric_list.append(metric_valid)

        score = round((metric_valid['ap'] + metric_valid['auc']) / 2, 4)

        if score > current_best_metric:
            # 保存score最大时的模型权重
            current_best_metric = score
            current_best_epoch = epoch
            pdl.save(model.state_dict(), "weight/" + model_version + ".pkl")
        print("=========================================================")
        print("Epoch", epoch)
        pprint(("Train", metric_train))
        pprint(("Validate", metric_valid))
        print('current_best_epoch', current_best_epoch, 'current_best_metric', current_best_metric)
        if epoch > current_best_epoch + max_bearable_epoch:
            break

    return train_metric_list, valid_metric_list

最终效果

如有想组队的伙伴,请加入:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
新冠肺炎传播和防控的数学模型主要是基于传染病模型来进行建模的。下面是一个完整的建模过程: 1.确定变量及其含义。 在建立数学模型之前,首先需要确定变量及其含义。在新冠肺炎传播和防控,常用的变量有: - S:易感者数量 - E:潜伏期感染者数量 - I:感染者数量 - R:康复者数量 - D:死亡者数量 2.确定模型类型。 根据疾病的传播方式和特点,选择适合的传染病模型类型。常用的模型有: - SIR模型:适用于传染病无潜伏期,感染后马上出现症状的情况。 - SEIR模型:适用于传染病有潜伏期,感染后一段时间才出现症状的情况。 - SEIRD模型:在SEIR模型的基础上增加死亡者数量变量,适用于需要考虑死亡人数的情况。 在新冠肺炎的传播和防控,由于存在潜伏期,因此一般采用SEIR模型进行建模。 3.列出微分方程。 根据模型类型和变量的含义,列出微分方程组。以SEIR模型为例,其微分方程组为: dS/dt = -βSI dE/dt = βSI - αE dI/dt = αE - γI dR/dt = γI 其,β表示感染率,α表示潜伏期转化率,γ表示康复率。 4.确定模型参数。 模型参数是指在微分方程组出现的常数,包括感染率、潜伏期转化率、康复率等。这些参数需要根据具体的疾病和传播情况进行估计和确定。 5.模型求解和分析。 求解微分方程组,得到感染者、康复者和死亡者数量随时间变化的函数。通过对这些函数进行分析和比较,可以得出疾病传播速度、流行程度、防控措施的效果等结论。 6.模型验证和修正。 将模型预测结果与实际情况进行对比,验证模型的准确性。如果模型存在偏差,需要对模型进行修正和改进,以提高预测精度。 以上是一般的建模过程,具体情况需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wormhacker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值