Hãy thử một mô hình QSAR đơn giản với Chainer【Dự đoán tính thấm qua hàng rào máu não của các hợp chất】

Ngày 2020 tháng 3 năm 2

QSAR (Mối quan hệ cấu trúc-hoạt động định lượng) là mối tương quan thống kê giữa cấu trúc của một chất hóa học và hoạt động sinh lý của nó (độc tính, khả năng liên kết với enzyme, hoạt động như một loại thuốc, v.v.).Dự đoán hiệu suất hợp chất từ ​​các mối tương quan dựa trên bộ dữ liệu thực nghiệm lớn về hóa chất.

Lần này, chúng tôi sẽ sử dụng Chainer, một khung học sâu của Nhật Bản, để tạo ra một mô hình QSAR đơn giản "dự đoán tính thấm qua hàng rào máu não của các hợp chất" và xác minh hiệu suất của nó trên bộ thử nghiệm.

Dự đoán mục tiêu và dữ liệu

BBBP của MoleculeNet được sử dụng cho dữ liệu.Để có cái nhìn toàn cảnh về dữ liệu, hãy tham khảo phần sau đã được thực hiện trước đó.

Dữ liệu tóm tắt tính thấm của hàng rào máu não của các hợp chất với XNUMX cho "thâm nhập" và XNUMX cho "không thâm nhập".

Tạo một mô hình

Môi trường

from rdkit import rdBase
import chainer
print('rdkit version: ',rdBase.rdkitVersion)
chainer.print_runtime_info()
phiên bản rdkit: 2019.03.4 Nền tảng: Linux-5.0.0-37-generic-x86_64-with-debian-buster-sid Chainer: 6.2.0 NumPy: 1.17.4 CuPy: Phiên bản CuPy: 6.2.0 CUDA Root: /usr /local/cuda Phiên bản bản dựng CUDA: 10010 Phiên bản trình điều khiển CUDA: 10010 Phiên bản thời gian chạy CUDA: 10010 Phiên bản bản dựng cuDNN: 7500 Phiên bản cuDNN: 7605 Phiên bản bản dựng NCCL: 2402 Phiên bản thời gian chạy NCCL: 2402 iDeep: Không khả dụng

Bạn có thể kiểm tra các phiên bản Chainer, Numpy và Cupy mà bạn đang sử dụng với chainer.print_runtime_info().

xây dựng mô hình

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,) 

Xem ở đây để tạo bộ mô tả từ các đối tượng mol.
Tính toán các mô tả phân tử và dấu vân tay từ SMILES và lưu trữ chúng trong khung dữ liệu [Python, RDKit]

Hướng dẫn chính thức về cách sử dụng cơ bản của Chainer rất đầy đủ.
Giới thiệu về Hướng dẫn Deep Learning Chainer

# 説明変数と目的変数のセットで使えるように変換する
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'))

Nó dường như có một mức độ chính xác nhất định, nhưng ngay cả khi quá trình học tập tiến triển, độ chính xác trong bộ kiểm tra vẫn không được cải thiện nhiều ...

推論

# 学習したモデルで推論してみる
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))
 mảng([[21, 7], [ 5, 69]]) 

độ chính xác là một giá trị như bạn có thể thấy từ hình.Khi đánh giá độ chính xác của phân loại lớp bằng cách sử dụng ma trận nhầm lẫn, sẽ có kết quả dương tính giả và âm tính giả, nhưng có vẻ như độ chính xác không đạt được khi phân loại một phía.

# 一部予測結果を見てみる
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)

Hình ảnh là một phần của đầu ra, nhưng đúng là nó có thể được phân biệt ngay cả bằng mắt người.Thật thú vị khi xem xét kỹ lưỡng những gì bạn đã làm sai.