非プログラマーのためのインフォマティクス入門。(仮)

非プログラマーがインフォマティクスについて勉強したことを記録します。主にKNIMEというソフトを使用しています。

非プログラマーのためのインフォマティクス入門。(仮)

【KNIME 】scikit-learnをKNIMEで動かすよ 〜t-SNEを題材に〜

 みなさん、年度末が近づいてきました。色々と忙しい日々ですが体調には気をつけないといけません(私は、先日発熱しました…)。

 

さてさて、今回はKNIME上でpython書いて、scikit-learnを動かしてみます。

で紹介した可視化を、t-SNEを使ってやってみます。

 

その前に!

KNIME上でpython、どうやって使うの?に軽くふれます。

まず、python3を使いたければ、KNIME3.5以上が良い気がします(3.4でもいけそうですが)。

File >> preferencesと進んで、検索窓にpythonと入れれば、下のような設定画面にたどり着きます。ここに使いたいpythonの実行ファイルを指定すればOKです。私の場合はanacondaを使ってpython環境を用意しているので、所望のenvのbinの中のpythonを指定しています。

f:id:sumtat:20180220235834p:plain

ここで、私のようなど素人+化合物情報を扱いたい&windowsユーザーの方!!!

RDKitってのを入れることになると思います。anaconda環境であれば

conda install -c rdkit rdkit

をすればinstallできますし、ターミナル・コマンドプロンプトやjupyterでは動くはずです。でもでも、KNIME上だと多分動かないです。同じようなことを言っている人がいましたので、リンクを貼っておきます。

私もlinux(centos7)、mac(sierra)では特に気になりませんでしたが、win7ではうまくいきませんでしたので、システム環境変数のPathに、anaconda系の足りない部分を強引に追記しました(強引だと思うので自己責任でお願いしますね)。

環境変数の足りない部分は

import os

print(os.environ["PATH"])

をrdkitが動く環境と、動かない環境(KNIME)でくらべてやればわかると思います。*1

 

前置きはこのくらいにします。

今回の全体像は次のようなものです。

 

f:id:sumtat:20180221215506p:plain

以前と同様にNS5Bポリメラーゼ阻害剤関する5つの文献に記載されている化合物を、構造ベースでクラスタリングしていきます。過去記事ではKNIMEのMDSノードを利用して次元を削減し(対distance matrix)可視化を行いましたが、今回はdistance matrixを挟まず、fingerprintに対して直接t-SNEを用いて次元を落とし、可視化してみます。

t-SNE

次元削減法の一つで、人気なんだそうです。下記サイトが雰囲気を掴みやすかったです。

perplexityという調整可能なパラメータ…(中略)…は、おおざっぱに言うと、データの局所的な特性と全体的な特性のどちらをより考慮するか、そのバランスを表しています。

と書かれており、このパラメータを動かしながら可視化をやってみます。

 SDFを読むところ(SDF Reader)は割愛しますが、ファイルの中身はこんな感じです。

f:id:sumtat:20180221220909p:plain

化合物のIDに相当するカラムがないので、毎度おなじみString Manipulationを使って、新たに1つカラムを作成しました。

f:id:sumtat:20180221221117p:plain

「compound_」という文字列と1から始まる数字を足してIDという名前のカラムに入れることにしました。joinは文字列の連結なので、数字部分はstring()でくくって文字列にしています。また、ROWINDEXはテーブル内の行数(スタートはゼロ)なので、ROWINDEX+1の意味するところは「1から始まる行番号」です。ここまでを実行すると次のようになります。

f:id:sumtat:20180221221452p:plain

 

つづいてcanonical smilesを書きます。

python内ではrdkitを使って構造を扱うので、なんとなくKNIMEのノードもRDkit Canon SMILESを使いました。設定は簡単で、構造情報が入っているカラムをRDKit Mol columnに指定して、SMILESを書き出すカラム名を何にするかNew column nameに指定すればOKです。 

f:id:sumtat:20180221221725p:plain

実行すると次のようになります。

f:id:sumtat:20180221221950p:plain

構造式が2つになりましたが、SDFとSMILESなので見え方は同じでも、中身は違います。文字列で表示させてみますね。

f:id:sumtat:20180221222202p:plain

カラム名の上で右クリックすると表示メニューがでるので、SDF StringやStringを選択するとその違いがわかると思います。

 

Parameter Oprimization Loop Start

ちょっと脇道に逸れて、loop startを先に紹介します。先に述べた通り、今回はperplexityというパラメータを動かしながら可視化を行います。そこで、その値をpという変数にすることとして、開始を10、終了を90で10刻みに数字を発生させてループを回してねという条件設定に下のキャプチャでは設定している様子がわかると思います。

for i in numpy.arange(10, 100, 10):

みたいな感じです。

f:id:sumtat:20180221222443p:plain

Python Script

入りの▶︎と出口の▶︎のパターンが違ういくつかがありますが、今回は1=>2を使います。

