DeepChem教程16:为分子学习无监督的 Embeddings

这个教程我用SeqToSeq模型来产生指纹以分类分子。这是基于以下论文的,尽管一些实施细节不同:Xu et al., "Seq2seq Fingerprint: An Unsupervised Deep Molecular Embedding for Drug Discovery" (https://doi.org/10.1145/3107411.3107424).

SeqToSeq学习Embeddings

有许多的模型要求输入有固定的长度。由于分子的原子数量和键的数量变化,使得很难应用模型。我们要一种方法来为分子产生固定长度的指纹。为此设计了多种不同的方法,如我们前面用过的Extended-Connectivity Fingerprints (ECFPs)。但是这次我们不是手工设计指纹,我们让SeqToSeq模型学习它的方法来产生指纹。

SeqToSeq模型进行序列到序列的变换。例如,通常用于将文本从一种语言转换为另一种语言。它有两部分,称为“编码器解码器。编码器是一种循环层。给它饲入输入序列,一次一个,它就产生固定长度的向量叫做"embedding vector"。解码器是另一种循环层堆叠,它进行反向操作:它以embedding vector为输入,得到输出序列。通过适当的输入/输出对训练它,你就可以得到模型进行各种转换。

这种情况下,我们使用描述分子的SMILES字串作为输入序列。我们将要训练一个模型作为autoencoder,使得它能产生与输入序列一样的输出序列。为此,编码器必须产生含有所有来自原始序列的信息的embedding vectors。这正是我们的指纹中想要的,因此那些embedding vectors然后就可以被其它模型当作表示分子的方法。

我们从加载数据开始。我们将使用MUV数据集。它包括74,501个分子在训练集中,9313个分子在验证集中,所以它有足够多的SMILES供我们使用。

In [1]:

import deepchem as dc

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

我们要为我们的SeqToSeq模型确定“字母”,所有可以出现在序列中的标记的列表。(对于输入和输出序列也可能有不同的字母,但是因为我们要训练它作为自编码器,这种情况下它们是相同的。)列出所有训练序列中出现的每个字符的列表。

In [2]:

tokens = set()

for s in train_smiles:

  tokens = tokens.union(set(c for c in s))

tokens = sorted(list(tokens))

创建模型并确定使用的优化方法。本例,如果我们不断降低学习速率,学习工作会越来越好。我们用ExponentialDecay,每个epoch将学习速率乘于0.9

In [3]:

from deepchem.models.optimizers import Adam, ExponentialDecay

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))

我们来训练它!fit_sequences()函数的输入是生成器能产生输入/输出对。对于好的GPU,要花费几个小时的时间。

In [4]:

def generate_sequences(epochs):

  for i in range(epochs):

    for s in train_smiles:

      yield (s, s)

model.fit_sequences(generate_sequences(40))

让我们来看一下作为自编码器它工作的到底好不好。我们从验证集中给它运行500个分子,看有多少个正好重新生成。

In [5]:

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')

reproduced 161 of 500 validation SMILES strings

现在有编码器作为一种产生分子指纹的方法。我们为训练集和验证集中的所有分子计算embedding vectors,并产生新的数据集作为它们的特征向量。由于数据的数量足够小,所以我们可以把所有的东西存进内存。

In [6]:

import numpy as np

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)

对于分类,我们将使用一个简单的全链接网络带一个隐藏层。

In [7]:

classifier = dc.models.MultitaskClassifier(n_tasks=len(tasks),

                                                      n_features=256,

                                                      layer_sizes=[512])

classifier.fit(train_embeddings_dataset, nb_epoch=10)

Out[7]:

0.0014195525646209716

看看它到底工作得好不好。为训练集和验证集计算ROC AUC

In [8]:

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)
Training set ROC AUC: {'mean-roc_auc_score': 0.9598792603154332}
Validation set ROC AUC: {'mean-roc_auc_score': 0.7251350862464794}

下载全文请到www.data-vision.net,技术联系电话13712566524

猜你喜欢

转载自blog.csdn.net/lishaoan77/article/details/114334730