Molecular Fingerprints DeepChem チュートリアル 4

Pythonでインフォマティクス

このカテゴリーの記事では、「Pythonを使った機械学習やケモ・バイオインフォマティクスの実装や論文」を紹介していきたいと考えています。Python は3系(3.7)、anacondaを中心にして環境構築していきます。以下のようなハード・ソフト環境(CentOS Linux)を用いますが、Python(anaconda)が利用できれば、異なる環境下でも類似の実装が可能かと思います。

● CPU Intel® Core™ i7-6700K CPU @ 4.00GHz × 8
● メモリ  64GB
● GPU GeForce GTX 1080/PCIe/SSE2
● OS  CentOS Linux 8
● Python 3.7


はじめに

これまでにケモインフォマティクス、特にグラフ畳み込みネットワーク(GCN; Graph Convolutional Network)による深層学習が実行可能な、DeepChem をインストールし、チュートリアル1, 2, 3 を実行してきました。

これまでみてきたように、化学分野に機械学習を適用する場合、分子構造の情報を機械学習で扱える形、特徴量にしなればなりません。これまでのチュートリアルでは、主に featurizer=’GraphConv’ と指定することで、GraphConvModel を適用してきました。今回は、チュートリアル 4 Molecular Fingerprints にて、「分子フィンガープリント」と呼ばれる表現方法、分子構造を特徴量とする方法を紹介します。フィンガープリントとは、指紋のことで、非常にシンプルに分子を表現することができ、低分子化合物に適した方法であると考えられています。


フィンガープリントとは?

多くの場合、深層学習モデルは数値を特徴量とします。つまり、各データポイント(分子)を、1つまたは複数の数値の配列として表現する必要があります。また、多くの深層学習モデルでは、各データポイントの次元が揃っていることが求められます。分子は、その種類によって原子の数、その構造が大きく異なるため、分子構造の情報を維持したまま次元を揃える工夫が必要になります。即ち、可変サイズである分子構造(原子の数や種類、またその結合の数や種類)を、固定サイズの配列で表現する必要があります。

このような問題を解決するために考案されたのが Molecular Fingerprints (分子フィンガープリント)です。フィンガープリントは固定長の配列で、異なる要素は分子の異なる特徴の存在を示します。フィンガープリントが似ているということは、同じ特徴を多く含んでいることを示しており、似たような化学的性質を有したり、類似の化学反応を起こす可能性が高いと考えることができます。

DeepChem は、チュートリアル3 An Introduction To MoleculeNet でも少し紹介した、「Extended Connectivity Fingerprint」(ECFP)と呼ばれる特殊なタイプのフィンガープリントをサポートしています。ECFPは、「Circular Fingerprints」と呼ばれることもあります。ECFPアルゴリズムは、まず、原子の直接的な特性と結合のみに基づいて原子を分類します。例えば、「2つの水素と2つの重原子に結合した炭素原子」が特徴量となり、この特徴を含む分子に対して、フィンガープリントの特定の特徴量が 「1(有り)」に設定されます。「2つの水素と2つの重原子に結合した炭素原子」を含まない分子は、この特徴量が「0」となるわけです。そして、この原子のより外側の近傍領域へと範囲を拡げ、新たな特徴量を繰り返し特定していきます。ある特定の特徴量が他の2つの特定の特徴量と結合し、上位の特徴量となります。

今回もJupyter notebookを起動し、notebook上で実行していきます。

$ jupyter notebook

まずはセルに以下を入力し、Run して下さい。

In [1]:
import deepchem as dc
dc.__version__
Out[1]:
'2.6.0.dev'

1行目でDeepChem をインポートし、dc…の形で使えるようにしています。2行目はDeepChemのバージョンを表示する指示で、2.6.0.dev とバージョンが表示されました。

次の入力から実際のチュートリアルの内容に入っていきます。以下を実行し、tox21 データセットにECFPを適用してみましょう。

