Coba model QSAR sederhana dengan Chainer 【Prediksi permeabilitas senyawa penghalang darah-otak】

2020 3 年 月 日 2

QSAR (Hubungan Struktur-Aktivitas Kuantitatif) adalah korelasi statistik antara struktur zat kimia dan aktivitas fisiologisnya (toksisitas, kemampuan mengikat enzim, aktivitas sebagai obat, dll.).Memprediksi kinerja senyawa dari korelasi berdasarkan set data eksperimen bahan kimia yang besar.

Kali ini, kami akan menggunakan Chainer, kerangka pembelajaran mendalam Jepang, untuk membuat model QSAR sederhana yang "memprediksi permeabilitas penghalang darah-otak senyawa" dan memverifikasi kinerjanya pada set pengujian.

Target prediksi dan data

BBBP dari MoleculeNet digunakan untuk data.Untuk melihat sekilas data, lihat yang berikut ini yang telah dilakukan sebelumnya.

Data merangkum permeabilitas penghalang darah-otak senyawa dengan XNUMX untuk "penetrasi" dan XNUMX untuk "non-penetrasi".

Buat model

Lingkungan

from rdkit import rdBase
import chainer
print('rdkit version: ',rdBase.rdkitVersion)
chainer.print_runtime_info()
versi rdkit: 2019.03.4 Platform: Linux-5.0.0-37-generic-x86_64-with-debian-buster-sid Chainer: 6.2.0 NumPy: 1.17.4 CuPy: CuPy Versi : 6.2.0 CUDA Root : /usr /local/cuda CUDA Build Version : 10010 CUDA Driver Version : 10010 CUDA Runtime Version : 10010 cuDNN Build Version : 7500 cuDNN Versi : 7605 NCCL Build Version : 2402 NCCL Runtime Version : 2402 iDeep: Tidak Tersedia

Anda dapat memeriksa versi Chainer, Numpy, dan Cupy yang Anda gunakan dengan chainer.print_runtime_info().

bangunan model

import numpy as np
import pandas as pd
from rdkit import Chem
from rdkit.Chem import Draw, PandasTools, Descriptors
 
# データの読み込み
df = pd.read_csv('BBBP.csv',index_col=0)
 
# smilesからmolファイルを生成し、データフレーム中に加える
PandasTools.AddMoleculeColumnToFrame(df, smilesCol = 'smiles')
 
# molができなかった行を削除する
df = df.dropna()
 
# molファイルから化合物記述子を算出する
for i,j in Descriptors.descList:
    df[i] = df['ROMol'].map(j)
df['Ipc'] = [Descriptors.Ipc(mol, avg=True) for mol in df['ROMol']]  
 
# chainer用にデータ型を変換
x = df.iloc[:,4:].values.astype('float32')
y = df['p_np'].values.astype('int32')
indices = np.array(range(x.shape[0])) # train_test_split後も列番号を保持しておく
 
# train, test, valに分割
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test, indices_train, indices_test = train_test_split(x, y, indices, test_size=0.05, random_state=123)
 
# 説明変数の標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(x_train)
x_train= scaler.transform(x_train)
x_test = scaler.transform(x_test)
 
print(type(x_train), x_train.shape, type(y_train), y_train.shape)
print(type(x_test), x_test.shape, type(y_test), y_test.shape)
(1937, 200) (1937,) (102, 200) (102,) 

Lihat di sini untuk membuat deskriptor dari objek mol.
Hitung deskriptor molekuler dan sidik jari dari SMILES dan simpan dalam bingkai data [Python, RDKit]

Tutorial resmi untuk penggunaan dasar Chainer sangat lengkap.
Pengantar Tutorial Chainer Pembelajaran Jauh

# 説明変数と目的変数のセットで使えるように変換する
from chainer.datasets import TupleDataset
train = TupleDataset(x_train, y_train)
test = TupleDataset(x_test, y_test)
 
