Проектирование сверточной нейронной сети для машинного обучения каннабиса, часть 1

May 01 2023
Хорошее и яркое воскресное утро для разработки сверточных нейронных сетей. CNN — это нейронная сеть, обученная использованию изображений и пропущенная через ряд фильтров для определения признаков.

Хорошее и яркое воскресное утро для разработки сверточных нейронных сетей. CNN — это нейронная сеть, обученная использованию изображений и пропущенная через серию фильтров для определения признаков. Как химик-органик, мы используем наши глаза при проектировании структур, так что, возможно, это интуитивный подход к машинному обучению и фрагментация молекулы с использованием наших собственных внутренних фильтров. Кажется естественным попробовать это.

Наша цель для этой сети — мы хотим знать, будет ли молекула вести себя как каннабис, исходя из ее константы связывания (насколько сильно лиганд связывается) с общим эндоканнабиноидным рецептором, CB1, основной мишенью для ТГК. Кристаллическая структура была получена Hua et al.

Структура представляет собой серию альфа-спиралей в форме башмака с карманом для связывания, расположенным очень глубоко внутри рецептора.

Влияние ТГК на рецептор CB1 можно количественно определить с помощью константы ингибирования Ki, которая указывает на то, насколько мощным является ингибитор. Небольшие значения Ki в 100 микромолей считаются сильными.

Если мы возьмем список ингибиторов для CB1 и их константы ингибирования, записанные в нМ из этой статьи:

Можем ли мы предсказать, будет ли новое каннабиноидное соединение вести себя аналогично терпену, такому как ТГК, исходя из его значения константы ингибирования. Вот некоторые данные, извлеченные из статьи. Не стесняйтесь брать больше.

compounds = {
    'CCCCC1=CC(=C2C3C=C(CCC3C(OC2=C1)(C)C)C)O': 36,
    'CCCC1=CC(=C2C3C=C(CCC3C(OC2=C1)(C)C)C)O': 22,
    'CCCCCC1=CC2=C(C3C=C(CCC3C(O2)(C)C)C)C(=C1C(=O)O)O': 620,
    'CCCCCC1=CC(=C(C(=C1)O)C/C=C(\C)/CCC=C(C)C)O': 1045,
    'CCCC1=CC(=C(C(=C1)O)C/C=C(\C)/CCC=C(C)C)O': 2865,
    'CCCCCC1=CC(=C(C(=C1C(=O)O)O)C/C=C(\C)/CCC=C(C)C)O': 13116,
    'COC1=C(C/C=C(CC/C=C(C)\C)\C)C(O)=CC(CCCCC)=C1': 10000,
    'CCCCCC1=CC(=C(C(=C1)O)C2C=C(CCC2C(=C)C)C)O': 1690,
    'CCCC1=CC(=C(C(=C1)O)C2C=C(CCC2C(=C)C)C)O': 14445,
    'CCCCCC1=CC(=C(C(=C1C(=O)O)O)C2C=C(CCC2C(=C)C)C)O': 626,
}

Давайте начнем наш импорт:


import rdkit
import numpy as np
import pandas as pd

from rdkit import Chem
from rdkit.Chem import AllChem

from matplotlib import pyplot as plt

df = pd.DataFrame()
df['smiles'] = list(compounds.keys())
df['ki'] = list(compounds.values())
df["mol"] = df["smiles"].apply(Chem.MolFromSmiles)

Влияние разрешения на изображение может быть там, где может преобладать пространство, занятое различной информацией.

Встраивание и разрешение вашего изображения очень важны, потому что это позволяет нейронной сети более эффективно абстрагировать функции. Итак, мы вычисляем размеры и 2D-координаты и устанавливаем 4 пустых нуля, которые будут действовать как метахранилище для такой информации, как атомный номер.

def chemcepterize_mol(mol, embed=10.0, res=0.2):

    dimensions = int(embed*2/res)
    chempcepterized_molecule = Chem.Mol(mol.ToBinary())
    chempcepterized_molecule.ComputeGasteigerCharges()
    AllChem.Compute2DCoords(chempcepterized_molecule)
    coords = chempcepterized_molecule.GetConformer(0).GetPositions()
    vector = np.zeros((dims,dims,4))

[[[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  ...
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]

 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  ...
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]

 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  ...
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]

for i,bond in enumerate(mol.GetBonds()):

    bond_order = bond.GetBondTypeAsDouble()
    start_atom_index = bond.GetBeginAtomIdx()
    end_atom_index = bond.GetEndAtomIdx()
    start_coordinates = coords[start_atom_index]
    end_coordinates = coords[end_atom_index]

fractional_space = np.linspace(0,1,int(1/res*2))

for fraction in fractional_space:
    coordinates = (fraction*start_coordinates + (1-fraction)*end_coordinates)
    x = int(round((coordinates[0] + embed)/res))
    y = int(round((coordinates[1]+ embed)/res))
    vector[ x, y, 0] = bond_order

for i,atom in enumerate(cmol.GetAtoms()):
   x = int(round((coords[i][0] + embed)/res))
   y = int(round((coords[i][1]+ embed)/res))
   
   vector[ x , y, 1] = atom.GetAtomicNum()
   
   hyptype = atom.GetHybridization().real
   vector[ x , y, 2] = hyptype

   charge = atom.GetProp("_GasteigerCharge")
   vector[ x , y, 3] = charge

return vect

def chemcepterize_mol(mol, embed=10.0, res=0.2):

    dimensions = int(embed*2/res)
    chempcepterized_molecule = Chem.Mol(mol.ToBinary())
    chempcepterized_molecule.ComputeGasteigerCharges()
    AllChem.Compute2DCoords(chempcepterized_molecule)
    coords = chempcepterized_molecule.GetConformer(0).GetPositions()
    vector = np.zeros((dims,dims,4))
    
    # Bonds

    for i,bond in enumerate(mol.GetBonds()):
    
        bond_order = bond.GetBondTypeAsDouble()
        start_atom_index = bond.GetBeginAtomIdx()
        end_atom_index = bond.GetEndAtomIdx()
        start_coordinates = coords[start_atom_index]
        end_coordinates = coords[end_atom_index]
        
        # Draw Bond A long Vector 

        fractional_space = np.linspace(0,1,int(1/res*2))

        for fraction in fractional_space:
            coordinates = (fraction*start_coordinates + (1-fraction)*end_coordinates)
            x = int(round((coordinates[0] + embed)/res))
            y = int(round((coordinates[1]+ embed)/res))
            vector[ x, y, 0] = bond_order
    
    # Atoms

    for i,atom in enumerate(cmol.GetAtoms()):
       x = int(round((coords[i][0] + embed)/res))
       y = int(round((coords[i][1]+ embed)/res))
       
       vector[ x , y, 1] = atom.GetAtomicNum()
       
       hyptype = atom.GetHybridization().real
       vector[ x , y, 2] = hyptype
    
       charge = atom.GetProp("_GasteigerCharge")
       vector[ x , y, 3] = charge
    
    return vect

def vectorize(mol):
    return chemcepterize_mol(mol, embed=12)

df["mol_image"] = df["mol"].apply(vectorize)