f:id:sumtat:20180221225957p:plain

レイアウトはこんな感じです。スクリプトを書く画面がエディタになっていて、少しずつ動きを確認しながら書いていくことができます。ノード自体を実行しているわけではないので、このエディタの中でrunしても、outputの▶︎にはデータはいきません。

画面中央にクスリプトを書きます。中身は雰囲気で書いてるので、間違ってたらごめんなさい。こういうの初出しですよ。結構恥ずかしいですね。

画面左にはKNIMEのフローで流れてきた情報があって、使用することができます。上側がinput_table、下側がflow_variablesというDataFrameだというイメージかと思います。このエディタ内でちょっと動かしてみます。

f:id:sumtat:20180221230815p:plain

選択した行をExecute selected linesをクリックして実行しました。すると画面右側に読み込んだモジュールや、定義したリストなどなど、表示されます。またそれらをダブルクリックすると標準出力エリアに内容が表示されます。例ではrefsをダブルクリックした後の様子をキャプチャしました。

まあ、私も含めて「まずは慣れろ」です。

 

実行後の結果は次のようになります。

f:id:sumtat:20180221231320p:plain
f:id:sumtat:20180221231337p:plain

左が上▶︎、右が下▶︎です。

Joinerを使って2つをくっつけておきました。

f:id:sumtat:20180221231557p:plain

 

f:id:sumtat:20180221231701p:plain

 

Color Manager

plotが見やすくなるように(今回の場合、論文ごとに色づけすると上手く分かれることは過去記事の内容で分かっているので)色をつけました。

f:id:sumtat:20180221231927p:plain

分岐先のstring manipulationではplotのタイトルをつけるために下のような処理をしています。ここのstring manipulationはvariable用のを使っているところがポイントですね(出入り口が赤丸)。

f:id:sumtat:20180221232211p:plain

 

次元を落として作成したcol1とcol2をプロットしたものが次のキャプチャです。下の例はloopの最終iterationが終わったとこなのでpreplexity=90です。

f:id:sumtat:20180221232627p:plain

image to tableを使って、plotの画像をtableに入れていきます。

f:id:sumtat:20180221232906p:plain

これをloopしているので、loop endが終わった後は次のようになります。

f:id:sumtat:20180221233031p:plain

全てのplotがテーブルの埋め込み画像として溜まっています。今回のloop endは2portのものを使いました。上▶︎から入ったデータは上▶︎出口から、下▶︎から入ったデータは下▶︎出口から吐き出されます。

f:id:sumtat:20180221233328p:plain

molecule type castでSMILES(文字列)を構造として認識させています。column filterではいらないカラムを捨てました。loop endの下▶︎出口を見てみましょう。

f:id:sumtat:20180221233551p:plain

こんな感じで、全ての結果がtableとして保持できますので、好みの条件のiterationを指定してフィルター後、処理を続けることなどができると思います。ご紹介まで。

 

最後にgrid to tableです

f:id:sumtat:20180221233839p:plain

指定したカラムをgridにします。今回はGrid Column Countを3に指定しました。説明するより見た方がはやいです。結果のキャプチャを載せます。

f:id:sumtat:20180221234206p:plain

はい、こういうことです(語彙不足)。

perplexityの値によって、プロットの様子が変化していることがわかります。値が小さいほうが局所に視点がいくんですかね?perplexity=20~40あたりではオレンジが2つに割れているように見えます。実際中身を見てみると、2つの系統があるように見えました。論文では5~50くらいの設定を推奨しているようです。前回のMDSにくらべて、スパッと分かれている印象を受けました。

このようにt-SNE、結構優秀です。数十万クラスのデータになるとわかりませんが、(少なくとも今回の例では)〜600化合物のクラスタリングをする前処理として、視覚的に全体を捉えることができました。先にも少し述べましたが、この中で気に入ったperplexityで得られたcol1,col2を使って再度クラスタリングすれば分かりやすいのでは?と思います。

 

KNIMEの枠を超えたところには、いろんな便利なものがまだまだ沢山あるようです。少しずつ身につけられるように頑張ります。

 

【追記】Scatter Plotのタイトルを変数を使って指定する方法(2018.04.16)

id:rkakamilanさんのご指摘通り、"変数をタイトルにする"部分を書いてなかったので追記します。

f:id:sumtat:20180416000256p:plain

特別、凝った操作は必要なくて、今回の場合

Scatter Plotノードの設定画面内上部のタブから"Flow Variables"を選んだ後、chartTitleの部分に所望の変数を指定すればOKです(この記事内ではtitleという名前の変数)!

大体のKNIMEノードでは設定画面にFlow Variablesのタブが用意されているので、そのの中で、それっぽいところに指定してやればいけちゃう感じです。

 

 

*1:ここにたどり着くのに数時間かかった。動かすための環境を用意するので一苦労です。