ただのメモ

他の人に見せても良い方のメモ

化学構造と畳み込みネットワーク

  • こちらの文献をまとめる。
  •  化学と深層学習の組み合わせがHotらしい。例えば、
    • Virtual screening(化合物探索)
    • 定量的な構造と活性の関係性の評価
    • 吸収、分布、代謝、毒性、の予測
  • などに使われている。
  • 分子構造に基づいた予測では、Graph neural networkがよく使われる(うまくいくから)
    • 化学構造をグラフにする
    • タンパク質を、記号の配列、としたりも出来る。
  • では、どうやって化学構造をグラフに落とし込むのか、という問題がある。そこの知識を固めよう。
  • 分子は、タプル M = (V, E, F)とおける。Vは頂点集合、Eは辺集合(端点を2つ指定して、さらに、辺ごとに特徴を指定している。特徴は、単結合か、二重結合か、という、結合の種類を指定するもの)、Fは特徴集合(ここでの特徴は、頂点に対応する特徴。頂点がどの原子か、荷電、Hybridizationを指定する。)
    • Hybridizationについては、こちら
    • Valence Bond Theoryは、分子の中で原子がどのように結合を作るか、という理論。
    • その中で、共有結合は、原子の、電子の軌道と、他の原子の、電子の軌道をかぶらせることで、形成される。
    • 結合が形成されると、2つの核の間で電子が見つかる確率が上がる。
    • 軌道をかぶらせるには、エネルギー準位があっていなければならない。この、エネルギーと結合距離が等しくなる過程を、Hybridizationという。
    •  sp^3混成軌道の話が出てくる。
  • 隣接行列群Aを用意する。
    • 結合の種類tにつき、隣接行列 A^{(t)}を作る。
    • 辺があれば、1を、なければ、0を、要素として返す。
  • 特徴行列を用意する。
    • 辺だけでなく、点にもある特徴(どの原子か、など)を拾うため。
  • この隣接行列群Aと特徴行列Fのペアで、分子を表現し、入力情報とする。
  • その後、
    • Convolution Layer
      •  X^{(l+1)} = \sigma(\Sigma_t \tilde{A_t} X^{(l)} W_t^{(l)}
      • 入力情報をもとに、次々に隣接行列と重みパラメータをかけていく
      • 何度も隣接行列を掛けることで、最初は隣の情報、次は隣の隣の情報、というように、掛けるにつれて、より遠くの特徴を反映させられる。最終的に全体を反映した量になる。
    • Dense Layer
      •  (行列を行列に)
      •  X^{(l+1)} =  X^{(l)} W^{(l)}
      • 掛け算していく
    • Gather Layer
      •  行列をベクトルにする
      •  (X^{(l+1)})_j = \Sigma_j (X^{(l)} )_{ij}
      • 行列の要素を足し合わせて、一つ次元を落とす。
  • このようなGraph Convolutional Networkは、いろんな分野(人間関係(ひととひとのグラフ)、購買情報(ものとひとのグラフ)、道路網(場所と場所の有向グラフ、辺は道)などに使われる。こちら

次は、畳み込みネットワークをお絵描きする。

  • こちらの記事がとても役に立った。
  • また、家族関係の話なら、こちらが面白い(し、わかりやすい)。
  • 最適化アルゴリズムについては、こちらが良かった。
  • epoch数は過学習を防ぐため、いい感じのところで止める(Early stopping)。今回はしていない。こちら
  • Early stoppingのほかに、過学習を防ぐため、Dropoutというものがある。毎回発火するわけではない。今回はしていない。こちら
  • 今回はConv2Dを使用する。こちらが参考になった。
  • ちなみに、以下のコードは、Tutorialである。こちら

 

import tensorflow as tf
from tensorflow.keras import datasets, layers, models
(train_images, train_labels), (test_images, 
                               test_labels) = datasets.mnist.load_data()
#データを訓練用とテスト用に分ける
train_images = train_images.reshape*1
test_images = test_images.reshape*2
#データの形を整える
train_images, test_images = train_images / 255.0, test_images / 255.0
ピクセルの値を 0~1 の間に正規化
model = models.Sequential()
#モデルを逐次的に処理するものとする。
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(28, 28, 1)))
#3×3のカーネル(フィルタ)で畳み込む
#フィルタを32枚生成する。(32種類の特徴量)
#活性化関数がRelu(負なら0、正なら恒等)何も指定しないと、そのまま
#ReLUはニューロンの発火がスパースになる
model.add(layers.MaxPooling2D((2, 2))) 
#2×2の行列の中で一番大きな要素を取り出す。
#取り出すだけなので、パラメータは不要。
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#32種類の処理後の画像(26×26)をさらに、畳み込み
model.add(layers.MaxPooling2D*3
model.add(layers.Flatten())
#(3×3×64)のテンソルをここで、1列のベクトルにする。
 
model.add(layers.Dense(64, activation='relu'))
#layers.Denseは、全結合ネットワーク
#完全2部グラフとして見れる
model.add(layers.Dense(10, activation='softmax'))
#0~9の数字を当てるので、最終出力は10行のベクトル
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
#AdamはSGDの発展版。
#SGDはパラメータ更新にランダムな1つのデータを使う。
#だから確率的勾配降下が起きる。
#これ以上はAdamは触れない
#損失関数も触れない。そんなに難しくない。答えがあってたら良い。
#精度として、正解率を指標としている。これを高めるように学ぶ
model.fit(train_images, train_labels, epochs=5)
#訓練の問題と答えを指定し、学習する。
#epochとは、1つのデータを何回使うか
#この場合、5回使う。
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
#verbose は詳細表示。そんなに気にしなくていいい
print(test_acc)

 

 

*1:60000, 28, 28, 1

*2:10000, 28, 28, 1

*3:2, 2)))

model.add(layers.Conv2D(64, (3, 3), activation='relu'