当今许多药物的发现需要专业知识和昂贵的生物实验来确定化学分子的性质。然而,尽管越来越多地研究人员使用监督机器学习算法来自动识别这些化学分子的性质,但由于训练数据有限,模型性能和准确性方面很难满足药物研发的需求。
许多类型的模型要求输入的训练数据需要有固定的形状。由于分子在其包含的原子和键的数量上差异很大,这使得将这些模型应用于这些分子变得很困难。我们需要一种生成固定长度的分子,生成唯一的“分子指纹”。目前已经有方法可以实现这一点,比如我们在之前的教程(DeepChem:分子指纹)中使用的扩展连接指纹(ECFPs)。但在这个例子中,我们不会手动设计指纹,而是让一个Seq2Seq模型学习自己创建指纹的方法。
Seq2Seq模型执行序列到序列的翻译。例如,该模型最早应用于将文本从一种语言翻译成另一种语言。它由称为“编码器”和“解码器”的两个部分组成。编码器是一个多层门控循环单元(Gated Recurrent Unit,GRU)网络。输入序列被逐个标记并输入到其中,生成一个称为“嵌入向量”的固定长度向量。解码器是另一个多层门控循环单元网络,执行相反的操作:它将嵌入向量作为输入,并生成输出序列。通过在适当选择的输入/输出对上进行训练,您可以创建执行许多类型转换的模型。
SeqToSeq模型应用于分子指纹有如下优势:
1)模型是数据驱动的,不需要专业知识。
2)Seq2Seq方法生成的指纹可以完全还原为原始分子表示,确保指纹向量中编码的信息充分性。
3)Seq2Seq方法在一个庞大的无标签数据集上采用无监督训练,充分释放了深度神经网络的计算能力。
在Seq2Seq学习中,输入和输出都是相同的SMILE字符串,即分子的文本表示。我们将SMILE字符串映射到一个固定大小的向量,然后将其翻译回原始的SMILE字符串。中间的固定大小向量被提取为Seq2Seq指纹。一旦模型训练良好,中间的特征向量被认为编码了恢复原始分子表示所需的所有信息。因此,Seq2Seq指纹能够捕捉到详尽的信息,从而准确预测分子的性质。
模型构建流程包括三个步骤:
1)在大量未标记的训练数据上训练Seq2Seq指纹模型。
2)使用训练好的模型为标记的数据集生成Seq2Seq指纹
3)将生成的指纹及其标签输入到某种监督学习方法中进行训练,例如梯度提升(Gradient Boosting)、多层感知机(Multi-Layer Perceptron,MLP)等预测模型。
下面我们使用MUV数据集为例构建Seq2Seq模型,该数据集包括74,501个分子的训练集和9,313个分子的验证集,因此我们有足够多的SMILES字符串可以使用,代码如下。
import deepchem as dc
import numpy as np
from deepchem.models.optimizers import Adam, ExponentialDecay
tasks, datasets, transformers = dc.molnet.load_muv(split='stratified')
train_dataset, valid_dataset, test_dataset = datasets
train_smiles = train_dataset.ids
valid_smiles = valid_dataset.ids
tokens = set()
# 将训练集中的所有smile制作成一个无重复字符的list
for s in train_smiles:
tokens = tokens.union(set(c for c in s))
tokens = sorted(list(tokens))
# 创建模型并定义优化方法
max_length = max(len(s) for s in train_smiles)
batch_size = 100
batches_per_epoch = len(train_smiles)/batch_size
model = dc.models.SeqToSeq(tokens,
tokens,
max_length,
encoder_layers=2,
decoder_layers=2,
embedding_dimension=256,
model_dir='fingerprint',
batch_size=batch_size,
learning_rate=ExponentialDecay(0.001, 0.9, batches_per_epoch))
# tokens:模型可以使用的标记词汇表。编码器和解码器将具有相同的标记集合。
# max_length:模型可以处理的序列的最大长度。
# encoder_layers:编码器网络中的层数。默认值为2。
# decoder_layers:解码器网络中的层数。默认值为2。
# embedding_dimension:每个标记的嵌入向量的大小。默认值为256。
# model_dir:保存模型的目录。
# batch_size:训练期间每个小批次中的样本数。
# learning_rate:优化器的学习率。在这种情况下,它设置为ExponentialDecay类的实例,
# 该类实现了随着每个纪元的指数下降的学习率计划。0.001参数是初始学习率,0.9参数是衰减率,
def generate_sequences(epochs):
for i in range(epochs):
for s in train_smiles:
yield (s, s)
model.fit_sequences(generate_sequences(40))
predicted = model.predict_from_sequences(valid_smiles[:500])
count = 0
for s,p in zip(valid_smiles[:500], predicted):
if ''.join(p) == s:
count += 1
print('reproduced', count, 'of 500 validation SMILES strings')
train_embeddings = model.predict_embeddings(train_smiles)
train_embeddings_dataset = dc.data.NumpyDataset(train_embeddings,
train_dataset.y,
train_dataset.w.astype(np.float32),
train_dataset.ids)
valid_embeddings = model.predict_embeddings(valid_smiles)
valid_embeddings_dataset = dc.data.NumpyDataset(valid_embeddings,
valid_dataset.y,
valid_dataset.w.astype(np.float32),
valid_dataset.ids)
classifier = dc.models.MultitaskClassifier(n_tasks=len(tasks),
n_features=256,
layer_sizes=[512])
classifier.fit(train_embeddings_dataset, nb_epoch=10)
metric = dc.metrics.Metric(dc.metrics.roc_auc_score, np.mean, mode="classification")
train_score = classifier.evaluate(train_embeddings_dataset, [metric], transformers)
valid_score = classifier.evaluate(valid_embeddings_dataset, [metric], transformers)
print('Training set ROC AUC:', train_score)
print('Validation set ROC AUC:', valid_score)
从训练集和测试集的AUC数值可以看出,模型训练结果还算不错。
参考文献:
https://dl.acm.org/doi/10.1145/3107411.3107424
https://github.com/deepchem/deepchem/tree/master/examples/tutorials
联系客服