Mol2vecは自然言語処理で化合物空間の特徴を学習する教師なし学習アルゴリズムです。学習後のモデルは化合物の特徴量を抽出する目的で利用できます。
詳細は理解しきっていませんが「化合物のフィンガープリント表現で欠損する情報を大量データでの教師なし学習で補完するようなアプローチ」という認識です。
考案者のGithubにはPythonで利用できるプログラムと学習済みモデルが公開されています。
リポジトリはアーカイブとなっており推奨のインストール方法ではインストールできませんでしたが、setup.pyを変更したらインストールできたので使ってみたいと思います。
実行環境
- OS: Ubuntu 22.04.3 LTS
- CPU: AMD Ryzen 7 5700X 8-Core Processor
- GPU: NVIDIA GeForce RTX 3060 Ti
- メモリ: 32GB
Mol2vecおよび今回の機械学習モデルではGPUは使用しません。
Mol2vecのインストール
推奨のインストール方法だと、Word2vecの実装で利用しているgensimというパッケージでバージョンエラーが発生しました。こちらを回避していきたいと思います。
condaの仮想環境を利用しますが他の仮想環境やコンテナで利用する場合は適宜読み替えてください。
仮想環境の作成
condaの仮想環境を作成します。pythonのバージョンは3.8です。
作成後は忘れないように仮想環境に入っておきましょう。
conda create -n mol2vec python=3.8
conda activate mol2vec
リポジトリをローカル環境にコピーする
GithubからMol2vecのリポジトリをコピーします。
下記のコードではコピー先がカレントディレクトリになるので注意しましょう。また、コピー後はリポジトリ内で作業するため移動しておきましょう。
git clone https://github.com/samoturk/mol2vec.git
cd mol2vec
setup.pyの編集
フォルダ内のsetup.pyをテキストエディタで開き次のように内容を変更します。
- pythonのバージョンを”3.6″から”3.8″に変更
- gensimの記述を”gensim”から”gensim==3.8.3″に変更
書き換えたら上書き保存してください。
必要なパッケージのインストール
以下のコマンドで必要なパッケージをインストールします。pip推奨です。
pip install .
pip install rdkit
pip install scikit-learn
RDkitは2025年2月現在で最新バージョン(2024.3.5)でも問題ありませんが、バージョンアップによりAllChem.GetMorganFingerprintAsBitVectが廃止された場合は使えなくなりそうです。
その場合はバージョンを2024.3.5以前に指定してあげましょう。
Mol2vecを機械学習に利用する
リポジトリのexsamplsフォルダにはMol2vecを教師あり学習に利用する例があります。
そちらをもとにMol2vecの特徴量を用いた変異原性(Ames)の判別モデルをj作成したいと思います。流れは以下の通りです。
- データの読み込み
- Mol2vecによる特徴量生成
- クロスバリデーションによるモデルの精度確認
以下、jupyter notebookでの利用を想定しています。管理人がMol2vecの練習に利用したipynbファイルはGithubに置いているので参考になれば幸いです。
データの読み込み
examplesフォルダ内のSDFをpandasのデータフレームとして読み込みます。
import os
from rdkit.Chem import PandasTools
# パスの設定
# Mol2vecフォルダのパスを"MOL2VEC_PATH"に格納します。
MOL2VEC_PATH = '/path/to/your/mol2vec'
# データの読み込み
df = PandasTools.LoadSDF(os.path.join(MOL2VEC_PATH, 'examples/data/ames.sdf'))
Mol2vecによる特徴量作成
examplesフォルダ内の学習済みモデルを利用して特徴量を算出します。
モデルの学習はZINCデータベースの2,000万化合物をもとに行われています。半径1、ビット長1024(RDkitのデフォルト?)のMorgan Fingerprintで原子単位に識別子を与えてコーパスを作成し、skip-gramベースのWord2vecで学習することにより300次元表現ベクトルを獲得しているようです。
以下のコードではモデル作成ように目的変数と特徴量の分割まで行っています。
import numpy as np
import pandas as pd
from mol2vec.features import mol2alt_sentence, MolSentence, DfVec, sentences2vec
from gensim.models import word2vec
# モデルの読み込み
model = word2vec.Word2Vec.load(os.path.join(MOL2VEC_PATH, 'examples/models/model_300dim.pkl'))
# 特徴量を算出
df['sentence'] = df.apply(lambda x: MolSentence(mol2alt_sentence(x['ROMol'], 1)), axis=1)
df['mol2vec'] = [DfVec(x) for x in sentences2vec(df['sentence'], model, unseen='UNK')]
# データの分割
X = pd.DataFrame(np.array([x.vec for x in df['mol2vec']]))
y = df['class'].astype(int)
クロスバリデーションによるモデルの精度確認
scikit-learnのRandomForestClassifierで判別モデルを作成し、ROC-AUCでモデルの精度を確認します。
クロスバリデーションは層状K分割で行います。クロスバリデーションでモデルの精度を確認する場合、目的に応じて手法を考える必要はありますが、今回はシンプルに正負ラベルが偏らないようにするだけにとどめておこうと思います。
まず、以下のコードでモデルの作成と予測値の算出を行います。
from sklearn.model_selection import StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# StratifieKFold
kf = StratifiedKFold(n_splits=4, shuffle=True, random_state=0)
y_pred_all = pd.DataFrame()
for i, (train_idx, test_idx) in enumerate(kf.split(X, y)):
# データの設定
y_train, y_test = y.loc[train_idx], y.loc[test_idx]
X_train, X_test = X.loc[train_idx, :], X.loc[test_idx, :]
# モデルの設定
model = RandomForestClassifier(n_jobs=-1, random_state=0)
# モデルの訓練と予測値の算出
model.fit(X_train, y_train)
y_pred = model.predict_proba(X_test)[:, 1]
y_pred = pd.DataFrame(data=y_pred, columns=['proba'], index=test_idx)
y_pred['kFold'] = i
y_pred_all = pd.concat([y_pred_all, y_pred], axis=0)
# データの集約
y_pred_all.sort_index(ascending=True, inplace=True)
y_mol2vec = pd.concat([y, y_pred_all], axis=1)
y_mol2vec
次に、以下のコードでデータ全体と各イテレーションのROC-AUCを求めます。
# 評価値の算出
roc_auc_all = roc_auc_score(y_mol2vec['class'], y_mol2vec['proba'])
print('ROC-AUC: ', f'{roc_auc_all:.3f}')
for i in range(0, 4):
roc_auc_k = roc_auc_score(y_mol2vec[y_mol2vec['kFold']==i]['class'], y_mol2vec[y_mol2vec['kFold']==i]['proba'])
print(f'ROC-AUC_K{i}: ', f'{roc_auc_k:.3f}')
ROC-AUC: 0.863
ROC-AUC_K0: 0.859
ROC-AUC_K1: 0.866
ROC-AUC_K2: 0.861
ROC-AUC_K3: 0.867
他のアルゴリズムや特徴量と比較していないので解釈が難しいですが、QSARの特徴量として使えなくはなさそうですね。
Githubの方では、外挿性を確認したり、Morgan Fingerprintの場合と比較したりもしましたが、簡単な検証では特徴を把握しきれませんでした…。
最後に
Mol2vecのインストールと機械学習への活用方法を紹介しました。
特徴を十分に把握しきれていませんが、少なくとも2,000万化合物の情報が入っているユニークな特徴量なのでマルチモーダルでは活躍しそうな印象です。今後色んなデータで試していきたいですね。
コメント