1

私は見ています..分子オートエンコーダーを使用すると、化合物の補間と勾配ベースの最適化を行うことができますhttps://arxiv.org/pdf/1610.02415.pdf

この論文は、入力 Smiles 文字列 (分子のテキスト表現) を受け取り、変分エンコーダを使用して 2D 潜在空間にマッピングします。

ヘキサン-3-オール「CCCC(O)CC」のスマイル文字列の例

この論文では、短い文字列をスペースで 120 文字まで埋めています。

この論文では、1D 畳み込みネットワークのスタックを使用して文字列をエンコードし、笑顔文字列の潜在表現にしました。

次に、3 Gated recurrent Units GRU を使用して、潜在空間内の位置を笑顔文字列にマッピングします。

この論文を理解する上で私が抱えている問題は、入力構造と出力構造がどのように見えるかを判断することです。

この論文は、入力と出力の構造について少し曖昧です。1D conv ネットの使用から、入力は次のようなベクトル化された表現であると思われます

'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 文字列の各位置で可能なすべての文字の確率分布を定義します

したがって、35 の可能なスマイル文字を含む用紙で使用されている 120 の最大スマイル長は、出力が [120x35] 配列であることを意味しますか?

そのロジックを進めることは、入力が代わりに平坦化された[120 * 35]配列であることを示唆しています-オートエンコーダーを念頭に置いてください。

それに関する私の問題は、フラット化された[120 * 35]配列の場合、シーケンス内の次のアトムをカバーするのに十分ではない最大長9を使用する1dConvです

ご協力いただきありがとうございます...

4

2 に答える 2

2

SMILES の定義は、グラフの線形表現であるため、予想よりも複雑です。

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

つまり、文字は、C=炭素、O=酸素などの原子を指定します。グラフは括弧で分岐できます。つまり、C(C)C は「Y」構造を形成します。最後に、数値として表されるクロージャを使用してサイクルを作成できます。つまり、「C1CCC1」は正方形を形成します (つまり、文字 1 が他の文字 1 に結合されます)。

この説明は完全ではありませんが、十分な基礎となるはずです。

文字列が有効なスマイル文字列である場合、それを別の有効なスマイル文字列に追加するだけで、ほとんどの場合、別の有効な文字列が作成されます。つまり、"C1CC1" + "C1CC1" => "C1CC1C1CC1" が有効です。

多くの場合、笑顔文字列の線形部分を抽出して別の文字列に「埋め込む」ことができ、有効な笑顔文字列が形成されます。

自動エンコーダーが学習していると私が信じているのは、これらの変換を行う方法です。上記の例に付加されたハロゲン化物 (塩素、臭素、ヨウ素) を置き換える愚かな例は、次のようになります。

C1CCC1Cl C1CCC1Br C1CCC1I

自動エンコーダーは、定数部分と変数部分を学習しますが、線形の文字列空間で学習します。これは完全ではありません。論文で気づいた場合、連続微分可能空間を探索するときに、最も近い有効なスマイル文字列を見つける必要があります。

笑顔の文字列を調べたい場合は、論文で使用されているものはすべて rdkit を使用して生成されたものです。

https://github.com/rdkit/

完全な開示で、私はそれを維持するのに役立ちます. うまくいけば、これが役に立ちます。

于 2016-11-03T16:53:48.323 に答える
1

ソースコードは次の場所にあります。

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

私はそれをいじっていましたが、入力と出力の構造は MxN 行列で、M は SMILES 文字列の最大長 (この場合は 120) で、N は文字セットのサイズです。各行 M はゼロのベクトルですが、位置 M_i の文字が文字 N_j と一致する位置を除きます。出力行列を SMILE にデコードするには、行ごとに進み、文字セットの文字位置に一致させます。

このエンコーディングの問題は、大量のメモリを消費することです。keras イメージ イテレータ アプローチを使用すると、次のことができます。

最初に、すべての笑顔を「スパース」形式にエンコードします。これは、セット内の各笑顔の文字セット位置のリストです。

これで、すべての SMILES (文字セット) に対して文字セットが定義され、各 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)
于 2016-11-22T15:18:36.080 に答える