【问题标题】:String Input output representation in RNN Variational autoencoderRNN 变分自动编码器中的字符串输入输出表示
【发布时间】:2016-10-15 09:40:07
【问题描述】:

我正在看.. 分子自动编码器让我们可以对化合物进行插值和基于梯度的优化https://arxiv.org/pdf/1610.02415.pdf

本文采用输入的 Smiles 字符串(分子的文本表示),然后使用变分编码器将其映射到 2D 潜在空间。

hexan-3-ol "CCCC(O)CC" 的示例微笑字符串

在论文中,他们用空格将短字符串填充为 120 个字符。

论文使用一堆一维卷积网络将字符串编码为微笑字符串的潜在表示

然后它使用 3 Gated 循环单元 GRU 将潜在空间中的位置映射回微笑字符串。

我在理解这篇论文时遇到的问题是确定输入和输出结构是什么样的。

论文对输入和输出结构有点模糊。从一维卷积网络的使用中,我怀疑输入是类似于

的矢量化表示
'C' = 1
'O' = 2
'(' = 3
')' =4
' ' = 0 #for padding

#so the hexan-3-ol smiles above would be 

[1,1,1,1,3,2,4,1,1,0...padding to fixed length]

纸上说的输出

RNN 解码器的最后一层定义了 SMILES 字符串中每个位置所有可能字符的概率分布

那么对于论文中使用的最大微笑长度 120 和 35 个可能的微笑字符,这是否意味着输出是 [120x35] 数组?

向前推进该逻辑是否表明输入是一个扁平的 [120*35] 数组 - 请记住它是一个自动编码器。

我的问题是 1dConv,它使用的最大长度为 9,如果它是扁平的 [120*35] 数组,则不足以覆盖序列中的下一个原子

感谢您的帮助...

【问题讨论】:

    标签: keras recurrent-neural-network autoencoder cheminformatics


    【解决方案1】:

    SMILES 的定义比您想象的要复杂,因为它是图形的线性表示。

    https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system

    简而言之,一个字母表示一个原子,例如 C=碳,O=氧。该图可以用括号进行分支,即 C(C)C 将形成“Y”结构。最后,可以使用以数字表示的闭包来创建循环。 IE。 “C1CCC1”形成一个正方形(即字母 1 与另一个字母 1 相连)。

    请注意,此描述并不完整,但应该是一个很好的基础。

    如果一个字符串是一个有效的微笑字符串,只需将它添加到另一个有效的微笑字符串中,通常会生成另一个有效的字符串。 IE。 "C1CC1" + "C1CC1" => "C1CC1C1CC1" 有效。

    通常,on 可以提取微笑字符串的线性部分并将其“嵌入”到另一个中,从而形成有效的微笑字符串。

    我认为自动编码器正在学习的是如何进行这些转换。上面示例中替换卤化物(氯、溴、碘)的愚蠢示例可能是:

    C1CCC1Cl C1CCC1Br C1CCC1I

    自动编码器学习常量部分和可变部分 - 但在线性字符串空间中。现在这并不完美,如果您在论文中注意到,在探索连续可微空间时,他们需要找到最接近的有效微笑字符串。

    如果你想探索微笑字符串,论文中使用的所有字符串都是使用 rdkit 生成的:

    https://github.com/rdkit/

    我完全公开,帮助维护。希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      你可以在这里找到源代码:

      https://github.com/maxhodak/keras-molecules

      我一直在玩它,输入和输出结构是 MxN 矩阵,其中 M 是 SMILES 字符串的最大长度(在本例中为 120),N 是字符集的大小。除了位置 M_i 处的字符与字符 N_j 匹配的位置之外,每一行 M 都是一个零向量。要将输出矩阵解码为 SMILE,然后逐行匹配字符集中的字符位置。

      这种编码的一个问题是它占用了大量内存。使用 keras 图像迭代器方法,您可以执行以下操作:

      首先将所有微笑编码为“稀疏”格式,该格式是您集中每个微笑的字符集位置列表。

      现在您已经定义了所有 SMILE(字符集)的字符集,并且每个 SMILE 现在都是一个数字列表,表示每个字符在字符集中的位置。然后,您可以在使用 fit_generator 函数训练 keras 模型的同时开始使用迭代器进行动态处理。

      import numpy as np
      import threading
      import collections
      
      class SmilesIterator(object):
          def __init__(self, X, charset, max_length, batch_size=256, shuffle=False, seed=None):
              self.X = X
              self.charset = charset
              self.max_length = max_length
              self.N = len(X)
              self.batch_size = batch_size
              self.shuffle = shuffle
              self.batch_index = 0
              self.total_batches_seen = 0
              self.lock = threading.Lock()
              self.index_generator = self._flow_index(len(X), batch_size, shuffle, seed)
      
          def reset(self):
              self.batch_index = 0
      
          def __iter__(self):
              return self
      
          def _flow_index(self, N, batch_size, shuffle=False, seed=None):
              self.reset()
              while True:
                  if self.batch_index == 0:
                  index_array = np.arange(N)
                  if shuffle:
                      if seed is not None:
                          np.random.seed(seed + total_batches_seen)
                      index_array = np.random.permutation(N)
                  current_index = (self.batch_index * batch_size) % N
                  if N >= current_index + batch_size:
                      current_batch_size = batch_size
                      self.batch_index += 1
                  else:
                      current_batch_size = N - current_index
                      self.batch_index = 0
                  self.total_batches_seen += 1
                  yield(index_array[current_index: current_index +    current_batch_size],
                  current_index, current_batch_size)
      
          def next(self):
              with self.lock:
                  index_array, current_index, current_batch_size = next(self.index_generator)
              #one-hot encoding is not under lock and can be done in parallel
              #reserve room for the one-hot encoded
              #batch, max_length, charset_length
              batch_x = np.zeros(tuple([current_batch_size, self.max_length, len(self.charset)]))
              for i, j in enumerate(index_array):
                  x = self._one_hot(self.X[j])
                  batch_x[i] = x
              return (batch_x, batch_x) #fit_generator returns input and target
      
          def _one_hot(self, sparse_smile):
              ss = []
              counter = 0
              for s in sparse_smile:
                  cur = [0] * len(self.charset)
                  cur[s] = 1
                  ss.append(cur)
                  counter += 1
              #handle end of line, make sure space ' ' is first in the charset
              for i in range(counter, len(self.charset)):
                  cur = [0] * len(self.charset)
                  cur[0] = 1
                  ss.append(cur)
              ss = np.array(ss)
              return(ss)
      

      【讨论】:

        猜你喜欢
        • 2020-01-29
        • 2018-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        • 2019-10-13
        相关资源
        最近更新 更多