andreamena commited on
Commit
837ee6d
·
verified ·
1 Parent(s): e1f27c7

Upload 7 files

Browse files
Files changed (7) hide show
  1. PDC_2023.h5 +3 -0
  2. PDC_2024.h5 +3 -0
  3. PDC_2025.h5 +3 -0
  4. dataset.py +164 -0
  5. encoding.py +100 -0
  6. model.py +240 -0
  7. utils.py +110 -0
PDC_2023.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e809a36078ca3d39d255aab3edaf2ec5b93e6715442074ec3da43984814e3c7e
3
+ size 30278752
PDC_2024.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8295cd6bb8a03b51474e85e419c47d395682ea44e772816f9c3d1781990d938a
3
+ size 30279144
PDC_2025.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b6ef69dc4bb3d1e160b86114def079e038e930d0c32423ff0b226ad23d251488
3
+ size 30279144
dataset.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from os.path import split
2
+ from operator import concat
3
+ import re
4
+ from cProfile import label
5
+ from cgi import test
6
+ from tkinter import Label
7
+ import pandas as pd
8
+ import numpy as np
9
+ import tensorflow as tf
10
+ from utils import smiles2adjoin, molecular_fg
11
+ from rdkit import Chem
12
+ from random import Random
13
+ from collections import defaultdict
14
+ from rdkit.Chem.Scaffolds import MurckoScaffold
15
+ from itertools import compress
16
+
17
+ str2num = {'<pad>':0 ,'H': 1, 'C': 2, 'N': 3, 'O': 4, 'S': 5, 'F': 6, 'Cl': 7, 'Br': 8, 'P': 9,
18
+ 'I': 10,'Na': 11,'B':12,'Se':13,'Si':14,'<unk>':15,'<mask>':16,'<global>':17}
19
+ num2str = {i:j for j,i in str2num.items()}
20
+
21
+ class Graph_Classification_Dataset(object):
22
+ def __init__(self,path,smiles_field1='Smiles1',smiles_field2='Smiles2',label_field=label, index_field=label, max_len=500,seed=1,batch_size=16,a=1,addH=True):
23
+ if path.endswith('.txt') or path.endswith('.tsv'):
24
+ self.df = pd.read_csv(path,sep='\t',encoding='latin1')
25
+ elif path.endswith('.xlsx'):
26
+ self.df = pd.read_excel(path)
27
+ else:
28
+ self.df = pd.read_csv(path, encoding='latin1')
29
+ self.smiles_field1 = smiles_field1
30
+ self.smiles_field2 = smiles_field2
31
+ self.label_field = label_field
32
+ self.index_field = index_field
33
+ self.vocab = str2num
34
+ self.devocab = num2str
35
+ self.df = self.df[self.df[smiles_field1].str.len() <= max_len]
36
+ self.df = self.df[[True if Chem.MolFromSmiles(smi) is not None else False for smi in self.df[smiles_field1]]]
37
+ self.seed = seed
38
+ self.batch_size = batch_size
39
+ self.a = a
40
+ self.addH = addH
41
+
42
+ def get_data(self):
43
+ '''Randomized Split Dataset'''
44
+ data = self.df
45
+ data = data.fillna(666)
46
+ train_idx = []
47
+ idx = data.sample(frac=0.8).index
48
+ train_idx.extend(idx)
49
+ train_data = data[data.index.isin(train_idx)]
50
+ data = data[~data.index.isin(train_idx)]
51
+ test_idx = []
52
+ idx = data[~data.index.isin(train_data)].sample(frac=0.5).index
53
+ test_idx.extend(idx)
54
+ test_data = data[data.index.isin(test_idx)]
55
+ val_data = data[~data.index.isin(train_idx+test_idx)]
56
+ df_train_data = pd.DataFrame(train_data)
57
+ df_test_data = pd.DataFrame(test_data)
58
+ df_val_data = pd.DataFrame(val_data)
59
+
60
+ self.dataset1 = tf.data.Dataset.from_tensor_slices(
61
+ (df_train_data[self.smiles_field1], df_train_data[self.label_field], df_train_data[self.smiles_field2], df_train_data[self.index_field]))
62
+ self.dataset1 = self.dataset1.map(self.tf_numerical_smiles).cache().padded_batch(batch_size=self.batch_size, padded_shapes=(
63
+ tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).shuffle(1000).prefetch(50)
64
+
65
+ self.dataset2 = tf.data.Dataset.from_tensor_slices((df_test_data[self.smiles_field1], df_test_data[self.label_field], df_test_data[self.smiles_field2], df_test_data[self.index_field]))
66
+ self.dataset2 = self.dataset2.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
67
+ tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).cache().prefetch(100)
68
+
69
+ self.dataset3 = tf.data.Dataset.from_tensor_slices((df_val_data[self.smiles_field1], df_val_data[self.label_field], df_val_data[self.smiles_field2], df_val_data[self.index_field]))
70
+ self.dataset3 = self.dataset3.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
71
+ tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([self.a]),tf.TensorShape([None]), tf.TensorShape([None, None]), tf.TensorShape([1]))).cache().prefetch(100)
72
+
73
+ return self.dataset1, self.dataset2, self.dataset3
74
+
75
+ def numerical_smiles(self, smiles, label):
76
+ smiles = smiles.numpy().decode()
77
+ atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
78
+ atoms_list = ['<global>'] + atoms_list
79
+ nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
80
+ temp = np.ones((len(nums_list),len(nums_list)))
81
+ temp[1:, 1:] = adjoin_matrix
82
+ adjoin_matrix = (1-temp)*(-1e9)
83
+ x = np.array(nums_list).astype('int64')
84
+ y = np.array(label).astype('int64')
85
+ return x, adjoin_matrix, y
86
+
87
+ def tf_numerical_smiles(self, smiles1, label, smiles2, index):
88
+ x1,adjoin_matrix1,y= tf.py_function(self.numerical_smiles, [smiles1,label], [tf.int64, tf.float32 ,tf.int64])
89
+ x1.set_shape([None])
90
+ adjoin_matrix1.set_shape([None,None])
91
+ y.set_shape([None])
92
+ x2,adjoin_matrix2,index = tf.py_function(self.numerical_smiles, [smiles2,index], [tf.int64, tf.float32 ,tf.int64])
93
+ x2.set_shape([None])
94
+ adjoin_matrix2.set_shape([None,None])
95
+ index.set_shape([None])
96
+ return x1, adjoin_matrix1, y, x2,adjoin_matrix2, index
97
+
98
+ class Inference_Dataset(object):
99
+ def __init__(self,sml_list,max_len=500,addH=True):
100
+ self.vocab = str2num
101
+ self.devocab = num2str
102
+ self.sml_list = [i for i in sml_list if len(i)<max_len]
103
+ self.addH = addH
104
+
105
+ def get_data(self):
106
+ self.dataset = tf.data.Dataset.from_tensor_slices((self.sml_list,))
107
+ self.dataset = self.dataset.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
108
+ tf.TensorShape([None]), tf.TensorShape([None,None]),tf.TensorShape([1]),tf.TensorShape([None]))).cache().prefetch(20)
109
+
110
+ return self.dataset
111
+
112
+ def numerical_smiles(self, smiles):
113
+ smiles_origin = smiles
114
+ smiles = smiles.numpy().decode()
115
+ atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
116
+ atoms_list = ['<global>'] + atoms_list
117
+ nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
118
+ temp = np.ones((len(nums_list),len(nums_list)))
119
+ temp[1:,1:] = adjoin_matrix
120
+ adjoin_matrix = (1-temp)*(-1e9)
121
+ x = np.array(nums_list).astype('int64')
122
+ return x, adjoin_matrix,[smiles], atoms_list
123
+
124
+ def tf_numerical_smiles(self, smiles):
125
+ x,adjoin_matrix,smiles,atom_list = tf.py_function(self.numerical_smiles, [smiles], [tf.int64, tf.float32,tf.string, tf.string])
126
+ x.set_shape([None])
127
+ adjoin_matrix.set_shape([None,None])
128
+ smiles.set_shape([1])
129
+ atom_list.set_shape([None])
130
+ return x, adjoin_matrix,smiles,atom_list
131
+
132
+ class Inference_Dataset(object):
133
+ def __init__(self,sml_list,max_len=500,addH=True):
134
+ self.vocab = str2num
135
+ self.devocab = num2str
136
+ self.sml_list = [i for i in sml_list if len(i)<max_len]
137
+ self.addH = addH
138
+
139
+ def get_data(self):
140
+ self.dataset = tf.data.Dataset.from_tensor_slices((self.sml_list,))
141
+ self.dataset = self.dataset.map(self.tf_numerical_smiles).padded_batch(512, padded_shapes=(
142
+ tf.TensorShape([None]), tf.TensorShape([None,None]),tf.TensorShape([1]),tf.TensorShape([None]))).cache().prefetch(20)
143
+
144
+ return self.dataset
145
+
146
+ def numerical_smiles(self, smiles):
147
+ smiles_origin = smiles
148
+ smiles = smiles.numpy().decode()
149
+ atoms_list, adjoin_matrix = smiles2adjoin(smiles,explicit_hydrogens=self.addH)
150
+ atoms_list = ['<global>'] + atoms_list
151
+ nums_list = [str2num.get(i,str2num['<unk>']) for i in atoms_list]
152
+ temp = np.ones((len(nums_list),len(nums_list)))
153
+ temp[1:,1:] = adjoin_matrix
154
+ adjoin_matrix = (1-temp)*(-1e9)
155
+ x = np.array(nums_list).astype('int64')
156
+ return x, adjoin_matrix,[smiles], atoms_list
157
+
158
+ def tf_numerical_smiles(self, smiles):
159
+ x,adjoin_matrix,smiles,atom_list = tf.py_function(self.numerical_smiles, [smiles], [tf.int64, tf.float32,tf.string, tf.string])
160
+ x.set_shape([None])
161
+ adjoin_matrix.set_shape([None,None])
162
+ smiles.set_shape([1])
163
+ atom_list.set_shape([None])
164
+ return x, adjoin_matrix,smiles,atom_list
encoding.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ def zscale_padding(seq_list, padding):
4
+ zscale = {
5
+ 'A': [0.24, -2.32, 0.60, -0.14, 1.30],
6
+ 'C': [0.84, -1.67, 3.71, 0.18, -2.65],
7
+ 'D': [3.98, 0.93, 1.93, -2.46, 0.75],
8
+ 'E': [3.11, 0.26, -0.11, -0.34, -0.25],
9
+ 'F': [-4.22, 1.94, 1.06, 0.54, -0.62],
10
+ 'G': [2.05, -4.06, 0.36, -0.82, -0.38],
11
+ 'H': [2.47, 1.95, 0.26, 3.90, 0.09],
12
+ 'I': [-3.89, -1.73, -1.71, -0.84, 0.26],
13
+ 'K': [2.29, 0.89, -2.49, 1.49, 0.31],
14
+ 'L': [-4.28, -1.30, -1.49, -0.72, 0.84],
15
+ 'M': [-2.85, -0.22, 0.47, 1.94, -0.98],
16
+ 'N': [3.05, 1.62, 1.04, -1.15, 1.61],
17
+ 'P': [-1.66, 0.27, 1.84, 0.70, 2.00],
18
+ 'Q': [1.75, 0.50, -1.44, -1.34, 0.66],
19
+ 'R': [3.52, 2.50, -3.50, 1.99, -0.17],
20
+ 'S': [2.39, -1.07, 1.15, -1.39, 0.67],
21
+ 'T': [0.75, -2.18, -1.12, -1.46, -0.40],
22
+ 'V': [-2.59, -2.64, -1.54, -0.85, -0.02],
23
+ 'W': [-4.36, 3.94, 0.59, 3.44, -1.59],
24
+ 'Y': [-2.54, 2.44, 0.43, 0.04, -1.47],
25
+ '-': [0.00, 0.00, 0.00, 0.00, 0.00] # For gaps or unknown amino acids
26
+ }
27
+ feat_list = []
28
+ for seq in seq_list:
29
+ feat = [zscale.get(aa, zscale['-']) for aa in seq]
30
+ feat += [[0] * 5] * (padding - len(seq))
31
+ feat_list.append(feat)
32
+ return np.array(feat_list)
33
+
34
+
35
+ def one_hot_padding(seq_list, padding):
36
+ feat_list = []
37
+ one_hot = {}
38
+ aa = ['A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y']
39
+ for i in range(len(aa)):
40
+ one_hot[aa[i]] = [0] * 20
41
+ one_hot[aa[i]][i] = 1
42
+ for seq in seq_list:
43
+ feat = [one_hot[aa] for aa in seq] + [[0] * 20] * (padding - len(seq))
44
+ feat_list.append(feat)
45
+ return np.array(feat_list)
46
+
47
+
48
+ def position_encoding(padding, d=20, b=1000):
49
+ pos_encoding = np.zeros((padding, d))
50
+ for pos in range(padding):
51
+ for i in range(d // 2):
52
+ pos_encoding[pos, 2 * i] = np.sin(pos / (b ** (2 * i / d)))
53
+ pos_encoding[pos, 2 * i + 1] = np.cos(pos / (b ** (2 * i / d)))
54
+ return pos_encoding
55
+
56
+
57
+ blosum62 = {
58
+ 'A': [4, -1, -2, -2, 0, -2, -1, 0, -2, -1, -1, -1, -1, -1, -1, 1, 0, 0, -3, -2],
59
+ 'C': [-1, 9, -3, -4, -2, -3, -3, -3, -3, -1, -1, -3, -3, -3, -3, -1, -1, -1, -2, -2],
60
+ 'D': [-2, -3, 6, 2, -3, 1, -1, -1, -1, -4, -3, 1, 0, -3, -3, 0, -1, -3, -4, -3],
61
+ 'E': [-2, -4, 2, 5, -3, 0, -2, -1, 1, -3, -2, 0, 0, -3, -2, 0, -1, -2, -3, -2],
62
+ 'F': [0, -2, -3, -3, 6, -3, -1, -3, -1, 0, 0, -3, -4, -3, -3, -2, -2, -3, 1, 3],
63
+ 'G': [-2, -3, 1, 0, -3, 6, -2, -4, -2, -4, -3, 0, -2, -3, -2, 0, -2, -3, -2, -3],
64
+ 'H': [-1, -3, -1, -2, -1, -2, 8, -3, -1, -3, -2, -1, -2, -1, -2, -2, -2, -2, 2, 2],
65
+ 'I': [0, -3, -1, -1, -3, -4, -3, 4, -3, -3, -3, -1, -3, -3, -3, -3, -1, 2, -3, -1],
66
+ 'K': [-2, -3, -1, 1, -1, -2, -1, -3, 5, -2, -1, 0, -1, 1, 0, -1, 0, -2, -3, -2],
67
+ 'L': [-1, -1, -4, -3, 0, -4, -3, -3, -2, 4, 2, -3, -3, -2, -2, -2, -1, 1, -2, -1],
68
+ 'M': [-1, -1, -3, -2, 0, -3, -2, -3, -1, 2, 5, -2, -2, 0, -1, -2, -1, 1, -1, -1],
69
+ 'N': [-1, -3, 1, 0, -3, 0, -1, -1, 0, -3, -2, 6, 2, -3, -3, 1, 0, -3, -4, -2],
70
+ 'P': [-1, -3, 0, 0, -4, -2, -2, -3, -1, -3, -2, 2, 7, -1, -1, -1, -1, -2, -4, -3],
71
+ 'Q': [-1, -3, -3, -3, -3, -3, -1, -3, 1, -2, 0, -3, -1, 5, 2, -1, 0, -2, -2, -1],
72
+ 'R': [-1, -3, -3, -2, -3, -2, -2, -3, 0, -2, -1, -3, -1, 2, 5, -1, 0, -2, -3, -2],
73
+ 'S': [1, -1, 0, 0, -2, 0, -2, -3, -1, -2, -2, 1, -1, -1, -1, 4, 1, -2, -3, -2],
74
+ 'T': [0, -1, -1, -1, -2, -2, -2, -1, 0, -1, -1, 0, -1, 0, 0, 1, 5, 0, -2, -2],
75
+ 'V': [0, -1, -3, -2, -3, -3, -2, 2, -2, 1, 1, -3, -2, -2, -2, -2, 0, 4, -3, -1],
76
+ 'W': [-3, -2, -4, -3, 1, -2, 2, -3, -3, -2, -1, -4, -4, -2, -3, -3, -2, -3, 11, 2],
77
+ 'Y': [-2, -2, -3, -2, 3, -3, 2, -1, -2, -1, -1, -2, -3, -1, -2, -2, -2, -1, 2, 7],
78
+ 'X': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # For unknown amino acids
79
+ }
80
+
81
+ def blosum62_padding(seq_list, padding):
82
+ feat_list = []
83
+ for seq in seq_list:
84
+ feat = [blosum62.get(aa, blosum62['X']) for aa in seq] + [[0] * 20] * (padding - len(seq))
85
+ feat_list.append(feat)
86
+ return np.array(feat_list)
87
+
88
+ def combined_encoding(seq_list, padding):
89
+ one_hot_encoded = one_hot_padding(seq_list, padding)
90
+ pos_encoded = position_encoding(padding)
91
+ blosum_encoded = blosum62_padding(seq_list, padding)
92
+ zscale_encoded = zscale_padding(seq_list, padding)
93
+
94
+ pos_encoded_expanded = np.expand_dims(pos_encoded, axis=0).repeat(len(seq_list), axis=0)
95
+
96
+
97
+ combined_encoding = np.concatenate(
98
+ (one_hot_encoded, pos_encoded_expanded, blosum_encoded, zscale_encoded), axis=2
99
+ )
100
+ return combined_encoding
model.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from cProfile import label
3
+ import tensorflow as tf
4
+ from layers import Attention, MultiHeadAttention
5
+ from tf_keras.models import Model
6
+ from tf_keras.layers import Masking, Dense, LSTM, Bidirectional, Input, Dropout
7
+
8
+
9
+
10
+ def gelu(x):
11
+ return 0.5 * x * (1.0 + tf.math.erf(x / tf.sqrt(2.)))
12
+
13
+
14
+ def scaled_dot_product_attention(q, k, v, mask,adjoin_matrix):
15
+
16
+ matmul_qk = tf.matmul(q, k, transpose_b=True)
17
+
18
+
19
+ dk = tf.cast(tf.shape(k)[-1], tf.float32)
20
+ scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)
21
+
22
+
23
+ if mask is not None:
24
+ scaled_attention_logits += (mask * -1e9)
25
+ if adjoin_matrix is not None:
26
+ scaled_attention_logits += adjoin_matrix
27
+
28
+ attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)
29
+
30
+ output = tf.matmul(attention_weights, v)
31
+
32
+ return output, attention_weights
33
+
34
+
35
+ class MultiHeadAttention(tf.keras.layers.Layer):
36
+ def __init__(self, d_model, num_heads):
37
+ super(MultiHeadAttention, self).__init__()
38
+ self.num_heads = num_heads
39
+ self.d_model = d_model
40
+
41
+ assert d_model % self.num_heads == 0
42
+
43
+ self.depth = d_model // self.num_heads
44
+
45
+ self.wq = tf.keras.layers.Dense(d_model)
46
+ self.wk = tf.keras.layers.Dense(d_model)
47
+ self.wv = tf.keras.layers.Dense(d_model)
48
+
49
+ self.dense = tf.keras.layers.Dense(d_model)
50
+
51
+ def split_heads(self, x, batch_size):
52
+ """Split the last dimension into (num_heads, depth).
53
+ Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
54
+ """
55
+ x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
56
+ return tf.transpose(x, perm=[0, 2, 1, 3])
57
+
58
+ def call(self, v, k, q, mask,adjoin_matrix):
59
+ batch_size = tf.shape(q)[0]
60
+
61
+ q = self.wq(q)
62
+ k = self.wk(k)
63
+ v = self.wv(v)
64
+
65
+ q = self.split_heads(q, batch_size)
66
+ k = self.split_heads(k, batch_size)
67
+ v = self.split_heads(v, batch_size)
68
+
69
+ scaled_attention, attention_weights = scaled_dot_product_attention(
70
+ q, k, v, mask,adjoin_matrix)
71
+
72
+ scaled_attention = tf.transpose(scaled_attention,
73
+ perm=[0, 2, 1, 3])
74
+
75
+ concat_attention = tf.reshape(scaled_attention,
76
+ (batch_size, -1, self.d_model))
77
+
78
+ output = self.dense(concat_attention)
79
+
80
+ return output, attention_weights
81
+
82
+ def point_wise_feed_forward_network(d_model, dff):
83
+ return tf.keras.Sequential([
84
+ tf.keras.layers.Dense(dff, activation=gelu),
85
+ tf.keras.layers.Dense(d_model)
86
+ ])
87
+
88
+
89
+ class EncoderLayer(tf.keras.layers.Layer):
90
+ def __init__(self, d_model, num_heads, dff, rate=0.1):
91
+ super(EncoderLayer, self).__init__()
92
+
93
+ self.mha = MultiHeadAttention(d_model, num_heads)
94
+ self.ffn = point_wise_feed_forward_network(d_model, dff)
95
+
96
+ self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
97
+ self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
98
+
99
+ self.dropout1 = tf.keras.layers.Dropout(rate)
100
+ self.dropout2 = tf.keras.layers.Dropout(rate)
101
+
102
+ def call(self, x, training, mask,adjoin_matrix):
103
+ attn_output, attention_weights = self.mha(x, x, x, mask,adjoin_matrix)
104
+ attn_output = self.dropout1(attn_output, training=training)
105
+ out1 = self.layernorm1(x + attn_output)
106
+
107
+ ffn_output = self.ffn(out1)
108
+ ffn_output = self.dropout2(ffn_output, training=training)
109
+ out2 = self.layernorm2(out1 + ffn_output)
110
+
111
+ return out2,attention_weights
112
+
113
+
114
+
115
+ class Encoder(tf.keras.Model):
116
+ def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
117
+ maximum_position_encoding, rate=0.1):
118
+ super(Encoder, self).__init__()
119
+
120
+ self.d_model = d_model
121
+ self.num_layers = num_layers
122
+
123
+ self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
124
+
125
+ self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
126
+ for _ in range(num_layers)]
127
+
128
+ self.dropout = tf.keras.layers.Dropout(rate)
129
+
130
+ def call(self, x, training, mask,adjoin_matrix):
131
+ seq_len = tf.shape(x)[1]
132
+ adjoin_matrix = adjoin_matrix[:,tf.newaxis,:,:]
133
+ x = self.embedding(x)
134
+ x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
135
+
136
+ x = self.dropout(x, training=training)
137
+
138
+ for i in range(self.num_layers):
139
+ x, attention_weights = self.enc_layers[i](x, training=training, mask=mask, adjoin_matrix=adjoin_matrix)
140
+ return x
141
+
142
+ class Encoder_test(tf.keras.Model):
143
+ def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
144
+ maximum_position_encoding, rate=0.1):
145
+ super(Encoder_test, self).__init__()
146
+
147
+ self.d_model = d_model
148
+ self.num_layers = num_layers
149
+
150
+ self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
151
+
152
+ self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
153
+ for _ in range(num_layers)]
154
+
155
+ self.dropout = tf.keras.layers.Dropout(rate)
156
+
157
+ def call(self, x, training, mask,adjoin_matrix):
158
+ seq_len = tf.shape(x)[1]
159
+ adjoin_matrix = adjoin_matrix[:,tf.newaxis,:,:]
160
+ x = self.embedding(x)
161
+ x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
162
+
163
+ x = self.dropout(x, training=training)
164
+ attention_weights_list = []
165
+ xs = []
166
+
167
+ for i in range(self.num_layers):
168
+ x,attention_weights = self.enc_layers[i](x, training, mask,adjoin_matrix)
169
+ attention_weights_list.append(attention_weights)
170
+ xs.append(x)
171
+
172
+ return x,attention_weights_list,xs
173
+
174
+ class BertModel_test(tf.keras.Model):
175
+ def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size = 18,dropout_rate = 0.1):
176
+ super(BertModel_test, self).__init__()
177
+ self.encoder = Encoder_test(num_layers=num_layers,d_model=d_model,
178
+ num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
179
+ self.fc1 = tf.keras.layers.Dense(d_model, activation=gelu)
180
+ self.layernorm = tf.keras.layers.LayerNormalization(-1)
181
+ self.fc2 = tf.keras.layers.Dense(vocab_size)
182
+ def call(self,x,adjoin_matrix,mask,training=False):
183
+ x,att,xs = self.encoder(x,training=training,mask=mask,adjoin_matrix=adjoin_matrix)
184
+ x = self.fc1(x)
185
+ x = self.layernorm(x)
186
+ x = self.fc2(x)
187
+ return x,att,xs
188
+
189
+
190
+ class BertModel(tf.keras.Model):
191
+ def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size = 18,dropout_rate = 0.1):
192
+ super(BertModel, self).__init__()
193
+ self.encoder = Encoder(num_layers=num_layers,d_model=d_model,
194
+ num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
195
+ self.fc1 = tf.keras.layers.Dense(d_model, activation=gelu)
196
+ self.layernorm = tf.keras.layers.LayerNormalization(-1)
197
+ self.fc2 = tf.keras.layers.Dense(vocab_size)
198
+
199
+ def call(self,x,adjoin_matrix,mask,training=False):
200
+ x = self.encoder(x,training=training,mask=mask,adjoin_matrix=adjoin_matrix)
201
+ x = self.fc1(x)
202
+ x = self.layernorm(x)
203
+ x = self.fc2(x)
204
+ return x
205
+
206
+
207
+ class PredictModel(tf.keras.Model):
208
+ def __init__(self,num_layers = 6,d_model = 256,dff = 512,num_heads = 8,vocab_size =18, a=2, dropout_rate = 0.1,dense_dropout=0.1):
209
+ super(PredictModel, self).__init__()
210
+ self.encoder = Encoder(num_layers=num_layers,d_model=d_model,
211
+ num_heads=num_heads,dff=dff,input_vocab_size=vocab_size,maximum_position_encoding=200,rate=dropout_rate)
212
+ self.fc1 = tf.keras.layers.Dense(256,activation=tf.keras.layers.LeakyReLU(0.1))
213
+ self.dropout1 = tf.keras.layers.Dropout(dense_dropout)
214
+ self.fc2 = tf.keras.layers.Dense(a)
215
+ self.t2_processing_network = self.build_layer()
216
+
217
+ def build_layer(self, maxlen=71):
218
+ inputs = Input(shape=(maxlen, 65), name='t2_Input')
219
+ masking = Masking(mask_value=0.0, input_shape=(maxlen, 65), name='Masking')(inputs)
220
+ hidden = Bidirectional(LSTM(512, use_bias=True, dropout=0.5, return_sequences=True), name='Bidirectional-LSTM')(
221
+ masking)
222
+ hidden = Dropout(0.2, name='Dropout_1')(hidden)
223
+ hidden = Attention(name='Attention')(hidden)
224
+ hidden = Dense(512, activation='relu')(hidden)
225
+
226
+ model = Model(inputs=inputs, outputs=hidden)
227
+ return model
228
+
229
+ def call(self,x1,adjoin_matrix1,mask1,x2,adjoin_matrix2,mask2,t1,t2, training=False):
230
+ x1 = self.encoder(x1,training=False,mask=mask1,adjoin_matrix=adjoin_matrix1)
231
+ x1 = x1[:,0,:]
232
+ x2 = self.encoder(x2,training=False,mask=mask2,adjoin_matrix=adjoin_matrix2)
233
+ x2 = x2[:,0,:]
234
+ x = tf.concat([x1,x2], axis=1)
235
+ t2 = self.t2_processing_network(t2)
236
+ x = tf.concat([x, t1, t2], axis=1)
237
+ x = self.fc1(x)
238
+ x = self.dropout1(x,training=training)
239
+ x = self.fc2(x)
240
+ return x
utils.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from rdkit import Chem
2
+ from rdkit.Chem import rdmolfiles, rdmolops
3
+ import numpy as np
4
+ import openbabel as ob
5
+ import os
6
+ import csv
7
+ from rdkit import RDConfig
8
+ from rdkit.Chem import FragmentCatalog
9
+
10
+ def fg_list(): # 47 FGs list
11
+ fName=os.path.join(RDConfig.RDDataDir,'FunctionalGroups.txt')
12
+ fparams = FragmentCatalog.FragCatParams(1,6,fName)
13
+ fg_list = []
14
+ for i in range(fparams.GetNumFuncGroups()):
15
+ fg_list.append(fparams.GetFuncGroup(i))
16
+ fg_list.pop(27)
17
+
18
+ x = [Chem.MolToSmiles(_) for _ in fg_list]+['*C=C','*F','*Cl','*Br','*I','[Na+]','*P','*P=O','*[Se]','*[Si]']
19
+ y = set(x)
20
+ return list(y)
21
+
22
+ def obsmitosmile(smi):
23
+ conv = ob.OBConversion()
24
+ conv.SetInAndOutFormats("smi", "can")
25
+ conv.SetOptions("K", conv.OUTOPTIONS)
26
+ mol = ob.OBMol()
27
+ conv.ReadString(mol, smi)
28
+ smile = conv.WriteString(mol)
29
+ smile = smile.replace('\t\n', '')
30
+ return smile
31
+
32
+ def molecular_fg(smiles): # Getting functional groups (including rings) in molecules
33
+
34
+ mol = Chem.MolFromSmiles(smiles)
35
+ if mol is None:
36
+ print('error')
37
+ mol = Chem.MolFromSmiles(obsmitosmile(smiles))
38
+ assert mol is not None, smiles + ' is not valid '
39
+ a = fg_list()
40
+
41
+
42
+ ssr = Chem.GetSymmSSSR(mol)
43
+ num_ring = len(ssr)
44
+ ring_dict = {}
45
+ for i in range(num_ring):
46
+ ring_dict[i+1] = list(ssr[i])
47
+
48
+ f_g_list = []
49
+ for i in ring_dict.values():
50
+ f_g_list.append(i)
51
+
52
+ for i in a:
53
+ patt = Chem.MolFromSmarts(i)
54
+ flag = mol.HasSubstructMatch(patt)
55
+ if flag:
56
+ atomids = mol.GetSubstructMatches(patt)
57
+ for atomid in atomids:
58
+ f_g_list.append(list(atomid))
59
+ return f_g_list
60
+
61
+
62
+ def smiles2adjoin(smiles,explicit_hydrogens=True,canonical_atom_order=False): # Converting molecules in SMILES format to atom lists and adjacency matrices
63
+
64
+ mol = Chem.MolFromSmiles(smiles)
65
+ if mol is None:
66
+ print('error')
67
+ mol = Chem.MolFromSmiles(obsmitosmile(smiles))
68
+ assert mol is not None, smiles + ' is not valid '
69
+
70
+ if explicit_hydrogens:
71
+ mol = Chem.AddHs(mol)
72
+ else:
73
+ mol = Chem.RemoveHs(mol)
74
+
75
+ if canonical_atom_order:
76
+ new_order = rdmolfiles.CanonicalRankAtoms(mol)
77
+ mol = rdmolops.RenumberAtoms(mol, new_order)
78
+ num_atoms = mol.GetNumAtoms()
79
+
80
+ atoms_list = []
81
+ for i in range(num_atoms):
82
+ atom = mol.GetAtomWithIdx(i)
83
+ atoms_list.append(atom.GetSymbol())
84
+
85
+
86
+ adjoin_matrix = np.eye(num_atoms)
87
+ num_bonds = mol.GetNumBonds()
88
+
89
+ for i in range(num_bonds):
90
+ bond = mol.GetBondWithIdx(i)
91
+ u = bond.GetBeginAtomIdx()
92
+ v = bond.GetEndAtomIdx()
93
+ adjoin_matrix[u,v] = 1.0
94
+ adjoin_matrix[v,u] = 1.0
95
+
96
+ return atoms_list,adjoin_matrix
97
+
98
+
99
+ def get_header(path):
100
+ with open(path) as f:
101
+ header = next(csv.reader(f))
102
+
103
+ return header
104
+
105
+
106
+ def get_task_names(path, use_compound_names=False):
107
+ index = 2 if use_compound_names else 1
108
+ task_names = get_header(path)[index:]
109
+
110
+ return task_names