In [2]:
tasks, datasets, transformers = dc.molnet.load_tox21(featurizer='ECFP')
train_dataset, valid_dataset, test_dataset = datasets
print(train_dataset)
RDKit WARNING: [19:19:18] WARNING: not removing hydrogen atom without neighbors
[19:19:18] WARNING: not removing hydrogen atom without neighbors
RDKit WARNING: [19:19:30] WARNING: not removing hydrogen atom without neighbors
[19:19:30] WARNING: not removing hydrogen atom without neighbors
<DiskDataset X.shape: (6264, 1024), y.shape: (6264, 12), w.shape: (6264, 12), task_names: ['NR-AR' 'NR-AR-LBD' 'NR-AhR' ... 'SR-HSE' 'SR-MMP' 'SR-p53']>

train_dataset の特徴量配列である X は、その形状が (6264, 1024) と示されています。つまり、train_dataset には6264個のサンプル(分子)が含まれており、各分子が長さ1024のフィンガープリントで表現されています。

また、ラベル配列 y、その形状が(6264, 12)となっています。つまり、6264個のサンプル(分子)に対して、12種類のラベルが付されたマルチタスクデータセットであることがわかります。今回使用している tox21 は、分子の毒性に関するデータセットで、12種類の毒性試験結果が、それぞれ独立に12種類のラベルとして記録されています。

次に重みの配列も確認してみましょう。

In [3]:
train_dataset.w
Out[3]:
array([[1.04502242, 1.03632599, 1.12502653, ..., 1.05576503, 1.17464996,
        1.05288369],
       [1.04502242, 1.03632599, 1.12502653, ..., 1.05576503, 1.17464996,
        1.05288369],
       [1.04502242, 1.03632599, 1.12502653, ..., 1.05576503, 0.        ,
        1.05288369],
       ...,
       [1.04502242, 0.        , 1.12502653, ..., 1.05576503, 6.7257384 ,
        1.05288369],
       [1.04502242, 1.03632599, 1.12502653, ..., 1.05576503, 6.7257384 ,
        1.05288369],
       [1.04502242, 1.03632599, 1.12502653, ..., 0.        , 1.17464996,
        1.05288369]])

いくつかの要素が 0 になっています。重み 0 はデータの欠落を示すために使われています。全ての分子について、12種類全ての毒性評価試験が行われたわけではないためです。重み 0 のサンプルは、フィッティングや評価の際に無視されます。

また、ほとんどのウェイトは1に近いですが、正確には1ではありません。モデルを学習する際には、12個のタスクのそれぞれが均等に寄与するように、各タスクにおける正と負のサンプル全体の重みを均一にするために用いられています。


フィンガープリントによるモデルの学習

それでは、機械学習モデルをトレーニングしてみましょう。これまでのチュートリアルで使用したGraphConvModel と比べ、フィンガープリントはよりシンプルな固定長の配列になっています。そこで、よりシンプルなモデルを使ってみましょう。

In [4]:
model = dc.models.MultitaskClassifier(n_tasks=12, n_features=1024, layer_sizes=[1000])

MultitaskClassifier は、全結合層の単純なスタックで、この例では、幅 1000 の単一隠れ層を設定しています。また、各サンプルは1024個の特徴があり、12種類のタスクの予測が行われるように指定しています。タスクごとに別のモデルを学習することもできますが、1つのモデルを複数のタスクに対応させる学習の方が、性能が上ると考えられています。この例については、後のチュートリアルで取り上げます。

それでは、モデルを学習して評価してみましょう。

In [5]:
import numpy as np

model.fit(train_dataset, nb_epoch=10)
metric = dc.metrics.Metric(dc.metrics.roc_auc_score)
print('training set score:', model.evaluate(train_dataset, [metric], transformers))
print('test set score:', model.evaluate(test_dataset, [metric], transformers))
training set score: {'roc_auc_score': 0.9583719439123399}
test set score: {'roc_auc_score': 0.6779650179316041}

学習に用いたデータへのオーバーフィッティング(過学習)の状態ですが、フィンガープリントによる簡単な特徴量とモデルで、悪くないスコアが得られました。DeepChem で実行できる特徴量生成と学習モデルについて、次回以降さらに紹介していきます。


コメント

タイトルとURLをコピーしました