Machine Learnig Aided Drug Design (MLADD)

Mishima.sykに参加された皆様お疲れ様でした。深層学習のフレームワークのハンズオン如何でしたでしょうか?次回に何をやるかは未定ですが、反省会という名の(新年会?忘年会?)でテーマに関して話し合う予定なので興味ある内容があれば私まで伝えてもらえるとありがたいです。

僕はkerasを触ったことがなかったので、一通り学べて助かりました。tf.contribe.learnはできるだけ何も考えなくていいように作っているのに対してkerasはもうちょっと構築の仕組みを楽にする感じのフレームワークかなぁと。tflearn](https://github.com/tflearn/tflearn)と似たものを感じた。

尚、当日の資料とデータはGitHubにあるので必要に応じてダウンロードするなり好きに使ってください。尚slideshareを使わないのは今の職場が何故かブロックしているからですw

ここからは、最近ちょっと考えていることをだらっと書いておきます。

その昔(というか今も)CADD(Computer Aided Drug Design)という言葉はあるのだが、あれはコンピューターを利用して解析をするオペレーター(モデラーともいう)のヒトと、実際に合成するケミストがいるので、主観のぶつかり合いというか、お互いの経験による解釈の違いというのが起こりやすい。あとは精度がそんなに良くないので確度を考慮しながら結果を解釈する必要があったりして色々面倒事が多い。

最近、DeepLearningのようなそこそこ精度の高い手法を淡々と自動的に構造最適化プロジェクトに適用するような環境を作ったらどういうことが起こるのだろうか?というあたりに興味が湧いている。機械学習はヒトの解釈の余地が入らないので淡々と受け止めるしかなく、それをどう使うかというのはどちらかというとケミストに委ねられるようになるし、モデラーにとってもそれ以上の何かを出さないと存在価値がないという状況になるのかなーとか思ったり。

将棋ウォーズで常に棋神がガイドしてくれる感じに近いのかなぁ。

pychembldbでアッセイ数の多いJ.M.C由来のデータを抜き出す

土曜のテスト用データになんかないかなーと探してたのだけど、ChEMBLのサイトではアッセイ数とかでフィルタリングができなかったので。

from pychembldb import *
for assay in chembldb.query(Assay).all():
    if assay.doc.journal == "J. Med. Chem.":
        act_num = len(assay.activities)
        if act_num > 100:
            print act_num, assay.chembl_id, assay.description

これだと効率が悪いのでものすごい時間かかるけど、一回流すだけだからまぁいいやと。

pychembldbで活性値付きのSDFをつくる

次回のMishima.sykまで2週間を切りました。そろそろハンズオンの準備を開始しています。

尚、ハンズオンでは作業環境を揃えるために事前準備が必要なのでよろしくお願いします。一応cloud9でもいけるように用意しているそうなのでネットに繋げさえすればOKみたいですが。

さて、ハンズオンのためにサンプルデータを選ばなきゃいけないんだけど、ChEMBLからアッセイ系選んで含まれている全ての化合物情報をsdfでダウンロードしたけど属性に活性値が付いてなかった。

アレレのレですよ。

なんかやり方あると思うんだけど、とりあえずはpychembldbで活性値付きのsdfを出力するようなものを作った。しかも自分の中で最近ブームが来まくり100%中の100%なclickを使ってコマンドにしてみた。

from rdkit import Chem
from pychembldb import *
import click

@click.command()
@click.argument("chembl_id")
def chemblid2sdf(chembl_id):
    assay = chembldb.query(Assay).filter_by(chembl_id=chembl_id).first()
    w = Chem.SDWriter("{}.sdf".format(chembl_id))
    for activity in assay.activities:
        m = Chem.MolFromMolBlock(activity.compound.molecule.structure.molfile)
        act = activity.standard_value
        m.SetProp("ACTIVITY", str(act))
        w.write(m)

if __name__ == '__main__':
    chemblid2sdf()

尚、幽遊白書コラボでモンストに戻ってみたけど、持てる(無料)オーブの全てをつぎ込んだけど、ガチャは飛影しか出ないし戸愚呂100%中の100%は3ステージくらいまでしか進めないしで心が折れた。

心が折れたといえば、ポケモンGoも寒すぎて歩く気力も削がれた上にレベル31で飽きが来た。メタモンは取ったけど…

DNN Regressionの自分の実装がダメな件

TensorflowのDNN Regressionを使っていて便利なんだけどハイレベルなAPIばっかり使っていると自分でもっと別なの実装したくなった時に困るだろうなぁと、自分で実装してみたら…

$python boston.py
 RF: R2: 0.736624, RMSE:4.631010
SVM: R2: 0.515467, RMSE:6.281300
TFL: R2: 0.647992, RMSE:5.353827
 MY R2: -1.007581, RMSE:12.785702

精度悪すぎ… sofでも同じような質問を見つけたが同業だろう…w

ログを取ってみたところ、どうも収束が悪いっぽい。

import numpy as np
import tensorflow as tf
from sklearn import cross_validation
from sklearn import datasets
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
from math import sqrt
import random

tf.logging.set_verbosity(tf.logging.ERROR)

def test_svm(x_train, x_test, y_train, y_test):
    clf = SVR(kernel='linear').fit(x_train, y_train)
    y_pred = clf.predict(x_test)
    r2 = r2_score(y_test, y_pred)
    rmse = sqrt(mean_squared_error(y_test, y_pred))
    print('SVM: R2: {0:f}, RMSE:{1:f}'.format(r2, rmse))

def test_rf(x_train, x_test, y_train, y_test):
    rlf = RandomForestRegressor().fit(x_train, y_train)
    y_pred = rlf.predict(x_test)
    r2 = r2_score(y_test, y_pred)
    rmse = sqrt(mean_squared_error(y_test, y_pred))
    print(' RF: R2: {0:f}, RMSE:{1:f}'.format(r2, rmse))

def test_tf_learn_dnn(x_train, x_test, y_train, y_test, steps=10000, hidden=[20, 20]):
    feature_columns = [tf.contrib.layers.real_valued_column("", dimension=13)]
    tfl = tf.contrib.learn.DNNRegressor(hidden_units=hidden, feature_columns=feature_columns)
    tfl.fit(x=x_train, y=y_train, steps=steps)
    y_pred = tfl.predict(x_test)
    r2 = r2_score(y_test, y_pred)
    rmse = sqrt(mean_squared_error(y_test, y_pred))
    print('TFL: R2: {0:f}, RMSE:{1:f}'.format(r2, rmse))

def inference(x):
    hidden1 = 20
    hidden2 = 20

    with tf.name_scope("l1") as scope:
        w1 = tf.Variable(tf.truncated_normal([13, hidden1]), name="w1")
        b1 = tf.Variable(tf.zeros([hidden1]), name="b1")
        h1 = tf.nn.relu(tf.matmul(x, w1) + b1)
        #h1 = tf.nn.dropout(h1, 0.9)

    with tf.name_scope("l2") as scope:
        w2 = tf.Variable(tf.truncated_normal([hidden1, hidden2]), name="w1")
        b2 = tf.Variable(tf.zeros([hidden2]), name="b2")
        h2 = tf.nn.relu(tf.matmul(h1, w2) + b2)
        #h2 = tf.nn.dropout(h2, 0.9)

    with tf.name_scope("l3") as scope:
        w3 = tf.Variable(tf.truncated_normal([hidden2, 1]), name="w2")
        b3 = tf.Variable(tf.zeros([1]), name="b3")
        y = tf.matmul(h2, w3) + b3
    return y

def loss(model, y_):
    return tf.reduce_mean(tf.square(tf.sub(model, y_)))

def training(loss, rate):
    return tf.train.AdagradOptimizer(rate).minimize(loss)

def test_my_dnn(x_train, x_test, y_train, y_test, batch_size=32, epoch=10000, shuffle=True):
    max_size = x_train.shape[0]
    n = max_size - batch_size
    idx = list(range(x_train.shape[0]))
    x = tf.placeholder(tf.float32, shape=[None, 13])
    y_ = tf.placeholder(tf.float32, shape=[None])

    model = inference(x)
    loss_value = loss(model, y_)
    train_op = training(loss_value, 0.1)

    init = tf.initialize_all_variables()
    sess = tf.Session()
    sess.run(init)

    for e in range(epoch):
        if shuffle:
            random.shuffle(idx)
            x_train = x_train[idx]
            y_train = y_train[idx]
        for i in range(n / batch_size):
            batch = batch_size * i
            x_train_b = x_train[batch:batch + batch_size]
            y_train_b = y_train[batch:batch + batch_size]
            _, l = sess.run([train_op, loss_value], feed_dict={x: x_train_b, y_: y_train_b})
        #if e % 100 == 0:
        #    print e, l

    y_pred = sess.run(model, feed_dict={x: x_test})
    y_pred = y_pred.T[0]
    r2 = r2_score(y_test, y_pred)
    rmse = sqrt(mean_squared_error(y_test, y_pred))
    print(' MY R2: {0:f}, RMSE:{1:f}'.format(r2, rmse))

if __name__ == "__main__":
    boston = datasets.load_boston()
    x_train, x_test, y_train, y_test = cross_validation.train_test_split(
        boston.data, boston.target, test_size=0.2, random_state=0)

    test_rf(x_train, x_test, y_train, y_test)
    test_svm(x_train, x_test, y_train, y_test)
    test_tf_learn_dnn(x_train, x_test, y_train, y_test)
    test_my_dnn(x_train, x_test, y_train, y_test, shuffle=True, epoch=30000)

というわけでソースコードを読んでみたんだけど、わかりにくかったので途中までしか追えてなく、結局原因がつかめていない状態。

以下メモ

  • 実際に使われているクラスはDNNLinearCombinedRegressorで、名前の由来がわからなかったけど、TensorFlow Wide & Deep Learning Tutorialを読めばわかる

  • fitで訓練するんだけど、_get_input_fnで入力、出力のplaceholderを返すinput_fnとバッチ用のデータセットを返すfeed_fnという関数が返される。

  • バッチは_get_input_fnでランダムシャッフルされているし、デフォルトのサイズは32

  • デフォルトのoptimizerはAdaGrad

  • clip-gradientsというオプションがあるのだがどこで使われているのかわからなかった

DNNをRandom Forest (RF)やSupport Vector Machine (SVM)と比較したい

TensorFlowのDNNチュートリアルだとトレーニングセットとテストセットをファイルから読みだすので、実用的にはちょっと面倒くさい。scikit-learnのよろしく分割してくれるメソッド使ったほうが楽でしょう。

またこScikit-learnとTensorFlowを組み合わせることでそれぞれのアルゴリズムの精度を比較することが簡単にできるので便利。

import tensorflow as tf
import numpy as np
from sklearn import datasets
from sklearn import svm
from sklearn.ensemble import RandomForestClassifier
from sklearn import cross_validation

iris = datasets.load_iris()
x_train, x_test, y_train, y_test = cross_validation.train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)

classifier = tf.contrib.learn.DNNClassifier(hidden_units=[10, 20, 10], n_classes=3)
classifier.fit(x=x_train, y=y_train, steps=200)
dnn_accuracy_score = classifier.evaluate(x=x_test, y=y_test)["accuracy"]
print('DNN Accuracy: {0:f}'.format(dnn_accuracy_score))

clf = svm.SVC(kernel='linear').fit(x_train, y_train)
svm_accuracy_score = clf.score(x_test, y_test)
print('SVM Accuracy: {0:f}'.format(svm_accuracy_score))

rlf = RandomForestClassifier().fit(x_train, y_train)
rf_accuracy_score = rlf.score(x_test, y_test)
print('RF Accuracy: {0:f}'.format(rf_accuracy_score))