# イテレータの準備
from chainer.iterators import SerialIterator
train_iter = SerialIterator(train, batch_size=64, repeat=True, shuffle=True)
test_iter = SerialIterator(test, batch_size=64, shuffle=False, repeat=False)
 
# ニューラルネットワークの作成
# 3層のmulti layer perceptron(MLP)
import chainer.links as L
import chainer.functions as F
from chainer import Chain
from chainer import optimizers, training
from chainer.training import extensions

class MLP(chainer.Chain):
 
    def __init__(self):
        super().__init__()
        with self.init_scope():
            self.fc1 = L.Linear(None, 100)
            self.fc2 = L.Linear(None, 20)
            self.fc3 = L.Linear(None, 2)
 
    def forward(self, x):
        h = F.relu(self.fc1(x))
        h = F.relu(self.fc2(h))
        h = self.fc3(h)
        return h
 
# ネットワークをClassifierでラップしする
# (目的関数(デフォルトはsoftmax交差エントロピー)の計算し、損失を返す)
predictor = MLP()
net = L.Classifier(predictor)
 
# 最適化手法を選択して、オプティマイザを作成する
optimizer = optimizers.MomentumSGD(lr=0.1).setup(net)
 
# アップデータにイテレータとオプティマイザを渡す
updater = training.StandardUpdater(train_iter, optimizer, device=-1)
trainer = training.Trainer(updater, (50, 'epoch'), out='/results/')
from chainer.training import extensions
 
trainer.extend(extensions.LogReport(trigger=(5, 'epoch'), log_name='log'))
trainer.extend(extensions.snapshot(filename='snapshot_epoch-{.updater.epoch}'))
trainer.extend(extensions.dump_graph('main/loss'))
trainer.extend(extensions.Evaluator(test_iter, net, device=-1), name='val')
trainer.extend(extensions.PrintReport(['epoch', 'iteration', 'main/loss', 'main/accuracy', 'val/main/loss', 'val/main/accuracy', 'fc1/W/data/mean', 'elapsed_time']))
trainer.extend(extensions.PlotReport(['fc1/W/grad/mean'], x_key='epoch', file_name='mean.png'))
trainer.extend(extensions.PlotReport(['main/loss', 'val/main/loss'], x_key='epoch', file_name='loss.png'))
trainer.extend(extensions.PlotReport(['main/accuracy', 'val/main/accuracy'], x_key='epoch', file_name='accuracy.png'))
trainer.extend(extensions.ParameterStatistics(net.predictor.fc1, {'mean': np.mean}, report_grads=True))
 
trainer.run()
from IPython.display import Image, display
display(Image(filename='results/accuracy.png'))

Tampaknya memiliki tingkat akurasi tertentu, tetapi bahkan saat pembelajaran berlangsung, akurasi pada set tes belum banyak meningkat ...

kesimpulan

# 学習したモデルで推論してみる
with chainer.using_config('train', False), chainer.using_config('enable_backprop', False):
    y_pred = predictor(x_test)
 
# 推論結果の確認
print('accuracy', F.accuracy(y_pred, y_test)) # accuracy variable(0.88235295)
 
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_pred.data.argmax(axis=1))
 larik([[21, 7], [ 5, 69]]) 

akurasi adalah nilai seperti yang Anda lihat dari gambar.Saat mengevaluasi akurasi klasifikasi kelas menggunakan matriks kebingungan, ada positif palsu dan negatif palsu, tetapi tampaknya akurasi tidak diperoleh dengan klasifikasi satu sisi.

# 一部予測結果を見てみる
for i in range(int(len(y_pred)/10)):
    print('No.', indices_test[i])
    print('label:', y_test[i])
    print('pred :', np.argmax(y_pred[i].array))
    img = Draw.MolToImage(df.ROMol[indices_test[i]])
    display(img)

Gambar adalah bagian dari keluaran, tetapi memang benar dapat dibedakan bahkan oleh mata manusia.Ini juga menyenangkan untuk meneliti apa yang Anda lakukan salah.