#14 REINVENTのupdate版をさわってみた

Source: Deep Learning on Medium

やったこと

というわけでUpdated REINVNETを触ってみたところ、かなり使い勝手がよくなっている印象を受けました。以下に構造を発生させる手順をまとめます。

  1. Prior networkからAgent networkを構築する

オリジナルのREINVNET同様Prior networkがpriors/ChEMBL/Prior.ckptとしてアップロードされていました。こちらからFine tuningをしてAgent networkを構築するのが reinforce_model.py です(オリジナルのmain.pyと同等の作業です)

例えば、sitagliptinに似た構造を発生させるAgent networkを構築したい場合は以下のようになります。
(py4cheminformaticsでsitagliptinをreferenceにしていたのを真似してます)

python reinforce_model.py --scoring-function tanimoto --steps 500 \
--name 'sitagliptin' --resultdir 'result' \
--query-smi 'N[C@@H](CC(=O)N1CCn2c(C1)nnc2C(F)(F)F)Cc3cc(F)c(F)cc3F'

scoring functionの種類も増えておりました。詳しくみたい方は以下のリンクをどうぞ。

tblaschkeさんが作ってた中で、特に面白いのがdockingを行なってそのdocking scoreがよくなるような構造を発生するdockingと呼ばれるscoring functionですね。ただ、残念なことにOpenEyeという有料のケモインフォマティクスツールをimportする必要がありました。

こちらのツールを利用できる方はそのままでよいと思いますが、モジュールがない場合はimport errorが出るので、anacondaの仮想環境を作るためのenvironment.yamlとこちらのdocking.pyを削除したものが私がクローンしたリポジトリになります。ご自身のモジュールと相談して使い分けてくれたらよいと思います。

再掲

2. Agent networkから化学構造を発生する

続けて構築したAgent networkから構造を発生する時sample_from_models.pyを用います(オリジナルだとPython上で一度RNNモデルを呼び出しsampleメソッドを実行したりする必要がありました)

python sample_from_model.py --save-smiles generated_smiles.smi \
--number 19 --model result/Agent.ckpt

オプション modelに構築したAgent networkを指定してあげればOKです。Referenceであるsitagliptinを含めて20個にしたいので今回は19個発生してみました。オリジナルだとVocと呼ばれるデータを別途用意しておいて読み込んだりしましたがそれも必要ないようです。

!cat generated_smiles.smi
NC(CC(=O)N1CCn2c(nnc2Cc2cc(Cl)ccc2F)C1)Cc1cc(Cl)c(Cl)cc1F Nc1nc(N)c(Cl)c(Cl)c1C(=O)Nc1cc(Cl)c(Cl)c(Cl)c1 NC(CC(=O)N1CCn2c(nnc2CCc2ccccc2Cl)C1)Cc1cc(Cl)c(Cl)cc1F CC(N)Cc1cc(F)cc(F)c1 NC(CC(=O)N1CCn2c(nnc2-c2ccc(Cl)c(Cl)c2)C1)Cc1cc(Cl)c(F)cc1Cl NC(CC(=O)N1CCn2c(nnc2-c2c(F)c(F)c(F)c(Cl)c2)C1)Cc1cc(Cl)c(Cl)cc1F NC(CC(=O)N1CCn2c(nnc2Cn2ccnn2)C1)Cc1cc(F)c(F)cc1Cl NC(CC(=O)N1CCn2c(nnc2Cc2c(F)cccc2F)C1)Cc1cc(F)c(F)cc1Cl NC(CC(=O)N1CCn2c(nnc2Cc2cccc(Br)c2)C1)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2CCc2ccccc2Cl)C1)Cc1cc(Cl)c(Cl)cc1Cl NC(CC(=O)N1CCn2c(nnc2CCc2ccccc2Cl)C1)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2Cc2ccc(Cl)cc2F)C1)Cc1cc(Cl)c(Cl)cc1F NC(CC(=O)N1CCn2c(nnc2Cc2c(F)cccc2F)C1)Cc1cc(F)c(F)cc1Cl NC(CC(=O)N1CCn2c(nnc2Cc2ccc(Cl)cc2F)C1)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2CC2CC2)C1)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2-c2cccnc2Cl)C1)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2CCc2ccc(F)c(F)c2)C1)Cc1cc(Cl)c(Cl)cc1F CN(Cc1cc(Cl)c(Cl)c(Cl)c1)C(=O)CC(N)Cc1cc(F)c(F)cc1F NC(CC(=O)N1CCn2c(nnc2-c2cc(Cl)c(Cl)c(Br)c2)C1)Cc1cc(Cl)c(Cl)cc1F

最後はJupyter Notebook上で描画してみましょう!

from rdkit.Chem import AllChem as Chem
from rdkit.Chem import Draw
supp = Chem.SmilesMolSupplier('generated_smiles.smi')
_mols = [m for m in supp if m is not None]
sitagliptin = 'N[C@@H](CC(=O)N1CCn2c(C1)nnc2C(F)(F)F)Cc3cc(F)c(F)cc3F'
mols = [Chem.MolFromSmiles(sitagliptin)]
mols.extend(_mols)
legends = [f'Generated {i}' for i in range(len(mols))]
legends[0] = 'Sitagliptin'
Draw.MolsToGridImage(
mols, legends=legends, molsPerRow=4, subImgSize=(300, 300))

こんな感じです。結局1個うまく化学構造が発生できず表示は19個になってしまいました。少しですがオリジナルのREINVENTより使い勝手がよくなったかなと思います。