wuxing0105 commited on
Commit
53ebf66
·
verified ·
1 Parent(s): 34393ef

Upload folder using huggingface_hub (part 2)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. model/src/mrl_te_optimization/models/Modules/__pycache__/Backbone.cpython-310.pyc +0 -0
  2. model/src/mrl_te_optimization/models/Modules/__pycache__/Backbone.cpython-311.pyc +0 -0
  3. model/src/mrl_te_optimization/models/Modules/__pycache__/GP_net.cpython-310.pyc +0 -0
  4. model/src/mrl_te_optimization/models/Modules/__pycache__/GP_net.cpython-311.pyc +0 -0
  5. model/src/mrl_te_optimization/models/Modules/__pycache__/Koo_net.cpython-310.pyc +0 -0
  6. model/src/mrl_te_optimization/models/Modules/__pycache__/Koo_net.cpython-311.pyc +0 -0
  7. model/src/mrl_te_optimization/models/Modules/__pycache__/__init__.cpython-310.pyc +0 -0
  8. model/src/mrl_te_optimization/models/Modules/__pycache__/__init__.cpython-311.pyc +0 -0
  9. model/src/mrl_te_optimization/models/Modules/__pycache__/_operator.cpython-310.pyc +0 -0
  10. model/src/mrl_te_optimization/models/Modules/__pycache__/_operator.cpython-311.pyc +0 -0
  11. model/src/mrl_te_optimization/models/Modules/_operator.py +246 -0
  12. model/src/mrl_te_optimization/models/Modules/nonDeep.py +69 -0
  13. model/src/mrl_te_optimization/models/ScheduleOptimizer.py +105 -0
  14. model/src/mrl_te_optimization/models/Self_attention.py +102 -0
  15. model/src/mrl_te_optimization/models/__pycache__/Backbone.cpython-310.pyc +0 -0
  16. model/src/mrl_te_optimization/models/__pycache__/Backbone.cpython-311.pyc +0 -0
  17. model/src/mrl_te_optimization/models/bucket_sampler.py +99 -0
  18. model/src/mrl_te_optimization/models/log_and_save.py +271 -0
  19. model/src/mrl_te_optimization/models/loss.py +86 -0
  20. model/src/mrl_te_optimization/models/max_activation_patch.py +795 -0
  21. model/src/mrl_te_optimization/models/popen.py +150 -0
  22. model/src/mrl_te_optimization/models/reader.py +512 -0
  23. model/src/mrl_te_optimization/models/train_val.py +337 -0
  24. model/src/mrl_te_optimization/popen.py +150 -0
  25. model/src/mrl_te_optimization/script/Nupack_MFE_prediction.py +48 -0
  26. model/src/mrl_te_optimization/script/PATH.py +3 -0
  27. model/src/mrl_te_optimization/script/covar_test.py +203 -0
  28. model/src/mrl_te_optimization/script/covar_train.py +243 -0
  29. model/src/mrl_te_optimization/script/data_prepocessing.sh +2 -0
  30. model/src/mrl_te_optimization/script/detect_changepoint_featmap.py +146 -0
  31. model/src/mrl_te_optimization/script/download_training_data.sh +40 -0
  32. model/src/mrl_te_optimization/script/evaluate_channel_effect.py +112 -0
  33. model/src/mrl_te_optimization/script/fix_test_for_RP.py +32 -0
  34. model/src/mrl_te_optimization/script/generate_config_js.sh +13 -0
  35. model/src/mrl_te_optimization/script/iter_test.py +219 -0
  36. model/src/mrl_te_optimization/script/iter_train.py +251 -0
  37. model/src/mrl_te_optimization/script/main_train.py +201 -0
  38. model/src/mrl_te_optimization/script/preprocessing_MPA.py +115 -0
  39. model/src/mrl_te_optimization/script/preprocessing_RP.py +65 -0
  40. model/src/mrl_te_optimization/script/run-TF-modisco.py +99 -0
  41. model/src/mrl_te_optimization/script/train_kmer_classifer.py +239 -0
  42. model/src/mrl_te_optimization/script/train_kmer_models.py +167 -0
  43. model/src/mrl_te_optimization/script/train_oneLayer_CNN.py +114 -0
  44. model/src/mrl_te_optimization/util.py +384 -0
  45. model/src/mrl_te_optimization/utils.py +209 -0
  46. model/src/mrl_te_optimization/xpresso_input.json +0 -0
  47. requirements.txt +62 -0
  48. scripts/optimize_te_mrl.py +424 -0
  49. scripts/predict.py +213 -0
  50. scripts/train.py +398 -0
model/src/mrl_te_optimization/models/Modules/__pycache__/Backbone.cpython-310.pyc ADDED
Binary file (23.6 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/Backbone.cpython-311.pyc ADDED
Binary file (43.8 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/GP_net.cpython-310.pyc ADDED
Binary file (5.89 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/GP_net.cpython-311.pyc ADDED
Binary file (10.5 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/Koo_net.cpython-310.pyc ADDED
Binary file (3.76 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/Koo_net.cpython-311.pyc ADDED
Binary file (6.74 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (287 Bytes). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (292 Bytes). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/_operator.cpython-310.pyc ADDED
Binary file (9.88 kB). View file
 
model/src/mrl_te_optimization/models/Modules/__pycache__/_operator.cpython-311.pyc ADDED
Binary file (16.9 kB). View file
 
model/src/mrl_te_optimization/models/Modules/_operator.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import math
3
+ import numpy as np
4
+ from torch import nn
5
+ from scipy import stats
6
+ import torch.nn.functional as F
7
+ from einops import rearrange
8
+ from sklearn.metrics import roc_auc_score, r2_score
9
+ from torch.nn.modules import activation
10
+ from torch.nn.modules.dropout import Dropout
11
+
12
+ class Conv1d_block(nn.Module):
13
+ """
14
+ the Convolution backbone define by a list of convolution block
15
+ """
16
+ def __init__(self,channel_ls,kernel_size,stride, padding_ls=None,diliation_ls=None,pad_to=None, activation='ReLU'):
17
+ """
18
+ Argument
19
+ channel_ls : list, [int] , channel for each conv layer
20
+ kernel_size : int
21
+ stride : list , [int]
22
+ padding_ls : list , [int]
23
+ diliation_ls : list , [int]
24
+ """
25
+ super(Conv1d_block,self).__init__()
26
+ ### property
27
+ self.activation = activation
28
+ self.channel_ls = channel_ls
29
+ self.kernel_size = kernel_size
30
+ self.stride = stride
31
+ if padding_ls is None:
32
+ self.padding_ls = [0] * (len(channel_ls) - 1)
33
+ else:
34
+ assert len(padding_ls) == len(channel_ls) - 1
35
+ self.padding_ls = padding_ls
36
+ if diliation_ls is None:
37
+ self.diliation_ls = [1] * (len(channel_ls) - 1)
38
+ else:
39
+ assert len(diliation_ls) == len(channel_ls) - 1
40
+ self.diliation_ls = diliation_ls
41
+
42
+ self.encoder = nn.ModuleList(
43
+ # in_C out_C padding diliation
44
+ [self.Conv_block(channel_ls[i],channel_ls[i+1],self.padding_ls[i],self.diliation_ls[i],self.stride[i]) for i in range(len(self.padding_ls))]
45
+ )
46
+
47
+ def Conv_block(self,in_Chan,out_Chan,padding,dilation,stride):
48
+
49
+ activation_layer = eval(f"nn.{self.activation}")
50
+
51
+ block = nn.Sequential(
52
+ nn.Conv1d(in_Chan,out_Chan,self.kernel_size,stride,padding,dilation),
53
+ nn.BatchNorm1d(out_Chan),
54
+ activation_layer())
55
+
56
+ return block
57
+
58
+ def forward(self,x):
59
+ if x.shape[2] == 4:
60
+ out = x.transpose(1,2)
61
+ else:
62
+ out = x
63
+ for block in self.encoder:
64
+ out = block(out)
65
+ return out
66
+
67
+ def forward_stage(self,x,stage):
68
+ """
69
+ return the activation of each stage for exchanging information
70
+ """
71
+ assert stage < len(self.encoder)
72
+
73
+ out = self.encoder[stage](x)
74
+ return out
75
+
76
+ def cal_out_shape(self,L_in=100,padding=0,diliation=1,stride=2):
77
+ """
78
+ For convolution 1D encoding , compute the final length
79
+ """
80
+ L_out = 1+ (L_in + 2*padding -diliation*(self.kernel_size-1) -1)/stride
81
+ return L_out
82
+
83
+ def last_out_len(self,L_in=100):
84
+ for i in range(len(self.padding_ls)):
85
+ padding = self.padding_ls[i]
86
+ diliation = self.diliation_ls[i]
87
+ stride = self.stride[i]
88
+ L_in = self.cal_out_shape(L_in,padding,diliation,stride)
89
+ # assert int(L_in) == L_in , "convolution out shape is not int"
90
+
91
+ return int(L_in) if L_in >=0 else 1
92
+
93
+ class ConvTranspose1d_block(Conv1d_block):
94
+ """
95
+ the Convolution transpose backbone define by a list of convolution block
96
+ """
97
+ def __init__(self,channel_ls,kernel_size,stride,padding_ls=None,diliation_ls=None,pad_to=None):
98
+ channel_ls = channel_ls[::-1]
99
+ stride = stride[::-1]
100
+ padding_ls = padding_ls[::-1] if padding_ls is not None else [0] * (len(channel_ls) - 1)
101
+ diliation_ls = diliation_ls[::-1] if diliation_ls is not None else [1] * (len(channel_ls) - 1)
102
+ super(ConvTranspose1d_block,self).__init__(channel_ls,kernel_size,stride,padding_ls,diliation_ls,pad_to)
103
+
104
+ def Conv_block(self,in_Chan,out_Chan,padding,dilation,stride):
105
+ """
106
+ replace `Conv1d` with `ConvTranspose1d`
107
+ """
108
+ block = nn.Sequential(
109
+ nn.ConvTranspose1d(in_Chan,out_Chan,self.kernel_size,stride,padding,dilation=dilation),
110
+ nn.BatchNorm1d(out_Chan),
111
+ nn.ReLU())
112
+
113
+ return block
114
+
115
+ def cal_out_shape(self,L_in,padding=0,diliation=1,stride=1,out_padding=0):
116
+ # L_in=100,padding=0,diliation=1,stride=2
117
+ """
118
+ For convolution Transpose 1D decoding , compute the final length
119
+ """
120
+ L_out = (L_in -1 )*stride + diliation*(self.kernel_size -1 )+1-2*padding + out_padding
121
+ return L_out
122
+
123
+
124
+ class linear_block(nn.Module):
125
+ def __init__(self,in_Chan,out_Chan,dropout_rate=0.2):
126
+ """
127
+ building block func to define dose network
128
+ """
129
+ super(linear_block,self).__init__()
130
+ self.block = nn.Sequential(
131
+ nn.Linear(in_Chan,out_Chan),
132
+ nn.Dropout(dropout_rate),
133
+ nn.BatchNorm1d(out_Chan),
134
+ nn.ReLU()
135
+ )
136
+ def forward(self,x):
137
+ return self.block(x)
138
+
139
+
140
+ class Self_Attention(nn.Module):
141
+ """
142
+ self attention operator for Conv1d sequences output
143
+ """
144
+ def __init__(self, in_dim:int, out_dim:int, qk_dim:int, n_head:int):
145
+ super().__init__()
146
+
147
+ self.n_head = n_head
148
+ self.total_qk_dim = qk_dim * n_head
149
+ self.transform = nn.ModuleDict({
150
+ k : nn.Linear(in_dim, self.total_qk_dim) for k in ['k', 'q', 'v']
151
+ })
152
+
153
+ self.fc_out = nn.Linear(self.total_qk_dim, out_dim)
154
+
155
+ def dim_rerrange(self, x):
156
+
157
+ # first break down total qk dimension
158
+ # then transpose length with heads
159
+ x1 = rearrange(x, "b l (n c) -> b n c l", n=self.n_head)
160
+ return x1
161
+
162
+ def _get_attention_map(self,X):
163
+ """
164
+ break the forward function to access attention mat
165
+ """
166
+ # assume we have a 3 dimension input X (b, len, in_dim)
167
+ # each out in qkv is also 3 dimension (b, len , qk_dim)
168
+ qkv = [self.transform[key](X) for key in ['k', 'q', 'v']]
169
+ q, k, v = map(self.dim_rerrange, qkv)
170
+
171
+ # here i and j is the channel
172
+ sim = torch.einsum("b n c i, b n c j -> b n i j", q, k)
173
+ sim = sim - sim.amax(dim=-1, keepdim=True).detach()
174
+ attn = sim.softmax(dim=-1)
175
+ return attn, v
176
+
177
+ def forward(self, X):
178
+
179
+ attn, v = self._get_attention_map(X)
180
+
181
+ out = torch.einsum("b n i j, b n c j -> b n i c", attn, v)
182
+ out = rearrange(out, "b n i c -> b i (n c)")
183
+ return self.fc_out(out)
184
+
185
+
186
+ class Self_Attention_for_GP(Self_Attention):
187
+ """
188
+ self attention operator for Conv1d sequences Global Pooling output
189
+ The input has 2 dimension (no length dim),
190
+ """
191
+ def __init__(self, in_dim:int, out_dim:int, qk_dim:int, n_head:int):
192
+ super().__init__(in_dim, out_dim, qk_dim, n_head)
193
+
194
+ def _get_attention_map(self,X):
195
+ # assume we have a 3 dimension input X (b, len, in_dim)
196
+ # each out in qkv is also 3 dimension (b, len , qk_dim)
197
+ qkv = [self.transform[key](X) for key in ['k', 'q', 'v']]
198
+ q, k, v = map(
199
+ lambda x : rearrange(x, "b (n c)-> b n c"), qkv
200
+ )
201
+
202
+ # here i and j is the channel
203
+ sim = torch.einsum("b n i, b n j -> b n i j", q, k).softmax(dim=-2, keepdim=True)
204
+ sim = sim - attn.amax(dim=-1, keepdim=True).detach()
205
+ attn = sim.softmax(dim=-1)
206
+ return attn, v
207
+
208
+ def forward(self, X):
209
+ #
210
+ attn, v = self._get_attention_map(X)
211
+
212
+ out = torch.einsum("b n i j, b n j -> b n i", attn, v)
213
+ out = rearrange(out, "b n i -> b (n i)")
214
+ return self.fc_out(out)
215
+
216
+ class Residual(nn.Module):
217
+ def __init__(self, fn):
218
+ super().__init__()
219
+ self.fn = fn
220
+
221
+ def forward(self, x, *args, **kwargs):
222
+ return self.fn(x, *args, **kwargs) + x
223
+
224
+ class PreNorm(nn.Module):
225
+ def __init__(self, dim, fn):
226
+ super().__init__()
227
+ self.fn = fn
228
+ self.norm = nn.GroupNorm(1, dim)
229
+
230
+ def forward(self, x):
231
+ x = self.norm(x.transpose(1,2))
232
+ return self.fn(x.transpose(1,2))
233
+
234
+ class SinusoidalPositionEmbeddings(nn.Module):
235
+ def __init__(self, dim):
236
+ super().__init__()
237
+ self.dim = dim
238
+
239
+ def forward(self, time):
240
+ device = time.device
241
+ half_dim = self.dim // 2
242
+ embeddings = math.log(10000) / (half_dim -1) # why do we minus 1 ?
243
+ embeddings = torch.exp(torch.arange(half_dim, device=device)* -embeddings)
244
+ embeddings = time[:, None] * embeddings[None, :] # expand to 2 dimension
245
+ embeddings = torch.cat((embeddings.sin(), embeddings.cos()), dim=-1)
246
+ return embeddings
model/src/mrl_te_optimization/models/Modules/nonDeep.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ sys.path.append(os.path.abspath("../"))
4
+ import numpy as np
5
+ import pandas as pd
6
+ import torch
7
+ from torch import nn
8
+ import reader
9
+
10
+
11
+ class Kmer_LinReg(nn.Module):
12
+ """
13
+ simple kmer model detect motifs
14
+ """
15
+ def __init__(self, kmer_size, pad_to):
16
+ super().__init__()
17
+ self.k = kmer_size
18
+ self.input_length = pad_to
19
+
20
+ # define Conv then replace the parameters
21
+ channel_size = 4**kmer_size
22
+ self.kmer_conv = nn.Conv1d(4, 1, kmer_size)
23
+ self.custom_conv()
24
+
25
+ self.kmer_binarizer = nn.ReLU()
26
+
27
+ out_length = self.compute_kmer_outshape()
28
+ self.fc_out = nn.Linear(channel_size * out_length, 1)
29
+
30
+ def compute_kmer_outshape(self):
31
+ """
32
+ default stride = 1, pad = 0
33
+ """
34
+ dilation = 1
35
+ padding = 0
36
+ stride = 1
37
+ L_in = self.input_length
38
+ L_out = 1 + L_in + 2 * padding - dilation * (self.k - 1) - 1
39
+ return L_out
40
+
41
+ def create_kmer(self):
42
+ all_kmer = {0:['']}
43
+ k = 1
44
+ while k <= self.k:
45
+ k_mer = [] # 1 ; 4 ; 2: 4**2 ...
46
+ for source in all_kmer[k-1]:
47
+ k_mer += [source + base for base in ['A','C','G','T']]
48
+
49
+ assert len(k_mer) == 4**k, f"new kmers {len(k_mer)}, not equal to {4**k}"
50
+ all_kmer[k] = k_mer
51
+ k += 1
52
+
53
+ all_kmer.pop(0)
54
+ return all_kmer
55
+
56
+ def custom_conv(self):
57
+
58
+ # only detect 5-mer is kmersize is 5
59
+ # Zhang et al includes shorter kmers in their features
60
+ kmers = self.create_kmer()[self.k]
61
+
62
+ matrix = [reader.one_hot(kmer).T for kmer in kmers]
63
+ kernels = np.stack(matrix)
64
+
65
+ kernels = matrix[0].reshape(1, 4, 3)
66
+
67
+ self.kmer_conv.weight = nn.Parameter(torch.from_numpy(kernels).long(), requires_grad=False)
68
+
69
+
model/src/mrl_te_optimization/models/ScheduleOptimizer.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import os
3
+ import sys
4
+ import numpy as np
5
+ import torch
6
+ from torch import nn
7
+ from matplotlib import pyplot as plt
8
+ from matplotlib import cm
9
+
10
+ global scheduleoptim_text
11
+ scheduleoptim_text="ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), betas=(0.9, 0.98), eps=1e-09, weight_decay=1e-4, amsgrad=True),n_warmup_steps=20)"
12
+
13
+ scheduleoptim_dict_str="""ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
14
+ betas=(0.9, 0.98),
15
+ eps=1e-09,
16
+ weight_decay={weight_decay},
17
+ amsgrad={amsgrad}),
18
+ n_warmup_steps={n_warmup_steps})"""
19
+
20
+ class ScheduledOptim(object):
21
+ """A simple wrapper class for learning rate scheduling"""
22
+
23
+ def __init__(self, optimizer, n_warmup_steps):
24
+ self.optimizer = optimizer
25
+ self.d_model = 128
26
+ self.n_warmup_steps = n_warmup_steps
27
+ self.n_current_steps = 0
28
+ self.delta = 1
29
+
30
+ def state_dict(self):
31
+ return self.optimizer.state_dict()
32
+
33
+ def load_state_dict(self,state):
34
+ self.optimizer.load_state_dict(state)
35
+
36
+ def step(self):
37
+ """Step by the inner optimizer"""
38
+ self.optimizer.step()
39
+
40
+ def zero_grad(self):
41
+ """Zero out the gradients by the inner optimizer"""
42
+ self.optimizer.zero_grad()
43
+
44
+ def increase_delta(self):
45
+ self.delta *= 2
46
+ self.delta = min(1024,self.delta)
47
+
48
+ def update_learning_rate(self):
49
+ """Learning rate scheduling per step"""
50
+
51
+ self.n_current_steps += self.delta
52
+ new_lr = np.power(self.d_model, -0.5) * np.min([
53
+ np.power(self.n_current_steps, -0.5),
54
+ np.power(self.n_warmup_steps, -1.5) * self.n_current_steps])
55
+ # -1.5
56
+ for param_group in self.optimizer.param_groups:
57
+ param_group['lr'] = new_lr
58
+ return new_lr
59
+
60
+
61
+ def find_lr(net,train_data,Variable):
62
+ criterion = torch.nn.CrossEntropyLoss()
63
+
64
+ net.fc = nn.Linear(2048, 120)
65
+
66
+ with torch.cuda.device(0):
67
+ net = net.cuda()
68
+
69
+ basic_optim = torch.optim.SGD(net.parameters(), lr=1e-5)
70
+ optimizer = ScheduledOptim(basic_optim)
71
+
72
+
73
+ lr_mult = (1 / 1e-5) ** (1 / 100)
74
+ lr = []
75
+ losses = []
76
+ best_loss = 1e9
77
+ for data, label in train_data:
78
+ with torch.cuda.device(0):
79
+ data = Variable(data.cuda())
80
+ label = Variable(label.cuda())
81
+ # forward
82
+ out = net(data)
83
+ loss = criterion(out, label)
84
+ # backward
85
+ optimizer.zero_grad()
86
+ loss.backward()
87
+ optimizer.step()
88
+ lr.append(optimizer.learning_rate)
89
+ losses.append(loss.data[0])
90
+ optimizer.set_learning_rate(optimizer.learning_rate * lr_mult)
91
+ if loss.data[0] < best_loss:
92
+ best_loss = loss.data[0]
93
+ if loss.data[0] > 4 * best_loss or optimizer.learning_rate > 1.:
94
+ break
95
+
96
+ plt.figure()
97
+ plt.xticks(np.log([1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1]), (1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1))
98
+ plt.xlabel('learning rate')
99
+ plt.ylabel('loss')
100
+ plt.plot(np.log(lr), losses)
101
+ plt.show()
102
+ plt.figure()
103
+ plt.xlabel('num iterations')
104
+ plt.ylabel('learning rate')
105
+ plt.plot(lr)
model/src/mrl_te_optimization/models/Self_attention.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import torch
4
+ from torch import nn
5
+ import numpy as np
6
+
7
+ class self_attention(nn.Module):
8
+
9
+ def __init__(self,in_channel,n_head,d_k,d_v):
10
+ super(self_attention,self).__init__()
11
+ self.n_head=n_head
12
+ self.d_k = d_k
13
+ self.d_v = d_v
14
+ self.W_dict = nn.ModuleDict({"Wq" : nn.Linear(in_channel,n_head*d_k),
15
+ "Wk" : nn.Linear(in_channel,n_head*d_k),
16
+ "Wv" : nn.Linear(in_channel,n_head*d_v)})
17
+
18
+ def forward(self,X):
19
+
20
+ # some dimension
21
+ dk_sqrt = int(np.sqrt(self.d_k))
22
+
23
+ querys = self.W_dict['Wq'](X) # B*X_dim*dk
24
+ keys = self.W_dict['Wk'](X) # B* hs_out -> B*64
25
+ values = self.W_dict['Wv'](X) # B* hs_out -> B*128
26
+
27
+ sim_M = torch.bmm(querys,keys.transpose(1,2))/8 # B* X_dim * X_dim
28
+ attention = torch.softmax(sim_M,dim=-1)
29
+ # result
30
+ result = torch.bmm(attention,values).squeeze(2) # B*X_dim*1 -> B*X_dim
31
+
32
+ return result
33
+
34
+ class task_attention(nn.Module):
35
+ """
36
+ Task Attention Layer, it contains a task specific mask `Wq` as the Query. Key is computed from the input
37
+
38
+ Arguments:
39
+
40
+ d_v : int , dimension of the network width input , i.e : (Batch_size, d_v)
41
+ d_k : int , dimension of the Query and Key.
42
+ """
43
+ def __init__(self,d_v:int,d_k=64):
44
+ super(task_attention,self).__init__()
45
+
46
+ self.d_k = d_k
47
+ self.d_v = d_v
48
+ self.W_dict = nn.ModuleDict({"Wq" : nn.Linear(d_k,d_v),
49
+ "Wk" : nn.Linear(d_v,d_k)})
50
+
51
+ def forward(self,X):
52
+ # i.e X : (B ,128)
53
+ # if len(X.shape) == 2:
54
+ # X = X
55
+
56
+ # some dimension
57
+ dk_sqrt = int(np.sqrt(self.d_k))
58
+
59
+ keys = self.W_dict['Wk'](X).squeeze(2) # (B, 128) -> (B ,64)
60
+
61
+ # dot product similarity is used here , which is implemented by `nn.Linear`
62
+ sim_M =self.W_dict['Wq'](keys) /dk_sqrt # (B,128,64) * (B,64,128) -> (B, 128, 128)
63
+ attention = torch.softmax(sim_M,dim=-1)
64
+ # result
65
+ result = torch.mul(attention,X) # (B, 128) * (B, 128) -> B*128
66
+
67
+ return result
68
+
69
+ class task_attention(nn.Module):
70
+ """
71
+ Task Attention Layer, it contains a task specific mask `Wq` as the Query. Key is computed from the input
72
+
73
+ Arguments:
74
+
75
+ d_v : int , dimension of the network width input , i.e : (Batch_size, d_v)
76
+ d_k : int , dimension of the Query and Key.
77
+ """
78
+ def __init__(self,d_v:int,d_k=64):
79
+ super(task_attention,self).__init__()
80
+
81
+ self.d_k = d_k
82
+ self.d_v = d_v
83
+ self.W_dict = nn.ModuleDict({"Wq" : nn.Linear(d_v,d_k),
84
+ "Wk" : nn.Linear(d_v,d_k)})
85
+
86
+ def forward(self,X):
87
+ # i.e X : (B ,128)
88
+ # if len(X.shape) == 2:
89
+ # X = X
90
+
91
+ # some dimension
92
+ dk_sqrt = int(np.sqrt(self.d_k))
93
+ query = self.W_dict['Wq'](X).squeeze(2)
94
+ keys = self.W_dict['Wk'](X).squeeze(2) # (B, 128) -> (B ,64)
95
+
96
+ # dot product similarity is used here , which is implemented by `nn.Linear`
97
+ sim_M =self.W_dict['Wq'](keys) /dk_sqrt # (B,128,64) * (B,64,128) -> (B, 128, 128)
98
+ attention = torch.softmax(sim_M,dim=-1)
99
+ # result
100
+ result = torch.mul(attention,X) # (B, 128) * (B, 128) -> B*128
101
+
102
+ return result
model/src/mrl_te_optimization/models/__pycache__/Backbone.cpython-310.pyc ADDED
Binary file (23.7 kB). View file
 
model/src/mrl_te_optimization/models/__pycache__/Backbone.cpython-311.pyc ADDED
Binary file (44.1 kB). View file
 
model/src/mrl_te_optimization/models/bucket_sampler.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import numpy as np
3
+ import pandas as pd
4
+ from torch.utils.data.sampler import Sampler,BatchSampler,SubsetRandomSampler
5
+
6
+ class Basic_sampler(Sampler):
7
+ def __init__(self, data):
8
+ super().__init__(data)
9
+ self.data= data
10
+
11
+ def __len__(self):
12
+ return self.data.shape[0]
13
+
14
+ def __iter__(self):
15
+ return (i for i in range(self.data.shape[0]))
16
+
17
+ class sort_sampler(Sampler):
18
+ def __init__(self, data, sort_key="utr_len"):
19
+ super().__init__(data)
20
+ self.data = data
21
+ self.sort_key = sort_key
22
+ zip_ = [(i, seq_len) for i, seq_len in enumerate(data[sort_key].values)]
23
+ zip_ = sorted(zip_, key=lambda r: r[1])
24
+ self.sorted_indexes = [item[0] for item in zip_]
25
+
26
+ def __iter__(self):
27
+ return iter(self.sorted_indexes)
28
+
29
+ def __len__(self):
30
+ return len(self.data)
31
+
32
+ class Bucket_Sampler(BatchSampler):
33
+ """ `BucketBatchSampler` toggles between `sampler` batches and sorted batches.
34
+
35
+ Typically, the `sampler` will be a `RandomSampler` allowing the user to toggle between
36
+ random batches and sorted batches. A larger `bucket_size_multiplier` is more sorted and vice
37
+ versa.
38
+
39
+ Background:
40
+ ``BucketBatchSampler`` is similar to a ``BucketIterator`` found in popular libraries like
41
+ ``AllenNLP`` and ``torchtext``. A ``BucketIterator`` pools together examples with a similar
42
+ size length to reduce the padding required for each batch while maintaining some noise
43
+ through bucketing.
44
+
45
+ **AllenNLP Implementation:**
46
+ https://github.com/allenai/allennlp/blob/master/allennlp/data/iterators/bucket_iterator.py
47
+
48
+ **torchtext Implementation:**
49
+ https://github.com/pytorch/text/blob/master/torchtext/data/iterator.py#L225
50
+
51
+ Args:
52
+ sampler (torch.data.utils.sampler.Sampler):
53
+ batch_size (int): Size of mini-batch.
54
+ drop_last (bool): If `True` the sampler will drop the last batch if its size would be less
55
+ than `batch_size`.
56
+ sort_key (callable, optional): Callable to specify a comparison key for sorting.
57
+ bucket_size_multiplier (int, optional): Buckets are of size
58
+ `batch_size * bucket_size_multiplier`.
59
+
60
+ Example:
61
+ >>> from torchnlp.random import set_seed
62
+ >>> set_seed(123)
63
+ >>>
64
+ >>> from torch.utils.data.sampler import SequentialSampler
65
+ >>> sampler = SequentialSampler(list(range(10)))
66
+ >>> list(BucketBatchSampler(sampler, batch_size=3, drop_last=False))
67
+ [[6, 7, 8], [0, 1, 2], [3, 4, 5], [9]]
68
+ >>> list(BucketBatchSampler(sampler, batch_size=3, drop_last=True))
69
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
70
+ """
71
+ def __init__(self,
72
+ data,
73
+ batch_size,
74
+ drop_last=False,
75
+ sort_key='utr_len',
76
+ bucket_size_multiplier=100):
77
+ self.data = data
78
+ self.sampler = Basic_sampler(data)
79
+ super().__init__(self.sampler, batch_size, drop_last)
80
+ self.sort_key = sort_key
81
+ _bucket_size = batch_size * bucket_size_multiplier
82
+ if hasattr(self.sampler, "__len__"):
83
+ _bucket_size = min(_bucket_size, len(self.sampler))
84
+ self.bucket_sampler = BatchSampler(self.sampler, _bucket_size, False)
85
+
86
+ def __iter__(self):
87
+ for bucket in self.bucket_sampler:
88
+ sorted_sampler = sort_sampler(self.data.iloc[bucket], self.sort_key)
89
+ for batch in SubsetRandomSampler(
90
+ list(BatchSampler(sorted_sampler, self.batch_size, self.drop_last))):
91
+ yield [bucket[i] for i in batch]
92
+
93
+ def __len__(self):
94
+ if self.drop_last:
95
+ return len(self.sampler) // self.batch_size
96
+ else:
97
+ return np.ceil(len(self.sampler) / self.batch_size)
98
+
99
+
model/src/mrl_te_optimization/models/log_and_save.py ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import logging
4
+ import re
5
+ import pandas as pd
6
+ import numpy as np
7
+ from matplotlib import pyplot as plt
8
+ import copy
9
+
10
+ def snapshot(dir_path, run_name, state,logger):
11
+ snapshot_file = os.path.join(dir_path,
12
+ run_name + '-model_best.pth')
13
+ # torch.save can save any object
14
+ # dict type object in our cases
15
+ torch.save(state, snapshot_file)
16
+ logger.info("Snapshot saved to {}\n".format(snapshot_file))
17
+
18
+ class Log_parser(object):
19
+ def __init__(self,log_path,val_split_line=False,use_line_as_valtest=1):
20
+ # -------- read --------
21
+ self.val_split_line = val_split_line
22
+ self.use_line_as_valtest = use_line_as_valtest
23
+ if os.path.exists(log_path):
24
+ with open(log_path,'r') as f:
25
+ log_file = f.readlines()
26
+ f.close()
27
+ # stripping
28
+ log_file = np.array([line.strip() for line in log_file])
29
+ else:
30
+ print('log path error !')
31
+ self.log_file = log_file
32
+
33
+ # self.possible_metric = ['LOSS','lr','Avg_ACC','teaching_rate','TOTAL','KLD','MSE','M_N','CrossEntropy','chimerla_weight','Total','TE','Loop','Match','MAE','RMSE','RL_loss','Recons_loss','Motif_loss','RL_Acc','Recons_Acc','Motif_Acc','Acc','Mean_Total', 'DTP_wt_RL','DTP_wt_Recons','DTP_wt_Motif']
34
+
35
+ # -------- basic matcher --------
36
+ self.epoch_line_matcher = r"\s.* epoch (\d{1,4}).*"
37
+ self.start_val_line_matcher = r"\s*.* start validation .*\s*"
38
+ self.match_logging_time = r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} -"
39
+ self.match_percentage = r"\s*\d{1,6} /\s*\d{1,6}\s*\((\d|\.){,6}%\):"
40
+
41
+ self.match_sub_verbose = lambda x : r"\s*%s:\s*(?P<%s>(-|\d|\.|e|){,40})"%(x,x)
42
+
43
+ # -------- high level matcher --------
44
+ self.train_verbose_finder = self.match_logging_time + self.match_percentage
45
+
46
+ # --------- get output DF ---------
47
+ self.extract_training_verbose_data()
48
+ self.extract_val_verbose_data()
49
+
50
+ def lines_to_json(self, line, sett):
51
+ remove_time = line.split('%):')[1].split() if sett=='train' else line.split(' - \t ')[1].split()
52
+ line_json = {metrics.split(':')[0]:metrics.split(':')[1] for metrics in remove_time}
53
+ return line_json
54
+
55
+ def lines_matching(self,matcher):
56
+ """
57
+ return lines that can match certain syntax
58
+ """
59
+ return [line for line in self.log_file if re.match(matcher,line) is not None]
60
+
61
+ def position_matching(self,matcher):
62
+ """
63
+ return position of the line that can match certain syntax
64
+ """
65
+ return [i for i,line in enumerate(self.log_file) if re.match(matcher,line) is not None]
66
+
67
+ # def get_metrics_order(self):
68
+ # """
69
+ # get train verbose line and define train_verbose_matcher automatically
70
+ # """
71
+ # # find all the train verbose lines
72
+
73
+ # test_t_v = self.train_verbose_lines[0] # a testing train verbose
74
+
75
+ # # using the esting trainverbose to determine metric order
76
+ # # train_metric = np.array([metric for metric in self.possible_metric if metric in test_t_v])
77
+ # # train_metric = self.check_dup_metric(train_metric,test_t_v)
78
+
79
+ # # train_metric_posi = np.array([test_t_v.index(metric) for metric in train_metric])
80
+
81
+ # # order = train_metric_posi.argsort()
82
+ # # self.train_metric = train_metric[order]
83
+
84
+ # # # ----|| automatically determine train verbose matcher ||----
85
+ # # self.train_verbose_matcher = self.train_verbose_finder
86
+ # # for metric in self.train_metric:
87
+ # # self.train_verbose_matcher += self.match_sub_verbose(metric)
88
+
89
+ # # def check_dup_metric(self,train_metric,test_t_v):
90
+ # # """
91
+ # # to deal with the problem of `MSE` and `RMSE`
92
+ # # """
93
+ # # train_metric = list(train_metric)
94
+ # # if ("MSE" in train_metric) & ("RMSE" in train_metric):
95
+ # # if test_t_v.index('MSE') == test_t_v.index('RMSE')+1:
96
+ # # train_metric.remove('MSE')
97
+ # # return np.array(train_metric)
98
+
99
+ def extract_training_verbose_data(self):
100
+ """
101
+ regular expression to match the printed metric during training and save to pd.DataFrame
102
+ """
103
+ self.train_verbose_lines = self.lines_matching(self.train_verbose_finder)
104
+
105
+ self.train_verbose_dict = [self.lines_to_json(line,'train') for line in self.train_verbose_lines]
106
+
107
+ self.train_metric = list(self.train_verbose_dict[0].keys())
108
+
109
+ self.train_verbose_DF = pd.json_normalize(self.train_verbose_dict).astype(float)
110
+
111
+ # return self.train_verbose_DF
112
+
113
+ def extract_val_verbose_data(self):
114
+ """
115
+ regular expression to match the printed metric during training and save to pd.DataFrame
116
+ """
117
+ self.start_val_posi = self.position_matching(self.start_val_line_matcher)
118
+ val_verbose_posi = np.array(self.start_val_posi) +1 # observe from log
119
+ self.val_verbose_posi = val_verbose_posi[val_verbose_posi < len(self.log_file)]
120
+ self.val_verbose_lines = self.log_file[self.val_verbose_posi]
121
+ if self.val_split_line:
122
+ self.val_verbose_lines = ["\t".join(self.log_file[[posi,posi+1,posi+2,posi+3,posi+4]]) for posi in self.val_verbose_posi]
123
+
124
+ # test_v_v = self.val_verbose_lines[self.use_line_as_valtest]
125
+
126
+ # using the esting trainverbose to determine metric order
127
+ # val_metric = np.array([metric for metric in self.possible_metric if metric in test_v_v])
128
+ # val_metric = self.check_dup_metric(val_metric,test_v_v)
129
+ # val_metric_posi = np.array([test_v_v.index(metric) for metric in val_metric])
130
+ # order = val_metric_posi.argsort() # sort
131
+ # self.val_metric = val_metric[order]
132
+
133
+
134
+ # # ----|| automatically determine val verbose matcher ||----
135
+ # self.val_verbose_matcher = self.match_logging_time
136
+
137
+ # if re.match(self.match_logging_time + self.match_percentage,test_v_v) is not None:
138
+ # self.val_verbose_matcher += self.match_percentage # detect whether validation set also get percentage info
139
+
140
+ # for metric in self.val_metric:
141
+ # self.val_verbose_matcher += self.match_sub_verbose(metric)
142
+
143
+ self.val_verbose_dict = [self.lines_to_json(line, 'val') for line in self.val_verbose_lines]
144
+ self.val_metric = list(self.val_verbose_dict[0].keys())
145
+ # np.array(
146
+ # [list(
147
+ # re.match(self.val_verbose_matcher,line).groupdict().values()
148
+ # ) for line in self.val_verbose_lines]
149
+ # ).astype(np.float64)
150
+
151
+ self.val_verbose_DF = pd.json_normalize(self.val_verbose_dict).astype(float)
152
+
153
+ # return self.val_verbose_DF
154
+
155
+ def plot_val_metric(self,fig=None,dataset='val'):
156
+ DF = self.val_verbose_DF if dataset == 'val' else self.train_verbose_DF
157
+ metrics = self.val_metric if dataset == 'val' else self.train_metric
158
+ n = len(metrics)
159
+
160
+ if fig is None:
161
+ fig = plt.figure(figsize=(18,5*np.ceil(n/3)))
162
+ if n <=3:
163
+ axs = fig.subplots(1,n)
164
+ for i in range(n):
165
+ axs[i].plot(DF[metrics[i]].values)
166
+ axs[i].set_title(dataset.capitalize()+" "+metrics[i]) # TRAIN or VAL
167
+ else:
168
+ axs = fig.add_subplot(n//3+1,n,1+i)
169
+
170
+
171
+ def plot_a_exp_set(log_list,log_name_ls,dataset='val',fig=None,layout=None,check_time=10,start_from=0,mean_of_train=None,define_order=None,esubset=None, cycle_train=False,**kwargs):
172
+ all_metric = [logg.__getattribute__(dataset+"_metric") for logg in log_list]
173
+ share_metric = [all_metric[0]]
174
+ for logg_metric in all_metric[1:]:
175
+ share_metric = np.intersect1d(share_metric,logg_metric)
176
+ if define_order is not None:
177
+ assert set(define_order) == set(share_metric)
178
+
179
+ n = len(share_metric) + 1 # val or train
180
+ fig = plt.figure(figsize=(20,5)) if fig is None else fig
181
+
182
+
183
+ if layout is None:
184
+ axs = fig.subplots(1,n);
185
+ else:
186
+ row,column = layout
187
+ axs = fig.subplots(row,column).flatten()
188
+
189
+
190
+ for i,metric in enumerate(share_metric):
191
+ # layout
192
+
193
+ ax = axs[i]
194
+ for st,log in enumerate(log_list):
195
+ DF = log.__getattribute__(dataset+"_verbose_DF")
196
+
197
+ if (dataset == 'train') & (type(mean_of_train)==int):
198
+ DF = mean_of(mean_of_train,DF)
199
+ elif (dataset == 'train') & (type(esubset)==slice):
200
+ DF = subset_of(esubset,DF)
201
+ X = np.arange(DF.shape[0])*check_time if dataset == 'val' else np.arange(DF.shape[0])
202
+ ax.plot(X[start_from:],DF[metric].values[start_from:],**kwargs)
203
+ ax.set_title(" ".join([dataset.capitalize(),metric]))
204
+ for st,log in enumerate(log_list):
205
+ axs[-1].plot(0,0,label=log_name_ls[st])
206
+ axs[-1].axis('off')
207
+ axs[-1].legend()
208
+
209
+ def plot_cycle_exp_set(log_ls,log_name,dataset='val',**kwargs):
210
+ interval = 2 if dataset=='val' else 6
211
+ new_log_ls = []
212
+ new_log_name = []
213
+ for i in range(len(log_ls)):
214
+ log = log_ls[i]
215
+ DF = log.__getattribute__(dataset+"_verbose_DF")
216
+ ds1_index = [i for i in range(DF.shape[0]) if i//interval%2 ==0]
217
+ ds2_index = [i for i in range(DF.shape[0]) if i//interval%2 ==1]
218
+ DF1 = DF.iloc[ds1_index]
219
+ DF2 = DF.iloc[ds2_index]
220
+ log1 = copy.deepcopy(log)
221
+ log2 = copy.deepcopy(log)
222
+
223
+ log1.__setattr__(dataset+'_verbose_DF', DF1)
224
+ log2.__setattr__(dataset+'_verbose_DF', DF2)
225
+
226
+ new_log_ls.append(log1)
227
+ new_log_ls.append(log2)
228
+
229
+ new_log_name.append(log_name[i]+"_ds1")
230
+ new_log_name.append(log_name[i]+"_ds2")
231
+
232
+ plot_a_exp_set(new_log_ls, new_log_name, **kwargs)
233
+
234
+
235
+ def subset_of(x,DF):
236
+
237
+ values = DF.values
238
+ mean_ls = []
239
+
240
+ for i in range(0,values.shape[0],x.stop):
241
+ # x : slice , x.stop , the slice window of the
242
+ mean_ls.append(values[i:i+x.stop][x])
243
+
244
+ mean_ls = np.concatenate(mean_ls,axis=0)
245
+ mean_DF = pd.DataFrame(mean_ls,columns=DF.columns)
246
+
247
+ return mean_DF
248
+
249
+ def mean_of(x,DF):
250
+
251
+ values = DF.values
252
+ mean_ls = []
253
+
254
+ for i in range(0,values.shape[0],x):
255
+
256
+ mean_ls.append(np.mean(values[i:i+x,:],axis=0))
257
+
258
+ mean_ls = np.stack(mean_ls)
259
+ mean_DF = pd.DataFrame(mean_ls,columns=DF.columns)
260
+
261
+ return mean_DF
262
+
263
+ def read_log_of_a_dir(log_dir):
264
+ """
265
+ ...log_dir : abs path of log dir
266
+ """
267
+ file_ls = [file for file in os.listdir(log_dir) if ".log" in file]
268
+ log_path = [os.path.join(log_dir,file) for file in file_ls]
269
+ log_name = [file.replace('.log','') for file in file_ls]
270
+ log_ls = [Log_parser(file) for file in log_path]
271
+ return log_ls,log_name
model/src/mrl_te_optimization/models/loss.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ from torch import nn
4
+ import numpy as np
5
+
6
+
7
+ def softmax(x):
8
+ """
9
+ one dimensional softmax designed for numpy array
10
+ """
11
+ e_x = np.exp(x)
12
+ out = e_x / e_x.sum()
13
+ return out
14
+
15
+ class Dynamic_Weight_Averaging():
16
+ def __init__(self,tasks,tau,init_weight):
17
+ """
18
+ Dynamic Weight Averaging implementation
19
+ """
20
+ # number of tasks
21
+ self.N = len(tasks)
22
+ # self.loss_list = np.array([loss_dict[t+'_loss'].detach().cpu().item() for t in tasks])
23
+ self.step = 0
24
+ self.omega = np.array([init_weight]*self.N ) # the weight , \omega_i(t)
25
+ self.tau = tau # † : a value to adjust the soft-max
26
+
27
+ def _magnitude_adjust(self):
28
+ """
29
+ automatic adjustment of loss magnitude
30
+ """
31
+ self.relative_magnitude = self.loss_list.min() / self.loss_list
32
+
33
+ def _update(self,loss_dict):
34
+ # update r with L_i(t-1)
35
+ self.step += 1
36
+ if self.step < 2:
37
+ self.loss_list = np.array([loss_dict[t+'_loss'].detach().cpu().item() for t in self.tasks])
38
+ return self.init_weight
39
+ else:
40
+ self._magnitude_adjust()
41
+ last_loss = self.loss_list
42
+ self.loss_list = np.array([loss_dict[t+'_loss'].detach().cpu().item() for t in self.tasks])
43
+ # computing DWA
44
+ r_t = np.divide(self.loss_list,last_loss) / self.tau
45
+ self.omega = self.N * softmax(r_t)
46
+ weight_t = np.multiply(self.relative_magnitude,self.omega)
47
+ return {self.tasks[i]:weight_t[i] for i in range(len(self.tasks))}
48
+
49
+ class Dynamic_Task_Priority(object):
50
+ def __init__(self,tasks,gamma,init_weight):
51
+ """
52
+ Dynamic Task Priority (DTP) wish to weight more on tasks with lower KPI
53
+ In our cases, we take accuracy as the KPI
54
+ """
55
+ self.gamma = np.array([gamma[t] for t in tasks]) if type(gamma) == dict else gamma # an adjustment param
56
+ self.tasks = tasks
57
+ # self.kappa = [loss_dict[t+'_Acc'] for t in tasks]
58
+ self.omega = init_weight
59
+ self.init_weight = init_weight
60
+ self.step = 0
61
+
62
+
63
+ def _magnitude_adjust(self):
64
+ """
65
+ automatic adjustment of loss magnitude
66
+ """
67
+ # TODO : test this effectiveness
68
+ self.relative_magnitude = self.kappa.min() / (self.kappa+1e-8)
69
+ if np.any(self.kappa==1):
70
+ self.kappa[np.where(self.kappa==1)[0]] -= 1e-8
71
+
72
+ def _update(self,loss_dict):
73
+ """
74
+ weight is updated like belowing
75
+ `math` : w_i(t) = -(1-\kappa_i(t))^{\gamma_i} log \kappa_i(t)
76
+ """
77
+ self.step += 1
78
+ self.kappa = np.array([loss_dict[t+'_Acc'] for t in self.tasks])
79
+ self._magnitude_adjust()
80
+ self.omega = -1 * np.multiply(np.power(1 - self.kappa,self.gamma),np.log(self.kappa+1e-8))
81
+
82
+ if self.step < 2:
83
+ return self.init_weight
84
+ else:
85
+ weight_t = np.multiply(self.relative_magnitude,self.omega)
86
+ return {self.tasks[i]:weight_t[i] for i in range(len(self.tasks))}
model/src/mrl_te_optimization/models/max_activation_patch.py ADDED
@@ -0,0 +1,795 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import re
4
+ sys.path.append(os.path.dirname(__file__))
5
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
6
+ import utils
7
+ import copy
8
+ import torch
9
+ import train_val
10
+ import reader
11
+ import logomaker
12
+ from torch import nn
13
+ import numpy as np
14
+ import pandas as pd
15
+ import seaborn as sns
16
+ from tqdm.auto import tqdm
17
+ from importlib import reload
18
+ from scipy import stats
19
+ from matplotlib import pyplot as plt
20
+ from sklearn import cluster
21
+ from sklearn.manifold import TSNE
22
+ import ruptures as rpt
23
+ from popen import Auto_popen
24
+
25
+ tensor_2_numpy = lambda x: x.detach().cpu().numpy()
26
+
27
+ class Maximum_activation_patch(object):
28
+ def __init__(self, popen, which_layer, n_patch=9, kfold_index=None, device_string='cpu'):
29
+ self.popen = popen
30
+ self.layer = which_layer
31
+ self.popen.cuda_id = torch.device("cuda:%s"%device_string) if device_string.isdigit() else torch.device('cpu')
32
+ self.n_patch = n_patch
33
+ self.kfold_index = kfold_index
34
+ self.total_stride = np.product(popen.stride[:self.layer])
35
+ self.compute_reception_field()
36
+ self.compute_virtual_pad()
37
+
38
+ def load_indexed_dataloader(self,task):
39
+ # True or 'train_val'
40
+ assert (self.popen.kfold_cv!=False) == (self.kfold_index != None), \
41
+ "kfold CV should match with kfold index"
42
+
43
+ self.popen.kfold_index = self.kfold_index
44
+ self.popen.shuffle = False
45
+ self.popen.pad_to = 57 if self.popen.cycle_set==None else 105
46
+
47
+ tmp_popen = copy.copy(self.popen)
48
+ if self.popen.cycle_set != None:
49
+ base_path = copy.copy(self.popen.split_like)
50
+ base_csv = copy.copy(self.popen.csv_path)
51
+ # base_csv = "/mnt/sina/run/ml/gan/motif/MTtrans/test.csv"
52
+
53
+ if base_path is not None:
54
+ assert task != None , "task is not defined !"
55
+ tmp_popen.split_like = [path.replace('cycle', task) for path in base_path]
56
+ else:
57
+ tmp_popen.csv_path = base_csv.replace('cycle', task)
58
+ # tmp_popen.csv_path = "/mnt/sina/run/ml/gan/motif/MTtrans/test.csv"
59
+
60
+ # tmp_popen.csv_path = "/mnt/sina/run/ml/gan/motif/MTtrans/test.csv"
61
+ # base_csv = "/mnt/sina/run/ml/gan/motif/MTtrans/test.csv"
62
+
63
+ return reader.get_dataloader(tmp_popen)
64
+
65
+ def load_model(self):
66
+ if self.kfold_index is not None:
67
+ base_pth = self.popen.vae_log_path
68
+ self.popen.vae_log_path = base_pth.replace(".pth","_cv%s.pth"%self.kfold_index)
69
+
70
+ model = utils.load_model(self.popen, None)
71
+ if self.kfold_index is not None:
72
+ self.popen.vae_log_path = base_pth
73
+ return model
74
+
75
+ def get_filter_param(self, model):
76
+ Conv_layer = model.soft_share.encoder[self.layer-1]
77
+
78
+ return tensor_2_numpy( next(Conv_layer[0][0].parameters()) )
79
+
80
+ def loading(self,task, which_set):
81
+ model = self.load_model().to(self.popen.cuda_id)
82
+ dataloader = self.load_indexed_dataloader(task)[which_set]
83
+ self.df = dataloader.dataset.df
84
+ return model, dataloader
85
+
86
+ @torch.no_grad()
87
+ def cumulative_rl_decision(self, task=None,which_set=0, extra_loader=None):
88
+ """
89
+ take out the memory h_i of each position and pass to output layer
90
+ Arg:
91
+ task : str
92
+ which_set : int, 0 : training set, 1 : val set, 2 : test set
93
+ """
94
+ model, dataloader= self.loading(task, which_set)
95
+ model.eval()
96
+
97
+ Y_ls = []
98
+ for Data in tqdm(dataloader):
99
+ # iter each batch
100
+ x,y = train_val.put_data_to_cuda(Data,self.popen,False)
101
+ x = torch.transpose(x, 1, 2)
102
+ y_pred = model.predict_each_position(x)
103
+ Y_ls.append( tensor_2_numpy(y_pred) )
104
+ Y_ay = np.concatenate(Y_ls, axis=0)
105
+
106
+ # release some cache
107
+ torch.cuda.empty_cache()
108
+ del model
109
+ return Y_ay.reshape(Y_ay.shape[0],-1)
110
+
111
+ def extract_feature_map(self, task=None, which_set=0, extra_loader=None):
112
+ """
113
+ load trained model and unshuffled dataloader, make model forwarded
114
+ Arg:
115
+ task : str
116
+ which_set : int, 0 : training set, 1 : val set, 2 : test set
117
+ """
118
+ model, dataloader= self.loading(task, which_set)
119
+ if extra_loader is not None:
120
+ dataloader = extra_loader
121
+ self.df = extra_loader.dataset.df
122
+
123
+ feature_map = []
124
+ X_ls = []
125
+ Y_ls = []
126
+ # print(type(dataloader))
127
+ model.eval()
128
+ with torch.no_grad():
129
+ print(len(dataloader))
130
+ for Data in tqdm(dataloader):
131
+ # print(Data)
132
+ # print(Data[0].shape)
133
+ # print(Data[1].shape)
134
+ # iter each batch
135
+ x,y = train_val.put_data_to_cuda(Data,self.popen,False)
136
+ # print(x)
137
+ # print(np.shape(Data[0].numpy()))
138
+ shape = np.shape(Data[0].numpy()[0])
139
+ xt = torch.tensor(np.reshape(Data[0].numpy()[0],(1,shape[0],shape[1])),dtype=torch.float64)
140
+ # print(type(xt))
141
+ # print(type(x))
142
+ xt = xt.float()
143
+ # xt = torch.transpose(xt, 1, 2)
144
+ # print(model.forward(xt))
145
+ # print(model.predict_each_position(x))
146
+
147
+ # print(type(y))
148
+ # print(x.shape)
149
+ x = torch.transpose(x, 1, 2)
150
+ # X_ls.append(x.numpy())
151
+ Y_ls.append( tensor_2_numpy(y))
152
+
153
+ for layer in model.soft_share.encoder[:self.layer]:
154
+ out = layer(x)
155
+ x = out
156
+ feature_map.append( tensor_2_numpy(out))
157
+
158
+ torch.cuda.empty_cache()
159
+
160
+
161
+ feature_map_l = np.concatenate( feature_map, axis=0)
162
+
163
+ # self.X_ls = np.concatenate(X_ls, axis=0)
164
+ self.Y_ls = np.concatenate(Y_ls, axis=0)
165
+
166
+ print("activation map of layer |%d|"%self.layer,feature_map_l.shape)
167
+ # print(self.X_ls.shape)
168
+ print("Y : ",self.Y_ls.shape)
169
+ self.feature_map = feature_map_l
170
+
171
+ self.filters = self.get_filter_param(model)
172
+
173
+ del model
174
+
175
+ return feature_map_l
176
+
177
+ def compute_reception_field(self):
178
+ r = 1
179
+ strides = self.popen.stride[:self.layer][::-1]
180
+
181
+ for i,s in enumerate(strides):
182
+ r = s*(r-1) + self.popen.kernel_size
183
+
184
+ self.r = r
185
+ self.strides = strides
186
+ print('the reception filed is ', r)
187
+
188
+ def compute_virtual_pad(self):
189
+ v = []
190
+ pd = self.popen.padding_ls[:self.layer]
191
+
192
+ for i,p in enumerate(pd):
193
+ v.append(p*np.product(self.popen.stride[:len(pd)-i-1]))
194
+
195
+ self.virtual_pad = np.sum(v)
196
+ print('the virtual pad is', self.virtual_pad)
197
+
198
+ def retrieve_input_site(self, high_layer_site):
199
+ """pad ?"""
200
+
201
+ virtual_start = high_layer_site*self.total_stride - self.virtual_pad
202
+ start = max(0, virtual_start)
203
+
204
+ end = virtual_start + self.r
205
+ return max(0,int(start)), int(end)
206
+
207
+ def detect_changepoint(self,time_series):
208
+ bkpt = rpt.KernelCPD(kernel="linear", min_size=1).fit_predict(time_series, n_bkps=1)[0]
209
+ return bkpt - 1
210
+
211
+ def retrieve_featmap_at_changepoint(self, featmap, rl_chain, threshold=1, direction='less', detect_region=None):
212
+ """
213
+ Using the change point of rl series, to retrieve feature map at the same position
214
+ e.g. : to find negative change point threshold=-1, direction='less'
215
+ e.g. : to find positive change point threshold=0.5, direction='greater'
216
+
217
+ featmap : np.ndarray, (n_sample, n_channel, n_position)
218
+ rl_chain : np.ndarray, (n_sample, n_position)
219
+
220
+ threshold : the threshold define the rl after change point minus that ahead the point that are considered
221
+ direction : the direction of changes
222
+ detect_region : list of slice [], which region of the rl chain is used to detect change point, default None (full sequence is considered)
223
+ """
224
+ # take out the negative break point
225
+
226
+ if direction == 'less':
227
+ condition = lambda x1, x2 : x1 - x2 < threshold
228
+ elif direction == 'greater':
229
+ condition = lambda x1, x2 : x1 - x2 > threshold
230
+
231
+ if detect_region is None:
232
+ detect_region = [slice(0, None)] * rl_chain.shape[0]
233
+
234
+ change_point_act = []
235
+ for i, trend in enumerate(rl_chain):
236
+ region = detect_region[i]
237
+ bkpt= self.detect_changepoint(trend[region]) + region.start
238
+
239
+ if condition(trend[bkpt+1] , trend[bkpt]):
240
+ activation_vec = featmap[i, :, bkpt+1]
241
+ change_point_act.append(activation_vec)
242
+
243
+ chagnepoint_map = np.asarray(change_point_act)
244
+ return chagnepoint_map
245
+
246
+ def locate_MA_seq(self, channel, feature_map=None):
247
+ """
248
+
249
+ """
250
+ if feature_map is None:
251
+ feature_map = self.feature_map
252
+
253
+ channel_feature = feature_map[:, channel,:]
254
+ F0_ay = channel_feature.max(axis=-1)
255
+
256
+ max_n_index = np.argpartition(F0_ay, -1*self.n_patch, axis=0)[-1*self.n_patch:]
257
+
258
+
259
+ # a patch of sequences
260
+ max_patch = self.df[self.popen.seq_col].values[max_n_index]
261
+
262
+ # find the location of maximally acitvated
263
+ Conv4_sites = np.argmax(channel_feature[max_n_index],axis=1)
264
+
265
+ mapped_input_sites = [self.retrieve_input_site(site) for site in Conv4_sites]
266
+
267
+ # the mapped region of the sequences
268
+ max_act_region = []
269
+ for utr, (start, end) in zip(max_patch, mapped_input_sites):
270
+
271
+
272
+ pad_gap = self.popen.pad_to - len(utr)
273
+ field = utr[max(0, start-pad_gap): end-pad_gap]
274
+
275
+ max_act_region.append(field)
276
+
277
+ # print(mapped_input_sites)
278
+
279
+ full_field = [len(field)==self.r for field in max_act_region]
280
+
281
+ return np.array(max_act_region)[full_field], max_n_index[full_field], np.array(mapped_input_sites)[full_field]
282
+
283
+ def sequence_to_matrix(self, max_act_region, weight=None, transformation='counts'):
284
+
285
+ assert np.all([seq != "" for seq in max_act_region])
286
+
287
+ max_len = max([len(seq) for seq in max_act_region])
288
+
289
+ M = np.zeros((max_len,4))
290
+ if weight is None:
291
+ weight = np.ones((self.n_patch,))
292
+ for seq, w in zip(max_act_region, weight):
293
+ oh_M = reader.one_hot(seq)*w
294
+ M += np.concatenate([np.zeros((max_len - len(seq),4)), oh_M],axis=0)
295
+
296
+
297
+ seq_logo_df = pd.DataFrame(M, columns=['A', 'C', 'G', 'U'])
298
+ if transformation!='counts':
299
+ seq_logo_df = logomaker.transform_matrix(seq_logo_df, from_type='counts', to_type=transformation)
300
+
301
+ return seq_logo_df
302
+
303
+ def plot_sequence_logo(self, seq_logo_df, save_fig_path=None, ax=None):
304
+ """
305
+ input : max_act_region ; list of str
306
+ """
307
+ # plot
308
+ if ax is None:
309
+ fig = plt.figure(dpi=300)
310
+ ax = fig.gca()
311
+ MA_C = logomaker.Logo(seq_logo_df,ax=ax)
312
+
313
+ ax.spines['right'].set_visible(False)
314
+ ax.spines['top'].set_visible(False)
315
+ ax.spines['bottom'].set_visible(False)
316
+
317
+ # save
318
+ if save_fig_path is not None:
319
+ MA_C.fig.savefig(save_fig_path,transparent=True,dpi=600)
320
+ save_dir = os.path.dirname(save_fig_path)
321
+
322
+ try:
323
+ self.save_dir
324
+ except:
325
+ # which is the first time we save
326
+ self.save_dir = save_dir
327
+ print('fig saved to',self.save_dir)
328
+ plt.close(MA_C.fig)
329
+
330
+
331
+
332
+
333
+
334
+ def fast_logo(self, channel, feature_map=None, n_patch=None, transformation='information', save_fig_path=None, title=None,ax=None):
335
+
336
+ if n_patch is not None:
337
+ self.n_patch = n_patch
338
+ max_act_region, _, _ = self.locate_MA_seq(channel, feature_map)
339
+ M = self.sequence_to_matrix(max_act_region, transformation=transformation)
340
+
341
+ # print(max_act_region)
342
+
343
+ F0_ay, (spr,pr) = self.activation_density(channel, feature_map=feature_map, to_print=False, to_plot=False)
344
+ # print(np.shape(F0_ay))
345
+ # print(type(F0_ay))
346
+
347
+ self.plot_sequence_logo(M, save_fig_path=save_fig_path, ax=ax)
348
+ if ax is None:
349
+ ax=plt.gca()
350
+ if title is None:
351
+ title = "filter {} : $r =$ {}".format(channel, spr)
352
+
353
+ ax.set_title(title, fontsize=35)
354
+ return M, spr
355
+
356
+
357
+ def activation_density(self, channel, to_print=True, to_plot=True, feature_map=None, **kwargs):
358
+ if feature_map is None:
359
+ feature_map = self.feature_map
360
+
361
+ channel_feature = feature_map[:, channel,:]
362
+ F0_ay = channel_feature.max(axis=-1)
363
+ if to_plot:
364
+ sns.kdeplot(F0_ay, **kwargs);
365
+ if to_print:
366
+ print("num of max acti: %s"%np.sum(F0_ay==F0_ay.max()))
367
+
368
+ n_gtr = [np.sum(F0_ay > q) for q in np.quantile(F0_ay,[0.5,0.8,0.95])]
369
+ print("quantiles: 50% {} 80% {} 95% {}".format(*n_gtr))
370
+
371
+ spr = stats.spearmanr(F0_ay, self.Y_ls.flatten())
372
+ pr = stats.pearsonr(F0_ay, self.Y_ls.flatten())
373
+ return F0_ay, (round(spr[0],3),round(pr[0],3))
374
+
375
+ def within_patch_clustering(self, channel, n_clusters, n_patch=None , to_plot=True,**kwargs):
376
+ """
377
+ return:
378
+ subclusters : list, list of patch (alignments)
379
+ """
380
+ self.n_patch = n_patch
381
+ act_patch, _, _ = self.locate_MA_seq(channel)
382
+ flatten_seq = np.stack([reader.one_hot(seq).flatten() for seq in act_patch])
383
+ print("the shape of sequence matrix {}".format(flatten_seq.shape))
384
+
385
+ # clsutering
386
+ cluster_index = cluster.KMeans(n_clusters=n_clusters).fit_predict(flatten_seq)
387
+ # down
388
+ if to_plot:
389
+ tsne = TSNE(metric='cosine').fit(flatten_seq)
390
+ self.tsne=tsne
391
+ plt.figure(figsize=(6,5),dpi=150)
392
+ # sns.set_theme(style='ticks', palette='viridis')
393
+ scatter_args = {"palette":'viridis'}
394
+ scatter_args.update(kwargs)
395
+ sns.scatterplot(x=tsne.embedding_[:,0], y=tsne.embedding_[:,1],
396
+ hue=cluster_index, **scatter_args);
397
+
398
+ return act_patch, flatten_seq, cluster_index
399
+
400
+ def activation_overview(self, **kwargs):
401
+ channel_spearman = []
402
+
403
+ fig, ax = plt.subplots(1,1, figsize=(10,5), dpi=300)
404
+ ax.spines['top'].set_visible(False)
405
+ ax.spines['right'].set_visible(False)
406
+
407
+ n_channel = self.popen.channel_ls[self.layer]
408
+ for i in tqdm(range(n_channel)):
409
+ act, (spr, pr) = self.activation_density(i, to_print=False, feature_map=None, **kwargs);
410
+ channel_spearman.append(spr[0])
411
+ return fig, ax, np.array(channel_spearman)
412
+
413
+ def matrix_to_seq(self, matrix):
414
+ """
415
+ return the sequence with maximum weight at each site
416
+ """
417
+ max_act_seq = ''
418
+ assert matrix.shape[1] == 4
419
+ for i in matrix.argmax(axis=1):
420
+ max_act_seq += ['A', 'C', 'G', 'T'][i]
421
+
422
+ return max_act_seq
423
+
424
+ def save_as_meme_format(self,channels:list, save_path, filter_prefix='filter', transformation='probability'):
425
+ motifs = []
426
+ success_channel = []
427
+ for cc in channels:
428
+ try:
429
+ region, index, patches = self.locate_MA_seq(channel=cc)
430
+ M = self.sequence_to_matrix(region, transformation=transformation);
431
+ motifs.append(M)
432
+ success_channel.append(cc)
433
+ except ValueError:
434
+ continue
435
+
436
+ write_meme(success_channel, motifs ,save_path, filter_prefix)
437
+
438
+ def gradience_scaler(self,array):
439
+ """
440
+ a scaling function to
441
+ """
442
+ meann = np.mean(array)
443
+ ranges = array.max() - array.min()
444
+ return (array-meann)/ranges
445
+
446
+ def get_input_grad(self, task, focus=True, fm=None, starting_layer=None):
447
+ """
448
+ compute the gradience of Y over feature_map
449
+ fm : specify feature map
450
+ starting_layer: or None [0,3]
451
+ """
452
+ All_grad = []
453
+ current_layer = self.layer if starting_layer is None else starting_layer
454
+ model = self.load_model().to(self.popen.cuda_id)
455
+ model.train()
456
+ if fm is None:
457
+ fm = self.feature_map
458
+
459
+ for start in tqdm(range(0, fm.shape[0], 64)):
460
+ # prepare input
461
+ minibatch = fm[start:start+64]
462
+ X = torch.as_tensor(minibatch, device=self.popen.cuda_id).float()
463
+ X.requires_grad=True
464
+
465
+ # forward
466
+ # x = model.soft_share.encoder[3](X)
467
+ out=X
468
+ for layer in model.soft_share.encoder[current_layer:]:
469
+ out = layer(out)
470
+ Z_t = torch.transpose(out, 1, 2)
471
+ h_prim,(c1,c2) = model.tower[task][0](Z_t)
472
+ out = model.tower[task][1](c2)
473
+
474
+ # auto grad
475
+ external_grad = torch.ones_like(out)
476
+ out.backward(gradient=external_grad,retain_graph=True)
477
+ grad = X.grad
478
+
479
+ if focus:
480
+ indices = self.argmax_to_indeces(np.argmax(minibatch, axis=2))
481
+ grad = grad[indices].reshape(-1,256)
482
+
483
+ All_grad.append( tensor_2_numpy(grad) )
484
+
485
+ # concate each channel and average over input sequences
486
+ grad_ay = np.concatenate(All_grad, axis=0)#.mean(axis=0)
487
+
488
+ # return self.gradience_scaler(grad_ay)
489
+ return grad_ay
490
+
491
+ def argmax_to_indeces(self,index):
492
+ "index : of shape [batch, 256] , the result of "
493
+ s_index = []
494
+ ch_index = []
495
+ loc_index = []
496
+ for sample in range(index.shape[0]):
497
+ sam_loc = index[sample]
498
+ for ch, pos in enumerate(sam_loc):
499
+ s_index.append(sample)
500
+ ch_index.append(ch)
501
+ loc_index.append(pos)
502
+
503
+ return (s_index, ch_index, loc_index)
504
+
505
+ def extract_max_seq_pattern(self, condition, n_clusters=6, n_patch=3000):
506
+ pattern = []
507
+ channel_source = []
508
+ for channel in np.where(condition)[0]:
509
+
510
+ try:
511
+ act_patch, flatten_seq, cluster_index = self.within_patch_clustering(channel, n_clusters=n_clusters, to_plot=False,n_patch=n_patch)
512
+ except ValueError:
513
+ continue
514
+
515
+ for i in range(n_clusters):
516
+ sub_cluster = act_patch[cluster_index==i]
517
+ if len(sub_cluster) > 0:
518
+ matrix = self.sequence_to_matrix(sub_cluster)
519
+ pattern.append(self.matrix_to_seq(matrix))
520
+ channel_source.append(channel)
521
+ return pattern, channel_source
522
+
523
+ def sum_occurrance(df, pattern):
524
+ pattern_occurance = []
525
+ for p in pattern:
526
+ pattern_occurance.append(np.sum([(p in utr) for utr in df.seq.values]))
527
+ return np.array(pattern_occurance)
528
+
529
+ def generate_scramble_index(size , N_1):
530
+ scramble_index=np.zeros((size,))
531
+
532
+ while scramble_index.sum() < N_1:
533
+ num_ = int(N_1 - scramble_index.sum())
534
+ randindex = np.random.randint(0, size, size=(num_,))
535
+
536
+ for i in randindex:
537
+ scramble_index[i]
538
+ return scramble_index
539
+
540
+
541
+ class merge_task_map(Maximum_activation_patch):
542
+ def __init__(self, popen, which_layer, n_patch , kfold_index=None, device_string='cpu'):
543
+ """merging all tasksa"""
544
+ super().__init__(popen, which_layer, n_patch , kfold_index, device_string)
545
+ self.old_popen = copy.copy(popen)
546
+ self.df_dict = {}
547
+ self.Y_2_task = {}
548
+ self.patches_ls = None
549
+
550
+ def load_indexed_dataloader(self,task):
551
+
552
+ if task in ['Andrev2015','muscle','pc3']:
553
+ self.popen.seq_col = 'utr'
554
+ self.popen.aux_task_columns = ['log_te']
555
+ self.popen.split_like = None
556
+ self.popen.kfold_cv = True
557
+
558
+ loader_ls = super().load_indexed_dataloader(task)
559
+ self.popen = copy.copy(self.old_popen)
560
+ return loader_ls
561
+
562
+ def extract_feature_map(self, which_set=0):
563
+ feature_map = {}
564
+ for task in self.popen.cycle_set:
565
+ feature_map[task] = super().extract_feature_map(task=task, which_set=which_set)
566
+ self.Y_2_task[task] = self.Y_ls
567
+ self.feature_map = feature_map
568
+ return feature_map
569
+
570
+ def loading(self,task, which_set):
571
+ model = self.load_model().to(self.popen.cuda_id)
572
+ dataloader = self.load_indexed_dataloader(task)[which_set]
573
+ self.df_dict[task] = dataloader.dataset.df
574
+ return model, dataloader
575
+
576
+ def locate_MA_seq(self, channel, feature_map=None, patches_ls=None):
577
+ """A multi-task version of MA region retrieve"""
578
+ regions = []
579
+ indeces = {}
580
+ patches = []
581
+
582
+ if patches_ls is None:
583
+ patches_ls = self.patches_ls
584
+
585
+ for i, task in enumerate(self.popen.cycle_set):
586
+ # task out : region, index, patches
587
+ if patches_ls is not None:
588
+ self.n_patch = patches_ls[i]
589
+ # print(f"{task} n_patch: {self.n_patch}")
590
+ self.df = self.df_dict[task]
591
+ # _region , index , patches
592
+ r, i, p = super().locate_MA_seq(channel, feature_map=self.feature_map[task])
593
+ regions.append(r)
594
+ indeces[task] = i
595
+ patches.append(p)
596
+
597
+ return np.concatenate(regions) , indeces , np.concatenate(patches)
598
+
599
+ def activation_density(self, channel, to_print=True, to_plot=True, feature_map=None, **kwargs):
600
+ all_F0 = []
601
+ all_spr = []
602
+ all_pr = []
603
+ for i, task in enumerate(self.popen.cycle_set):
604
+ # task out : region, index, patches
605
+ task_featmap = self.feature_map[task]
606
+ self.Y_ls = self.Y_2_task[task]
607
+
608
+ if to_print:
609
+ print(task)
610
+ F0, (spr,pr) = super().activation_density(channel, to_print=to_print,
611
+ to_plot=False,
612
+ feature_map = task_featmap)
613
+ all_F0.append(F0)
614
+ all_spr.append(spr)
615
+ all_pr.append(pr)
616
+
617
+ # merge all activateion
618
+
619
+ if to_plot:
620
+ for F0_ay in all_F0:
621
+ sns.kdeplot(F0_ay, **kwargs)
622
+
623
+ return all_F0 , (all_spr, all_pr)
624
+
625
+ def flexible_n_patch(self,channel, qtl=0.95):
626
+ """
627
+ call this function before the all other functions will enable a flexible task-wise n_patch
628
+
629
+ """
630
+ all_F0 , (all_spr, all_pr) = self.activation_density(channel,False, False,None)
631
+ thres = np.max([np.quantile(f0, qtl) for f0 in all_F0])
632
+ self.patches_ls = [np.sum(f0 > thres) for f0 in all_F0]
633
+ return self.patches_ls
634
+
635
+ def activation_overview(self):
636
+ pr_ay=[]
637
+ spr_ay=[]
638
+
639
+ # the number of convolution filters in layer 3
640
+ # the index is also 3 because input channel = 4 for layer 0
641
+ for i in tqdm(range(self.popen.channel_ls[self.layer])):
642
+ #
643
+ _,(spr,pr) = self.activation_density(i,False,False)
644
+ pr_ay.append(pr)
645
+ spr_ay.append(spr)
646
+
647
+ # convert to ndarray
648
+ pr_ay = np.stack(pr_ay)
649
+ spr_ay = np.stack(spr_ay)
650
+ return pr_ay, spr_ay
651
+
652
+ def save_as_meme_format(self,channels:list, save_path, filter_prefix='filter', transformation='probability', qtl=0.95, fix_patches_ls=None):
653
+ """
654
+ Save the position weight matrix as the meme-suite acceptale minimal motif format
655
+ """
656
+
657
+ with open(save_path, 'w') as f:
658
+ f.write("MEME version 5.3.0\n\n")
659
+ f.write("ALPHABET= ACGT\n\n")
660
+ f.write("strands: + -\n\n")
661
+ f.write("Background letter frequencies\n")
662
+ f.write("A 0.25 C 0.25 G 0.25 T 0.25\n")
663
+
664
+ for cc in channels:
665
+ if fix_patches_ls is None:
666
+ n_patches_ls = self.flexible_n_patch(cc, qtl=qtl)
667
+ else:
668
+ n_patches_ls = fix_patches_ls
669
+ try:
670
+ region, index, patches = self.locate_MA_seq(channel=cc, patches_ls=n_patches_ls)
671
+ M = self.sequence_to_matrix(region, transformation=transformation);
672
+ f.write('\n')
673
+ f.write(f"MOTIF {filter_prefix}_{cc}\n")
674
+ seq_len = len(region[0])
675
+ f.write(f"letter-probability matrix: alength= 4 w= {seq_len} \n")
676
+ for line in M.values:
677
+ f.write(" "+line.__str__()[1:-1]+'\n')
678
+ except ValueError:
679
+ continue
680
+
681
+ f.close()
682
+ print('writed')
683
+
684
+ def get_input_grad(self, focus=True):
685
+ grads = {}
686
+ for task in self.popen.cycle_set:
687
+ grads[task] = super().get_input_grad(focus=True, task=task, fm=self.feature_map[task])
688
+ return grads
689
+
690
+ class Maximum_activation_kmer(Maximum_activation_patch):
691
+ def __init__(self,popen, which_layer, n_patch, kfold_index):
692
+ super().__init__(popen, which_layer, n_patch, kfold_index)
693
+ self.virtual_pad = 0
694
+
695
+ def compute_virtual_pad(self):
696
+ self.virtual_pad = 0
697
+ print('the virtual pad is', self.virtual_pad)
698
+
699
+ def load_indexed_dataloader(self, task='kmer'):
700
+ self.csv_path = f"<DATA_DIR>/all_{self.r}mer.csv"
701
+ self.popen.split_like = [self.csv_path,self.csv_path]
702
+ self.popen.csv_path = None
703
+ self.popen.kfold_cv = False
704
+ self.popen.kfold_index = self.kfold_index
705
+ self.popen.pad_to = self.r
706
+ self.popen.seq_col = 'utr'
707
+ self.popen.aux_task_columns = ['rl']
708
+ return reader.get_dataloader(self.popen)
709
+
710
+ def extract_feature_map(self):
711
+
712
+ model, dataloader= self.loading('kmer', 1)
713
+
714
+ for l in range(self.layer):
715
+ # remove padding to precisely locate
716
+ model.soft_share.encoder[l][0][0].padding = (0,)
717
+
718
+ feature_map = []
719
+ X_ls = []
720
+ Y_ls = []
721
+
722
+ model.eval()
723
+ with torch.no_grad():
724
+ for Data in tqdm(dataloader):
725
+ # iter each batch
726
+ x,y = train_val.put_data_to_cuda(Data,self.popen,False)
727
+ x = torch.transpose(x, 1, 2)
728
+ # X_ls.append(x.numpy())
729
+ Y_ls.append( tensor_2_numpy(y) )
730
+
731
+ for layer in model.soft_share.encoder[:self.layer]:
732
+ out = layer(x)
733
+ x = out
734
+ feature_map.append( tensor_2_numpy(out) )
735
+
736
+ torch.cuda.empty_cache()
737
+
738
+
739
+ feature_map_l = np.concatenate( feature_map, axis=0)
740
+
741
+ # self.X_ls = np.concatenate(X_ls, axis=0)
742
+ self.Y_ls = np.concatenate(Y_ls, axis=0)
743
+
744
+ print("activation map of layer |%d|"%self.layer,feature_map_l.shape)
745
+ # print(self.X_ls.shape)
746
+ print("Y : ",self.Y_ls.shape)
747
+ self.feature_map = feature_map_l
748
+
749
+ self.filters = self.get_filter_param(model)
750
+
751
+ del model
752
+ self.df = pd.read_csv(self.csv_path)
753
+ return feature_map_l
754
+
755
+ def write_meme(channels:list, PWMs:list ,save_path, filter_prefix='filter'):
756
+ """
757
+ Save the position weight matrix as the meme-suite acceptale minimal motif format
758
+ """
759
+ assert len(channels)==len(PWMs)
760
+ with open(save_path, 'w') as f:
761
+ f.write("MEME version 5.4.1\n\n")
762
+ f.write("ALPHABET= ACGT\n\n")
763
+ f.write("strands: + -\n\n")
764
+ f.write("Background letter frequencies\n")
765
+ f.write("A 0.25 C 0.25 G 0.25 T 0.25\n")
766
+
767
+ for cc,M in zip(channels, PWMs):
768
+ f.write('\n')
769
+ f.write(f"MOTIF {filter_prefix}_{cc}\n")
770
+ seq_len = M.shape[0]
771
+ f.write(f"letter-probability matrix: alength= 4 w= {seq_len} \n")
772
+ for line in M.values:
773
+ f.write(" "+line.__str__()[1:-1]+'\n')
774
+
775
+
776
+ f.close()
777
+ print('writed to', save_path)
778
+
779
+ def extract_meme(memepath):
780
+ """
781
+ read the meme file and extract motifs to rewrite
782
+ """
783
+ with open(memepath,'r') as f:
784
+ all_lines = f.readlines()[9:]
785
+
786
+ all_blocks = []
787
+ for i, line in enumerate(all_lines):
788
+ if line.startswith("MOTIF"):
789
+ width = re.match(r"letter-probability matrix: alength= 4 w= (\d)*",all_lines[i+1]).groups(1)
790
+ width = int(width[0])
791
+
792
+ all_blocks.append( all_lines[i:i+3+width])
793
+
794
+ return all_blocks
795
+
model/src/mrl_te_optimization/models/popen.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import numpy as np
4
+ import utils
5
+ import json
6
+ from models import Modules
7
+ import configparser
8
+ import logging
9
+
10
+ class Auto_popen(object):
11
+ def __init__(self,config_file):
12
+ """
13
+ read the config_fiel
14
+ """
15
+ # machine config path
16
+ self.shuffle = True
17
+ self.script_dir = utils.script_dir
18
+ self.data_dir = utils.data_dir
19
+ self.data_dir = '/mnt/sina/run/ml/gan/motif/MTtrans/test.csv'
20
+ self.log_dir = utils.log_dir
21
+ self.pth_dir = utils.pth_dir
22
+ self.set_attr_as_none(['te_net_l2','loss_fn','modual_to_fix','other_input_columns','pretrain_pth','kfold_index'])
23
+ self.split_like = False
24
+ self.loss_schema = 'constant'
25
+
26
+ # transform to dict and convert to specific data type
27
+ self.config = configparser.ConfigParser()
28
+ self.config.read(config_file)
29
+ self.config_file = config_file
30
+ self.config_dict = {item[0]: eval(item[1]) for item in self.config.items('DEFAULT')}
31
+ print(self.config_dict)
32
+ # assign some attr from config_dict
33
+ self.set_attr_from_dict(self.config_dict.keys())
34
+ self.check_run_and_setting_name() # check run name
35
+ self._dataset = "_" + self.dataset if self.dataset != '' else self.dataset
36
+ # the saving direction
37
+ self.path_category = self.config_file.split('/')[-4]
38
+ self.vae_log_path = config_file.replace('.ini','.log')
39
+
40
+
41
+ self.Resumable = False
42
+
43
+ # covariates for other input
44
+ self.n_covar = len(self.other_input_columns) if self.other_input_columns is not None else 0
45
+
46
+ # generate self.model_args
47
+ self.get_model_config()
48
+
49
+ @property
50
+ def vae_pth_path(self):
51
+ save_to = os.path.join(self.pth_dir,self.model_type+self._dataset,self.setting_name)
52
+ if self.kfold_index is None:
53
+ pth = os.path.join(save_to, self.run_name + '-model_best.pth')
54
+ elif type(self.kfold_index) == int:
55
+ k = self.kfold_index
56
+ pth = os.path.join(save_to, self.run_name + f'-model_best_cv{k}.pth')
57
+ return pth
58
+
59
+ @vae_pth_path.setter
60
+ def vae_pth_path(self, path):
61
+ self._vae_pth_path = path
62
+
63
+ def set_attr_from_dict(self,attr_ls):
64
+ for attr in attr_ls:
65
+ self.__setattr__(attr,self.config_dict[attr])
66
+
67
+ def set_attr_as_none(self,attr_ls):
68
+ for attr in attr_ls:
69
+ self.__setattr__(attr,None)
70
+
71
+ def check_run_and_setting_name(self):
72
+ file_name = self.config_file.split("/")[-1]
73
+ dir_name = self.config_file.split("/")[-2]
74
+ self.setting_name = dir_name
75
+ assert self.run_name == file_name.split(".")[0]
76
+
77
+ def get_model_config(self):
78
+ """
79
+ assert we type in the correct model type and group them into model_args
80
+ """
81
+
82
+ if self.model_type in dir(Modules):
83
+ self.Model_Class = eval("Modules.{}".format(self.model_type))
84
+ else:
85
+ raise NameError("not such model type")
86
+
87
+ # conv_args define the soft-sharing part
88
+ conv_args = ["channel_ls","kernel_size","stride","padding_ls","diliation_ls","pad_to"]
89
+ self.conv_args = tuple([self.__getattribute__(arg) for arg in conv_args])
90
+
91
+ # left args dfine the tower part in which the arguments are different among tasks
92
+ left_args={# Backbone models
93
+ 'RL_regressor':["tower_width","dropout_rate"],
94
+ 'RL_clf':["n_class","tower_width","dropout_rate"],
95
+ 'RL_gru':["tower_width","dropout_rate"],
96
+ 'RL_FACS': ["tower_width","dropout_rate"],
97
+ 'RL_hard_share':["tower_width","dropout_rate", "activation","cycle_set" ],
98
+ 'RL_covar_reg':["tower_width","dropout_rate", "activation", "n_covar", "cycle_set" ],
99
+ 'RL_covar_intercept':["tower_width","dropout_rate", "activation", "n_covar", "cycle_set" ],
100
+ 'RL_mish_gru':["tower_width","dropout_rate"],
101
+ # GP models
102
+ 'GP_net': ['tower_width', 'dropout_rate', 'global_pooling', 'activation', 'cycle_set'],
103
+ 'Frame_GP': ['tower_width', 'dropout_rate', 'activation', 'cycle_set'],
104
+ 'RL_Atten': ['qk_dim', 'n_head', 'n_atten_layer', 'tower_width', 'dropout_rate', 'activation', 'cycle_set'],
105
+ # Koo net
106
+ 'Conf_CNN' : ['pool_size'],
107
+ }[self.model_type]
108
+
109
+ self.model_args = [self.conv_args] + [self.__getattribute__(arg) for arg in left_args]
110
+
111
+
112
+ def check_experiment(self,logger):
113
+ """
114
+ check any unfinished experiment ?
115
+ """
116
+ log_save_dir = os.path.dirname(self.vae_log_path)
117
+ pth_save_dir = os.path.join(self.pth_dir,self.model_type+self._dataset,self.setting_name)
118
+ # make dirs
119
+ if not os.path.exists(log_save_dir):
120
+ os.makedirs(log_save_dir)
121
+ if not os.path.exists(pth_save_dir):
122
+ os.makedirs(pth_save_dir)
123
+
124
+ # check resume
125
+ if os.path.exists(self.vae_log_path) & os.path.exists(self.vae_pth_path):
126
+ self.Resumable = True
127
+ logger.info(' \t \t ==============<<< Experiment detected >>>============== \t \t \n')
128
+
129
+ def update_ini_file(self,E,logger):
130
+ """
131
+ E is the dict contain the things to update
132
+ """
133
+ # update the ini file
134
+ self.config_dict.update(E)
135
+ strconfig = {K: repr(V) for K,V in self.config_dict.items()}
136
+ self.config['DEFAULT'] = strconfig
137
+
138
+ with open(self.config_file,'w') as f:
139
+ self.config.write(f)
140
+
141
+ logger.info(' ini file updated ')
142
+
143
+ def chimera_weight_update(self):
144
+ # TODO : progressively update the loss weight between tasks
145
+
146
+ # TODO : 1. scale the loss into the same magnitude
147
+
148
+ # TODO : 2. update the weight by their own learning progress
149
+
150
+ return None
model/src/mrl_te_optimization/models/reader.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import copy
4
+ sys.path.append(os.path.dirname(__file__))
5
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
6
+
7
+ import json
8
+ import torch
9
+ import numpy as np
10
+ import pandas as pd
11
+ from torch import nn
12
+
13
+ from Bio import SeqIO
14
+ from Bio.SeqRecord import SeqRecord
15
+
16
+ from torch.utils.data import DataLoader, Dataset ,random_split,IterableDataset
17
+ from sklearn.model_selection import KFold,train_test_split
18
+ from bucket_sampler import Bucket_Sampler
19
+ from utils import Seq_one_hot
20
+
21
+ global script_dir
22
+ global data_dir
23
+
24
+ with open(os.path.join(os.path.dirname(os.path.dirname(__file__)),"machine_configure.json"),'r') as f:
25
+ config = json.load(f)
26
+
27
+ script_dir = config['script_dir']
28
+ data_dir = config['data_dir']
29
+
30
+ def one_hot(seq,complementary=False):
31
+ """
32
+ one_hot encoding on sequence
33
+ complementary: encode nucleatide into complementary one
34
+ """
35
+ # setting
36
+ seq = list(seq.replace("U","T"))
37
+ seq_len = len(seq)
38
+ complementary = -1 if complementary else 1
39
+ # compose dict
40
+ keys = ['A', 'C', 'G', 'T'][::complementary]
41
+ oh_dict = {keys[i]:i for i in range(4)}
42
+ # array
43
+ oh_array = np.zeros((seq_len,4))
44
+ for i,C in enumerate(seq):
45
+ try:
46
+ oh_array[i,oh_dict[C]]=1
47
+ except:
48
+ continue # for nucleotide that are not in A C G T   
49
+ return oh_array
50
+
51
+ def read_bpseq(test_bpseq_path):
52
+ """
53
+ read bpseq file, extract sequence and ptable
54
+ """
55
+ with open(test_bpseq_path,'r') as f:
56
+ test_bpseq = f.readlines()
57
+ f.close()
58
+
59
+ for i in range(8):
60
+ if test_bpseq[i].startswith('1'):
61
+ start_index = i
62
+
63
+ bp_seq = test_bpseq[start_index:]
64
+
65
+ seq = ''.join([line.strip().split(" ")[1] for line in bp_seq])
66
+ ptable = [int(line.strip().split(" ")[2]) for line in bp_seq]
67
+
68
+ assert len(ptable) == int(bp_seq[-1].split(" ")[0])
69
+
70
+ return seq,ptable
71
+
72
+ def pad_zeros(X,pad_to):
73
+ """
74
+ zero padding at the right end of the sequence
75
+ """
76
+ if pad_to == 0:
77
+ # pad_to = 8*(X.shape[0]//8 + 1) + 1
78
+ try:
79
+ seq_len = X.shape[0]
80
+ except:
81
+ seq_len = X[0].shape[0]
82
+ pad_to = 3*(seq_len//3 + 1) + 1
83
+
84
+ seq_len = X.shape[0] if isinstance(X, np.ndarray) else X[0].shape[0]
85
+ gap = pad_to - seq_len
86
+
87
+ # here we change to padding ahead , previously nn.ZeroPad2d([0,0,0,gap])
88
+ pad_fn = nn.ZeroPad2d([0,0,gap,0]) # (padding_left , padding_right , padding_top , padding_bottom )
89
+ # gap_array = np.zeros()
90
+ if isinstance(X, list): # additional input
91
+ X_padded = [pad_fn(torch.tensor(X[0])), X[1]]
92
+ elif isinstance(X, np.ndarray):
93
+ X_padded = pad_fn(torch.tensor(X))
94
+ return X_padded
95
+
96
+ def pack_seq(ds_zls:list,pad_to:int):
97
+ X_ts = [X for X,Y in ds_zls]
98
+ if pad_to == 0:
99
+ try:
100
+ max_len = np.max([X.shape[0] for X in X_ts])
101
+ except:
102
+ max_len = np.max([X[0].shape[0] for X in X_ts])
103
+
104
+ pad_to = 3*(max_len//3 + 1) + 1
105
+
106
+ if isinstance(X_ts[0],np.ndarray):
107
+ X_packed = torch.stack([pad_zeros(X=x,pad_to=pad_to) for x in X_ts])
108
+ else:
109
+ X_packed = [torch.stack([pad_zeros(X=x[0],pad_to=pad_to) for x in X_ts]), torch.tensor([x[1] for x in X_ts])]
110
+ Y_packed = torch.tensor(np.array([Y for X,Y in ds_zls]))
111
+
112
+ return X_packed , Y_packed
113
+
114
+
115
+
116
+ class mask_reader(Dataset):
117
+ def __init__(self,npy_path):
118
+ """
119
+ read the mask A549 sequence and with real sequence
120
+ """
121
+ self.data_set = np.load(npy_path)
122
+ self.X = self.data_set[:,0]
123
+ self.Y = self.data_set[:,1]
124
+
125
+ def __len__(self):
126
+ return self.X.shape[0]
127
+
128
+ def __getitem__(self,index):
129
+ return (self.X[index,:,:],self.Y[index,:,:])
130
+
131
+ class mix_dataset(Dataset):
132
+ def __init__(self):
133
+ # dataset_ls = [mask_reader(os.path.join(data_dir,'mix_data',"mix_%s.npy"%set)) for set in ['train','val','test']]
134
+ raise ValueError("the dataset is not defined")
135
+
136
+ class mask_dataset(Dataset):
137
+ def __init__(self):
138
+ raise ValueError("the dataset is not defined")
139
+
140
+ class ribo_dataset(Dataset):
141
+
142
+ def __init__(self,DF, pad_to, trunc_len=50, seq_col='utr',
143
+ aux_columns='TE_count', other_input_columns=None):
144
+ """
145
+ Dataset to trancate sequence and return in one-hot encoding way
146
+ `dataset(DF,pad_to,trunc_len=50,seq_col='utr')`
147
+ ...DF: the dataframe contain sequence and its meta-info
148
+ ...pad_to: final size of the output tensor
149
+ ...trunc_len: maximum sequence to retain. number of nt preceding AUG
150
+ ...seq_col : which col of the DF contain sequence to convert
151
+ """
152
+ DF[seq_col] = DF[seq_col].astype(str)
153
+ self.df = DF
154
+ self.pad_to = pad_to
155
+ self.trunc_len = 0 if trunc_len is None else trunc_len
156
+
157
+ # X and Y
158
+ self.seqs = self.df.loc[:,seq_col].values
159
+ self.other_input_columns = other_input_columns
160
+ self.Y = self.df.loc[:,aux_columns].values
161
+
162
+ def __len__(self):
163
+ return self.df.shape[0]
164
+
165
+ def __getitem__(self,i):
166
+ seq = self.seqs[i]
167
+ x_padded = self.seq_chunk_N_oh(seq)
168
+ input = x_padded
169
+ if self.other_input_columns is not None:
170
+ input = [x_padded]
171
+ for col in self.other_input_columns:
172
+ input.append(self.df.loc[:,col].values[i])
173
+ y = self.Y[i]
174
+ return input,y
175
+
176
+ def seq_chunk_N_oh(self,seq):
177
+ """
178
+ truncate the sequence and encode in one hot
179
+ """
180
+ if (len(seq) > self.trunc_len)&(self.trunc_len >0):
181
+ seq = seq[-1* self.trunc_len:]
182
+
183
+ X = one_hot(seq)
184
+ X = torch.tensor(X)
185
+
186
+ # X_padded = pad_zeros(X, self.pad_to)
187
+
188
+ return X.float()
189
+
190
+
191
+ class MTL_dataset(Dataset):
192
+ def __init__(self, DF, pad_to=100, seq_col='utr', aux_columns=None,
193
+ other_input_columns=None, trunc_len=None):
194
+ """
195
+ the dataset for Multi-task learning, will return sequence in one-hot encoded version, together with some auxilary task label
196
+ arguments:
197
+ ...csv_path: abs path of csv file, column `utr` should be in the csv
198
+ ...pad_to : maximum length of the sequences
199
+ ...columns : list contains what axuslary task label will be
200
+ """
201
+ self.pad_to = pad_to
202
+ self.trunc_len = trunc_len
203
+ DF[seq_col] = DF[seq_col].astype(str)
204
+ self.df = DF # read Df
205
+ self.seqs = self.df[seq_col].values # take out all the sequence in DF
206
+ self.columns = aux_columns
207
+ self.other_input_columns = other_input_columns
208
+
209
+ assert trunc_len == None, "MTL dataset does not support argument trunc len"
210
+
211
+ def __len__(self):
212
+ return self.df.shape[0]
213
+
214
+ def __getitem__(self,index):
215
+ seq = self.seqs[index] # sequence: str of len 25~100
216
+
217
+ X = one_hot(seq).astype(float) # seq_oh : np array, one hot encoding sequence
218
+ # X = pad_zeros(X) # X : torch.tensor , zero padded to 100
219
+
220
+ if self.columns == None:
221
+ # which means no auxilary label is needed
222
+ item = X ,X
223
+ elif (type(self.columns) == list) & (len(self.columns)!=0):
224
+ # return what's in columns
225
+ aux_labels = self.df.loc[:,self.columns].values[index]
226
+ # if len(self.columns) == 1:
227
+ # aux_labels = aux_labels.reshape(-1,1)
228
+ item = X ,aux_labels
229
+
230
+ if self.other_input_columns is not None:
231
+ input = []
232
+ for col in self.other_input_columns:
233
+ input.append(self.df.loc[:,col].values[index])
234
+ item = (X, input),aux_labels
235
+
236
+ return item
237
+
238
+ class kmer_scan_dataset(Dataset):
239
+ def __init__(self, DF, seq_col, kmer_size, aux_columns=None, *args):
240
+ super().__init__()
241
+ self.df = DF
242
+ self.seqs = DF[seq_col].values
243
+ self.rls = DF[aux_columns].values
244
+ self.k = kmer_size
245
+ self.kmer_sets = self.create_kmer()
246
+ self.kmer_lookup = { kmer : i for i, kmer in enumerate(self.kmer_sets) }
247
+
248
+ def __len__(self):
249
+ return self.df.shape[0]
250
+
251
+ def __getitem__(self, index):
252
+ seq = self.seqs[index]
253
+ y = self.rls[index]
254
+
255
+ x = self.scan_kmer(seq)
256
+ return torch.tensor(x.astype(float)), torch.tensor(y)
257
+
258
+ def scan_kmer(self, seq):
259
+
260
+ mat = np.zeros((len(self.kmer_lookup), len(seq)-self.k))
261
+ for i in range(0, len(seq)-self.k):
262
+ seq_let = seq[i:i+self.k]
263
+ mat[self.kmer_lookup[seq_let], i] = 1
264
+
265
+ return mat
266
+
267
+
268
+ def create_kmer(self):
269
+ all_kmer = {0:['']}
270
+ k = 1
271
+ while k <= self.k:
272
+ k_mer = [] # 1 ; 4 ; 2: 4**2 ...
273
+ for source in all_kmer[k-1]:
274
+ k_mer += [source + base for base in ['A','C','G','T']]
275
+
276
+ assert len(k_mer) == 4**k, f"new kmers {len(k_mer)}, not equal to {4**k}"
277
+ all_kmer[k] = k_mer
278
+ k += 1
279
+
280
+ all_kmer.pop(0)
281
+ return all_kmer[self.k]
282
+
283
+
284
+
285
+
286
+ class FASTA_dataset(MTL_dataset):
287
+ def __init__(self,DF, pad_to,trunc_len, seq_col, aux_columns, other_input_columns):
288
+ super().__init__(DF=DF, pad_to=pad_to, trunc_len=trunc_len, seq_col=seq_col,
289
+ aux_columns=aux_columns, other_input_columns=other_input_columns)
290
+
291
+ def get_splited_dataloader(dataset_func, df_ls, ratio:list, batch_size, shuffle, pad_to, seed=42,return_dataset=False):
292
+ """
293
+ split the total dataset into train val test, and return in a DataLoader (train_loader,val_loader,test_loader)
294
+ dataset : the defined <UTR_dataset>
295
+ ratio : the ratio of train : val : test
296
+ batch_size : int
297
+ """
298
+
299
+ # determined set-ls
300
+
301
+ set_ls = [dataset_func(df) for df in df_ls]
302
+ if return_dataset:
303
+ return set_ls
304
+
305
+ if pad_to == 0 :
306
+ # automatic padding to `8x -1`
307
+ # and we will pad the sequence of similar length with bucket sampler
308
+ col_fn = lambda x: pack_seq(x,0)
309
+ sampler_ls = [{"batch_sampler":Bucket_Sampler(df,batch_size=batch_size,drop_last=True),
310
+ "num_workers":4,
311
+ "drop_last":False,
312
+ "collate_fn":col_fn} for df in df_ls]
313
+ # wrap dataset to dataloader
314
+ loader_ls = [DataLoader(subset,**kwargs) for subset,kwargs in zip(set_ls,sampler_ls)]
315
+ else:
316
+ col_fn = lambda x: pack_seq(x,pad_to)
317
+ loaderargs = {"batch_size": batch_size,
318
+ "generator":torch.Generator().manual_seed(42),
319
+ "drop_last":False ,
320
+ "num_workers":4,
321
+ "shuffle":shuffle,
322
+ "collate_fn":col_fn}
323
+ # wrap dataset to dataloader
324
+ loader_ls = [DataLoader(subset,**loaderargs) for subset in set_ls]
325
+
326
+ if len(loader_ls) == 2:
327
+ # a complement of empty test set
328
+ loader_ls.append(None)
329
+
330
+ return loader_ls
331
+
332
+ def split_DF(data_path,split_like,ratio, kfold_cv, kfold_index=None,seed=42):
333
+
334
+ class _cf_data(object):
335
+ def __init__(self,data_path):
336
+ self.path = data_path
337
+ self.is_fasta = data_path.endswith('.fasta')
338
+ self.__read__()
339
+
340
+ def __read__(self):
341
+ if self.is_fasta:
342
+ self.data = list(SeqIO.parse(self.path,'fasta'))
343
+ else:
344
+ self.data = pd.read_csv(os.path.join(data_dir,self.path),low_memory=False)
345
+
346
+ def __len__(self):
347
+ return len(self.data)
348
+
349
+ def _slice_(self, indices):
350
+ if isinstance(self.data, list) & self.is_fasta:
351
+ return np.array(self.data)[indices]
352
+ elif isinstance(self.data, pd.DataFrame):
353
+ return self.data.iloc[indices]
354
+
355
+
356
+ if kfold_cv == True:
357
+ full_df = pd.read_csv(os.path.join(data_dir,data_path),low_memory=False)
358
+ # K-fold CV : 8:1:1 for each partition
359
+ df_ls = KFold_df_split(full_df,kfold_index)
360
+
361
+ if kfold_cv == 'train_val':
362
+ train_val, test = [_cf_data(data_path).data for data_path in split_like]
363
+ # K-fold CV : 8:1:1 for each partition
364
+ train, val = KFold_1_split(train_val,kfold_index)
365
+ df_ls = [train, val , test]
366
+
367
+ elif type(split_like) == list:
368
+ df_ls = [_cf_data(data_path).data for data_path in split_like]
369
+
370
+ elif type(kfold_cv) == str:
371
+ full_df = pd.read_csv(os.path.join(data_dir,data_path),low_memory=False)
372
+ if kfold_cv in full_df.columns:
373
+ kfold_index = str(kfold_index)
374
+ test = full_df.query(f"`{kfold_cv}` == @kfold_index")
375
+ train_val = full_df.query(f"`{kfold_cv}` != @kfold_index")
376
+ train, val = train_test_split(train_val, test_size=0.05)
377
+ df_ls = [train, val, test]
378
+
379
+ else:
380
+ full_df = _cf_data(data_path)
381
+ # POPEN.ratio will determine train :val :test ratio
382
+ total_len = len(full_df)
383
+ lengths = [int(total_len*sub_ratio) for sub_ratio in ratio[:-1]]
384
+ lengths.append(total_len-sum(lengths)) # make sure the sum of length is the total len
385
+
386
+ set_ls = random_split(full_df,lengths,generator=torch.Generator().manual_seed(seed))
387
+ df_ls = [full_df._slice_(subset.indices) for subset in set_ls] # df.iloc [ idx ]
388
+
389
+ return df_ls
390
+
391
+ def split_DF_call(data_path,split_like,ratio, kfold_cv, kfold_index=None,seed=42):
392
+
393
+ class _cf_data(object):
394
+ def __init__(self,data_path):
395
+ self.path = data_path
396
+ self.is_fasta = data_path.endswith('.fasta')
397
+ self.__read__()
398
+
399
+ def __read__(self):
400
+ if self.is_fasta:
401
+ self.data = list(SeqIO.parse(self.path,'fasta'))
402
+ else:
403
+ self.data = pd.read_csv(os.path.join(data_dir,self.path),low_memory=False)
404
+
405
+ def __len__(self):
406
+ return len(self.data)
407
+
408
+ def _slice_(self, indices):
409
+ if isinstance(self.data, list) & self.is_fasta:
410
+ return np.array(self.data)[indices]
411
+ elif isinstance(self.data, pd.DataFrame):
412
+ return self.data.iloc[indices]
413
+
414
+
415
+ if kfold_cv == True:
416
+ full_df = pd.read_csv(os.path.join(data_dir,data_path),low_memory=False)
417
+ # K-fold CV : 8:1:1 for each partition
418
+ df_ls = KFold_df_split(full_df,kfold_index)
419
+
420
+ if kfold_cv == 'train_val':
421
+ train_val, test = [_cf_data(data_path).data for data_path in split_like]
422
+ # K-fold CV : 8:1:1 for each partition
423
+ train, val = KFold_1_split(train_val,kfold_index)
424
+ df_ls = [train, val , test]
425
+
426
+ elif type(split_like) == list:
427
+ df_ls = [_cf_data(data_path).data for data_path in split_like]
428
+
429
+ elif type(kfold_cv) == str:
430
+ full_df = pd.read_csv(os.path.join(data_dir,data_path),low_memory=False)
431
+ if kfold_cv in full_df.columns:
432
+ kfold_index = str(kfold_index)
433
+ test = full_df.query(f"`{kfold_cv}` == @kfold_index")
434
+ train_val = full_df.query(f"`{kfold_cv}` != @kfold_index")
435
+ train, val = train_test_split(train_val, test_size=0.05)
436
+ df_ls = [train, val, test]
437
+
438
+ else:
439
+ full_df = _cf_data(data_path)
440
+ # POPEN.ratio will determine train :val :test ratio
441
+ total_len = len(full_df)
442
+ lengths = [int(total_len*sub_ratio) for sub_ratio in ratio[:-1]]
443
+ lengths.append(total_len-sum(lengths)) # make sure the sum of length is the total len
444
+
445
+ set_ls = random_split(full_df,lengths,generator=torch.Generator().manual_seed(seed))
446
+ df_ls = [full_df._slice_(subset.indices) for subset in set_ls] # df.iloc [ idx ]
447
+
448
+ return df_ls
449
+
450
+
451
+ def KFold_df_split(df,K,**kfoldargs):
452
+ """
453
+ split the dataset DF in a ratio of 8:1:1 , train:val:test in the framework of K-fold CV
454
+ set random seed = 43
455
+ arguments:
456
+ df : the `pd.DataFrame` object containing all data info
457
+ K : [0,4] , the index of subfold
458
+ """
459
+
460
+ # K-fold partition : n_splits=5
461
+ fold_index = list(KFold(10,shuffle=True,random_state=42).split(df))
462
+ train_val_index, test_index = fold_index[K]
463
+ # the first 4/5 part of it is train set
464
+
465
+ # index the df
466
+ train_val_df = df.iloc[train_val_index]
467
+ test_df = df.iloc[test_index]
468
+
469
+ # the remaining 1/5 data will further break into val and test
470
+ train_df, val_df = train_test_split(train_val_df,test_size=0.05,random_state=42)
471
+
472
+ return [train_df,val_df,test_df]
473
+
474
+ def KFold_1_split(df,K,**kfoldargs):
475
+ """
476
+ for dataset with standard test set, where only train_val can be splited
477
+ """
478
+ fold_index = list(KFold(10,shuffle=True,random_state=42).split(df))
479
+ train_index, val_index = fold_index[K]
480
+ # the first 4/5 part of it is train set
481
+
482
+ # index the df
483
+ train = df.iloc[train_index]
484
+ val = df.iloc[val_index]
485
+
486
+ return train , val
487
+
488
+ def get_dataloader(POPEN):
489
+ """
490
+ wrapper
491
+ """
492
+
493
+ # POPEN.csv_path = "/mnt/sina/run/ml/gan/motif/MTtrans/test.csv"
494
+ # print(POPEN.csv_path)
495
+ # print(POPEN.split_like)
496
+ # print(POPEN.train_test_ratio)
497
+ # print(POPEN.kfold_cv)
498
+ # print(POPEN.kfold_index)
499
+ df_ls = split_DF(POPEN.csv_path,POPEN.split_like,POPEN.train_test_ratio,POPEN.kfold_cv,POPEN.kfold_index,seed=42)
500
+
501
+
502
+ DS_Class = eval(POPEN.dataset+"_dataset")
503
+
504
+ dataset_func = lambda x : DS_Class(x,pad_to=POPEN.pad_to,trunc_len=POPEN.trunc_len,
505
+ seq_col=POPEN.seq_col, aux_columns=POPEN.aux_task_columns,
506
+ other_input_columns=POPEN.other_input_columns)
507
+
508
+ loader_ls = get_splited_dataloader(dataset_func, df_ls,ratio=POPEN.train_test_ratio,
509
+ batch_size=POPEN.batch_size, shuffle=POPEN.shuffle,
510
+ pad_to=POPEN.pad_to, seed=42) # new function
511
+
512
+ return loader_ls
model/src/mrl_te_optimization/models/train_val.py ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import time
4
+ import numpy as np
5
+ import pandas as pd
6
+ import logging
7
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
8
+ import utils
9
+ import torch
10
+ from scipy.stats import pearsonr
11
+ from torch import optim
12
+ from sklearn.metrics import r2_score, f1_score, roc_auc_score
13
+ from models.ScheduleOptimizer import ScheduledOptim , find_lr
14
+ from models.loss import Dynamic_Task_Priority as DTP
15
+
16
+ def train(dataloader,model,optimizer,popen,epoch,lr=None, verbose=True):
17
+
18
+ logger = logging.getLogger("VAE")
19
+ loader_len = len(dataloader) # number of iteration
20
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
21
+
22
+ model = model.to(device)
23
+
24
+ model.train()
25
+ verbose_list=[]
26
+ verbose_df = pd.DataFrame()
27
+ for idx,data in enumerate(dataloader):
28
+
29
+ X,Y = put_data_to_cuda(data,popen,require_grad=True)
30
+ optimizer.zero_grad()
31
+
32
+ out = model(X)
33
+
34
+ loss_dict = model.compute_loss(out,X,Y,popen)
35
+ loss = loss_dict['Total']
36
+ acc_dict = model.compute_acc(out,X,Y,popen)
37
+ loss_dict.update(acc_dict) # adding the acc ditc into loss dict
38
+
39
+ loss.backward()
40
+ optimizer.step()
41
+
42
+ # ====== update lr =======
43
+ if type(optimizer) == ScheduledOptim:
44
+ lr = optimizer.update_learning_rate() # see model.optim.py
45
+ loss_dict["lr"]=lr
46
+ elif popen.optimizer == 'Adam':
47
+ lr = optimizer.param_groups[0]['lr']
48
+ if popen.loss_schema != 'constant':
49
+ popen.chimerla_weight = popen.loss_schedualer._update(loss_dict)
50
+ for t in popen.tasks:
51
+ loss_dict[popen.loss_schema+"_wt_"+t] = popen.chimerla_weight[t]
52
+
53
+ with torch.no_grad():
54
+ loss_dict= utils.clean_value_dict(loss_dict)
55
+ verbose_list.append(loss_dict)
56
+
57
+ # ======== verbose ========
58
+ # record result 5 times for a epoch
59
+ if verbose:
60
+ if idx % int(loader_len/5) == 0:
61
+
62
+ # plot that in loss dict
63
+ loss_dict_keys = list(loss_dict.keys())
64
+
65
+ train_verbose = "{:5d} / {:5d} ({:s}%):"
66
+ verbose_args = [idx,loader_len,str(int(idx/loader_len*100)).zfill(3)]
67
+ for key in loss_dict_keys:
68
+ train_verbose += "\t %s:{:.7f}"%key
69
+ verbose_args.append(loss_dict[key])
70
+
71
+ # plot the cumulative mean total loss
72
+ short_batch_df = pd.json_normalize(verbose_list) # this will be cumulative
73
+ mean_total = short_batch_df.loc[:,'Total'].mean()
74
+ train_verbose += "\t %s:{:.7f}"%"Mean_Total"
75
+ verbose_args.append(mean_total)
76
+
77
+ train_verbose = train_verbose.format(*verbose_args)
78
+
79
+ logger.info(train_verbose)
80
+ if popen.cuda_id != torch.device('cpu'):
81
+ with torch.cuda.device(popen.cuda_id):
82
+ torch.cuda.empty_cache()
83
+
84
+ def validate(dataloader,model,popen,epoch):
85
+
86
+ logger = logging.getLogger("VAE")
87
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
88
+
89
+ model = model.to(device)
90
+ model.teacher_forcing = False # turn off teacher_forcing
91
+
92
+ # ====== set up empty =====
93
+ verbose_list=[]
94
+ Y_ls = []
95
+ pred_ls = []
96
+ metric_dict = {}
97
+ # ======== evaluate =======
98
+ model.eval()
99
+ with torch.no_grad():
100
+ for idx,data in enumerate(dataloader):
101
+ X,Y = put_data_to_cuda(data,popen,require_grad=False)
102
+ Y_ls.append(Y.cpu().numpy())
103
+ out = model(X)
104
+ pred_ls.append(out.cpu().numpy())
105
+ loss_dict = model.compute_loss(out,X,Y,popen)
106
+ loss = loss_dict['Total']
107
+ acc_dict = model.compute_acc(out,X,Y,popen)
108
+ loss_dict.update(acc_dict)
109
+
110
+ loss_dict = utils.clean_value_dict(loss_dict) # convert possible torch to single item
111
+ verbose_list.append(loss_dict)
112
+
113
+ if popen.cuda_id != torch.device('cpu'):
114
+ with torch.cuda.device(popen.cuda_id):
115
+ torch.cuda.empty_cache()
116
+
117
+ # # average among batch
118
+
119
+ # ======== verbose ========
120
+ Y_ay = np.concatenate(Y_ls,axis=0).flatten()
121
+ pred_ay = np.concatenate(pred_ls,axis=0).flatten()
122
+
123
+ if popen.model_type == 'RL_clf':
124
+ metric_dict["F1"] = f1_score(Y_ay, pred_ay>0.5, average='binary')
125
+ metric_dict["AUROC"] = roc_auc_score(Y_ay, pred_ay)
126
+ else:
127
+ metric_dict[f"r2"] = r2_score(Y_ay, pred_ay)
128
+ metric_dict[f"pr"] = pearsonr(Y_ay, pred_ay)[0]
129
+
130
+ verbose_df = pd.json_normalize(verbose_list)
131
+
132
+ val_verbose = ""
133
+ verbose_args = []
134
+ verbose_dict = {key:verbose_df[key].mean() for key in verbose_df.columns}
135
+ verbose_dict.update(metric_dict)
136
+
137
+ for key,values in verbose_dict.items():
138
+ val_verbose += "\t %s:{:.7f}"%key
139
+ verbose_args.append(values)
140
+
141
+ val_verbose = val_verbose.format(*verbose_args)
142
+
143
+ logger.info(val_verbose)
144
+
145
+ # what avg acc return : mean of RL_Acc , Recons_Acc, Motif_Acc
146
+ acc_col = list(acc_dict.keys())
147
+ Avg_acc = np.mean(verbose_df.loc[:,acc_col].mean(axis=0))
148
+
149
+ # return these to save current performance
150
+ return (verbose_df['Total'].mean(),Avg_acc) if 'RL_loss' not in verbose_df.keys() else (verbose_df['RL_loss'].mean(),verbose_df['RL_Acc'].mean())
151
+
152
+ def iter_train(loader_dict, model, optimizer, popen, epoch, verbose=True):
153
+
154
+ logger = logging.getLogger("VAE")
155
+ # loader_len = len(dataloader) # number of iteration
156
+ all_len = [len(loader[0]) for loader in loader_dict.values()]
157
+ max_len = np.max(all_len)
158
+ n_task = len(popen.cycle_set)
159
+ total_len = max_len*n_task
160
+
161
+ all_train = {task : iter(loader[0]) for task,loader in loader_dict.items()}
162
+ def try_next(all_train, task):
163
+ try:
164
+ data = next(all_train[task])
165
+ return data
166
+ except StopIteration:
167
+ all_train[task] = iter(loader_dict[task][0])
168
+ data = next(all_train[task])
169
+ return data
170
+
171
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
172
+ model = model.to(device)
173
+ model.train()
174
+
175
+ verbose_list=[]
176
+ for idx in range(total_len):
177
+ task = popen.cycle_set[idx%n_task]
178
+ model.task = task
179
+
180
+ data = try_next(all_train, task)
181
+
182
+ X,Y = put_data_to_cuda(data,popen,require_grad=True)
183
+ optimizer.zero_grad()
184
+
185
+ out = model(X)
186
+ loss_dict = model.compute_loss(out,X,Y,popen)
187
+ loss = loss_dict['Total']
188
+ acc_dict = model.compute_acc(out,X,Y,popen)
189
+ loss_dict.update(acc_dict) # adding the acc ditc into loss dict
190
+
191
+ loss.backward()
192
+ optimizer.step()
193
+
194
+ # ====== update lr =======
195
+ if type(optimizer) == ScheduledOptim:
196
+ lr = optimizer.update_learning_rate() # see model.optim.py
197
+ loss_dict["lr"]=lr
198
+ elif popen.optimizer == 'Adam':
199
+ lr = optimizer.param_groups[0]['lr']
200
+ if popen.loss_schema != 'constant':
201
+ popen.chimerla_weight = popen.loss_schedualer._update(loss_dict)
202
+ for t in popen.tasks:
203
+ loss_dict[popen.loss_schema+"_wt_"+t] = popen.chimerla_weight[t]
204
+
205
+ with torch.no_grad():
206
+ loss_dict= utils.clean_value_dict(loss_dict)
207
+ verbose_list.append(loss_dict)
208
+
209
+ # ======== verbose ========
210
+ # record result 5 times for a epoch
211
+ if verbose:
212
+ if idx % int(total_len/5) == 0:
213
+
214
+ # plot that in loss dict
215
+ loss_dict_keys = list(loss_dict.keys())
216
+
217
+ train_verbose = "{:5d} / {:5d} ({:s}%):"
218
+ verbose_args = [idx,total_len,str(int(idx/total_len*100)).zfill(3)]
219
+ for key in loss_dict_keys:
220
+ train_verbose += "\t %s:{:.7f}"%key
221
+ verbose_args.append(loss_dict[key])
222
+
223
+ # plot the cumulative mean total loss
224
+ short_batch_df = pd.json_normalize(verbose_list) # this will be cumulative
225
+ mean_total = short_batch_df.loc[:,'Total'].mean()
226
+ train_verbose += "\t %s:{:.7f}"%"Mean_Total"
227
+ verbose_args.append(mean_total)
228
+
229
+ train_verbose = train_verbose.format(*verbose_args)
230
+
231
+ logger.info(train_verbose)
232
+
233
+ if popen.cuda_id != torch.device('cpu'):
234
+ with torch.cuda.device(popen.cuda_id):
235
+ torch.cuda.empty_cache()
236
+
237
+ def cycle_validate(loader_dict, model, optimizer, popen, epoch , which_set=1, return_=False):
238
+
239
+ logger = logging.getLogger("VAE")
240
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
241
+
242
+ model = model.to(device)
243
+
244
+ # ====== set up empty =====
245
+ # model.loss_dict_keys = ['RL_loss', 'Recons_loss', 'Motif_loss', 'Total', 'RL_Acc', 'Recons_Acc', 'Motif_Acc']
246
+ verbose_list=[]
247
+ r2_dict = {}
248
+ Y_n_pred = {}
249
+ # ======== evaluate =======
250
+
251
+
252
+ for subset, dataloader in loader_dict.items():
253
+
254
+ # fix
255
+ model.task = subset
256
+ # # logger.info(" =======================| fix |======================= ")
257
+ # model = utils.fix_parameter(model, popen.modual_to_fix[0])
258
+ # train(dataloader[0], model, optimizer, popen, epoch, verbose=True)
259
+ Y_ls = []
260
+ pred_ls = []
261
+ with torch.no_grad():
262
+ model.eval()
263
+ for idx,data in enumerate(dataloader[which_set]):
264
+ X,Y = put_data_to_cuda(data,popen,require_grad=False)
265
+ out = model(X)
266
+
267
+ Y_ls.append(Y.detach().cpu().numpy())
268
+ pred_ls.append(out.detach().cpu().numpy())
269
+
270
+ loss_dict = model.compute_loss(out,X,Y,popen)
271
+ loss_dict['%s_loss'%subset] = loss_dict['Total']
272
+ acc_dict = model.compute_acc(out,X,Y,popen)
273
+ loss_dict.update(acc_dict)
274
+
275
+ loss_dict = utils.clean_value_dict(loss_dict) # convert possible torch to single item
276
+ verbose_list.append(loss_dict)
277
+
278
+ if popen.cuda_id != torch.device('cpu'):
279
+ with torch.cuda.device(popen.cuda_id):
280
+ torch.cuda.empty_cache()
281
+
282
+ Y_ay = np.concatenate(Y_ls,axis=0).flatten()
283
+ pred_ay = np.concatenate(pred_ls,axis=0).flatten()
284
+ if return_:
285
+ Y_n_pred[subset] = (Y_ay, pred_ay)
286
+ r2_dict[f"{subset}_r2"] = r2_score(Y_ay, pred_ay)
287
+ r2_dict[f"{subset}_pr"] = pearsonr(Y_ay, pred_ay)[0]
288
+
289
+ # # average among batch
290
+
291
+ # ======== verbose ========
292
+
293
+ verbose_df = pd.json_normalize(verbose_list)
294
+
295
+ val_verbose = ""
296
+ verbose_args = []
297
+ verbose_dict = {key:verbose_df[key].mean() for key in verbose_df.columns}
298
+ verbose_dict.update(r2_dict)
299
+ for key,values in verbose_dict.items():
300
+ val_verbose += "\t %s:{:.7f}"%key
301
+ verbose_args.append(values)
302
+
303
+ val_verbose = val_verbose.format(*verbose_args)
304
+
305
+ logger.info(val_verbose)
306
+
307
+ # what avg acc return : mean of RL_Acc , Recons_Acc, Motif_Acc
308
+ acc_col = list(acc_dict.keys())
309
+ Avg_acc = np.mean(verbose_df.loc[:,acc_col].mean(axis=0))
310
+
311
+ if return_:
312
+ return verbose_dict, Y_n_pred
313
+ else:
314
+ return verbose_dict
315
+
316
+
317
+ def put_data_to_cuda(data,popen,require_grad=True):
318
+
319
+ X,y = data
320
+ device = popen.cuda_id
321
+ # for X is a list [seq, uAUG ....]
322
+ if popen.other_input_columns is not None:
323
+ X = [x_i.float().to(device) for x_i in X]
324
+ if require_grad:
325
+ for x_i in X:
326
+ x_i.required_grad = True
327
+
328
+ # X is not a list : seq
329
+ else:
330
+ X = X.float().to(device)
331
+ if require_grad:
332
+ X.required_grad = True # check !!!
333
+
334
+ Y = y.float().to(device)
335
+
336
+ # Y = Y if X.shape == Y.shape else None # for mask data
337
+ return X,Y
model/src/mrl_te_optimization/popen.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import numpy as np
4
+ import utils
5
+ import json
6
+ from models import Modules
7
+ import configparser
8
+ import logging
9
+
10
+ class Auto_popen(object):
11
+ def __init__(self,config_file):
12
+ """
13
+ read the config_fiel
14
+ """
15
+ # machine config path
16
+ self.shuffle = True
17
+ self.script_dir = utils.script_dir
18
+ self.data_dir = utils.data_dir
19
+ self.log_dir = utils.log_dir
20
+ self.pth_dir = utils.pth_dir
21
+ self.set_attr_as_none(['te_net_l2','loss_fn','modual_to_fix','other_input_columns','pretrain_pth','kfold_index'])
22
+ self.split_like = False
23
+ self.loss_schema = 'constant'
24
+
25
+ # transform to dict and convert to specific data type
26
+ self.config = configparser.ConfigParser()
27
+ self.config.read(config_file)
28
+ self.config_file = config_file
29
+ self.config_dict = {item[0]: eval(item[1]) for item in self.config.items('DEFAULT')}
30
+
31
+ # assign some attr from config_dict
32
+ self.set_attr_from_dict(self.config_dict.keys())
33
+ self.check_run_and_setting_name() # check run name
34
+ self._dataset = "_" + self.dataset if self.dataset != '' else self.dataset
35
+ # the saving direction
36
+ self.path_category = self.config_file.split('/')[-4]
37
+ self.vae_log_path = config_file.replace('.ini','.log')
38
+
39
+
40
+ self.Resumable = False
41
+
42
+ # covariates for other input
43
+ self.n_covar = len(self.other_input_columns) if self.other_input_columns is not None else 0
44
+
45
+ # generate self.model_args
46
+ self.get_model_config()
47
+
48
+ @property
49
+ def vae_pth_path(self):
50
+ save_to = os.path.join(self.pth_dir,self.model_type+self._dataset,self.setting_name)
51
+ if self.kfold_index is None:
52
+ pth = os.path.join(save_to, self.run_name + '-model_best.pth')
53
+ elif type(self.kfold_index) == int:
54
+ k = self.kfold_index
55
+ pth = os.path.join(save_to, self.run_name + f'-model_best_cv{k}.pth')
56
+ return pth
57
+
58
+ @vae_pth_path.setter
59
+ def vae_pth_path(self, path):
60
+ self._vae_pth_path = path
61
+
62
+ def set_attr_from_dict(self,attr_ls):
63
+ for attr in attr_ls:
64
+ self.__setattr__(attr,self.config_dict[attr])
65
+
66
+ def set_attr_as_none(self,attr_ls):
67
+ for attr in attr_ls:
68
+ self.__setattr__(attr,None)
69
+
70
+ def check_run_and_setting_name(self):
71
+ file_name = self.config_file.split("/")[-1]
72
+ dir_name = self.config_file.split("/")[-2]
73
+ self.setting_name = dir_name
74
+ assert self.run_name == file_name.split(".")[0]
75
+ # assert self.run_name == file_name.split(".")[0]
76
+
77
+ def get_model_config(self):
78
+ """
79
+ assert we type in the correct model type and group them into model_args
80
+ """
81
+ self.model_type = 'RL_hard_share'
82
+ if self.model_type in dir(Modules):
83
+ self.Model_Class = eval("Modules.{}".format(self.model_type))
84
+ else:
85
+ raise NameError("not such model type")
86
+
87
+ # conv_args define the soft-sharing part
88
+ conv_args = ["channel_ls","kernel_size","stride","padding_ls","diliation_ls","pad_to"]
89
+ self.conv_args = tuple([self.__getattribute__(arg) for arg in conv_args])
90
+
91
+ # left args dfine the tower part in which the arguments are different among tasks
92
+ left_args={# Backbone models
93
+ 'RL_regressor':["tower_width","dropout_rate"],
94
+ 'RL_clf':["n_class","tower_width","dropout_rate"],
95
+ 'RL_gru':["tower_width","dropout_rate"],
96
+ 'RL_FACS': ["tower_width","dropout_rate"],
97
+ 'RL_hard_share':["tower_width","dropout_rate", "activation","cycle_set" ],
98
+ 'RL_covar_reg':["tower_width","dropout_rate", "activation", "n_covar", "cycle_set" ],
99
+ 'RL_covar_intercept':["tower_width","dropout_rate", "activation", "n_covar", "cycle_set" ],
100
+ 'RL_mish_gru':["tower_width","dropout_rate"],
101
+ # GP models
102
+ 'GP_net': ['tower_width', 'dropout_rate', 'global_pooling', 'activation', 'cycle_set'],
103
+ 'Frame_GP': ['tower_width', 'dropout_rate', 'activation', 'cycle_set'],
104
+ 'RL_Atten': ['qk_dim', 'n_head', 'n_atten_layer', 'tower_width', 'dropout_rate', 'activation', 'cycle_set'],
105
+ # Koo net
106
+ 'Conf_CNN' : ['pool_size'],
107
+ }[self.model_type]
108
+
109
+ self.model_args = [self.conv_args] + [self.__getattribute__(arg) for arg in left_args]
110
+
111
+
112
+ def check_experiment(self,logger):
113
+ """
114
+ check any unfinished experiment ?
115
+ """
116
+ log_save_dir = os.path.dirname(self.vae_log_path)
117
+ pth_save_dir = os.path.join(self.pth_dir,self.model_type+self._dataset,self.setting_name)
118
+ # make dirs
119
+ if not os.path.exists(log_save_dir):
120
+ os.makedirs(log_save_dir)
121
+ if not os.path.exists(pth_save_dir):
122
+ os.makedirs(pth_save_dir)
123
+
124
+ # check resume
125
+ if os.path.exists(self.vae_log_path) & os.path.exists(self.vae_pth_path):
126
+ self.Resumable = True
127
+ logger.info(' \t \t ==============<<< Experiment detected >>>============== \t \t \n')
128
+
129
+ def update_ini_file(self,E,logger):
130
+ """
131
+ E is the dict contain the things to update
132
+ """
133
+ # update the ini file
134
+ self.config_dict.update(E)
135
+ strconfig = {K: repr(V) for K,V in self.config_dict.items()}
136
+ self.config['DEFAULT'] = strconfig
137
+
138
+ with open(self.config_file,'w') as f:
139
+ self.config.write(f)
140
+
141
+ logger.info(' ini file updated ')
142
+
143
+ def chimera_weight_update(self):
144
+ # TODO : progressively update the loss weight between tasks
145
+
146
+ # TODO : 1. scale the loss into the same magnitude
147
+
148
+ # TODO : 2. update the weight by their own learning progress
149
+
150
+ return None
model/src/mrl_te_optimization/script/Nupack_MFE_prediction.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/ssd/users/wergillius/.conda/envs/pytorch/bin/python
2
+ import os
3
+ import sys
4
+ import numpy as np
5
+ import pandas as pd
6
+ import nupack
7
+ import PATH
8
+ import utils
9
+ import scipy
10
+ from tqdm import tqdm
11
+ tqdm.pandas()
12
+
13
+ my_model=nupack.Model(material='RNA')
14
+ eGFP_seq = utils.eGFP_seq
15
+
16
+ data_dir= utils.data_dir
17
+ csv_name = sys.argv[1]
18
+ csv_path = csv_name if os.path.exists(csv_name) else os.path.join(data_dir, csv_name)
19
+
20
+ assert os.path.exists(csv_path), "csv not found"
21
+
22
+
23
+ df = pd.read_csv(csv_path)
24
+ seq_col = 'seq' if 'seq' in df.columns else 'utr'
25
+ tr_col = 'rl' if 'rl' in df.columns else 'log_te'
26
+
27
+ def cor_fun(col):
28
+ pearson_r = scipy.stats.pearsonr(df[col].values,
29
+ df[tr_col].values)[0]
30
+ return pearson_r
31
+
32
+ nupck_engery_fn = lambda x: nupack.mfe(strands=[x], model=my_model)[0].energy
33
+ df['nupack_MFE'] = df[seq_col].progress_apply(nupck_engery_fn)
34
+
35
+ print("nupack_MFE : {}".format(cor_fun('nupack_MFE')))
36
+
37
+ # nupck_engery_fn = lambda x: nupack.mfe(strands=[x + eGFP_seq[:10]], model=my_model)[0].energy
38
+ # df['eGFP10_nupMFE'] = df[seq_col].progress_apply(nupck_engery_fn)
39
+
40
+ # print("eGFP10_nupMFE : {}".format(cor_fun('eGFP10_nupMFE')))
41
+
42
+ # nupck_engery_fn = lambda x: nupack.mfe(strands=[x + eGFP_seq[:50]], model=my_model)[0].energy
43
+ # df['eGFP50_nupMFE'] = df[seq_col].progress_apply(nupck_engery_fn)
44
+
45
+ # print("eGFP50_nupMFE : {}".format(cor_fun('eGFP50_nupMFE')))
46
+
47
+ df.to_csv(csv_path, index=False)
48
+ print(f"saved to {csv_path}")
model/src/mrl_te_optimization/script/PATH.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ from utils import *
model/src/mrl_te_optimization/script/covar_test.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import argparse
4
+
5
+ parser = argparse.ArgumentParser('the main to train model')
6
+ parser.add_argument('--config_file',type=str,required=True)
7
+ parser.add_argument('--cuda',type=str,default=0,required=False)
8
+ parser.add_argument("--kfold_index",type=int,default=1,required=False)
9
+ args = parser.parse_args()
10
+
11
+ cuda_id = args.cuda if args.cuda is not None else utils.get_config_cuda(args.config_file)
12
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(cuda_id)
13
+
14
+
15
+ import time
16
+ import torch
17
+ import copy
18
+ import utils
19
+ from torch import optim
20
+ import numpy as np
21
+ from models import reader,train_val
22
+ from models.ScheduleOptimizer import ScheduledOptim,scheduleoptim_dict_str
23
+ from models.popen import Auto_popen
24
+ from models.loss import Dynamic_Task_Priority,Dynamic_Weight_Averaging
25
+
26
+
27
+ POPEN = Auto_popen(args.config_file)
28
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
29
+ POPEN.cuda_id = device
30
+
31
+
32
+ POPEN.kfold_index = args.kfold_index
33
+ if POPEN.kfold_cv:
34
+ if args.kfold_index is None:
35
+ raise NotImplementedError("please specify the kfold index to perform K fold cross validation")
36
+ POPEN.vae_log_path = POPEN.vae_log_path.replace(".log","_cv%d.log"%args.kfold_index)
37
+ #POPEN.vae_pth_path = POPEN.vae_pth_path.replace(".pth","_cv%d.pth"%args.kfold_index)
38
+
39
+
40
+ # Run name
41
+ if POPEN.run_name is None:
42
+ run_name = POPEN.model_type + time.strftime("__%Y_%m_%d_%H:%M")
43
+ else:
44
+ run_name = POPEN.run_name
45
+
46
+ # log dir
47
+ logger = utils.setup_logs(POPEN.vae_log_path)
48
+ logger.info(f" ===========================| device {device}{cuda_id} |=========================== ")
49
+ # built model dir or check resume
50
+ POPEN.check_experiment(logger)
51
+
52
+ # |=====================================|
53
+ # |=========== setup part ==========|
54
+ # |=====================================|
55
+ # read data
56
+ loader_set = {}
57
+ n_covar_dict = {}
58
+ base_path = ['cycle_train_val.csv', 'cycle_test.csv']
59
+ base_csv = 'cycle_MTL_transfer.csv'
60
+ for task in POPEN.cycle_set:
61
+ if (task in ['MPA_U', 'MPA_H', 'MPA_V', 'SubMPA_H']):
62
+ datapopen = Auto_popen('log/Backbone/RL_covar_intercept/3M/no_covar.ini')
63
+ datapopen.split_like = [path.replace('cycle', task) for path in base_path]
64
+ datapopen.kfold_index = args.kfold_index
65
+ n_covar_dict[task] = datapopen.n_covar
66
+
67
+ elif (task in ['RP_293T', 'RP_muscle', 'RP_PC3']):
68
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3R/schedule_MTL.ini')
69
+ datapopen.csv_path = base_csv.replace("cycle",task)
70
+ datapopen.kfold_index = args.kfold_index
71
+ datapopen.pad_to = POPEN.pad_to
72
+ datapopen.other_input_columns = POPEN.other_input_columns
73
+ datapopen.n_covar = POPEN.n_covar
74
+ n_covar_dict[task] = datapopen.n_covar
75
+
76
+ elif (task in ['pcr3', '293']):
77
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/karollus_RPs/rp_cycle.ini')
78
+ datapopen.csv_path = base_csv.replace("cycle",task)
79
+ datapopen.kfold_index = args.kfold_index
80
+ datapopen.other_input_columns = POPEN.other_input_columns
81
+ datapopen.pad_to = POPEN.pad_to
82
+ datapopen.n_covar = POPEN.n_covar
83
+ n_covar_dict[task] = datapopen.n_covar
84
+ loader_set[task] = reader.get_dataloader(datapopen)
85
+
86
+ POPEN.n_covar = n_covar_dict
87
+ POPEN.get_model_config() # update model config
88
+
89
+
90
+ # =========== setup model ===========
91
+ # train_iter = iter(train_loader)
92
+ # X,Y = next(train_iter)
93
+ # -- pretrain --
94
+ if POPEN.pretrain_pth is not None:
95
+ # load pretran model
96
+ logger.info("===============================| pretrain |===============================")
97
+ logger.info(f" {POPEN.pretrain_pth}")
98
+ pretrain_popen = Auto_popen(os.path.join(utils.script_dir, POPEN.pretrain_pth))
99
+ if not os.path.exists(pretrain_popen.vae_pth_path):
100
+ if type(args.kfold_index) == int:
101
+ pretrain_popen.kfold_index = args.kfold_index
102
+ pretrain_model = torch.load(pretrain_popen.vae_pth_path, map_location=torch.device('cpu'))['state_dict']
103
+
104
+
105
+ if POPEN.model_type == pretrain_popen.model_type:
106
+ # if not POPEN.Resumable:
107
+ # # we only load pre-train for the first time
108
+ # # later we can resume
109
+ model = pretrain_model.to(device)
110
+ del pretrain_model
111
+
112
+ if (POPEN.cycle_set != pretrain_popen.cycle_set):
113
+ model.all_tasks = POPEN.cycle_set
114
+ model.tower = torch.nn.ModuleDict(
115
+ {POPEN.cycle_set[i] : model.tower[t] for i, t in enumerate(pretrain_popen.cycle_set)}
116
+ )
117
+
118
+ elif POPEN.modual_to_fix is not None:
119
+ # POPEN.model_type != pretrain_popen.model_type
120
+
121
+ model = POPEN.Model_Class(*POPEN.model_args)
122
+ for modual in POPEN.modual_to_fix:
123
+ if modual in dir(pretrain_model):
124
+ eval(f'model.{modual}').load_state_dict(
125
+ eval(f'model.{modual}').state_dict()
126
+ )
127
+
128
+ state_dict = {'epoch': 0,
129
+ 'validation_acc': 0,
130
+ 'state_dict': model.to('cpu'),
131
+ 'validation_loss': 0}
132
+ shared_pretrain_pth = POPEN.vae_pth_path.replace(f"_cv{args.kfold_index}", '')
133
+ if not os.path.exists(shared_pretrain_pth):
134
+ utils.snapshot(shared_pretrain_pth, state_dict)
135
+ utils.snapshot(POPEN.vae_pth_path, state_dict)
136
+
137
+ model = torch.load(POPEN.vae_pth_path, map_location=torch.device('cpu'))
138
+ model = model.to(device)
139
+
140
+ # -- end2end --
141
+ else:
142
+ Model_Class = POPEN.Model_Class # DL_models.LSTM_AE
143
+
144
+ model = Model_Class(*POPEN.model_args).to(device)
145
+
146
+ if POPEN.Resumable:
147
+ model = utils.load_model(POPEN, model, logger)
148
+
149
+ # =========== fix parameters ===========
150
+ if isinstance(POPEN.modual_to_fix, list):
151
+ for modual in POPEN.modual_to_fix:
152
+ model = utils.fix_parameter(model,modual)
153
+ model = model.to(device)
154
+ logger.info(' \t \t ==============| %s fixed |============== \t \t \n'%POPEN.modual_to_fix)
155
+ # =========== set optimizer ===========
156
+ if POPEN.optimizer == 'Schedule':
157
+ optimizer = ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
158
+ betas=(0.9, 0.98),
159
+ eps=1e-09,
160
+ weight_decay=1e-4,
161
+ amsgrad=True),
162
+ n_warmup_steps=20)
163
+ elif type(POPEN.optimizer) == dict:
164
+ optimizer = eval(scheduleoptim_dict_str.format(**POPEN.optimizer))
165
+ else:
166
+ optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
167
+ lr=POPEN.lr,
168
+ betas=(0.9, 0.98),
169
+ eps=1e-09,
170
+ weight_decay=POPEN.l2)
171
+ if POPEN.loss_schema == 'DTP':
172
+ POPEN.loss_schedualer = Dynamic_Task_Priority(POPEN.tasks,POPEN.gamma,POPEN.chimerla_weight)
173
+ elif POPEN.loss_schema == 'DWA':
174
+ POPEN.loss_schedualer = Dynamic_Weight_Averaging(POPEN.tasks,POPEN.tau,POPEN.chimerla_weight)
175
+ # =========== resume ===========
176
+ best_loss = np.inf
177
+ best_acc = 0
178
+ best_epoch = 0
179
+ previous_epoch = 0
180
+ if POPEN.Resumable:
181
+ previous_epoch,best_loss,best_acc = utils.resume(POPEN, optimizer,logger)
182
+ epoch = previous_epoch
183
+
184
+
185
+ # |=====================================|
186
+ # |========== test part ==========|
187
+ # |=====================================|
188
+
189
+
190
+
191
+ logger.info("===============================| testing |===============================")
192
+ verbose_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch, which_set=2)
193
+ # matching task performance influence what to save
194
+
195
+
196
+
197
+ if np.any(['r2' in key for key in verbose_dict.keys()]):
198
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'r2' in key])
199
+ acc_dict = {f"cv{args.kfold_index}_{key}":values for key, values in verbose_dict.items() if 'r2' in key}
200
+ else:
201
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'acc' in key])
202
+ acc_dict = {}
203
+ val_total_loss = verbose_dict['Total']
model/src/mrl_te_optimization/script/covar_train.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import argparse
4
+
5
+ parser = argparse.ArgumentParser('the main to train model')
6
+ parser.add_argument('--config_file',type=str,required=True)
7
+ parser.add_argument('--cuda',type=str,default=0,required=False)
8
+ parser.add_argument("--kfold_index",type=int,default=1,required=False)
9
+ args = parser.parse_args()
10
+
11
+ cuda_id = args.cuda if args.cuda is not None else utils.get_config_cuda(args.config_file)
12
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(cuda_id)
13
+
14
+
15
+ import time
16
+ import torch
17
+ import copy
18
+ import utils
19
+ from torch import optim
20
+ import numpy as np
21
+ from models import reader,train_val
22
+ from models.ScheduleOptimizer import ScheduledOptim,scheduleoptim_dict_str
23
+ from models.popen import Auto_popen
24
+ from models.loss import Dynamic_Task_Priority,Dynamic_Weight_Averaging
25
+
26
+
27
+ POPEN = Auto_popen(args.config_file)
28
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
29
+ POPEN.cuda_id = device
30
+
31
+
32
+ POPEN.kfold_index = args.kfold_index
33
+ if POPEN.kfold_cv:
34
+ if args.kfold_index is None:
35
+ raise NotImplementedError("please specify the kfold index to perform K fold cross validation")
36
+ POPEN.vae_log_path = POPEN.vae_log_path.replace(".log","_cv%d.log"%args.kfold_index)
37
+ #POPEN.vae_pth_path = POPEN.vae_pth_path.replace(".pth","_cv%d.pth"%args.kfold_index)
38
+
39
+
40
+ # Run name
41
+ if POPEN.run_name is None:
42
+ run_name = POPEN.model_type + time.strftime("__%Y_%m_%d_%H:%M")
43
+ else:
44
+ run_name = POPEN.run_name
45
+
46
+ # log dir
47
+ logger = utils.setup_logs(POPEN.vae_log_path)
48
+ logger.info(f" ===========================| device {device}{cuda_id} |=========================== ")
49
+ # built model dir or check resume
50
+ POPEN.check_experiment(logger)
51
+
52
+ # |=====================================|
53
+ # |=========== setup part ==========|
54
+ # |=====================================|
55
+ # read data
56
+ loader_set = {}
57
+ n_covar_dict = {}
58
+ base_path = ['cycle_train_val.csv', 'cycle_test.csv']
59
+ base_csv = 'cycle_MTL_transfer.csv'
60
+ for task in POPEN.cycle_set:
61
+ if (task in ['MPA_U', 'MPA_H', 'MPA_V', 'SubMPA_H']):
62
+ datapopen = Auto_popen('log/Backbone/RL_covar_intercept/3M/no_covar.ini')
63
+ datapopen.split_like = [path.replace('cycle', task) for path in base_path]
64
+ datapopen.kfold_index = args.kfold_index
65
+ n_covar_dict[task] = datapopen.n_covar
66
+
67
+ elif (task in ['RP_293T', 'RP_muscle', 'RP_PC3']):
68
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3R/schedule_MTL.ini')
69
+ datapopen.csv_path = base_csv.replace("cycle",task)
70
+ datapopen.kfold_index = args.kfold_index
71
+ datapopen.pad_to = POPEN.pad_to
72
+ datapopen.other_input_columns = POPEN.other_input_columns
73
+ datapopen.n_covar = POPEN.n_covar
74
+ n_covar_dict[task] = datapopen.n_covar
75
+
76
+ elif (task in ['pcr3', '293']):
77
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/karollus_RPs/rp_cycle.ini')
78
+ datapopen.csv_path = base_csv.replace("cycle",task)
79
+ datapopen.kfold_index = args.kfold_index
80
+ datapopen.other_input_columns = POPEN.other_input_columns
81
+ datapopen.pad_to = POPEN.pad_to
82
+ datapopen.n_covar = POPEN.n_covar
83
+ n_covar_dict[task] = datapopen.n_covar
84
+ loader_set[task] = reader.get_dataloader(datapopen)
85
+
86
+ POPEN.n_covar = n_covar_dict
87
+ POPEN.get_model_config() # update model config
88
+
89
+
90
+ # =========== setup model ===========
91
+ # train_iter = iter(train_loader)
92
+ # X,Y = next(train_iter)
93
+ # -- pretrain --
94
+ if POPEN.pretrain_pth is not None:
95
+ # load pretran model
96
+ logger.info("===============================| pretrain |===============================")
97
+ logger.info(f" {POPEN.pretrain_pth}")
98
+ pretrain_popen = Auto_popen(os.path.join(utils.script_dir, POPEN.pretrain_pth))
99
+ if not os.path.exists(pretrain_popen.vae_pth_path):
100
+ if type(args.kfold_index) == int:
101
+ pretrain_popen.kfold_index = args.kfold_index
102
+ pretrain_model = torch.load(pretrain_popen.vae_pth_path, map_location=torch.device('cpu'))['state_dict']
103
+
104
+
105
+ if POPEN.model_type == pretrain_popen.model_type:
106
+ # if not POPEN.Resumable:
107
+ # # we only load pre-train for the first time
108
+ # # later we can resume
109
+ model = pretrain_model.to(device)
110
+ del pretrain_model
111
+
112
+ if (POPEN.cycle_set != pretrain_popen.cycle_set):
113
+ model.all_tasks = POPEN.cycle_set
114
+ model.tower = torch.nn.ModuleDict(
115
+ {POPEN.cycle_set[i] : model.tower[t] for i, t in enumerate(pretrain_popen.cycle_set)}
116
+ )
117
+
118
+ elif POPEN.modual_to_fix is not None:
119
+ # POPEN.model_type != pretrain_popen.model_type
120
+
121
+ model = POPEN.Model_Class(*POPEN.model_args)
122
+ for modual in POPEN.modual_to_fix:
123
+ if modual in dir(pretrain_model):
124
+ eval(f'model.{modual}').load_state_dict(
125
+ eval(f'model.{modual}').state_dict()
126
+ )
127
+
128
+ state_dict = {'epoch': 0,
129
+ 'validation_acc': 0,
130
+ 'state_dict': model.to('cpu'),
131
+ 'validation_loss': 0}
132
+ shared_pretrain_pth = POPEN.vae_pth_path.replace(f"_cv{args.kfold_index}", '')
133
+ if not os.path.exists(shared_pretrain_pth):
134
+ utils.snapshot(shared_pretrain_pth, state_dict)
135
+ utils.snapshot(POPEN.vae_pth_path, state_dict)
136
+
137
+ model = torch.load(POPEN.vae_pth_path, map_location=torch.device('cpu'))
138
+ model = model.to(device)
139
+
140
+ # -- end2end --
141
+ else:
142
+ Model_Class = POPEN.Model_Class # DL_models.LSTM_AE
143
+
144
+ model = Model_Class(*POPEN.model_args).to(device)
145
+
146
+ if POPEN.Resumable:
147
+ model = utils.load_model(POPEN, model, logger)
148
+
149
+ # =========== fix parameters ===========
150
+ if isinstance(POPEN.modual_to_fix, list):
151
+ for modual in POPEN.modual_to_fix:
152
+ model = utils.fix_parameter(model,modual)
153
+ model = model.to(device)
154
+ logger.info(' \t \t ==============| %s fixed |============== \t \t \n'%POPEN.modual_to_fix)
155
+ # =========== set optimizer ===========
156
+ if POPEN.optimizer == 'Schedule':
157
+ optimizer = ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
158
+ betas=(0.9, 0.98),
159
+ eps=1e-09,
160
+ weight_decay=1e-4,
161
+ amsgrad=True),
162
+ n_warmup_steps=20)
163
+ elif type(POPEN.optimizer) == dict:
164
+ optimizer = eval(scheduleoptim_dict_str.format(**POPEN.optimizer))
165
+ else:
166
+ optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
167
+ lr=POPEN.lr,
168
+ betas=(0.9, 0.98),
169
+ eps=1e-09,
170
+ weight_decay=POPEN.l2)
171
+ if POPEN.loss_schema == 'DTP':
172
+ POPEN.loss_schedualer = Dynamic_Task_Priority(POPEN.tasks,POPEN.gamma,POPEN.chimerla_weight)
173
+ elif POPEN.loss_schema == 'DWA':
174
+ POPEN.loss_schedualer = Dynamic_Weight_Averaging(POPEN.tasks,POPEN.tau,POPEN.chimerla_weight)
175
+ # =========== resume ===========
176
+ best_loss = np.inf
177
+ best_acc = 0
178
+ best_epoch = 0
179
+ previous_epoch = 0
180
+ if POPEN.Resumable:
181
+ previous_epoch,best_loss,best_acc = utils.resume(POPEN, optimizer,logger)
182
+
183
+
184
+ # |=====================================|
185
+ # |========== training part ==========|
186
+ # |=====================================|
187
+ for epoch in range(POPEN.max_epoch-previous_epoch+1):
188
+ epoch += previous_epoch
189
+
190
+ #
191
+ logger.info("===============================| epoch {} |===============================".format(epoch))
192
+
193
+
194
+ train_val.iter_train(loader_set,model=model,optimizer=optimizer,popen=POPEN,epoch=epoch)
195
+
196
+ # -----------| validate |-----------
197
+ logger.info("===============================| start validation |===============================")
198
+ verbose_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch)
199
+ test_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch, which_set=2)
200
+
201
+ if np.any(['r2' in key for key in verbose_dict.keys()]):
202
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'r2' in key])
203
+ else:
204
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'acc' in key])
205
+ val_total_loss = verbose_dict['Total']
206
+
207
+ # matching task performance influence what to save
208
+
209
+
210
+ DICT ={"ran_epoch":epoch,"n_current_steps":optimizer.n_current_steps,"delta":optimizer.delta} if type(optimizer) == ScheduledOptim else {"ran_epoch":epoch}
211
+ POPEN.update_ini_file(DICT,logger)
212
+
213
+
214
+ # -----------| compare the result |-----------
215
+ if (best_loss > val_total_loss) :
216
+ # update best performance
217
+ best_loss = min(best_loss,val_total_loss)
218
+ best_acc = max(best_acc,val_avg_acc)
219
+ best_epoch = epoch
220
+
221
+ # save
222
+ utils.snapshot(POPEN.vae_pth_path, {
223
+ 'epoch': epoch + 1,
224
+ 'validation_acc': val_avg_acc,
225
+ # 'state_dict': model.state_dict(),
226
+ 'state_dict': model,
227
+ 'validation_loss': val_total_loss,
228
+ 'optimizer': optimizer.state_dict(),
229
+ })
230
+
231
+ # update the popen
232
+ POPEN.update_ini_file({'run_name':run_name,
233
+ "ran_epoch":epoch,
234
+ "best_acc":best_acc},
235
+ logger)
236
+
237
+ elif (epoch - best_epoch >= 30)&((type(optimizer) == ScheduledOptim)):
238
+ optimizer.increase_delta()
239
+
240
+ elif (epoch - best_epoch >= 60)&(epoch > POPEN.max_epoch/2):
241
+ # at the late phase of training
242
+ logger.info("<<<<<<<<<<< Early Stopping >>>>>>>>>>")
243
+ break
model/src/mrl_te_optimization/script/data_prepocessing.sh ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ python ./preprocessing_MPA.py
2
+ python ./preprocessing_RP.py
model/src/mrl_te_optimization/script/detect_changepoint_featmap.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import pandas as pd
4
+ import numpy as np
5
+ import PATH
6
+ import torch
7
+ import argparse
8
+ import seaborn as sns
9
+ #
10
+ from models import reader
11
+ from models import train_val
12
+ from models.popen import Auto_popen
13
+ from models import max_activation_patch as MAP
14
+ #
15
+ from sklearn.linear_model import Lasso, Ridge, ElasticNet, LassoCV, RidgeCV, ElasticNetCV
16
+ import warnings
17
+ from scipy.cluster import hierarchy
18
+ from matplotlib.backends.backend_pdf import PdfPages
19
+ warnings.filterwarnings('ignore')
20
+
21
+
22
+ #
23
+ parser = argparse.ArgumentParser('the script to evlauate the effect of ')
24
+ parser.add_argument("-c", "--config", type=str, required=True, help='the model config file: xxx.ini')
25
+ parser.add_argument("-s", "--set", type=int, default=2, help='train - 0 ,val - 1, test - 2 ')
26
+ parser.add_argument("-p", "--n_max_act", type=int, default=500, help='the number of seq')
27
+ parser.add_argument("-k", "--kfold_cv", type=int, default=1, help='the repeat')
28
+ parser.add_argument("-d", "--device", type=str, default='cpu', help='the device to use to extract featmap, digit or cpu')
29
+ args = parser.parse_args()
30
+
31
+ # args = parser.parse_args(["-c","/ssd/users/wergillius/Project/MTtrans/log/Backbone/RL_hard_share/3M/small_repective_filed_strides1113.ini",
32
+ # "-s","2",
33
+ # "-d", "1"])
34
+
35
+ config_path = args.config
36
+ save_path = config_path.replace(".ini", "_coef")
37
+ config = Auto_popen(config_path)
38
+ config.batch_size = 256
39
+ config.shuffle = False
40
+ config.kfold_cv = 'train_val'
41
+ all_task = config.cycle_set
42
+
43
+ task_channel_effect = {}
44
+ task_performance = {}
45
+
46
+ # path check
47
+ if os.path.exists(config_path) and not os.path.exists(save_path):
48
+ os.mkdir(save_path)
49
+
50
+ saved_pdf =os.path.join(save_path, 'changepoint_actmap.pdf')
51
+ pp = PdfPages(saved_pdf)
52
+ channel_cluster_task = {}
53
+ for task in all_task:
54
+
55
+ # .... format featmap as data ....
56
+ print(f"\n\nevaluating for task: {task}")
57
+ # re-instance the map for each task
58
+ map_task = MAP.Maximum_activation_patch(popen=config, which_layer=4,
59
+ n_patch=args.n_max_act,
60
+ kfold_index=args.kfold_cv,
61
+ device_string=args.device)
62
+
63
+ # extract feature map and rl decision chain
64
+ featmap = map_task.extract_feature_map(task=task, which_set=args.set)
65
+ cum_rl_trend = map_task.cumulative_rl_decision(task=task, which_set=args.set)
66
+
67
+ # truncate the featmap and rl trend according to sequence length
68
+ seq_len_ls = map_task.df[config.seq_col].apply(len)
69
+ total_stride = np.product(map_task.strides)
70
+ to_stay = seq_len_ls//total_stride - 4
71
+ trunc_start = featmap.shape[2] - to_stay
72
+
73
+ # if max_seq_len == 50:
74
+ # trunc_start = -12
75
+
76
+
77
+ # find the low rl sequences
78
+ rl_pred = cum_rl_trend[:,-1]
79
+ threshold = np.quantile(rl_pred, [0.05, 0.95])
80
+
81
+ low_rl = rl_pred < threshold[0]
82
+ high_rl = rl_pred > threshold[1]
83
+
84
+ # subset find low rl change point feature
85
+ lowrl_rl_chain = cum_rl_trend[low_rl]
86
+ lowrl_ft = featmap[low_rl]
87
+ lowrl_detect_region = [slice(s,None) for s in trunc_start[low_rl]]
88
+ changepoint_map = map_task.retrieve_featmap_at_changepoint(lowrl_ft, lowrl_rl_chain,
89
+ threshold=-1, direction='less', detect_region=lowrl_detect_region)
90
+ print(changepoint_map.shape)
91
+
92
+ # sample high rl feature
93
+ highrl_rl_chain = cum_rl_trend[high_rl]
94
+ highrl_ft = featmap[high_rl]
95
+ highrl_detect_region = [slice(s,None) for s in trunc_start[high_rl]]
96
+ background_map = map_task.retrieve_featmap_at_changepoint(highrl_ft, highrl_rl_chain,
97
+ threshold=0.5, direction='greater', detect_region=highrl_detect_region)
98
+
99
+ # and then subsample
100
+ n_background = background_map.shape[0]
101
+ n_foreground = changepoint_map.shape[0]
102
+ if n_background > n_foreground:
103
+ downsample_seed = np.random.choice(np.arange(0,n_background), size=n_foreground)
104
+ background_map = background_map[downsample_seed]
105
+ n_background = background_map.shape[0]
106
+
107
+ # concate and order two group
108
+ row_colors = ["#E09832"]*n_background + ["#192D48"]*n_foreground
109
+ all_act=np.concatenate([background_map, changepoint_map], axis=0)
110
+ feat_norm_act = (all_act - all_act.min(axis=0)) / (all_act.max(axis=0) - all_act.min(axis=0))
111
+
112
+
113
+ # Visualization
114
+ g=sns.clustermap(feat_norm_act, row_colors=row_colors);
115
+
116
+ # 'array', 'axis', 'calculate_dendrogram', 'calculated_linkage', 'data',
117
+ # 'dendrogram', 'dependent_coord', 'independent_coord', 'label', 'linkage',
118
+ # 'method', 'metric', 'plot', 'reordered_ind', 'rotate', 'shape', 'xlabel',
119
+ # 'xticklabels', 'xticks', 'ylabel', 'yticklabels', 'yticks'
120
+
121
+
122
+ Z_col=g.dendrogram_col.linkage
123
+ thres = 0.8*max(Z_col[:,2])
124
+ R = hierarchy.dendrogram(Z_col ,color_threshold=thres, truncate_mode=None,
125
+ above_threshold_color='#AAAAAA', p=10, orientation='top',ax=g.ax_col_dendrogram);
126
+ # R['leaves']
127
+ # R['ivl']
128
+
129
+ Z_row=g.dendrogram_row.linkage
130
+ thres = 0.8*max(Z_row[:,2])
131
+ R2 = hierarchy.dendrogram(Z_row ,color_threshold=thres, truncate_mode=None, orientation='left',
132
+ above_threshold_color='#AAAAAA', p=10, ax=g.ax_row_dendrogram);
133
+ g.ax_row_dendrogram.invert_yaxis()
134
+ g.figure.suptitle(task)
135
+
136
+ pp.savefig(g.figure)
137
+
138
+ channel_cluster_task[task] = pd.DataFrame(dict(zip(R['leaves'],R['leaves_color_list'])))
139
+ print("No..")
140
+ pp.close()
141
+ channel_cluster_df = pd.DataFrame(channel_cluster_task)
142
+ saved_csv = os.path.join(save_path, "changepoint_channel_cluster.csv")
143
+ channel_cluster_df.to_csv(saved_csv, index=False)
144
+ print("==DONE==")
145
+ print(f"result save to {saved_pdf}\n \t\t {saved_csv}")
146
+
model/src/mrl_te_optimization/script/download_training_data.sh ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ DATA_DIR=$(cat machine_configure.json |grep data_dir|awk -F ': "' '{print $2}'|awk -F '",' '{print $1}')
2
+
3
+ if [ ! -d ${DATA_DIR} ]; then
4
+ echo "=============================================================="
5
+ echo " "
6
+ echo ${DATA_DIR} does not exist! Redirect to ./data
7
+ echo " "
8
+ echo "=============================================================="
9
+ DATA_DIR=$(pwd)/data
10
+ fi
11
+
12
+ cd ${DATA_DIR}
13
+
14
+ ## download the ribosome profiling datasest
15
+ # RP-muscle
16
+ wget https://raw.githubusercontent.com/zzz2010/5UTR_Optimizer/master/data/df_counts_and_len.TE_sorted.Muscle.with_annot.txt
17
+ # RP-293T
18
+ wget https://raw.githubusercontent.com/zzz2010/5UTR_Optimizer/master/data/df_counts_and_len.TE_sorted.HEK_Andrev2015.with_annot.txt
19
+ # RP-PC3
20
+ wget https://raw.githubusercontent.com/zzz2010/5UTR_Optimizer/master/data/df_counts_and_len.TE_sorted.pc3.with_annot.txt
21
+ # ref
22
+ wget https://raw.githubusercontent.com/zzz2010/5UTR_Optimizer/master/data/gencode_v17_5utr_15bpcds.fa
23
+
24
+ ## download the Massively parallel report assay datasets
25
+ # MPA_U
26
+ wget ftp.ncbi.nlm.nih.gov/geo/samples/GSM3130nnn/GSM3130435/suppl/GSM3130435_egfp_unmod_1.csv.gz
27
+ # MPA_H
28
+ wget ftp.ncbi.nlm.nih.gov/geo/samples/GSM3130nnn/GSM3130443/suppl/GSM3130443_designed_library.csv.gz
29
+ # MPA_V
30
+ wget ftp.ncbi.nlm.nih.gov/geo/samples/GSM4084nnn/GSM4084997/suppl/GSM4084997_varying_length_25to100.csv.gz
31
+
32
+
33
+ ## dowlaod the yeast dataset
34
+ wget ftp.ncbi.nlm.nih.gov/geo/samples/GSM2793nnn/GSM2793752/suppl/GSM2793752_Random_UTRs.csv.gz
35
+
36
+
37
+ gzip -d *.gz
38
+
39
+ echo "Finished ! All data ready~"
40
+ echo "Please step to the pre-proccessing"
model/src/mrl_te_optimization/script/evaluate_channel_effect.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import pandas as pd
4
+ import numpy as np
5
+ import PATH
6
+ import torch
7
+ import argparse
8
+ #
9
+ from models import reader
10
+ from models import train_val
11
+ from models.popen import Auto_popen
12
+ from models import max_activation_patch as MAP
13
+ #
14
+ from sklearn.linear_model import LassoCV, RidgeCV, ElasticNetCV, LogisticRegressionCV
15
+ import warnings
16
+ warnings.filterwarnings('ignore')
17
+
18
+
19
+ #
20
+ parser = argparse.ArgumentParser('the script to evlauate the effect of ')
21
+ parser.add_argument("-c", "--config", type=str, required=True, help='the model config file: xxx.ini')
22
+ parser.add_argument("-s", "--set", type=int, default=2, help='train - 0 ,val - 1, test - 2 ')
23
+ parser.add_argument("-p", "--n_max_act", type=int, default=500, help='the number of seq')
24
+ parser.add_argument("-k", "--kfold_cv", type=int, default=1, help='the repeat')
25
+ parser.add_argument("-t", "--task", type=str, default='regression', help='either regression or classification')
26
+ parser.add_argument("-d", "--device", type=str, default='cpu', help='the device to use to extract featmap, digit or cpu')
27
+ args = parser.parse_args()
28
+
29
+ config_path = args.config
30
+ save_path = config_path.replace(".ini", "_coef")
31
+ config = Auto_popen(config_path)
32
+ config.batch_size = 256
33
+ # config.kfold_cv = 'train_val'
34
+ all_task = config.cycle_set
35
+
36
+ task_channel_effect = {}
37
+ task_performance = {}
38
+
39
+ # path check
40
+ if os.path.exists(config_path) and not os.path.exists(save_path):
41
+ os.mkdir(save_path)
42
+
43
+ for task in all_task:
44
+
45
+ # .... format featmap as data ....
46
+ print(f"\n\nevaluating for task: {task}")
47
+ # re-instance the map for each task
48
+ map_task = MAP.Maximum_activation_patch(popen=config, which_layer=4,
49
+ n_patch=args.n_max_act,
50
+ kfold_index=args.kfold_cv,
51
+ device_string=args.device)
52
+
53
+ # extract feature map and rl decision chain
54
+ featmap = map_task.extract_feature_map(task=task, which_set=args.set)
55
+ cum_rl_trend = map_task.cumulative_rl_decision(task=task, which_set=args.set)
56
+
57
+ # truncate the featmap and rl trend according to sequence length
58
+ max_seq_len = map_task.df[config.seq_col].apply(len).max()
59
+ to_stay = max_seq_len // np.product(map_task.strides) +1
60
+ trunc_start = featmap.shape[2] - to_stay
61
+ featmap = featmap[:,:,trunc_start:]
62
+ cum_rl_trend = cum_rl_trend[:,trunc_start:]
63
+
64
+ # construct input for linear regression
65
+ n_sample,n_channel,n_posi = featmap.shape
66
+
67
+ X = featmap.reshape(n_sample,-1)
68
+ Y = map_task.Y_ls.flatten()
69
+
70
+ # .... regression ....
71
+ if args.task == 'regression':
72
+ L1 = LassoCV(alphas=np.linspace(2e-3, 0.1, 49))
73
+ L2 = RidgeCV(alphas=np.linspace(0.001, 0.101, 20))
74
+ elastic = ElasticNetCV(alphas=np.linspace(2e-3, 0.1, 49), n_jobs=10)
75
+ models = [L1, L2, elastic]
76
+ model_names = ['Lasso', 'Ridge', 'Elastic']
77
+
78
+ else:
79
+ LR = LogisticRegressionCV(n_jobs=10)
80
+ # L1 = LogisticRegressionCV(n_jobs=10,penalty='l1', solver='saga')
81
+ # elastic = LogisticRegressionCV(n_jobs=10,penalty='elasticnet', solver='saga', l1_ratios=np.linspace(0.0, 0.5, 10))
82
+ models = [LR]
83
+ model_names = ['Logistic']
84
+
85
+
86
+ for model,name in zip(models, model_names):
87
+ print(f"\nregressing {name}..")
88
+ model.fit(X,Y)
89
+ r2 = model.score(X,Y) # will be
90
+ sparsity = np.sum(model.coef_==0) / X.shape[1] *100
91
+ try:
92
+ alpha = model.alpha_
93
+ except:
94
+ alpha = 0.0
95
+
96
+ print(f"{name} with optimal alpha {alpha:.5f}, r2/acc {r2:.3f} , zero coeff {sparsity:.1f}%")
97
+
98
+ # save df
99
+ effect = model.coef_.reshape(n_channel,-1)
100
+ fullcoef_df = pd.DataFrame(effect, columns=[f"{name}_posi_"+str(trunc_start+i) for i in range(to_stay)])
101
+ fullcoef_df.to_csv( os.path.join(save_path , f"{task}_{name}_coef.csv"), index=False)
102
+ task_channel_effect[f"{task}_{name}"] = effect.mean(axis=1)
103
+
104
+ task_performance[f"{task}_{name}"] = [alpha, r2, sparsity, model.coef_.max(), model.coef_.min()]
105
+
106
+
107
+ all_effect = pd.DataFrame(task_channel_effect)
108
+ all_effect.to_csv(os.path.join(save_path, "all_task_mean_effect.csv"), index=False)
109
+
110
+ report_df = pd.DataFrame(task_performance)
111
+ report_df.index = ['optim_alpha','r2', 'zero_pctg', 'max_coef', 'min_coef']
112
+ report_df.to_csv(os.path.join(save_path, "regression_report.csv"), index=False)
model/src/mrl_te_optimization/script/fix_test_for_RP.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ ## generating the hand craft featuress
3
+
4
+
5
+ ##
6
+
7
+ test_set_tid = []
8
+ trainval_dict = {}
9
+ test_set_dict = {}
10
+ for cell_line in ['muscle',"PC3","293T"]:
11
+
12
+ seed = 41
13
+
14
+ df = processed_dict[cell_line]
15
+ df_to_sample = df.query("`T_id` not in @test_set_tid")
16
+ df_overlap = df.query("(`T_id` in @test_set_tid)")
17
+
18
+ # the number to sample reduce as the list cumulated from previous cell type
19
+ # what to sample
20
+ n_2_sample = int(0.1*df.shape[0]) - df_overlap.shape[0]
21
+ sampled_subset = df_to_sample.sample(n=n_2_sample,random_state=seed)
22
+
23
+ # merge newly sampled with those in the list
24
+ test_set_df = sampled_subset.append(df_overlap)
25
+ trainval_dict[cell_line] = pd.concat([df,test_set_df]).drop_duplicates(keep=False)
26
+ test_set_dict[cell_line] = test_set_df
27
+ # adding new Tids
28
+ test_set_tid += sampled_subset.T_id.values.tolist()
29
+
30
+ for cell_line in ["muscle","PC3","293T"]:
31
+ trainval_dict[cell_line].to_csv(pj(f"RP_{cell_line}_train_val.csv"))
32
+ test_set_dict[cell_line].to_csv(pj(f"RP_{cell_line}_test.csv"))
model/src/mrl_te_optimization/script/generate_config_js.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ script_dir=$(pwd)
3
+ echo "{" > machine_configure.json
4
+ echo '"script_dir": "'${script_dir}'",' >> machine_configure.json
5
+ echo '"data_dir": "'${script_dir}'/data",' >> machine_configure.json
6
+ echo '"log_dir": "'${script_dir}'/log",' >> machine_configure.json
7
+ echo '"pth_dir": "'${script_dir}'/checkpoint"' >> machine_configure.json
8
+ echo "}" >> machine_configure.json
9
+
10
+ if [ ! -d ${script_dir}/data ]; then
11
+ mkdir data
12
+ mkdir checkpoint
13
+ fi
model/src/mrl_te_optimization/script/iter_test.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import argparse
4
+
5
+ parser = argparse.ArgumentParser('the main to train model')
6
+ parser.add_argument('--config_file',type=str,required=True)
7
+ parser.add_argument('--cuda',type=str,default=0,required=False)
8
+ parser.add_argument("--kfold_index",type=int,default=1,required=False)
9
+ args = parser.parse_args()
10
+
11
+ cuda_id = args.cuda if args.cuda is not None else utils.get_config_cuda(args.config_file)
12
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(cuda_id)
13
+
14
+
15
+ import time
16
+ import torch
17
+ import copy
18
+ import utils
19
+ from torch import optim
20
+ import numpy as np
21
+ from models import reader,train_val
22
+ from models.ScheduleOptimizer import ScheduledOptim,scheduleoptim_dict_str
23
+ from models.popen import Auto_popen
24
+ from models.loss import Dynamic_Task_Priority,Dynamic_Weight_Averaging
25
+
26
+
27
+ POPEN = Auto_popen(args.config_file)
28
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
29
+ POPEN.cuda_id = device
30
+
31
+
32
+ POPEN.kfold_index = args.kfold_index
33
+ if POPEN.kfold_cv:
34
+ if args.kfold_index is None:
35
+ raise NotImplementedError("please specify the kfold index to perform K fold cross validation")
36
+ POPEN.vae_log_path = POPEN.vae_log_path.replace(".log","_cv%d.log"%args.kfold_index)
37
+ #POPEN.vae_pth_path = POPEN.vae_pth_path.replace(".pth","_cv%d.pth"%args.kfold_index)
38
+
39
+
40
+ # Run name
41
+ if POPEN.run_name is None:
42
+ run_name = POPEN.model_type + time.strftime("__%Y_%m_%d_%H:%M")
43
+ else:
44
+ run_name = POPEN.run_name
45
+
46
+ # log dir
47
+ logger = utils.setup_logs(POPEN.vae_log_path)
48
+ logger.info(f" ===========================| device {device}{cuda_id} |=========================== ")
49
+ # built model dir or check resume
50
+ POPEN.check_experiment(logger)
51
+
52
+ # |=====================================|
53
+ # |=========== setup part ==========|
54
+ # |=====================================|
55
+ # read data
56
+ loader_set = {}
57
+ n_covar_dict = {}
58
+ base_path = ['cycle_train_val.csv', 'cycle_test.csv']
59
+ base_csv = 'cycle_MTL_transfer.csv'
60
+ for task in POPEN.cycle_set:
61
+ if (task in ['MPA_U', 'MPA_H', 'MPA_V', 'SubMPA_H']):
62
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3M/schedule_lr.ini')
63
+ datapopen.split_like = [path.replace('cycle', task) for path in base_path]
64
+ datapopen.kfold_index = args.kfold_index
65
+ n_covar_dict[task] = datapopen.n_covar
66
+
67
+ elif (task in ['RP_293T', 'RP_muscle', 'RP_PC3']):
68
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3R/schedule_MTL.ini')
69
+ datapopen.csv_path = base_csv.replace("cycle",task)
70
+ datapopen.kfold_index = args.kfold_index
71
+ datapopen.pad_to = POPEN.pad_to
72
+ datapopen.aux_task_columns = POPEN.aux_task_columns
73
+ datapopen.other_input_columns = POPEN.other_input_columns
74
+ datapopen.n_covar = POPEN.n_covar
75
+
76
+ elif (task in ['pcr3', '293']):
77
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/karollus_RPs/rp_cycle.ini')
78
+ datapopen.csv_path = base_csv.replace("cycle",task)
79
+ datapopen.kfold_index = args.kfold_index
80
+ datapopen.aux_task_columns = POPEN.aux_task_columns
81
+ datapopen.other_input_columns = POPEN.other_input_columns
82
+ datapopen.pad_to = POPEN.pad_to
83
+ datapopen.n_covar = POPEN.n_covar
84
+ datapopen.shuffle = False
85
+ loader_set[task] = reader.get_dataloader(datapopen)
86
+
87
+ POPEN.n_covar = n_covar_dict
88
+ POPEN.get_model_config() # update model config
89
+
90
+ # =========== setup model ===========
91
+ # train_iter = iter(train_loader)
92
+ # X,Y = next(train_iter)
93
+ # -- pretrain --
94
+ if POPEN.pretrain_pth is not None:
95
+ # load pretran model
96
+ logger.info("===============================| pretrain |===============================")
97
+ logger.info(f" {POPEN.pretrain_pth}")
98
+ pretrain_popen = Auto_popen(os.path.join(utils.script_dir, POPEN.pretrain_pth))
99
+ if not os.path.exists(pretrain_popen.vae_pth_path):
100
+ if type(args.kfold_index) == int:
101
+ pretrain_popen.kfold_index = args.kfold_index
102
+ pretrain_model = torch.load(pretrain_popen.vae_pth_path, map_location=torch.device('cpu'))['state_dict']
103
+
104
+
105
+ if POPEN.model_type == pretrain_popen.model_type:
106
+ # if not POPEN.Resumable:
107
+ # # we only load pre-train for the first time
108
+ # # later we can resume
109
+ model = pretrain_model.to(device)
110
+ del pretrain_model
111
+
112
+ if (POPEN.cycle_set != pretrain_popen.cycle_set):
113
+ model.all_tasks = POPEN.cycle_set
114
+ model.tower = torch.nn.ModuleDict(
115
+ {POPEN.cycle_set[i] : model.tower[t] for i, t in enumerate(pretrain_popen.cycle_set)}
116
+ )
117
+
118
+ elif POPEN.modual_to_fix is not None:
119
+ # POPEN.model_type != pretrain_popen.model_type
120
+
121
+ model = POPEN.Model_Class(*POPEN.model_args)
122
+ for modual in POPEN.modual_to_fix:
123
+ if modual in dir(pretrain_model):
124
+ eval(f'model.{modual}').load_state_dict(
125
+ eval(f'model.{modual}').state_dict()
126
+ )
127
+
128
+ state_dict = {'epoch': 0,
129
+ 'validation_acc': 0,
130
+ 'state_dict': model.to('cpu'),
131
+ 'validation_loss': 0}
132
+ shared_pretrain_pth = POPEN.vae_pth_path.replace(f"_cv{args.kfold_index}", '')
133
+ if not os.path.exists(shared_pretrain_pth):
134
+ utils.snapshot(shared_pretrain_pth, state_dict)
135
+ utils.snapshot(POPEN.vae_pth_path, state_dict)
136
+
137
+ model = torch.load(POPEN.vae_pth_path, map_location=torch.device('cpu'))
138
+ model = model.to(device)
139
+
140
+ # -- end2end --
141
+ elif POPEN.model_type == "CrossStitch_Model":
142
+ backbone = {}
143
+ for t in POPEN.tasks:
144
+ task_popen = Auto_popen(POPEN.backbone_config[t])
145
+ task_model = task_popen.Model_Class(*task_popen.model_args)
146
+ utils.load_model(task_popen,task_model,logger)
147
+ backbone[t] = task_model.to(device)
148
+ POPEN.model_args = [backbone] + POPEN.model_args
149
+ model = POPEN.Model_Class(*POPEN.model_args).to(device)
150
+ else:
151
+ Model_Class = POPEN.Model_Class # DL_models.LSTM_AE
152
+ model = Model_Class(*POPEN.model_args).to(device)
153
+
154
+ if POPEN.Resumable:
155
+ model = utils.load_model(POPEN, model, logger)
156
+
157
+ # =========== fix parameters ===========
158
+ if isinstance(POPEN.modual_to_fix, list):
159
+ for modual in POPEN.modual_to_fix:
160
+ model = utils.fix_parameter(model,modual)
161
+ model = model.to(device)
162
+ logger.info(' \t \t ==============| %s fixed |============== \t \t \n'%POPEN.modual_to_fix)
163
+ # =========== set optimizer ===========
164
+ if POPEN.optimizer == 'Schedule':
165
+ optimizer = ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
166
+ betas=(0.9, 0.98),
167
+ eps=1e-09,
168
+ weight_decay=1e-4,
169
+ amsgrad=True),
170
+ n_warmup_steps=20)
171
+ elif type(POPEN.optimizer) == dict:
172
+ optimizer = eval(scheduleoptim_dict_str.format(**POPEN.optimizer))
173
+ else:
174
+ optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
175
+ lr=POPEN.lr,
176
+ betas=(0.9, 0.98),
177
+ eps=1e-09,
178
+ weight_decay=POPEN.l2)
179
+ if POPEN.loss_schema == 'DTP':
180
+ POPEN.loss_schedualer = Dynamic_Task_Priority(POPEN.tasks,POPEN.gamma,POPEN.chimerla_weight)
181
+ elif POPEN.loss_schema == 'DWA':
182
+ POPEN.loss_schedualer = Dynamic_Weight_Averaging(POPEN.tasks,POPEN.tau,POPEN.chimerla_weight)
183
+ # =========== resume ===========
184
+ best_loss = np.inf
185
+ best_acc = 0
186
+ best_epoch = 0
187
+ previous_epoch = 0
188
+ epoch = 0
189
+ if POPEN.Resumable:
190
+ previous_epoch,best_loss,best_acc = utils.resume(POPEN, optimizer,logger)
191
+
192
+
193
+ # |=====================================|
194
+ # |========== training part ==========|
195
+ # |=====================================|
196
+ epoch += previous_epoch
197
+
198
+
199
+
200
+ # -----------| validate |-----------
201
+ logger.info("===============================| test |===============================")
202
+ verbose_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch, which_set=2)
203
+ # matching task performance influence what to save
204
+
205
+ if np.any(['r2' in key for key in verbose_dict.keys()]):
206
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'r2' in key])
207
+ acc_dict = {f"cv{args.kfold_index}_{key}":values for key, values in verbose_dict.items() if 'r2' in key}
208
+ else:
209
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'acc' in key])
210
+ acc_dict = {}
211
+ val_total_loss = verbose_dict['Total']
212
+
213
+ # DICT ={"ran_epoch":epoch,"n_current_steps":optimizer.n_current_steps,"delta":optimizer.delta} if type(optimizer) == ScheduledOptim else {"ran_epoch":epoch}
214
+ # POPEN.update_ini_file(DICT,logger)
215
+
216
+
217
+
218
+
219
+ # POPEN.update_ini_file(acc_dict,logger)
model/src/mrl_te_optimization/script/iter_train.py ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import argparse
4
+
5
+ parser = argparse.ArgumentParser('the main to train model')
6
+ parser.add_argument('--config_file',type=str,required=True)
7
+ parser.add_argument('--cuda',type=str,default=0,required=False)
8
+ parser.add_argument("--kfold_index",type=int,default=1,required=False)
9
+ args = parser.parse_args()
10
+
11
+ cuda_id = args.cuda if args.cuda is not None else utils.get_config_cuda(args.config_file)
12
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(cuda_id)
13
+
14
+
15
+ import time
16
+ import torch
17
+ import copy
18
+ import utils
19
+ from torch import optim
20
+ import numpy as np
21
+ from models import reader,train_val
22
+ from models.ScheduleOptimizer import ScheduledOptim,scheduleoptim_dict_str
23
+ from models.popen import Auto_popen
24
+ from models.loss import Dynamic_Task_Priority,Dynamic_Weight_Averaging
25
+
26
+
27
+ POPEN = Auto_popen(args.config_file)
28
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
29
+ POPEN.cuda_id = device
30
+
31
+
32
+ POPEN.kfold_index = args.kfold_index
33
+ if POPEN.kfold_cv:
34
+ if args.kfold_index is None:
35
+ raise NotImplementedError("please specify the kfold index to perform K fold cross validation")
36
+ POPEN.vae_log_path = POPEN.vae_log_path.replace(".log","_cv%d.log"%args.kfold_index)
37
+ #POPEN.vae_pth_path = POPEN.vae_pth_path.replace(".pth","_cv%d.pth"%args.kfold_index)
38
+
39
+
40
+ # Run name
41
+ if POPEN.run_name is None:
42
+ run_name = POPEN.model_type + time.strftime("__%Y_%m_%d_%H:%M")
43
+ else:
44
+ run_name = POPEN.run_name
45
+
46
+ # log dir
47
+ logger = utils.setup_logs(POPEN.vae_log_path)
48
+ logger.info(f" ===========================| device {device}{cuda_id} |=========================== ")
49
+ # built model dir or check resume
50
+ POPEN.check_experiment(logger)
51
+
52
+ # |=====================================|
53
+ # |=========== setup part ==========|
54
+ # |=====================================|
55
+ # read data
56
+ loader_set = {}
57
+ base_path = ['cycle_train_val.csv', 'cycle_test.csv']
58
+ base_csv = copy.deepcopy(POPEN.csv_path) #'cycle_MTL_transfer.csv'
59
+ for task in POPEN.cycle_set:
60
+ if (task in ['MPA_U', 'MPA_H', 'MPA_V', 'SubMPA_H']):
61
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3M/schedule_lr.ini')
62
+ datapopen.split_like = [path.replace('cycle', task) for path in base_path]
63
+ datapopen.kfold_index = args.kfold_index
64
+ datapopen.other_input_columns = POPEN.other_input_columns
65
+ datapopen.n_covar = POPEN.n_covar
66
+
67
+ elif (task in ['RP_293T', 'RP_muscle', 'RP_PC3']):
68
+ # base_csv = 'cycle_protein_coding.csv'
69
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/3R/schedule_MTL.ini')
70
+ datapopen.csv_path = base_csv.replace("cycle",task)
71
+ datapopen.kfold_index = args.kfold_index
72
+ datapopen.kfold_cv = POPEN.kfold_cv
73
+ datapopen.pad_to = POPEN.pad_to
74
+ datapopen.aux_task_columns = POPEN.aux_task_columns
75
+ datapopen.other_input_columns = POPEN.other_input_columns
76
+ datapopen.n_covar = POPEN.n_covar
77
+
78
+ elif (task in ['pcr3', '293']):
79
+ datapopen = Auto_popen('log/Backbone/RL_hard_share/karollus_RPs/rp_cycle.ini')
80
+ datapopen.csv_path = base_csv.replace("cycle",task)
81
+ datapopen.kfold_index = args.kfold_index
82
+ datapopen.kfold_cv = POPEN.kfold_cv
83
+ datapopen.aux_task_columns = POPEN.aux_task_columns
84
+ datapopen.other_input_columns = POPEN.other_input_columns
85
+ datapopen.pad_to = POPEN.pad_to
86
+ datapopen.n_covar = POPEN.n_covar
87
+
88
+
89
+ loader_set[task] = reader.get_dataloader(datapopen)
90
+
91
+
92
+ # =========== setup model ===========
93
+ # train_iter = iter(train_loader)
94
+ # X,Y = next(train_iter)
95
+ # -- pretrain --
96
+ if POPEN.pretrain_pth is not None:
97
+ # load pretran model
98
+ logger.info("===============================| pretrain |===============================")
99
+ logger.info(f" {POPEN.pretrain_pth}")
100
+ pretrain_popen = Auto_popen(os.path.join(utils.script_dir, POPEN.pretrain_pth))
101
+ if not os.path.exists(pretrain_popen.vae_pth_path):
102
+ if type(args.kfold_index) == int:
103
+ pretrain_popen.kfold_index = args.kfold_index
104
+ pretrain_model = torch.load(pretrain_popen.vae_pth_path, map_location=torch.device('cpu'))['state_dict']
105
+
106
+
107
+ if POPEN.model_type == pretrain_popen.model_type:
108
+ # if not POPEN.Resumable:
109
+ # # we only load pre-train for the first time
110
+ # # later we can resume
111
+ model = pretrain_model.to(device)
112
+ del pretrain_model
113
+
114
+ if (POPEN.cycle_set != pretrain_popen.cycle_set):
115
+ model.all_tasks = POPEN.cycle_set
116
+ model.tower = torch.nn.ModuleDict(
117
+ {POPEN.cycle_set[i] : model.tower[t] for i, t in enumerate(pretrain_popen.cycle_set)}
118
+ )
119
+
120
+ elif POPEN.modual_to_fix is not None:
121
+ # POPEN.model_type != pretrain_popen.model_type
122
+
123
+ model = POPEN.Model_Class(*POPEN.model_args)
124
+ for modual in POPEN.modual_to_fix:
125
+ if modual in dir(pretrain_model):
126
+ eval(f'model.{modual}').load_state_dict(
127
+ eval(f'model.{modual}').state_dict()
128
+ )
129
+
130
+ state_dict = {'epoch': 0,
131
+ 'validation_acc': 0,
132
+ 'state_dict': model.to('cpu'),
133
+ 'validation_loss': 0}
134
+ shared_pretrain_pth = POPEN.vae_pth_path.replace(f"_cv{args.kfold_index}", '')
135
+ if not os.path.exists(shared_pretrain_pth):
136
+ utils.snapshot(shared_pretrain_pth, state_dict)
137
+ utils.snapshot(POPEN.vae_pth_path, state_dict)
138
+
139
+ model = torch.load(POPEN.vae_pth_path, map_location=torch.device('cpu'))
140
+ model = model.to(device)
141
+
142
+ # -- end2end --
143
+ elif POPEN.model_type == "CrossStitch_Model":
144
+ backbone = {}
145
+ for t in POPEN.tasks:
146
+ task_popen = Auto_popen(POPEN.backbone_config[t])
147
+ task_model = task_popen.Model_Class(*task_popen.model_args)
148
+ utils.load_model(task_popen,task_model,logger)
149
+ backbone[t] = task_model.to(device)
150
+ POPEN.model_args = [backbone] + POPEN.model_args
151
+ model = POPEN.Model_Class(*POPEN.model_args).to(device)
152
+ else:
153
+ Model_Class = POPEN.Model_Class # DL_models.LSTM_AE
154
+ model = Model_Class(*POPEN.model_args).to(device)
155
+
156
+ if POPEN.Resumable:
157
+ model = utils.load_model(POPEN, model, logger)
158
+
159
+ # =========== fix parameters ===========
160
+ if isinstance(POPEN.modual_to_fix, list):
161
+ for modual in POPEN.modual_to_fix:
162
+ model = utils.fix_parameter(model,modual)
163
+ model = model.to(device)
164
+ logger.info(' \t \t ==============| %s fixed |============== \t \t \n'%POPEN.modual_to_fix)
165
+ # =========== set optimizer ===========
166
+ if POPEN.optimizer == 'Schedule':
167
+ optimizer = ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
168
+ betas=(0.9, 0.98),
169
+ eps=1e-09,
170
+ weight_decay=1e-4,
171
+ amsgrad=True),
172
+ n_warmup_steps=20)
173
+ elif type(POPEN.optimizer) == dict:
174
+ optimizer = eval(scheduleoptim_dict_str.format(**POPEN.optimizer))
175
+ else:
176
+ optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
177
+ lr=POPEN.lr,
178
+ betas=(0.9, 0.98),
179
+ eps=1e-09,
180
+ weight_decay=POPEN.l2)
181
+ if POPEN.loss_schema == 'DTP':
182
+ POPEN.loss_schedualer = Dynamic_Task_Priority(POPEN.tasks,POPEN.gamma,POPEN.chimerla_weight)
183
+ elif POPEN.loss_schema == 'DWA':
184
+ POPEN.loss_schedualer = Dynamic_Weight_Averaging(POPEN.tasks,POPEN.tau,POPEN.chimerla_weight)
185
+ # =========== resume ===========
186
+ best_loss = np.inf
187
+ best_acc = 0
188
+ best_epoch = 0
189
+ previous_epoch = 0
190
+ if POPEN.Resumable:
191
+ previous_epoch,best_loss,best_acc = utils.resume(POPEN, optimizer,logger)
192
+
193
+
194
+ # |=====================================|
195
+ # |========== training part ==========|
196
+ # |=====================================|
197
+ for epoch in range(POPEN.max_epoch-previous_epoch+1):
198
+ epoch += previous_epoch
199
+
200
+ #
201
+ logger.info("===============================| epoch {} |===============================".format(epoch))
202
+
203
+
204
+ train_val.iter_train(loader_set,model=model,optimizer=optimizer,popen=POPEN,epoch=epoch)
205
+
206
+ # -----------| validate |-----------
207
+ logger.info("===============================| start validation |===============================")
208
+ verbose_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch, which_set=1)
209
+ test_dict = train_val.cycle_validate(loader_set,model,optimizer,popen=POPEN,epoch=epoch, which_set=2)
210
+
211
+ if np.any(['r2' in key for key in verbose_dict.keys()]):
212
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'r2' in key])
213
+ else:
214
+ val_avg_acc = np.mean([values for key, values in verbose_dict.items() if 'acc' in key])
215
+ val_total_loss = verbose_dict['Total']
216
+
217
+
218
+ DICT ={"ran_epoch":epoch,"n_current_steps":optimizer.n_current_steps,"delta":optimizer.delta} if type(optimizer) == ScheduledOptim else {"ran_epoch":epoch}
219
+ POPEN.update_ini_file(DICT,logger)
220
+
221
+
222
+ # -----------| compare the result |-----------
223
+ if (best_loss > val_total_loss) :
224
+ # update best performance
225
+ best_loss = min(best_loss,val_total_loss)
226
+ best_acc = max(best_acc,val_avg_acc)
227
+ best_epoch = epoch
228
+
229
+ # save
230
+ utils.snapshot(POPEN.vae_pth_path, {
231
+ 'epoch': epoch + 1,
232
+ 'validation_acc': val_avg_acc,
233
+ # 'state_dict': model.state_dict(),
234
+ 'state_dict': model,
235
+ 'validation_loss': val_total_loss,
236
+ 'optimizer': optimizer.state_dict(),
237
+ })
238
+
239
+ # update the popen
240
+ POPEN.update_ini_file({'run_name':run_name,
241
+ "ran_epoch":epoch,
242
+ "best_acc":best_acc},
243
+ logger)
244
+
245
+ elif (epoch - best_epoch >= 30)&((type(optimizer) == ScheduledOptim)):
246
+ optimizer.increase_delta()
247
+
248
+ elif (epoch - best_epoch >= 60)&(epoch > POPEN.max_epoch/2):
249
+ # at the late phase of training
250
+ logger.info("<<<<<<<<<<< Early Stopping >>>>>>>>>>")
251
+ break
model/src/mrl_te_optimization/script/main_train.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys
2
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
3
+ import argparse
4
+
5
+ parser = argparse.ArgumentParser('the main to train model')
6
+ parser.add_argument('--config_file',type=str,required=True)
7
+ parser.add_argument('--cuda',type=int,default=None,required=False)
8
+ parser.add_argument("--kfold_index",type=int,default=None,required=False)
9
+ args = parser.parse_args()
10
+
11
+ cuda_id = args.cuda
12
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(cuda_id)
13
+
14
+
15
+ import time
16
+ import torch
17
+ import utils
18
+ from torch import optim
19
+ import numpy as np
20
+ from models import Modules,reader,train_val
21
+ from models.ScheduleOptimizer import ScheduledOptim,scheduleoptim_dict_str
22
+ from models.popen import Auto_popen
23
+ from models.loss import Dynamic_Task_Priority,Dynamic_Weight_Averaging
24
+
25
+
26
+ POPEN = Auto_popen(args.config_file)
27
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
28
+ torch.set_num_interop_threads(4)
29
+ POPEN.cuda_id = device
30
+
31
+
32
+ POPEN.kfold_index = args.kfold_index
33
+ if POPEN.kfold_cv:
34
+ if args.kfold_index is None:
35
+ raise NotImplementedError("please specify the kfold index to perform K fold cross validation")
36
+ POPEN.vae_log_path = POPEN.vae_log_path.replace(".log","_cv%d.log"%args.kfold_index)
37
+ #POPEN.vae_pth_path = POPEN.vae_pth_path.replace(".pth","_cv%d.pth"%args.kfold_index)
38
+
39
+
40
+ # Run name
41
+ if POPEN.run_name is None:
42
+ run_name = POPEN.model_type + time.strftime("__%Y_%m_%d_%H:%M")
43
+ else:
44
+ run_name = POPEN.run_name
45
+
46
+ # log dir
47
+ logger = utils.setup_logs(POPEN.vae_log_path)
48
+ logger.info(f" ==============<<< device used: {device}:{cuda_id} >>>============== ")
49
+ # built model dir or check resume
50
+ POPEN.check_experiment(logger)
51
+ # |=====================================|
52
+ # |=========== setup part ==========|
53
+ # |=====================================|
54
+ # read data
55
+ train_loader,val_loader,test_loader = reader.get_dataloader(POPEN)
56
+ # =========== setup model ===========
57
+ # train_iter = iter(train_loader)
58
+ # X,Y = next(train_iter)
59
+ # -- pretrain --
60
+ if POPEN.pretrain_pth is not None:
61
+ # load pretran model
62
+ pretrain_popen = Auto_popen(os.path.join(utils.script_dir, POPEN.pretrain_pth))
63
+ pretrain_model = pretrain_popen.Model_Class(*pretrain_popen.model_args)
64
+
65
+ if not os.path.exists(pretrain_popen.vae_pth_path):
66
+ if type(args.kfold_index) == int:
67
+ pretrain_popen.kfold_index = args.kfold_index
68
+ pretrain_model = utils.load_model(pretrain_popen,pretrain_model,logger)
69
+
70
+
71
+
72
+ if POPEN.Model_Class == pretrain_popen.Model_Class:
73
+ # if not POPEN.Resumable:
74
+ # # we only load pre-train for the first time
75
+ # # later we can resume
76
+ model = pretrain_model.to(device)
77
+ del pretrain_model
78
+ elif POPEN.modual_to_fix is not None:
79
+ # POPEN.model_type != pretrain_popen.model_type
80
+
81
+ model = POPEN.Model_Class(*POPEN.model_args)
82
+ for modual in POPEN.modual_to_fix:
83
+ if modual in dir(pretrain_model):
84
+ eval(f'model.{modual}').load_state_dict(
85
+ eval(f'model.{modual}').state_dict()
86
+ )
87
+
88
+ state_dict = {'epoch': 0,
89
+ 'validation_acc': 0,
90
+ 'state_dict': model.to('cpu'),
91
+ 'validation_loss': np.inf}
92
+ shared_pretrain_pth = POPEN.vae_pth_path.replace(f"_cv{args.kfold_index}", '')
93
+ if not os.path.exists(shared_pretrain_pth):
94
+ utils.snapshot(shared_pretrain_pth, state_dict)
95
+ utils.snapshot(POPEN.vae_pth_path, state_dict)
96
+
97
+ model = torch.load(POPEN.vae_pth_path, map_location=torch.device('cpu'))['state_dict']
98
+ model = model.to(device)
99
+
100
+
101
+ # -- end2end --
102
+ elif POPEN.model_type == "CrossStitch_Model":
103
+ backbone = {}
104
+ for t in POPEN.tasks:
105
+ task_popen = Auto_popen(POPEN.backbone_config[t])
106
+ task_model = task_popen.Model_Class(*task_popen.model_args)
107
+ task_model = utils.load_model(task_popen,task_model,logger)
108
+ backbone[t] = task_model.to(device)
109
+ POPEN.model_args = [backbone] + POPEN.model_args
110
+ model = POPEN.Model_Class(*POPEN.model_args).to(device)
111
+ else:
112
+ Model_Class = POPEN.Model_Class # DL_models.LSTM_AE
113
+ model = Model_Class(*POPEN.model_args).to(device)
114
+
115
+ if POPEN.Resumable:
116
+ model = utils.load_model(POPEN, model, logger)
117
+
118
+ # =========== fix parameters ===========
119
+ if isinstance(POPEN.modual_to_fix, list):
120
+ for modual in POPEN.modual_to_fix:
121
+ model = utils.fix_parameter(model,modual)
122
+ logger.info(' \t \t ==============<<< %s part is fixed>>>============== \t \t \n'%POPEN.modual_to_fix)
123
+ # =========== set optimizer ===========
124
+ if POPEN.optimizer == 'Schedule':
125
+ optimizer = ScheduledOptim(optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
126
+ betas=(0.9, 0.98),
127
+ eps=1e-09,
128
+ weight_decay=1e-4,
129
+ amsgrad=True),
130
+ n_warmup_steps=20)
131
+ elif type(POPEN.optimizer) == dict:
132
+ optimizer = eval(scheduleoptim_dict_str.format(**POPEN.optimizer))
133
+ else:
134
+ optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()),
135
+ lr=POPEN.lr,
136
+ betas=(0.9, 0.98),
137
+ eps=1e-09,
138
+ weight_decay=POPEN.l2)
139
+ if POPEN.loss_schema == 'DTP':
140
+ POPEN.loss_schedualer = Dynamic_Task_Priority(POPEN.tasks,POPEN.gamma,POPEN.chimerla_weight)
141
+ elif POPEN.loss_schema == 'DWA':
142
+ POPEN.loss_schedualer = Dynamic_Weight_Averaging(POPEN.tasks,POPEN.tau,POPEN.chimerla_weight)
143
+ # =========== resume ===========
144
+ best_loss = np.inf
145
+ best_acc = 0
146
+ best_epoch = 0
147
+ previous_epoch = 0
148
+ if POPEN.Resumable:
149
+ previous_epoch,best_loss,best_acc = utils.resume(POPEN, optimizer,logger)
150
+
151
+
152
+ # |=====================================|
153
+ # |========== training part ==========|
154
+ # |=====================================|
155
+ for epoch in range(POPEN.max_epoch-previous_epoch+1):
156
+ epoch += previous_epoch
157
+
158
+ # ----------| train |----------
159
+ logger.info("===============================| epoch {} |===============================".format(epoch))
160
+ train_val.train(dataloader=train_loader,model=model,optimizer=optimizer,popen=POPEN,epoch=epoch)
161
+
162
+ # -----------| validate |-----------
163
+
164
+ if epoch % POPEN.config_dict['setp_to_check'] == 0:
165
+ logger.info("===============================| start validation |===============================")
166
+ val_total_loss,val_avg_acc = train_val.validate(val_loader,model,popen=POPEN,epoch=epoch)
167
+ _,_ = train_val.validate(test_loader,model,popen=POPEN,epoch=epoch)
168
+
169
+ DICT ={"ran_epoch":epoch,"n_current_steps":optimizer.n_current_steps,"delta":optimizer.delta} if type(optimizer) == ScheduledOptim else {"ran_epoch":epoch}
170
+ POPEN.update_ini_file(DICT,logger)
171
+
172
+ # -----------| compare the result |-----------
173
+ if (best_loss > val_total_loss): #| (best_acc < val_avg_acc):
174
+ # update best performance
175
+ best_loss = min(best_loss,val_total_loss)
176
+ best_acc = max(best_acc,val_avg_acc)
177
+ best_epoch = epoch
178
+
179
+ # save
180
+ utils.snapshot(POPEN.vae_pth_path, {
181
+ 'epoch': epoch + 1,
182
+ 'validation_acc': val_avg_acc,
183
+ 'state_dict': model.to('cpu'),
184
+ 'validation_loss': val_total_loss,
185
+ # 'optimizer': optimizer.state_dict(),
186
+ })
187
+
188
+ # update the popen
189
+ POPEN.update_ini_file({'run_name':run_name,
190
+ "ran_epoch":epoch,
191
+ "best_acc":best_acc,
192
+ "cuda_id":cuda_id},
193
+ logger)
194
+
195
+ elif (epoch - best_epoch >= 30)&((type(optimizer) == ScheduledOptim)):
196
+ optimizer.increase_delta()
197
+
198
+ elif (epoch - best_epoch >= 60)&(epoch > POPEN.max_epoch/2):
199
+ # at the late phase of training
200
+ logger.info("<<<<<<<<<<< Early Stopping >>>>>>>>>>")
201
+ break
model/src/mrl_te_optimization/script/preprocessing_MPA.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import torch
4
+ import PATH
5
+ import utils
6
+ import numpy as np
7
+ import pandas as pd
8
+ import seaborn as sns
9
+ from matplotlib import pyplot as plt
10
+
11
+ from sklearn.preprocessing import StandardScaler
12
+
13
+
14
+ # ========== 1. preprocessing MPA datasets ==========
15
+
16
+ # read csv and load in to a dictionary
17
+ Ex_data_dir = utils.data_dir
18
+ csv_path_ls = [os.path.join(Ex_data_dir,csv) for csv in ['GSM3130435_egfp_unmod_1.csv','GSM3130443_designed_library.csv','GSM4084997_varying_length_25to100.csv']]
19
+ for path in csv_path_ls:
20
+ assert os.path.exists(path), f"The file {path} is not properly downloaded"
21
+
22
+ df_dict = {
23
+ csv_path.split("_")[-1].replace(".csv","") : pd.read_csv(csv_path,low_memory=False) for csv_path in csv_path_ls
24
+ }
25
+ # align the columns name across datasets
26
+ df_dict['library'].rename({'total':'total_reads'},axis=1,inplace=True)
27
+ df_dict['25to100']['r13'] = np.zeros((df_dict['25to100'].shape[0],))
28
+
29
+
30
+
31
+ # - MPA_U -
32
+ df = df_dict['1']
33
+ df.sort_values('total_reads', inplace=True, ascending=False)
34
+ df.reset_index(inplace=True, drop=True)
35
+
36
+
37
+ ## train_val test spliting
38
+ # the most abundant 5'UTR is used as test set
39
+ test_df = df.iloc[:20000]
40
+ train_val_df = df.iloc[20000:280000]
41
+
42
+
43
+
44
+ # - MPA_H -
45
+ df = df_dict['library']
46
+ # taking the natrual utr and sort by reads count
47
+ human_lib = df[(df['library'] == 'human_utrs') | (df['library'] == 'snv')]
48
+ human_lib = human_lib.sort_values('total_reads', ascending=False).reset_index(drop=True)
49
+
50
+ # the top 25k abundant reads as test set
51
+ sub = human_lib.iloc[:25000]
52
+ remaining = human_lib.iloc[25000:]
53
+
54
+
55
+ # - MPA_V -
56
+ df1 = df_dict['25to100']
57
+ # take the random seqs
58
+ df = df1[df1['set']=='random']
59
+
60
+ ## Filter out UTRs with too few less reads
61
+ df=df[df['total_reads']>=10]
62
+
63
+ df['utr100'] = 75*'N' +df['utr']
64
+ df['utr100'] = df['utr100'].str[-100:]
65
+ df.sort_values('total_reads', inplace=True, ascending=False)
66
+ df.reset_index(inplace=True, drop=True)
67
+
68
+ ## some natural sequence
69
+ human = df1[df1['set']=='human']
70
+ ## Filter out UTRs with too few less reads
71
+ human=human[human['total_reads']>=10]
72
+ human['utr100'] = 75*'N' +human['utr']
73
+ human['utr100'] = human['utr100'].str[-100:]
74
+ human.sort_values('total_reads', inplace=True, ascending=False)
75
+ human.reset_index(inplace=True, drop=True)
76
+
77
+ e_test = pd.DataFrame(columns=df.columns)
78
+ for i in range(25,101):
79
+ tmp = df[df['len']==i]
80
+ tmp.sort_values('total_reads', inplace=True, ascending=False)
81
+ tmp.reset_index(inplace=True, drop=True)
82
+ e_test = e_test.append(tmp.iloc[:100])
83
+
84
+ subhuman = pd.DataFrame(columns=human.columns)
85
+ for i in range(25,101):
86
+ tmp = human[human['len']==i]
87
+ tmp.sort_values('total_reads', inplace=True, ascending=False)
88
+ tmp.reset_index(inplace=True, drop=True)
89
+ subhuman = subhuman.append(tmp.iloc[:100])
90
+
91
+ e_train = pd.concat([df, e_test, e_test]).drop_duplicates(keep=False)
92
+
93
+ vleng_test = pd.concat([e_test,subhuman])
94
+ bins = np.arange(24, 105, 20)
95
+ labels = [ '25-44' , '45-64', '65-84', '85-100']
96
+ vleng_test['rng'] = pd.cut(vleng_test['len'], bins=bins)
97
+
98
+ # saving all
99
+ e_test.to_csv(os.path.join(Ex_data_dir,"MPA_V_test.csv"),index=False)
100
+ e_train.to_csv(os.path.join(Ex_data_dir,"MPA_V_train_val.csv"),index=False)
101
+
102
+ sub.to_csv(os.path.join(Ex_data_dir,"MPA_H_test.csv"),index=False)
103
+ remaining.to_csv(os.path.join(Ex_data_dir,"MPA_H_train_val.csv"),index=False)
104
+
105
+ # sub sample MPA-H
106
+ remaining.sample(frac=0.1).to_csv(os.path.join(Ex_data_dir,"SubMPA_H_train_val.csv"),index=False)
107
+ sub.to_csv(os.path.join(Ex_data_dir,"SubMPA_H_test.csv"),index=False)
108
+
109
+ test_df.to_csv(os.path.join(Ex_data_dir,"MPA_U_test.csv"),index=False)
110
+ train_val_df.to_csv(os.path.join(Ex_data_dir,"MPA_U_train_val.csv"),index=False)
111
+
112
+
113
+
114
+ print("The preprocssing for MPA tasks is Finished !!")
115
+ print(f"The files are saved to {utils.data_dir}")
model/src/mrl_te_optimization/script/preprocessing_RP.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import pandas as pd
4
+ import PATH
5
+ import utils
6
+ from Bio import SeqIO
7
+ from scipy import sparse
8
+
9
+
10
+ pj = lambda x: os.path.join(utils.data_dir,x)
11
+
12
+
13
+ # read in the sequence
14
+ fa = SeqIO.parse(pj('gencode_v17_5utr_15bpcds.fa'),'fasta')
15
+ tx_seq=dict()
16
+ for seq_record in fa:
17
+ tx=seq_record.id
18
+ seq=seq_record.seq
19
+ if len(seq)<30: #skip when it too short
20
+ continue
21
+ if "ATG" not in seq:
22
+ continue
23
+ if tx not in tx_seq or len(seq)>len(tx_seq[tx]):
24
+ tx_seq[tx]=seq
25
+
26
+ # txt records TE and rkpm
27
+ RP_data_path = {}
28
+ RP_data_path['muscle'] = pj('df_counts_and_len.TE_sorted.Muscle.with_annot.txt')
29
+ RP_data_path['PC3'] = pj('df_counts_and_len.TE_sorted.pc3.with_annot.txt')
30
+ RP_data_path['293T'] = pj('df_counts_and_len.TE_sorted.HEK_Andrev2015.with_annot.txt')
31
+
32
+ # read the hand crafted features
33
+ # (57415, 33)
34
+ feat_mat = pd.read_csv("util/Zhang_et_al_features.csv",index_col=0)
35
+ feat_mat.insert(0, 'seq', [tx_seq[x].upper().__str__() for x in feat_mat.index.values])
36
+
37
+
38
+ processed_dict = {}
39
+ for cell_line, csv_path in RP_data_path.items():
40
+
41
+ assert os.path.exists(csv_path), f"The raw data file for {cell_line} does not exist!"
42
+
43
+ print(f"processing {cell_line}...\n")
44
+ RP_raw_data = pd.read_table(csv_path, sep=' ')
45
+ RP_raw_data.loc[:,'T_id'] = RP_raw_data.index.values
46
+ # adding sequence in
47
+ RP_raw_data = RP_raw_data.query('rpkm_rnaseq >5 & rpkm_riboseq > 0.1')
48
+ RP_raw_data['log_te'] = np.log(RP_raw_data.te.values)
49
+
50
+ RP_feat_merge = RP_raw_data.merge(feat_mat,left_on=['T_id'],right_index=True,suffixes=["",""])
51
+ RP_feat_merge.sort_values('rpkm_rnaseq', ascending=False, inplace=True)
52
+
53
+ # drop duplicated UTRs
54
+ RP_raw_dedup = RP_feat_merge.drop_duplicates(RP_feat_merge.columns[17:], keep='first')
55
+ RP_raw_dedup['utr'] = RP_raw_dedup['seq'].apply(lambda x: x[-216:-16]) # max len 200
56
+ RP_raw_dedup['utr_len'] = RP_raw_dedup.utr.apply(len)
57
+ RP_raw_dedup.query('`utr_len`>30')
58
+ RP_raw_dedup = RP_raw_dedup.drop_duplicates(['utr'], keep='first')
59
+
60
+ # save them
61
+ processed_dict[cell_line] = RP_raw_dedup
62
+ processed_dict[cell_line].to_csv(pj(f"RP_{cell_line}_MTL_transfer.csv"))
63
+
64
+ print("The preprocssing for RP tasks is Finished !!")
65
+ print(f"The files are saved to {utils.data_dir}")
model/src/mrl_te_optimization/script/run-TF-modisco.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import pandas as pd
4
+ import numpy as np
5
+ import PATH
6
+ import torch
7
+ import argparse
8
+ import h5py
9
+ #
10
+ from subprocess import DEVNULL, STDOUT, check_call
11
+ from models import train_val
12
+ from models.popen import Auto_popen
13
+ from models import max_activation_patch as MAP
14
+ #
15
+ from sklearn.linear_model import Lasso, Ridge, ElasticNet, LassoCV, RidgeCV, ElasticNetCV
16
+ import warnings
17
+ warnings.filterwarnings('ignore')
18
+
19
+
20
+ #
21
+ parser = argparse.ArgumentParser('the script to evlauate the effect of ')
22
+ parser.add_argument("-c", "--config", type=str, required=True, help='the model config file: xxx.ini')
23
+ parser.add_argument("-s", "--set", type=int, default=2, help='train - 0 ,val - 1, test - 2 ')
24
+ parser.add_argument("-p", "--n_max_act", type=int, default=500, help='the number of seq')
25
+ parser.add_argument("-k", "--kfold_cv", type=int, default=1, help='the repeat')
26
+ parser.add_argument("-d", "--device", type=str, default='cpu', help='the device to use to extract featmap, digit or cpu')
27
+ args = parser.parse_args()
28
+
29
+ config_path = args.config
30
+ save_path = config_path.replace(".ini", "_coef")
31
+ config = Auto_popen(config_path)
32
+ config.batch_size = 256
33
+ config.kfold_cv = 'train_val'
34
+ all_task = config.cycle_set
35
+
36
+ task_channel_effect = {}
37
+ task_performance = {}
38
+
39
+ # path check
40
+ if os.path.exists(config_path) and not os.path.exists(save_path):
41
+ os.mkdir(save_path)
42
+
43
+ for task in all_task:
44
+
45
+ # .... format featmap as data ....
46
+ print(f"\n\nevaluating for task: {task}")
47
+ # re-instance the map for each task
48
+ map_task = MAP.Maximum_activation_patch(popen=config, which_layer=4,
49
+ n_patch=args.n_max_act,
50
+ kfold_index=args.kfold_cv,
51
+ device_string=args.device)
52
+
53
+ # extract feature map and rl decision chain
54
+ # get X
55
+ model, dataloader= map_task.loading(task=task, which_set=args.set)
56
+ max_seq_len = map_task.df[config.seq_col].apply(len).max()
57
+
58
+ X_ls = []
59
+ for Data in dataloader:
60
+ # iter each batch
61
+ x,y = train_val.put_data_to_cuda(Data, map_task.popen,False)
62
+ X_ls.append(x.detach().cpu().numpy())
63
+ X = np.concatenate(X_ls, axis=0)
64
+ X = np.transpose(X, (0,2,1))
65
+
66
+ attribute = map_task.get_input_grad(task=task, focus=False, fm=X, starting_layer=0)
67
+ X = X[:, :, -1*max_seq_len:]
68
+ attribute = attribute[:,:, -1*max_seq_len:]
69
+
70
+ x_npz_path = os.path.join(save_path, f"{task}_set{args.set}_x.npz")
71
+ grad_npz_path = os.path.join(save_path, f"{task}_set{args.set}_grad.npz")
72
+ np.savez(x_npz_path, X)
73
+ np.savez(grad_npz_path, attribute)
74
+
75
+
76
+
77
+ for n_seqlet in range(500, 4000, 500):
78
+ outfile = os.path.join(save_path, f"{task}_n{n_seqlet}_tfmodisco.h5")
79
+ command = f"modisco motifs -s {x_npz_path} -a {grad_npz_path} -n {n_seqlet} -o {outfile}"
80
+
81
+ check_call(command.split(), stdout=DEVNULL, stderr=STDOUT)
82
+
83
+ with h5py.File(outfile, "r") as f:
84
+ print(f.keys())
85
+ if 'pos_patterns' in f.keys():
86
+ pos_motif = f['pos_patterns']
87
+ n_pos = len(pos_motif.keys())
88
+ else:
89
+ n_pos = -1
90
+
91
+ if 'neg_patterns' in f.keys():
92
+ neg_motif = f['neg_patterns']
93
+ n_neg = len(neg_motif.keys())
94
+ else:
95
+ n_neg = -1
96
+ f.close()
97
+
98
+ print(f"discover {n_pos} pos pattern and {n_neg} neg patterns for n = {n_seqlet}")
99
+ print(f'done for {task}')
model/src/mrl_te_optimization/script/train_kmer_classifer.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ # os.environ["CUDA_VISIBLE_DEVICES"] = str(3)
3
+ import pytorch_lightning as pl
4
+ from torch.nn import functional as F
5
+ import PATH, utils
6
+ import torch
7
+ from torch import nn, optim
8
+ from models import reader
9
+ from models.popen import Auto_popen
10
+ import pandas as pd
11
+ import numpy as np
12
+ from collections import OrderedDict
13
+ import torchmetrics
14
+ from torch.utils.data import DataLoader
15
+ from pytorch_lightning import callbacks
16
+ from sklearn.model_selection import train_test_split
17
+ import argparse
18
+
19
+ ################
20
+ if __name__ == '__main__':
21
+ global_seed = int(sys.argv[6])
22
+ torch.manual_seed(global_seed)
23
+ torch.cuda.manual_seed_all(global_seed)
24
+
25
+
26
+ ###### data ######
27
+ def get_kmer_input_shape(csv_name, kernel_size):
28
+ MPA_U_test = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_test.csv"))
29
+
30
+ # dataset
31
+ test_DS = reader.kmer_scan_dataset(MPA_U_test, seq_col='utr',
32
+ kmer_size=kernel_size, aux_columns='rl')
33
+ return np.multiply(*test_DS[0][0].shape)
34
+
35
+ def get_kmer_dls(csv_name, kernel_size, seed, seq_col, label_col):
36
+
37
+ print("seed = %s"%seed)
38
+ train_df, val_df, test_df = reader.split_DF(csv_name, None, [0.8,0.1,0.1], kfold_cv=True, kfold_index=seed,seed=43)
39
+
40
+ # dataset
41
+ train_DS = reader.kmer_scan_dataset(train_df, seq_col=seq_col, kmer_size=kernel_size, aux_columns=label_col)
42
+ val_DS = reader.kmer_scan_dataset(val_df, seq_col=seq_col, kmer_size=kernel_size, aux_columns=label_col)
43
+ test_DS = reader.kmer_scan_dataset(test_df, seq_col=seq_col, kmer_size=kernel_size, aux_columns=label_col)
44
+
45
+ # dataloader
46
+ train_dl = DataLoader(train_DS, batch_size = 64, shuffle=True)
47
+ val_dl = DataLoader(val_DS, batch_size = 64, shuffle=False)
48
+ test_dl = DataLoader(test_DS, batch_size = 64, shuffle=False)
49
+ return train_dl, val_dl, test_dl
50
+
51
+ ##################
52
+ # PyTorch Light model #
53
+ class mlp_models(pl.LightningModule):
54
+ def __init__(self, dims):
55
+ super().__init__()
56
+ self.dims = dims
57
+ n_layer = len(dims) - 1
58
+ self.train_r2 = torchmetrics.R2Score()
59
+ self.val_r2 = torchmetrics.R2Score()
60
+ # add layers
61
+ nns = []
62
+ i = 1
63
+ for in_dim , out_dim in zip(dims[:-1], dims[1:]):
64
+ nns.append( (f"Linear_{i}", nn.Linear(in_dim, out_dim)) )
65
+ if i < n_layer:
66
+ nns += [(f"BN_{i}", nn.BatchNorm1d(out_dim)), (f"act_{i}", nn.Mish()) ]
67
+ i += 1
68
+
69
+ self.network = nn.Sequential(OrderedDict(nns))
70
+
71
+ def forward(self, x):
72
+ return self.network(x)
73
+
74
+ def configure_optimizers(self):
75
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
76
+ return optimizer
77
+
78
+ def training_step(self, train_batch, batch_idx):
79
+ x, y = train_batch
80
+ b = x.shape[0]
81
+ x = x.view(b, -1).float()
82
+ y = y.view(b,).float()
83
+ y_hat = self.network(x).view(b,)
84
+ loss = F.mse_loss(y_hat, y.float())
85
+ r2 = self.train_r2(y_hat, y)
86
+ self.log('train_loss', loss)
87
+ self.log('train_acc', self.train_r2)
88
+ return loss
89
+
90
+ def validation_step(self, val_batch, batch_idx):
91
+ x, y = val_batch
92
+ b = x.shape[0]
93
+ x = x.view(b, -1).float()
94
+ y = y.view(b,).float()
95
+ y_hat = self.network(x).view(b,)
96
+
97
+ loss = F.mse_loss(y_hat, y.float())
98
+ r2 = self.val_r2(y_hat, y)
99
+ self.log('val_loss', loss)
100
+ self.log('val_acc', self.val_r2)
101
+
102
+ # PyTorch Light model #
103
+ class rnn_models(pl.LightningModule):
104
+ def __init__(self, k, hidden=128):
105
+ super().__init__()
106
+ self.save_hyperparameters()
107
+ self.train_F1 = torchmetrics.F1Score()
108
+ self.train_AUROC = torchmetrics.AUROC()
109
+ self.train_ACC = torchmetrics.Accuracy()
110
+
111
+ self.val_F1 = torchmetrics.F1Score()
112
+ self.val_AUROC = torchmetrics.AUROC()
113
+ self.val_ACC = torchmetrics.Accuracy()
114
+
115
+ self.test_F1 = torchmetrics.F1Score()
116
+ self.test_AUROC = torchmetrics.AUROC()
117
+ self.test_ACC = torchmetrics.Accuracy()
118
+
119
+ tower = { f"GRU_layer" : nn.GRU(input_size=4**k, hidden_size=hidden,
120
+ num_layers=2,batch_first=True),
121
+ f"fc_out" : nn.Linear(hidden, 1),
122
+ }
123
+ self.sigmod = nn.Sigmoid()
124
+ self.tower = nn.ModuleDict(tower)
125
+
126
+ def forward(self, x):
127
+
128
+ x = x.transpose(1,2) # B C L -> B L C
129
+ h_prim,(c1,c2) = self.tower['GRU_layer'](x)
130
+ out = self.tower['fc_out'](c2)
131
+ return self.sigmod(out)
132
+
133
+ def configure_optimizers(self):
134
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
135
+ return optimizer
136
+
137
+ def training_step(self, train_batch, batch_idx):
138
+ x, y = train_batch
139
+ b = x.shape[0]
140
+ x = x.float()
141
+ y = y.view(b,)
142
+ y_hat = self.forward(x).view(b,)
143
+
144
+ loss = F.binary_cross_entropy(y_hat, y.float())
145
+ F1 = self.train_F1(y_hat, y.long())
146
+ auroc = self.train_AUROC(y_hat, y.long())
147
+ acc = self.train_ACC(y_hat, y.long())
148
+ self.log('train_loss', loss)
149
+ self.log('train_f1', self.train_F1)
150
+ self.log('train_AUROC', self.train_AUROC)
151
+ self.log('train_ACC', self.train_ACC)
152
+ return loss
153
+
154
+ def validation_step(self, val_batch, batch_idx):
155
+ x, y = val_batch
156
+ b = x.shape[0]
157
+ x = x.float()
158
+ y = y.view(b,)
159
+ y_hat = self.forward(x).view(b,)
160
+
161
+ loss = F.binary_cross_entropy(y_hat, y.float())
162
+ self.val_F1(y_hat, y.long())
163
+ self.val_AUROC(y_hat, y.long())
164
+ self.val_ACC(y_hat, y.long())
165
+ self.log('val_loss', loss)
166
+ self.log('val_F1', self.val_F1)
167
+ self.log('val_AUROC', self.val_AUROC)
168
+ self.log('val_ACC', self.val_ACC)
169
+
170
+ def test_step(self, test_batch, batch_idx):
171
+ x, y = test_batch
172
+ b = x.shape[0]
173
+ x = x.float()
174
+ y = y.view(b,)
175
+ y_hat = self.forward(x).view(b,)
176
+
177
+ loss = F.binary_cross_entropy(y_hat, y.float())
178
+ self.test_F1(y_hat, y.long())
179
+ self.test_AUROC(y_hat, y.long())
180
+ self.test_ACC(y_hat, y.long())
181
+ self.log('test_loss', loss)
182
+ self.log('test_F1', self.test_F1)
183
+ self.log('test_AUROC', self.test_AUROC)
184
+ self.log('test_ACC', self.test_ACC)
185
+
186
+ ################
187
+ if __name__ == '__main__':
188
+
189
+ csv_name = sys.argv[1]
190
+ kmer_size = int(sys.argv[2])
191
+ hidden = int(sys.argv[3])
192
+ seq_col = sys.argv[4]
193
+ label_col = sys.argv[5]
194
+
195
+
196
+
197
+ train_dl, val_dl, test_dl = get_kmer_dls(csv_name, kmer_size, global_seed, seq_col, label_col)
198
+
199
+
200
+ #### hyper-params ####
201
+ Input_length = np.multiply(*train_dl.dataset[0][0].shape)
202
+ # dims = [Input_length] + hidden + [1]
203
+
204
+ model = rnn_models(kmer_size, hidden)
205
+ default_root_dir="/data/users/wergillius/UTR_VAE/pth/Kmer_Alan"
206
+ # default_root_dir="/ssd/users/wergillius/Project/MTtrans/evaluation/Kmer_results"
207
+ data_name = os.path.basename(csv_name).split("_")[0]
208
+ log_dir = os.path.join(default_root_dir, f"{data_name}_K{kmer_size}H{hidden}_sd{global_seed}")
209
+ ################
210
+
211
+ # training
212
+ trainer = pl.Trainer(accelerator='gpu',devices=1, auto_select_gpus=False, #
213
+ default_root_dir=log_dir,
214
+ limit_train_batches=0.5, max_epochs=600,
215
+ #plugins=pl.plugins.DDPPlugin(find_unused_parameters=False),
216
+ callbacks=[
217
+ callbacks.ModelCheckpoint(monitor="val_loss",save_top_k=1),
218
+ callbacks.EarlyStopping(monitor="val_F1", mode="min", patience=15)
219
+ ])
220
+
221
+
222
+ trainer.fit(model, train_dl, val_dl)
223
+
224
+ ckpt_dir = os.path.join(trainer.log_dir,'checkpoints')
225
+ ckpt_path = os.path.join(ckpt_dir, [file for file in os.listdir(ckpt_dir) if file.endswith('.ckpt')][0])
226
+ print('model saved to : %s\n'%ckpt_path)
227
+ # trainer.validate(model, test_dl)
228
+
229
+ saved_model = rnn_models.load_from_checkpoint(ckpt_path)
230
+ trainer.validate(saved_model, val_dl)
231
+ trainer.test(saved_model, test_dl)
232
+
233
+ # debugging args:
234
+ # "/data/users/wergillius/UTR_VAE/Alan_dataset/AlanAll_binary_10pctg.csv",
235
+ # "3",
236
+ # "64",
237
+ # "seq",
238
+ # "Binary_10pc",
239
+ # "1"
model/src/mrl_te_optimization/script/train_kmer_models.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ # os.environ["CUDA_VISIBLE_DEVICES"] = str(3)
3
+ import pytorch_lightning as pl
4
+ from torch.nn import functional as F
5
+ import PATH, utils
6
+ import torch
7
+ from torch import nn, optim
8
+ from models import reader
9
+ from models.popen import Auto_popen
10
+ import pandas as pd
11
+ import numpy as np
12
+ from collections import OrderedDict
13
+ import torchmetrics
14
+ from torch.utils.data import DataLoader
15
+ from pytorch_lightning import callbacks
16
+
17
+
18
+ ###### data ######
19
+ def get_kmer_input_shape(csv_name, kernel_size):
20
+ MPA_U_test = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_test.csv"))
21
+
22
+ # dataset
23
+ test_DS = reader.kmer_scan_dataset(MPA_U_test, seq_col='utr',
24
+ kmer_size=kernel_size, aux_columns='rl')
25
+ return np.multiply(*test_DS[0][0].shape)
26
+
27
+ def get_kmer_dls(csv_name, kernel_size, seed):
28
+ train_val = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_train_val.csv"))
29
+ MPA_U_test = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_test.csv"))
30
+
31
+ MPA_U_val = train_val.sample(frac=0.1, random_state=seed)
32
+ MPA_U_train = pd.concat([train_val, MPA_U_val]).drop_duplicates(keep=False)
33
+
34
+ # dataset
35
+ train_DS = reader.kmer_scan_dataset(MPA_U_train, seq_col='utr', kmer_size=kernel_size, aux_columns='rl')
36
+ val_DS = reader.kmer_scan_dataset(MPA_U_val, seq_col='utr', kmer_size=kernel_size, aux_columns='rl')
37
+ test_DS = reader.kmer_scan_dataset(MPA_U_test, seq_col='utr', kmer_size=kernel_size, aux_columns='rl')
38
+
39
+ # dataloader
40
+ train_dl = DataLoader(train_DS, batch_size = 64, shuffle=True)
41
+ val_dl = DataLoader(test_DS, batch_size = 64, shuffle=False)
42
+ test_dl = DataLoader(test_DS, batch_size = 64, shuffle=False)
43
+ return train_dl, val_dl, test_dl
44
+
45
+ ##################
46
+ # PyTorch Light model #
47
+ class mlp_models(pl.LightningModule):
48
+ def __init__(self, dims):
49
+ super().__init__()
50
+ self.dims = dims
51
+ n_layer = len(dims) - 1
52
+ self.train_r2 = torchmetrics.R2Score()
53
+ self.val_r2 = torchmetrics.R2Score()
54
+ # add layers
55
+ nns = []
56
+ i = 1
57
+ for in_dim , out_dim in zip(dims[:-1], dims[1:]):
58
+ nns.append( (f"Linear_{i}", nn.Linear(in_dim, out_dim)) )
59
+ if i < n_layer:
60
+ nns += [(f"BN_{i}", nn.BatchNorm1d(out_dim)), (f"act_{i}", nn.Mish()) ]
61
+ i += 1
62
+
63
+ self.network = nn.Sequential(OrderedDict(nns))
64
+
65
+ def forward(self, x):
66
+ return self.network(x)
67
+
68
+ def configure_optimizers(self):
69
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
70
+ return optimizer
71
+
72
+ def training_step(self, train_batch, batch_idx):
73
+ x, y = train_batch
74
+ b = x.shape[0]
75
+ x = x.view(b, -1).float()
76
+ y = y.view(b,).float()
77
+ y_hat = self.network(x).view(b,)
78
+ loss = F.mse_loss(y_hat, y.float())
79
+ r2 = self.train_r2(y_hat, y)
80
+ self.log('train_loss', loss)
81
+ self.log('train_acc', self.train_r2)
82
+ return loss
83
+
84
+ def validation_step(self, val_batch, batch_idx):
85
+ x, y = val_batch
86
+ b = x.shape[0]
87
+ x = x.view(b, -1).float()
88
+ y = y.view(b,).float()
89
+ y_hat = self.network(x).view(b,)
90
+
91
+ loss = F.mse_loss(y_hat, y.float())
92
+ r2 = self.val_r2(y_hat, y)
93
+ self.log('val_loss', loss)
94
+ self.log('val_acc', self.val_r2)
95
+
96
+ # PyTorch Light model #
97
+ class rnn_models(pl.LightningModule):
98
+ def __init__(self, k):
99
+ super().__init__()
100
+
101
+ self.train_r2 = torchmetrics.R2Score()
102
+ self.val_r2 = torchmetrics.R2Score()
103
+
104
+
105
+ tower = { f"GRU_layer" : nn.GRU(input_size=4**k, hidden_size=128,
106
+ num_layers=2,batch_first=True),
107
+ f"fc_out" : nn.Linear(128, 1),
108
+ }
109
+
110
+ self.tower = nn.ModuleDict(tower)
111
+
112
+ def forward(self, x):
113
+
114
+ x = x.transpose(1,2) # B C L -> B L C
115
+ h_prim,(c1,c2) = self.tower['GRU_layer'](x)
116
+ out = self.tower['fc_out'](c2)
117
+ return out
118
+
119
+ def configure_optimizers(self):
120
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
121
+ return optimizer
122
+
123
+ def training_step(self, train_batch, batch_idx):
124
+ x, y = train_batch
125
+ b = x.shape[0]
126
+ x = x.float()
127
+ y = y.view(b,).float()
128
+ y_hat = self.forward(x).view(b,)
129
+
130
+ loss = F.mse_loss(y_hat, y)
131
+ r2 = self.train_r2(y_hat, y)
132
+ self.log('train_loss', loss)
133
+ self.log('train_acc', self.train_r2)
134
+ return loss
135
+
136
+ def validation_step(self, val_batch, batch_idx):
137
+ x, y = val_batch
138
+ b = x.shape[0]
139
+ x = x.float()
140
+ y = y.view(b,).float()
141
+ y_hat = self.forward(x).view(b,)
142
+
143
+ loss = F.mse_loss(y_hat, y)
144
+ self.val_r2(y_hat, y)
145
+ self.log('val_loss', loss)
146
+ self.log('val_acc', self.val_r2)
147
+
148
+ ################
149
+ if __name__ == '__main__':
150
+
151
+ csv_name = sys.argv[1]
152
+ kmer_size = sys.argv[2]
153
+ hidden = sys.argv[3]
154
+
155
+ #### hyper-params ####
156
+ Input_length = np.multiply(*train_DS[0][0].shape)
157
+ hidden = [512]
158
+ dims = [Input_length] + hidden + [1]
159
+ ################
160
+
161
+ # training
162
+ trainer = pl.Trainer(gpus=1, num_processes=8,
163
+ default_root_dir="/ssd/users/wergillius/Project/MTtrans/evaluation/Kmer_results",
164
+ limit_train_batches=0.5, max_epochs=6,
165
+ callbacks=[callbacks.EarlyStopping(monitor="val_loss", mode="min", patience=5)])
166
+ trainer.fit(model, train_dl, val_dl)
167
+ trainer.test(test_dl)
model/src/mrl_te_optimization/script/train_oneLayer_CNN.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ import pytorch_lightning as pl
3
+ from torch.nn import functional as F
4
+ import PATH, utils
5
+ import torch
6
+ from torch import nn, optim
7
+ from models import reader
8
+ from models.popen import Auto_popen
9
+ import pandas as pd
10
+ import numpy as np
11
+ from collections import OrderedDict
12
+ import torchmetrics
13
+ from torch.utils.data import DataLoader
14
+ from pytorch_lightning import callbacks
15
+
16
+
17
+ ###### data ######
18
+ def get_dls(csv_name, kernel_size, seed):
19
+ train_val = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_train_val.csv"))
20
+ MPA_U_test = pd.read_csv(os.path.join(utils.data_dir, f"{csv_name}_test.csv"))
21
+
22
+ MPA_U_val = train_val.sample(frac=0.1, random_state=seed)
23
+ MPA_U_train = pd.concat([train_val, MPA_U_val]).drop_duplicates(keep=False)
24
+
25
+ # dataset
26
+ train_DS = reader.MTL_dataset(MPA_U_train, seq_col='utr', aux_columns=['rl'])
27
+ val_DS = reader.MTL_dataset(MPA_U_val, seq_col='utr', aux_columns=['rl'])
28
+ test_DS = reader.MTL_dataset(MPA_U_test, seq_col='utr', aux_columns=['rl'])
29
+
30
+ # dataloader
31
+ train_dl = DataLoader(train_DS, batch_size = 64, shuffle=True)
32
+ val_dl = DataLoader(test_DS, batch_size = 64, shuffle=False)
33
+ test_dl = DataLoader(test_DS, batch_size = 64, shuffle=False)
34
+ return train_dl, val_dl, test_dl
35
+ ##################
36
+
37
+
38
+ # PyTorch Light model #
39
+ class Onelayer_CNN(pl.LightningModule):
40
+ def __init__(self, kernel_size):
41
+ super().__init__()
42
+
43
+ self.train_r2 = torchmetrics.R2Score()
44
+ self.val_r2 = torchmetrics.R2Score()
45
+
46
+ self.conv_layer = nn.Sequential(nn.Conv1d(4, 256, kernel_size),
47
+ nn.BatchNorm1d(256),
48
+ nn.Mish())
49
+
50
+ tower = { f"GRU_layer" : nn.GRU(input_size=256, hidden_size=128,
51
+ num_layers=2,batch_first=True),
52
+ f"fc_out" : nn.Linear(128, 1),
53
+ }
54
+
55
+ self.tower = nn.ModuleDict(tower)
56
+
57
+ def forward(self, x):
58
+ if x.shape[1] != 4:
59
+ x = x.transpose(1,2)
60
+ Z = self.conv_layer(x)
61
+ Z_t = torch.transpose(Z, 1, 2)
62
+ h_prim,(c1,c2) = self.tower['GRU_layer'](Z_t)
63
+ out = self.tower['fc_out'](c2)
64
+ return out
65
+
66
+ def configure_optimizers(self):
67
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
68
+ return optimizer
69
+
70
+ def training_step(self, train_batch, batch_idx):
71
+ x, y = train_batch
72
+ b = x.shape[0]
73
+ x = x.float()
74
+ y = y.view(b,).float()
75
+ y_hat = self.forward(x).view(b,)
76
+
77
+ loss = F.mse_loss(y_hat, y)
78
+ r2 = self.train_r2(y_hat, y)
79
+ self.log('train_loss', loss)
80
+ self.log('train_acc', self.train_r2)
81
+ return loss
82
+
83
+ def validation_step(self, val_batch, batch_idx):
84
+ x, y = val_batch
85
+ b = x.shape[0]
86
+ x = x.float()
87
+ y = y.view(b,).float()
88
+ y_hat = self.forward(x).view(b,)
89
+ loss = F.mse_loss(y_hat, y)
90
+ self.val_r2(y_hat, y)
91
+ self.log('val_loss', loss)
92
+ self.log('val_acc', self.val_r2)
93
+
94
+ ################
95
+ if __name__ == '__main__':
96
+
97
+ #### hyper-params ####
98
+ csv_name = sys.argv[1]
99
+ kernel_size = sys.argv[2]
100
+ seed = 41
101
+
102
+ ################
103
+ train_dl, val_dl, test_dl = get_dls(csv_name, kernel_size, seed)
104
+
105
+ model = Onelayer_CNN(int(kernel_size))
106
+
107
+
108
+ # training
109
+ trainer = pl.Trainer(gpus=1, num_processes=8,
110
+ default_root_dir="/ssd/users/wergillius/Project/MTtrans/evaluation/one_layer_logs",
111
+ limit_train_batches=0.5, max_epochs=60,
112
+ callbacks=[callbacks.EarlyStopping(monitor="val_loss", mode="min", patience=5)])
113
+ trainer.fit(model, train_dl, val_dl)
114
+ trainer.test(test_dl)
model/src/mrl_te_optimization/util.py ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import operator
3
+ import pickle
4
+ import time
5
+ import seaborn as sns
6
+ import matplotlib.pyplot as plt
7
+ import pandas as pd
8
+ import numpy as np
9
+ import math
10
+ import itertools
11
+ import random
12
+ import os
13
+ from polyleven import levenshtein
14
+ import operator
15
+ import pickle
16
+ import time
17
+ import tensorflow as tf
18
+
19
+ tf.random.set_seed(35)
20
+ np.random.seed(35)
21
+
22
+ rna_vocab = {"A":0,
23
+ "C":1,
24
+ "G":2,
25
+ "U":3,
26
+ "*":4}
27
+
28
+ rev_rna_vocab = {v:k for k,v in rna_vocab.items()}
29
+
30
+ def recover_seq(samples, rev_charmap=rev_rna_vocab):
31
+ """Convert samples to strings and save to log directory."""
32
+
33
+ char_probs = samples
34
+ argmax = np.argmax(char_probs, 2)
35
+ seqs = []
36
+ for line in argmax:
37
+ s = "".join(rev_charmap[d] for d in line)
38
+ s = s.replace('*','')
39
+ seqs.append(s)
40
+ return seqs
41
+
42
+ def file_to_list(file_name,size):
43
+ data = []
44
+ with open(file_name,'r') as f:
45
+ lines = f.readlines()
46
+
47
+ for seq in lines:
48
+ seq_ = seq.replace('\n','')
49
+ data.append(seq_)
50
+ # if len(seq) == size:
51
+ # data.append(seq)
52
+
53
+ return data
54
+
55
+ def one_hot_encode(seq):
56
+ mapping = dict(zip("ACGT", range(4)))
57
+ seq = seq.replace('U','T')
58
+ seq2 = [mapping[i] for i in seq]
59
+ return np.eye(4)[seq2]
60
+
61
+ def encode(seqs):
62
+ return np.reshape([one_hot_encode(seqs[i]) for i in range(len(seqs))],(np.array(seqs).shape[0],-1))
63
+
64
+ min_len = None
65
+ nuc_dict = {'a':[1.0,0.0,0.0,0.0],'c':[0.0,1.0,0.0,0.0],'g':[0.0,0.0,1.0,0.0],
66
+ 'u':[0.0,0.0,0.0,1.0], 't':[0.0,0.0,0.0,1.0],
67
+ 'n':[0.0,0.0,0.0,0.0], 'x':[1/4,1/4,1/4,1/4]}
68
+
69
+ def encode_seq_framepool(seq, max_len=128):
70
+ # print(seq)
71
+
72
+ length = len(seq)
73
+ if max_len > 0 and min_len is None:
74
+ padding_needed = max_len - length
75
+ seq = "N"*padding_needed + seq
76
+ if min_len is not None:
77
+ if len(seq) < min_len:
78
+ seq = "N"*(min_len - len(seq)) + seq
79
+
80
+ if len(seq) > min_len:
81
+ seq = seq[(len(seq) - min_len):]
82
+ seq = seq.lower()
83
+ one_hot = np.array([nuc_dict[x] for x in seq]) # get stacked on top of each other
84
+
85
+ return one_hot
86
+
87
+ def list_to_file(filename,list):
88
+ with open(filename + ".txt", 'w') as f:
89
+ for element in list[:-1]:
90
+ f.write(element+"\n")
91
+ f.write(list[-1])
92
+
93
+ def tsne_natural(file_name, length, key='seq'):
94
+ df = pd.read_csv(file_name)
95
+ seqs = np.array(df[key]).tolist()
96
+
97
+ selected_seqs = []
98
+
99
+ for i in range(len(seqs)):
100
+ seq = seqs[i]
101
+ seq = seq.upper()
102
+ if seq not in selected_seqs and len(seq) == length:
103
+ selected_seqs.append(seq)
104
+
105
+ return selected_seqs
106
+
107
+ def read_real(file_name, UTR_LEN, key='seq', all= True, samples= 128 ):
108
+ df = pd.read_csv(file_name)
109
+ seqs = np.array(df[key]).tolist()
110
+
111
+ selected_seqs = []
112
+
113
+ for i in range(len(seqs)):
114
+ if len(seqs[i]) < (UTR_LEN + 1) and len(seqs[i]) > int(UTR_LEN/2):
115
+ seqs[i] = seqs[i].upper()
116
+ if seqs[i] not in selected_seqs:
117
+ selected_seqs.append(seqs[i])
118
+
119
+ if all:
120
+ return selected_seqs
121
+
122
+ else:
123
+ indices = []
124
+
125
+ for i in range(len(selected_seqs)):
126
+
127
+ indices.append(i)
128
+
129
+ samples = np.random.choice(len(indices),samples,replace=False)
130
+
131
+ chosen = []
132
+
133
+ for i in range(len(samples)):
134
+ chosen.append(selected_seqs[samples[i]])
135
+
136
+ return chosen
137
+
138
+ def random_sample(length):
139
+ rna_vocab = {"A":0,
140
+ "C":1,
141
+ "G":2,
142
+ "T":3}
143
+
144
+ rev_rna_vocab = {v:k for k,v in rna_vocab.items()}
145
+
146
+ mapping = dict(zip([0,1,2,3],"ACGT"))
147
+
148
+ sample = ''
149
+ for i in range(length):
150
+ r = random.random()
151
+ if r < 0.6:
152
+ sample += random.choice(['C','G'])
153
+ else:
154
+ sample += random.choice(['A','T'])
155
+ # rsample = [random.randrange(4) for i in range(length)]
156
+ # rsample = [mapping[i] for i in rsample]
157
+ # string = ''
158
+ # for neuc in rsample:
159
+ # string += neuc
160
+
161
+ return sample
162
+
163
+ def random_data(length, size):
164
+ samples = []
165
+ for i in range(size):
166
+ samples.append(random_sample(length))
167
+
168
+ return samples
169
+
170
+ def motif_count(gens,motifs_path='./../../data/motifs.csv'):
171
+ motifs = pd.read_csv(motifs_path)
172
+ seqs = motifs['seq']
173
+ scores = motifs['spr']
174
+ gen_positive = 0
175
+ gen_negative = 0
176
+ for i in range(len(seqs)):
177
+ for j in range(len(gens)):
178
+ if seqs[i] in gens[j]:
179
+ if scores[i] < 0:
180
+ gen_negative += 1
181
+ else:
182
+ gen_positive += 1
183
+
184
+ return gen_positive, gen_negative
185
+
186
+ def tsne_gen(path,length=128,BATCH_SIZE=64,DIM=40):
187
+ wgan = tf.keras.models.load_model(path)
188
+
189
+ selected = []
190
+ while len(selected) < BATCH_SIZE:
191
+
192
+ noise = tf.Variable(tf.random.normal(shape=[64,DIM]))
193
+
194
+ sequences_init = wgan(noise)
195
+
196
+ gen_seqs_init = sequences_init.numpy().astype('float')
197
+
198
+ seqs_gen_init = recover_seq(gen_seqs_init, rev_rna_vocab)
199
+
200
+ for i in range(len(seqs_gen_init)):
201
+ if len(seqs_gen_init[i]) == length:
202
+ selected.append(seqs_gen_init[i])
203
+
204
+ return selected[:BATCH_SIZE]
205
+
206
+ def generate_data(path,BATCH_SIZE=64,UTR_LEN=128,DIM=40):
207
+ wgan = tf.keras.models.load_model(path)
208
+
209
+ gens = []
210
+
211
+ while len(gens) < BATCH_SIZE:
212
+
213
+ noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM]))
214
+
215
+ sequences_init = wgan(noise)
216
+
217
+ gen_seqs_init = sequences_init.numpy().astype('float')
218
+
219
+ seqs_gen_init = recover_seq(gen_seqs_init, rev_rna_vocab)
220
+
221
+ for i in range(len(seqs_gen_init)):
222
+ if len(seqs_gen_init[i]) > int(UTR_LEN/2) and len(seqs_gen_init[i])< UTR_LEN+1:
223
+ if seqs_gen_init[i] not in gens:
224
+ gens.append(seqs_gen_init[i])
225
+ if len(gens) == BATCH_SIZE:
226
+ break
227
+
228
+ return gens[:BATCH_SIZE]
229
+
230
+ def gc_percentage(seq):
231
+ count = 0.0
232
+ for char in seq:
233
+ if char == 'C' or char == 'G':
234
+ count +=1
235
+
236
+ return float(count/len(seq))
237
+
238
+ def get_gc_content(data):
239
+ gc_content = []
240
+ for seq in data:
241
+ seq.replace('\n','')
242
+ seq.replace('*','')
243
+ gc = gc_percentage(seq)
244
+ gc_content.append(gc)
245
+
246
+ return gc_content
247
+
248
+ def get_gc_content_many(data):
249
+
250
+ collection = []
251
+ gc_contents = []
252
+ for seq in data:
253
+ seq = seq.upper()
254
+ seq.replace('\n','')
255
+ seq.replace('*','')
256
+ gc = gc_percentage(seq)
257
+ gc_contents.append(gc)
258
+
259
+ return gc_contents
260
+
261
+ def get_4mers():
262
+ neucs = ['A','C','G','T']
263
+
264
+ mers = [p for p in itertools.product(neucs, repeat=4)]
265
+ for i in range(len(mers)):
266
+ mers[i] = mers[i][0] + mers[i][1] + mers[i][2] + mers[i][3]
267
+
268
+ return mers
269
+
270
+ def get_4mer_dic(seqs):
271
+
272
+ _4mers = get_4mers()
273
+ length = 0
274
+ dics = []
275
+
276
+ for seq in seqs:
277
+ dic = {}
278
+ for item in _4mers:
279
+ dic[item] = 0
280
+
281
+ # Iterate With the Sliding Window
282
+ length = len(seq)
283
+ limit = length - 4
284
+ for i in range(limit):
285
+ mer = seq[i:i+4]
286
+ dic[mer] += 1
287
+
288
+ dics.append(dic)
289
+
290
+ return dics
291
+
292
+ def euclidean_kmer(item, ref, mers):
293
+ dist = 0
294
+ for mer in mers:
295
+ diff = item[mer] - ref[mer]
296
+ dist += math.pow(diff,2)
297
+
298
+ return dist
299
+
300
+ def euclidean_kmer_all(item,refs,mers):
301
+ dists = []
302
+ for ref in refs:
303
+ dists.append(euclidean_kmer(item,ref,mers))
304
+
305
+ return min(dists)
306
+
307
+ def hamming_dist(src, target):
308
+
309
+ dists = []
310
+ for i in range(len(src)):
311
+ smallest = np.inf
312
+ for j in range(len(target)):
313
+ dist = levenshtein(src[i],target[j])
314
+ if dist > 0 and dist < smallest:
315
+ smallest = dist
316
+
317
+ dists.append(dist)
318
+
319
+ return np.array(dists)
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+ def one_hot_motif(seq,length=128,complementary=False):
330
+ """
331
+ one_hot encoding on sequence
332
+ complementary: encode nucleatide into complementary one
333
+ """
334
+
335
+ if length == -1:
336
+ length = len(seq)
337
+
338
+ # seq = str(seq)
339
+ # setting
340
+ seq = list(seq.replace("U","T"))
341
+ seq_len = len(seq)
342
+ complementary = -1 if complementary else 1
343
+ # compose dict
344
+ keys = ['A', 'C', 'G', 'T'][::complementary]
345
+ oh_dict = {keys[i]:i for i in range(4)}
346
+ # array
347
+ oh_array = np.zeros((length,4),dtype=np.double)
348
+ for i,C in enumerate(seq):
349
+ try:
350
+ oh_array[i,oh_dict[C]]=1
351
+ except:
352
+ continue # for nucleotide that are not in A C G T   
353
+ return oh_array
354
+
355
+ def one_hot_all_motif(seqs):
356
+ # length = np.max([len(seq) for seq in seqs])
357
+ return [one_hot_motif(seqs[i], length = 128) for i in range(len(seqs))]
358
+
359
+
360
+
361
+
362
+ def one_hot(seq):
363
+ convert = False
364
+ if isinstance(seq, tf.Tensor):
365
+ seq = seq.numpy().astype(str)
366
+ convert = True
367
+
368
+ num_seqs = len(seq)
369
+ seq_len = len(seq[0])
370
+ seqindex = {'A':0, 'C':1, 'G':2, 'T':3, 'a':0, 'c':1, 'g':2, 't':3}
371
+ seq_vec = np.zeros((num_seqs,seq_len,4), dtype='bool')
372
+ for i in range(num_seqs):
373
+ thisseq = seq[i]
374
+ for j in range(seq_len):
375
+ try:
376
+ seq_vec[i,j,seqindex[thisseq[j]]] = 1
377
+ except:
378
+ pass
379
+
380
+ if convert:
381
+ seq_vec = tf.convert_to_tensor(seq_vec,dtype=tf.float32)
382
+
383
+
384
+ return seq_vec
model/src/mrl_te_optimization/utils.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sklearn.preprocessing import OneHotEncoder
2
+ import logging
3
+ import numpy as np
4
+ import pandas as pd
5
+ import os
6
+ import json
7
+ import re
8
+ import torch
9
+ import collections
10
+ # from models import reader
11
+ from models.ScheduleOptimizer import ScheduledOptim
12
+
13
+ print(os.path.dirname(__file__))
14
+
15
+ # ====================| some path |=======================
16
+ global script_dir
17
+ global data_dir
18
+ global log_dir
19
+ global pth_dir
20
+ # global cell_lines
21
+
22
+ global egfp_seq
23
+
24
+ with open(os.path.join(os.path.dirname(__file__),"machine_configure.json"),'r') as f:
25
+ config = json.load(f)
26
+
27
+ script_dir = config['script_dir']
28
+ data_dir = config['data_dir']
29
+ log_dir = config['log_dir']
30
+ pth_dir = config['pth_dir']
31
+
32
+
33
+
34
+ # =====================| one hot encode |=======================
35
+
36
+ class Seq_one_hot(object):
37
+ def __init__(self,seq_type='nn',seq_len=100):
38
+ """
39
+ initiate the sequence one hot encoder
40
+ """
41
+ self.seq_len=seq_len
42
+ self.seq_type =seq_type
43
+ self.enable_encoder()
44
+
45
+ def enable_encoder(self):
46
+ if self.seq_type == 'nn':
47
+ self.encoder = OneHotEncoder(sparse=False)
48
+ self.encoder.drop_idx_ = None
49
+ self.encoder.categories_ = [np.array(['A', 'C', 'G', 'T'], dtype='<U1')]*self.seq_len
50
+
51
+ def discretize_seq(self,data):
52
+ """
53
+ discretize sequence into character
54
+ argument:
55
+ ...data: can be dataframe with UTR columns , or can be single string
56
+ """
57
+ if type(data) is pd.DataFrame:
58
+ return np.stack(data.UTR.apply(lambda x: list(x)))
59
+ elif type(data) is str:
60
+ return np.array(list(data))
61
+
62
+ def transform(self,data,flattern=True):
63
+ """
64
+ One hot encode
65
+ argument:
66
+ data : is a 2D array
67
+ flattern : True
68
+ """
69
+ X = self.encoder.transform(data) # 400 for each seq
70
+ X_M = np.stack([seq.reshape(self.seq_len,4) for seq in X]) # i.e 100*4
71
+ return X if flattern else X_M
72
+
73
+ def d_transform(self,data,flattern=True):
74
+ """
75
+ discretize data and put into transform
76
+ """
77
+ X = self.discretize_seq(data)
78
+ return self.transform(X,flattern)
79
+
80
+
81
+ # =====================| logger |=======================
82
+
83
+ def setup_logs(vae_log_path,level=None):
84
+ """
85
+
86
+ :param save_dir: the directory to set up logs
87
+ :param type: 'model' for saving logs in 'logs/cpc'; 'imp' for saving logs in 'logs/imp'
88
+ :param run_name:
89
+ :return:logger
90
+ """
91
+ # initialize logger
92
+ logger = logging.getLogger("VAE")
93
+ logger.setLevel(logging.INFO)
94
+ if level=='warning':
95
+ logger.setLevel(logging.WARNING)
96
+
97
+ # create the logging file handler
98
+ log_file = os.path.join(vae_log_path)
99
+ fh = logging.FileHandler(log_file)
100
+
101
+ # create the logging console handler
102
+ ch = logging.StreamHandler()
103
+
104
+ # format
105
+ formatter = logging.Formatter("%(asctime)s - %(message)s")
106
+ fh.setFormatter(formatter)
107
+
108
+ # add handlers to logger object
109
+ logger.addHandler(fh)
110
+ logger.addHandler(ch)
111
+
112
+ return logger
113
+
114
+ def clean_value_dict(dict):
115
+ """
116
+ deal with verbose dict where the values maybe torch object, extact the item and return clean dict
117
+ """
118
+ clean_dict={}
119
+ for k,v in dict.items():
120
+
121
+ try:
122
+ v = v.item()
123
+ except:
124
+ v = v
125
+ clean_dict[k] = v
126
+ return clean_dict
127
+
128
+ def fix_parameter(model,modual_to_fix,fix_or_unfix=False):
129
+ """
130
+ for a given model, fix part of the parameter to fine-tuning / transfering
131
+ args:
132
+ model : `nn.Modual`,initiated model instance
133
+ modual_to_fix : str, define which part of the model will not update by gradient
134
+ e.g. "soft_share" then
135
+ """
136
+
137
+ fix_part = eval("model."+modual_to_fix) # e.g. model.shoft_share
138
+
139
+ for param in fix_part.parameters():
140
+ param.requires_grad = fix_or_unfix
141
+
142
+ return model
143
+
144
+ def unfix_parameter(model,modual_to_fix,fix_or_unfix=False):
145
+ return fix_parameter(model,modual_to_fix,fix_or_unfix=True)
146
+
147
+ def snapshot(vae_pth_path, state):
148
+ logger = logging.getLogger("VAE")
149
+ # torch.save can save any object
150
+ # dict type object in our cases
151
+ torch.save(state, vae_pth_path)
152
+ logger.info("Snapshot saved to {}\n".format(vae_pth_path))
153
+
154
+
155
+ def load_model(popen,model,logger=None):
156
+
157
+ info = lambda x: print(x) if logger==None else logger.info(x)
158
+ # popen.vae_pth_path = '/mnt/sina/run/ml/gan/dev/git/UTRGAN/src/mrl_optimization/script/checkpoint/RL_hard_share_MTL/3M/small_repective_filed_strides1113-model_best_cv1.pth'
159
+ checkpoint = torch.load(popen.vae_pth_path, map_location=torch.device('cpu'))
160
+ if isinstance(checkpoint['state_dict'], collections.OrderedDict):
161
+ # optimizer.load_state_dict(checkpoint['optimizer'])
162
+ model.load_state_dict(checkpoint['state_dict'])
163
+ else:
164
+ model = checkpoint['state_dict']
165
+
166
+ info(' \t \t ==============<<< encoder load from >>>============== \t \t ')
167
+ info(" \t"+popen.vae_pth_path)
168
+
169
+ return model
170
+
171
+ def get_config_cuda(config_file):
172
+ with open(config_file,'r') as f:
173
+ lines = f.read_lines()
174
+ for line in lines:
175
+ if "cuda_id =" in line:
176
+ device = line.split("=")[1].strip()
177
+ break
178
+ device = int(device) if device.isdigit() else device
179
+ return device
180
+
181
+ def resume(popen,optimizer,logger):
182
+ """
183
+ for a experiment, check whether it;s a new run, and create dir
184
+ """
185
+ #run_name = model_stype + time.strftime("__%Y_%m_%d_%H:%M"))
186
+
187
+ if popen.Resumable:
188
+
189
+ checkpoint = torch.load(popen.vae_pth_path, map_location=torch.device('cpu')) # xx-model-best.pth
190
+ previous_epoch = checkpoint['epoch']
191
+ previous_loss = checkpoint['validation_loss']
192
+ previous_acc = checkpoint['validation_acc']
193
+
194
+
195
+ # very important
196
+ if (type(optimizer) == ScheduledOptim):
197
+ optimizer.n_current_steps = popen.n_current_steps
198
+ optimizer.delta = popen.delta
199
+
200
+ logger.info(" \t \t ========================================================= \t \t ")
201
+ logger.info(' \t \t ==============<<< Resume from checkpoint>>>============== \t \t \n')
202
+ logger.info(" \t"+popen.vae_pth_path+'\n')
203
+ logger.info(" \t \t ========================================================= \t \t \n")
204
+
205
+ return previous_epoch,previous_loss,previous_acc
206
+
207
+
208
+ egfp_seq = "atgggcgaattaagtaagggcgaggagctgttcaccggggtggtgcccatcctggtcgagctggacggcgacgtaaacggccacaagttcagcgtgtccggcgagggcgagggcgatgccacctacggcaagctgaccctgaagttcatctgcaccaccggcaagctgcccgtgccctggcccaccctcgtgaccaccctgacctacggcgtgcagtgcttcagccgctaccccgaccacatgaagcagcacgacttcttcaagtccgccatgcccgaaggctacgtccaggagcgcaccatcttct"
209
+ eGFP_seq = egfp_seq.upper()
model/src/mrl_te_optimization/xpresso_input.json ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # UTRGAN on the OneScience base environment
2
+ # Python 3.11; SCNet BW DCU
3
+ #
4
+ # IMPORTANT RUNTIME DIFFERENCE
5
+ # ----------------------------
6
+ # OneScience is pinned to DTK 25.04 / DAS1.7:
7
+ # torch==2.5.1+das.opt1.dtk25042
8
+ # tensorflow==2.18.0+das.opt1.dtk25042
9
+ # UTRGAN ReLU/model inference failed there with "Failure when generating HSACO".
10
+ # The validated UTRGAN environment therefore uses DTK 26.04 / DAS1.8 and must
11
+ # load `compiler/dtk/26.04` (or an equivalent /opt/dtk-26.04 runtime).
12
+ #
13
+ # Install the active entries without replacing their dependencies:
14
+ # python -m pip install --no-deps -r requirements.txt
15
+ # Recheck torch/TensorFlow/HIP/DCU visibility immediately after installation.
16
+
17
+ # Required replacements for the OneScience DTK 26.04 framework wheels.
18
+ tensorflow @ https://download.sourcefind.cn:65024/file/4/tensorflow/DAS1.8/tensorflow-2.18.0+das.opt1.dtk2604-cp311-cp311-manylinux_2_28_x86_64.whl
19
+ torch @ https://download.sourcefind.cn:65024/file/4/pytorch/DAS1.8/torch-2.5.1+das.opt1.dtk2604-cp311-cp311-manylinux_2_28_x86_64.whl
20
+
21
+ # Required compatibility/additional packages.
22
+ # OneScience includes tf-keras without a strict version; 2.18.0 is the tested
23
+ # version for loading the released legacy H5 files with TF_USE_LEGACY_KERAS=1.
24
+ tf-keras==2.18.0
25
+ polyleven==0.9.0
26
+
27
+ # Additional packages needed only by the repository's G4/analysis utilities.
28
+ # XGBoost is held below 2.3 because the released G4 JSON files use its old
29
+ # pre-1.6 JSON format, whose removal was announced for XGBoost 2.3.
30
+ xgboost==2.1.4
31
+ ViennaRNA==2.7.0
32
+ logomaker
33
+ ruptures
34
+ cliffs-delta
35
+
36
+ # NUPACK is used only by script/Nupack_MFE_prediction.py. NUPACK 4 is an
37
+ # externally licensed/downloaded Python package and is not installed from this
38
+ # requirements file. Install it separately from https://www.nupack.org/ only
39
+ # when that optional preprocessing script is needed.
40
+ # nupack # external optional dependency; no normal PyPI pin
41
+
42
+ # Provided by OneScience; complete UTRGAN dependency inventory follows.
43
+ # Keep these commented to avoid reinstalling generic wheels over OneScience.
44
+ # numpy==1.26.3
45
+ # pandas>=2.2.2
46
+ # scipy==1.14.1
47
+ # h5py>=3.7.0
48
+ # matplotlib
49
+ # seaborn
50
+ # tqdm>=4.60.0
51
+ # requests
52
+ # biopython==1.84
53
+ # scikit-learn>=1.2.2,<=1.6.0
54
+ # einops>=0.7.0
55
+ # pytorch-lightning==2.0.6
56
+ # torchmetrics
57
+
58
+ # Supplied transitively by the validated DTK TensorFlow stack; do not adjust
59
+ # these independently because doing so can break TensorFlow compatibility.
60
+ # keras==3.15.1
61
+ # protobuf
62
+ # ml-dtypes
scripts/optimize_te_mrl.py ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ PROJECT_ROOT = Path(__file__).resolve().parents[1]
7
+ MODEL_ROOT = PROJECT_ROOT / "model"
8
+ MODULE_ROOT = MODEL_ROOT / "src" / "mrl_te_optimization"
9
+ for import_root in (MODEL_ROOT, MODULE_ROOT):
10
+ if str(import_root) not in sys.path:
11
+ sys.path.insert(0, str(import_root))
12
+
13
+ os.environ.setdefault("TF_USE_LEGACY_KERAS", "1")
14
+
15
+ from tqdm import tqdm
16
+ import random
17
+ random.seed(1337)
18
+ import matplotlib.pyplot as plt
19
+ import argparse
20
+ import numpy as np
21
+ np.random.seed(1337)
22
+ import pandas as pd
23
+ import torch
24
+ from framepool import *
25
+ from util import *
26
+
27
+ import random
28
+ random.seed(1337)
29
+ import scipy.stats as stats
30
+
31
+ import tensorflow as tf
32
+ from tensorflow.keras import backend as K
33
+ from tensorflow.keras.models import load_model
34
+
35
+ tf.compat.v1.enable_eager_execution()
36
+
37
+ import pandas as pd
38
+ import numpy as np
39
+ import requests
40
+
41
+ parser = argparse.ArgumentParser()
42
+ parser.add_argument('-d', type=str, required=False,
43
+ default=str(PROJECT_ROOT / 'conf' / 'data' / 'utrdb2.csv'))
44
+ parser.add_argument('-bs', type=int, required=False ,default=64)
45
+ parser.add_argument('-lr', type=int, required=False ,default=1)
46
+ parser.add_argument('-task', type=str, required=False ,default="mrl")
47
+ parser.add_argument('-gpu', type=str, required=False ,default='-1')
48
+ parser.add_argument('-s', type=int, required=False ,default=10000)
49
+ parser.add_argument('--output-dir', type=str,
50
+ default=str(PROJECT_ROOT / 'outputs' / 'optimization'))
51
+ args = parser.parse_args()
52
+
53
+ if args.gpu == '-1':
54
+ device = 'cpu'
55
+ else:
56
+ os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
57
+ device = 'cuda'
58
+
59
+ def prepare_mttrans(seqs):
60
+ seqs_init = torch.tensor(np.array(one_hot_all_motif(seqs),dtype=np.float32))
61
+
62
+ seqs_init = torch.transpose(seqs_init, 1, 2)
63
+ seqs_init = torch.tensor(seqs_init,dtype=torch.float32).to(device)
64
+ return seqs_init
65
+
66
+ def prepare_framepool(seqs):
67
+ return tf.convert_to_tensor(np.array([encode_seq_framepool(seq) for seq in seqs]),dtype=tf.float32)
68
+
69
+
70
+
71
+ BATCH_SIZE = args.bs
72
+ motifs_path = str(PROJECT_ROOT / 'conf' / 'data' / 'motifs.csv')
73
+ STEPS = args.s
74
+ LR = args.lr
75
+ DIM = 40
76
+ SEQ_LEN = 128
77
+ UTR_LEN = 128
78
+
79
+ TASK = args.task
80
+
81
+ gpath = str(PROJECT_ROOT / 'weight' / 'checkpoint_3000.h5')
82
+
83
+
84
+ if TASK == 'te':
85
+ path = str(PROJECT_ROOT / 'weight' / 'mttrans' / 'RL_hard_share_MTL' /
86
+ '3R' / 'schedule_MTL-model_best_cv1.pth')
87
+ OPT = 'TE'
88
+ else:
89
+ path = str(PROJECT_ROOT / 'weight' / 'utr_model_combined_residual_new.h5')
90
+ OPT = 'FMRL'
91
+
92
+
93
+ # Check for GPU availability
94
+ gpus = tf.config.list_physical_devices('GPU')
95
+
96
+ if gpus:
97
+ print(f"GPU is available. Using GPU:{args.gpu} for computation.")
98
+ print("List of GPUs:", gpus)
99
+ else:
100
+ print("GPU is not available. Using CPU instead.")
101
+
102
+ out_folder = str(Path(args.output_dir).expanduser().resolve())
103
+ os.makedirs(out_folder, exist_ok=True)
104
+
105
+
106
+
107
+ def select_best(scores, seqs):
108
+ selected_scores = []
109
+ selected_seqs = []
110
+ for i in range(len(scores[0])):
111
+ best = scores[0][i]
112
+ best_seq = seqs[0][i]
113
+ for j in range(len(scores)-1):
114
+ if scores[j+1][i] > best:
115
+ best = scores[j+1][i]
116
+ best_seq = seqs[j+1][i]
117
+ selected_scores.append(best)
118
+ selected_seqs.append(best_seq)
119
+
120
+ return selected_seqs, selected_scores
121
+
122
+ if __name__ == '__main__':
123
+
124
+ if OPT == 'FMRL':
125
+ Optimize_FrameSlice = True
126
+ else:
127
+ Optimize_FrameSlice = False
128
+
129
+
130
+
131
+ if Optimize_FrameSlice:
132
+ model = load_framepool(path)
133
+
134
+ else:
135
+
136
+ model = torch.load(path,map_location=torch.device(device))['state_dict']
137
+ model.train()
138
+
139
+
140
+ wgan = tf.keras.models.load_model(gpath)
141
+
142
+ """
143
+ Data:
144
+ """
145
+
146
+ tf.random.set_seed(33)
147
+ np.random.seed(33)
148
+
149
+ diffs = []
150
+ init_exps = []
151
+ opt_exps = []
152
+ orig_vals = []
153
+
154
+ DIM = 40
155
+ MAX_LEN = 128
156
+ LR = np.exp(-LR)
157
+
158
+ tempnoise = tf.random.normal(shape=[BATCH_SIZE,DIM])
159
+ selectednoise = tempnoise
160
+
161
+ best = 10
162
+
163
+ LOW_START = False
164
+
165
+
166
+ if LOW_START:
167
+
168
+ for i in range(10000):
169
+ tempnoise = tf.random.normal(shape=[BATCH_SIZE,DIM])
170
+ sequences = wgan(tempnoise)
171
+
172
+ seqs_gen = recover_seq(sequences, rev_rna_vocab)
173
+ seqs_str = seqs_gen
174
+
175
+ shape_ = tf.shape(np.array([encode_seq_framepool(seq) for seq in recover_seq(sequences, rev_rna_vocab)]))
176
+
177
+ seqs = tf.convert_to_tensor(np.array([encode_seq_framepool(seq) for seq in recover_seq(sequences, rev_rna_vocab)]),dtype=tf.float32)
178
+
179
+
180
+ pred = model(seqs)
181
+
182
+ t = tf.reshape(pred,(-1))
183
+ t = t.numpy().astype('float')
184
+ score = np.mean(t)
185
+
186
+ if score < best:
187
+ best = score
188
+ selectednoise = tempnoise
189
+ noise = tf.Variable(selectednoise)
190
+ else:
191
+ noise = tf.Variable(tf.random.normal(shape=[BATCH_SIZE,DIM]))
192
+
193
+
194
+ noise_small = tf.random.normal(shape=[BATCH_SIZE,DIM],stddev=1e-4)
195
+
196
+ optimizer = tf.keras.optimizers.Adam(learning_rate=np.power(np.e,LR))
197
+
198
+ '''
199
+ Optimization takes place here.
200
+ '''
201
+
202
+ bind_scores_list = []
203
+ bind_scores_means = []
204
+ sequences_list = []
205
+
206
+ means = []
207
+ maxes = []
208
+ iters_ = []
209
+
210
+ OPTIMIZE = True
211
+
212
+ DNA_SEL = False
213
+
214
+
215
+ sequences_init = wgan(noise)
216
+
217
+ gen_seqs_init = sequences_init.numpy().astype('float')
218
+
219
+ seqs_gen_init = recover_seq(gen_seqs_init, rev_rna_vocab)
220
+
221
+ init_pos, init_neg = motif_count(seqs_gen_init,motifs_path)
222
+
223
+ if Optimize_FrameSlice:
224
+ seqs = prepare_framepool(seqs_gen_init)
225
+
226
+ seqs_init = prepare_mttrans(seqs_gen_init)
227
+
228
+ pred_init = model(seqs)
229
+
230
+ else:
231
+
232
+
233
+ one_hots = one_hot_all_motif(np.array(seqs_gen_init))
234
+ seqs = torch.tensor(one_hots,dtype=torch.double)
235
+ seqs = torch.transpose(seqs, 1, 2)
236
+ seqs = seqs.float().to(device)
237
+
238
+
239
+ pred_init = model.forward(seqs)
240
+
241
+ if Optimize_FrameSlice:
242
+
243
+ t = tf.reshape(pred_init,(-1))
244
+
245
+ init_t = t.numpy().astype('float')
246
+
247
+ else:
248
+
249
+ t = torch.flatten(pred_init)
250
+ t.float()
251
+
252
+ init_t = t.cpu().detach().numpy()
253
+
254
+ init_exp = np.mean(init_t)
255
+
256
+ max_init = np.max(init_t)
257
+
258
+ min_init = np.min(init_t)
259
+
260
+ predicted_mrls = []
261
+
262
+ STEPS = STEPS
263
+
264
+ seqs_collection = []
265
+ scores_collection = []
266
+ if OPTIMIZE:
267
+ iter_ = 0
268
+ for opt_iter in tqdm(range(int(STEPS))):
269
+
270
+ with tf.GradientTape() as gtape:
271
+ gtape.watch(noise)
272
+ sequences = wgan(noise)
273
+
274
+ seqs_gen = recover_seq(sequences, rev_rna_vocab)
275
+ seqs_collection.append(seqs_gen)
276
+ seqs_str = seqs_gen
277
+
278
+ if Optimize_FrameSlice:
279
+
280
+ seqs = tf.convert_to_tensor(np.array([encode_seq_framepool(seq) for seq in recover_seq(sequences, rev_rna_vocab)]),dtype=tf.float32)
281
+
282
+ else:
283
+ seqs = torch.tensor(np.array(one_hot_all_motif(seqs_gen),dtype=np.float32))
284
+
285
+ if Optimize_FrameSlice:
286
+
287
+ with tf.GradientTape() as ptape:
288
+ ptape.watch(seqs)
289
+
290
+ pred = model(seqs)
291
+ score = tf.reduce_mean(pred)
292
+ t = tf.reshape(pred,(-1))
293
+ mx = t.numpy().astype('float')
294
+ scores_collection.append(mx)
295
+ mx = np.max(mx)
296
+
297
+ sum_ = tf.reduce_sum(t).numpy().astype('float')
298
+
299
+ maxes.append(mx)
300
+ predicted_mrls.append(sum_/BATCH_SIZE)
301
+ means.append(sum_/BATCH_SIZE)
302
+
303
+ g1 = ptape.gradient(score,seqs)
304
+
305
+ OPTIMIZE_FULL = False
306
+ if OPTIMIZE_FULL:
307
+ tmp_g = g1.numpy().astype('float')
308
+ tmp_seqs = seqs_gen
309
+ tmp_lst = np.zeros(shape=(BATCH_SIZE,MAX_LEN,5))
310
+ for i in range(len(tmp_seqs)):
311
+
312
+ len_ = len(tmp_seqs[i])
313
+ edited_g = tmp_g[i][:len_,:]
314
+ edited_g = np.pad(edited_g,((0,MAX_LEN-len_),(0,1)),'constant')
315
+ tmp_lst[i] = edited_g
316
+
317
+ g1 = tf.convert_to_tensor(tmp_lst,dtype=tf.float32)
318
+
319
+ else:
320
+
321
+ g1 = tf.pad(g1,tf.constant([[0, 0], [0, 0], [0, 1]]),"CONSTANT")
322
+
323
+ g1 = tf.math.scalar_mul(-1.0,g1)
324
+
325
+
326
+ else:
327
+
328
+ seqs = torch.transpose(seqs, 1, 2)
329
+ seqs = seqs.float()
330
+ seqs = torch.tensor(seqs.to(device), requires_grad=True)
331
+ pred = model(seqs)
332
+ pred = torch.flatten(pred)
333
+ predicted_mrls.append(np.average(pred.cpu().detach().numpy()))
334
+ scores_collection.append(pred.cpu().detach().numpy())
335
+ score = torch.mean(pred)
336
+ t = torch.flatten(pred)
337
+ mx = t.cpu().detach().numpy()
338
+ mx = np.max(mx)
339
+
340
+ sum_ = torch.mean(t).cpu().detach().numpy()
341
+
342
+ maxes.append(mx)
343
+ means.append(sum_/BATCH_SIZE)
344
+ pred.backward(torch.ones_like(pred))
345
+
346
+ g1 = seqs.grad
347
+
348
+ g1 = g1.cpu().detach().numpy()
349
+ g1 = tf.convert_to_tensor(g1)
350
+ g1 = tf.transpose(g1, perm=[0,2,1])
351
+ g1 = tf.pad(g1,tf.constant([[0, 0], [0, 0], [0, 1]]),"CONSTANT")
352
+ g1 = tf.math.scalar_mul(-1.0,g1)
353
+
354
+
355
+ g2 = gtape.gradient(sequences,noise,output_gradients=g1)
356
+
357
+ a1 = g2 + noise_small
358
+ change = [(a1,noise)]
359
+ optimizer.apply_gradients(change)
360
+
361
+ iters_.append(iter_)
362
+ iter_ += 1
363
+
364
+ best_seqs, best_scores = select_best(scores_collection, seqs_collection)
365
+
366
+ sequences_opt = wgan(noise)
367
+
368
+ gen_seqs_opt = sequences_opt.numpy().astype('float')
369
+
370
+ seqs_gen_opt = recover_seq(gen_seqs_opt, rev_rna_vocab)
371
+
372
+ opt_pos, opt_neg = motif_count(seqs_gen_opt,motifs_path)
373
+
374
+ if Optimize_FrameSlice:
375
+
376
+ seqs_opt = prepare_framepool(seqs_gen_opt)
377
+
378
+
379
+
380
+ else:
381
+
382
+ one_hots = np.array(one_hot_all_motif(seqs_gen_opt))
383
+ # print(np.shape(one_hots))
384
+ seqs = torch.tensor(one_hots,dtype=torch.double)
385
+ seqs = torch.transpose(seqs, 1, 2)
386
+ seqs = seqs.float().to(device)
387
+
388
+ pred_opt = model(seqs)
389
+
390
+ if Optimize_FrameSlice:
391
+
392
+ t = tf.reshape(pred_opt,(-1))
393
+
394
+ opt_t = t.numpy().astype('float')
395
+
396
+ else:
397
+
398
+ t = torch.flatten(pred_opt)
399
+
400
+
401
+ opt_t = t.cpu().detach().numpy()
402
+
403
+ opt_exp = np.mean(opt_t)
404
+
405
+ min_opt = np.min(opt_t)
406
+ max_opt = np.max(opt_t)
407
+
408
+ with open(os.path.join(out_folder, f'init_mrl_{OPT}.txt'), 'w') as f:
409
+ f.writelines([str(x)+'\n' for x in init_t])
410
+
411
+ with open(os.path.join(out_folder, f'opt_mrl_{OPT}.txt'), 'w') as f:
412
+ f.writelines([str(x)+'\n' for x in best_scores])
413
+
414
+ with open(os.path.join(out_folder, f'opt_seqs_{OPT}.txt'), 'w') as f:
415
+ f.writelines([str(x)+'\n' for x in best_seqs])
416
+
417
+ with open(os.path.join(out_folder, f'init_seqs_{OPT}.txt'), 'w') as f:
418
+ f.writelines([str(x)+'\n' for x in seqs_gen_init])
419
+
420
+
421
+ print(f"Average Initial Pred: {np.average(init_t)}")
422
+ print(f"Max Initial Pred: {np.max(init_t)}")
423
+ print(f"Average Opt. Pred: {np.average(best_scores)}")
424
+ print(f"Max Opt. Pred: {np.max(best_scores)}")
scripts/predict.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate 5' UTR candidates and rank them with FramePool and MTtrans."""
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ import sys
7
+ from pathlib import Path
8
+
9
+
10
+ PROJECT_ROOT = Path(__file__).resolve().parents[1]
11
+ MODEL_ROOT = PROJECT_ROOT / "model"
12
+ MODULE_ROOT = MODEL_ROOT / "src" / "mrl_te_optimization"
13
+
14
+
15
+ def parse_args():
16
+ parser = argparse.ArgumentParser(
17
+ description="Generate UTRGAN candidates and rank by MRL and TE."
18
+ )
19
+ parser.add_argument("--num-candidates", type=int, default=1024)
20
+ parser.add_argument("--batch-size", type=int, default=128)
21
+ parser.add_argument("--seed", type=int, default=33)
22
+ parser.add_argument("--device", choices=("dcu", "cpu"), default="dcu")
23
+ parser.add_argument("--device-id", default="0")
24
+ parser.add_argument(
25
+ "--output-dir",
26
+ default=str(PROJECT_ROOT / "outputs" / "pretrained_batch_ranking"),
27
+ )
28
+ return parser.parse_args()
29
+
30
+
31
+ def configure_runtime(args):
32
+ os.environ.setdefault("TF_USE_LEGACY_KERAS", "1")
33
+ os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "2")
34
+ if args.device == "cpu":
35
+ os.environ["HIP_VISIBLE_DEVICES"] = "-1"
36
+ os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
37
+ else:
38
+ os.environ["HIP_VISIBLE_DEVICES"] = args.device_id
39
+ os.environ["CUDA_VISIBLE_DEVICES"] = args.device_id
40
+ for import_root in (MODEL_ROOT, MODULE_ROOT):
41
+ if str(import_root) not in sys.path:
42
+ sys.path.insert(0, str(import_root))
43
+
44
+
45
+ def main():
46
+ args = parse_args()
47
+ if args.num_candidates < 1 or args.batch_size < 1:
48
+ raise ValueError("--num-candidates and --batch-size must be positive")
49
+ configure_runtime(args)
50
+
51
+ import numpy as np
52
+ import pandas as pd
53
+ import tensorflow as tf
54
+ import torch
55
+
56
+ import framepool
57
+ import util
58
+
59
+ output_dir = Path(args.output_dir).expanduser().resolve()
60
+ output_dir.mkdir(parents=True, exist_ok=True)
61
+
62
+ generator_path = PROJECT_ROOT / "weight" / "checkpoint_3000.h5"
63
+ framepool_path = PROJECT_ROOT / "weight" / "utr_model_combined_residual_new.h5"
64
+ mttrans_path = (
65
+ PROJECT_ROOT
66
+ / "weight"
67
+ / "mttrans"
68
+ / "RL_hard_share_MTL"
69
+ / "3R"
70
+ / "schedule_MTL-model_best_cv1.pth"
71
+ )
72
+ for path in (generator_path, framepool_path, mttrans_path):
73
+ if not path.is_file():
74
+ raise FileNotFoundError(path)
75
+
76
+ tf_device = "/GPU:0" if args.device == "dcu" else "/CPU:0"
77
+ torch_device = torch.device("cuda:0" if args.device == "dcu" else "cpu")
78
+ if args.device == "dcu":
79
+ tf_gpus = tf.config.list_physical_devices("GPU")
80
+ if not tf_gpus:
81
+ raise RuntimeError("TensorFlow did not detect a DCU")
82
+ if not torch.cuda.is_available():
83
+ raise RuntimeError("PyTorch did not detect a DCU")
84
+ for gpu in tf_gpus:
85
+ try:
86
+ tf.config.experimental.set_memory_growth(gpu, True)
87
+ except RuntimeError:
88
+ pass
89
+
90
+ # Loading on CPU avoids device-side random-initializer kernels; inference
91
+ # is explicitly placed on the requested device below.
92
+ with tf.device("/CPU:0"):
93
+ generator = tf.keras.models.load_model(generator_path, compile=False)
94
+ mrl_model = framepool.load_framepool(str(framepool_path))
95
+ generator.trainable = False
96
+ mrl_model.trainable = False
97
+
98
+ checkpoint = torch.load(
99
+ mttrans_path, map_location="cpu", weights_only=False
100
+ )
101
+ te_model = checkpoint["state_dict"].to(torch_device)
102
+ te_model.eval()
103
+
104
+ np.random.seed(args.seed)
105
+ tf.random.set_seed(args.seed)
106
+ torch.manual_seed(args.seed)
107
+ if args.device == "dcu":
108
+ torch.cuda.manual_seed_all(args.seed)
109
+
110
+ noise = np.random.RandomState(args.seed).normal(
111
+ size=(args.num_candidates, 40)
112
+ ).astype(np.float32)
113
+
114
+ generated_batches = []
115
+ with tf.device(tf_device):
116
+ for start in range(0, args.num_candidates, args.batch_size):
117
+ stop = min(start + args.batch_size, args.num_candidates)
118
+ generated_batches.append(
119
+ generator(tf.convert_to_tensor(noise[start:stop]), training=False).numpy()
120
+ )
121
+ generated = np.concatenate(generated_batches, axis=0)
122
+ if generated.shape != (args.num_candidates, 128, 5):
123
+ raise RuntimeError(f"Unexpected generator shape: {generated.shape}")
124
+ if not np.isfinite(generated).all():
125
+ raise RuntimeError("Generator output contains NaN/Inf")
126
+
127
+ sequences = list(util.recover_seq(generated, util.rev_rna_vocab))
128
+ mrl_scores = []
129
+ with tf.device(tf_device):
130
+ for start in range(0, len(sequences), args.batch_size):
131
+ chunk = sequences[start : start + args.batch_size]
132
+ encoded = np.asarray(
133
+ [util.encode_seq_framepool(seq) for seq in chunk],
134
+ dtype=np.float32,
135
+ )
136
+ prediction = mrl_model(tf.convert_to_tensor(encoded), training=False)
137
+ mrl_scores.extend(tf.reshape(prediction, (-1,)).numpy().tolist())
138
+
139
+ te_scores = []
140
+ with torch.inference_mode():
141
+ for start in range(0, len(sequences), args.batch_size):
142
+ chunk = sequences[start : start + args.batch_size]
143
+ encoded = np.asarray(util.one_hot_all_motif(chunk), dtype=np.float32)
144
+ encoded = torch.from_numpy(encoded).transpose(1, 2).to(torch_device)
145
+ prediction = te_model(encoded)
146
+ te_scores.extend(prediction.reshape(-1).cpu().numpy().tolist())
147
+
148
+ mrl_scores = np.asarray(mrl_scores, dtype=np.float32)
149
+ te_scores = np.asarray(te_scores, dtype=np.float32)
150
+ if not np.isfinite(mrl_scores).all() or not np.isfinite(te_scores).all():
151
+ raise RuntimeError("MRL/TE scores contain NaN/Inf")
152
+
153
+ table = pd.DataFrame(
154
+ {
155
+ "candidate_id": [
156
+ f"UTRGAN_{index + 1:05d}" for index in range(len(sequences))
157
+ ],
158
+ "sequence": sequences,
159
+ "length": [len(sequence) for sequence in sequences],
160
+ "mrl_score": mrl_scores,
161
+ "te_score": te_scores,
162
+ }
163
+ )
164
+ table["is_duplicate"] = table.duplicated("sequence", keep="first")
165
+ table["mrl_rank"] = table["mrl_score"].rank(
166
+ method="first", ascending=False
167
+ ).astype(int)
168
+ table["te_rank"] = table["te_score"].rank(
169
+ method="first", ascending=False
170
+ ).astype(int)
171
+ unique = table.drop_duplicates("sequence", keep="first").copy()
172
+
173
+ table.to_csv(output_dir / "all_candidates_scores.csv", index=False)
174
+ unique.sort_values("mrl_score", ascending=False).to_csv(
175
+ output_dir / "ranked_by_mrl.csv", index=False
176
+ )
177
+ unique.sort_values("te_score", ascending=False).to_csv(
178
+ output_dir / "ranked_by_te.csv", index=False
179
+ )
180
+ np.save(output_dir / "generator_probabilities.npy", generated)
181
+
182
+ summary = {
183
+ "requested_candidates": args.num_candidates,
184
+ "generated_candidates": len(table),
185
+ "unique_sequences": len(unique),
186
+ "duplicate_sequences": int(table["is_duplicate"].sum()),
187
+ "generator_shape": list(generated.shape),
188
+ "generator_probability_max_error": float(
189
+ np.max(np.abs(generated.sum(axis=-1) - 1.0))
190
+ ),
191
+ "length_min": int(table["length"].min()),
192
+ "length_max": int(table["length"].max()),
193
+ "mrl_min": float(mrl_scores.min()),
194
+ "mrl_max": float(mrl_scores.max()),
195
+ "mrl_mean": float(mrl_scores.mean()),
196
+ "te_min": float(te_scores.min()),
197
+ "te_max": float(te_scores.max()),
198
+ "te_mean": float(te_scores.mean()),
199
+ "tensorflow_version": tf.__version__,
200
+ "torch_version": torch.__version__,
201
+ "torch_hip": torch.version.hip,
202
+ "device": args.device,
203
+ "seed": args.seed,
204
+ }
205
+ (output_dir / "summary.json").write_text(
206
+ json.dumps(summary, indent=2), encoding="utf-8"
207
+ )
208
+ print(json.dumps(summary, indent=2))
209
+ print("UTRGAN_PRETRAINED_BATCH_MRL_TE_RANKING_PASS")
210
+
211
+
212
+ if __name__ == "__main__":
213
+ main()
scripts/train.py ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ # Keep the official ``src`` package importable after adopting the standard
6
+ # conf/model/scripts/weight layout.
7
+ PROJECT_ROOT = Path(__file__).resolve().parents[1]
8
+ MODEL_ROOT = PROJECT_ROOT / "model"
9
+ if str(MODEL_ROOT) not in sys.path:
10
+ sys.path.insert(0, str(MODEL_ROOT))
11
+
12
+ # The released H5 files use the legacy Keras serialization format.
13
+ os.environ.setdefault("TF_USE_LEGACY_KERAS", "1")
14
+
15
+ import numpy as np
16
+ import pandas as pd
17
+ import pdb
18
+ import tensorflow as tf
19
+ # from IPython.display import clear_output
20
+ import time
21
+ from src.gan.lib import models
22
+ from src.gan.lib import utils
23
+ import socket
24
+ import datetime
25
+ from tqdm import tqdm
26
+ import random
27
+ import matplotlib.pyplot as plt
28
+ import argparse
29
+
30
+ import tensorflow.keras.backend as K
31
+ from tensorflow.keras.optimizers import Adam
32
+
33
+ tf.compat.v1.enable_eager_execution()
34
+
35
+
36
+ parser = argparse.ArgumentParser()
37
+ parser.add_argument('-d', type=str, required=False,
38
+ default=str(PROJECT_ROOT / 'conf' / 'data' / 'utrdb2.csv'))
39
+ parser.add_argument('-bs', type=int, required=False ,default=64)
40
+ parser.add_argument('-lr', type=int, required=False ,default=5)
41
+ parser.add_argument('-mil', type=int, required=False ,default=64)
42
+ parser.add_argument('-mxl', type=int, required=False ,default=128)
43
+ parser.add_argument('-dim', type=int, required=False ,default=40)
44
+ parser.add_argument('-gpu', type=str, required=False ,default='-1')
45
+ parser.add_argument('-e', '--epochs', type=int, default=4000,
46
+ help='Number of complete passes over the filtered UTRdb dataset.')
47
+ parser.add_argument('--output-dir', type=str,
48
+ default=str(PROJECT_ROOT / 'outputs' / 'train'),
49
+ help='Directory for logs, generated samples, and checkpoints.')
50
+ args = parser.parse_args()
51
+
52
+ MODEL_NAME = 'WGAN-TF2'
53
+ RUN_ROOT = Path(args.output_dir).expanduser().resolve()
54
+ OUTPUT_PATH = RUN_ROOT / 'outputs' / MODEL_NAME
55
+ TRAIN_LOGDIR = RUN_ROOT / 'tensorboard' / MODEL_NAME / 'train_data'
56
+ OUTPUT_PATH.mkdir(parents=True, exist_ok=True)
57
+ TRAIN_LOGDIR.mkdir(parents=True, exist_ok=True)
58
+ file_writer = tf.summary.create_file_writer(str(TRAIN_LOGDIR))
59
+
60
+ if args.gpu == '-1':
61
+ device = 'cpu'
62
+ else:
63
+ os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
64
+ device = 'cuda'
65
+
66
+ def plot(x, y, logdir, name, xlabel=None, ylabel=None, title=None):
67
+
68
+ plt.plot(x,y,'-')
69
+ plt.title(title)
70
+ plt.xlabel(xlabel)
71
+ plt.ylabel(ylabel)
72
+ plt.savefig(logdir+'/'+name+'.png')
73
+ plt.clf()
74
+
75
+
76
+ def plot_valid(x1, y1, x2, y2, logdir, name, xlabel=None, ylabel=None, title=None):
77
+
78
+ plt.plot(x2,y2,'-',color='tab:blue')
79
+ plt.plot(x1,y1,'-',color='tab:orange')
80
+
81
+ plt.title(title)
82
+ plt.xlabel(xlabel)
83
+ plt.ylabel(ylabel)
84
+
85
+ plt.savefig(logdir+'/'+name+'.png')
86
+ plt.clf()
87
+
88
+ def gradient_penalty_loss( y_true, y_pred, discriminator):
89
+ """
90
+ Computes gradient penalty based on prediction and weighted real / fake samples
91
+ """
92
+ alpha = K.random_uniform((DIM, 1, 1))
93
+ averaged_samples = (alpha * y_pred) + ((1 - alpha) * y_true)
94
+
95
+ gradients = K.gradients(y_pred, averaged_samples)[0]
96
+ # compute the euclidean norm by squaring ...
97
+ gradients_sqr = K.square(gradients)
98
+ # ... summing over the rows ...
99
+ gradients_sqr_sum = K.sum(gradients_sqr,
100
+ axis=np.arange(1, len(gradients_sqr.shape)))
101
+ # ... and sqrt
102
+ gradient_l2_norm = K.sqrt(gradients_sqr_sum)
103
+ # compute lambda * (1 - ||grad||)^2 still for each single sample
104
+ gradient_penalty = K.square(1 - gradient_l2_norm)
105
+ # return the mean as loss over all the batch samples
106
+ return K.mean(gradient_penalty)
107
+
108
+ def log(samples_dir=False,suff=None):
109
+ stamp = datetime.date.strftime(datetime.datetime.now(), "%Y.%m.%d-%Hh%Mm%Ss") + "_{}".format(socket.gethostname())
110
+ full_logdir = os.path.join(str(RUN_ROOT / "logs"), stamp)
111
+ if suff:
112
+ full_logdir = full_logdir + suff
113
+ os.makedirs(full_logdir, exist_ok=True)
114
+ if samples_dir: os.makedirs(os.path.join(full_logdir, "samples"), exist_ok=True)
115
+ log_dir = "{}:{}".format(socket.gethostname(), full_logdir)
116
+
117
+ return full_logdir, 0
118
+
119
+ data_path = args.d
120
+ data_utr = pd.read_csv(data_path)
121
+ UTRdf = data_utr['seq'].to_numpy()
122
+
123
+ seqs = []
124
+
125
+ UTR_LEN = args.mxl
126
+
127
+ for i in range(len(UTRdf)):
128
+ if len(UTRdf[i]) < UTR_LEN+1 and len(UTRdf[i]) > int(UTR_LEN/2):
129
+ if UTRdf[i] not in seqs:
130
+ seqs.append(UTRdf[i])
131
+
132
+ sequences = np.array(seqs)
133
+
134
+ sequences = [x.upper() for x in sequences]
135
+
136
+ rna_vocab = {"A":0,
137
+ "C":1,
138
+ "G":2,
139
+ "U":3,
140
+ "*":4}
141
+
142
+ rev_rna_vocab = {v:k for k,v in rna_vocab.items()}
143
+
144
+ def one_hot_encode(seq, SEQ_LEN=UTR_LEN):
145
+ mapping = dict(zip("ACGT*", range(5)))
146
+ seq2 = [mapping[i] for i in seq]
147
+ if len(seq2) < SEQ_LEN:
148
+ extra = [np.eye(5)[4]] * (SEQ_LEN - len(seq2))
149
+ return np.vstack([np.eye(5)[seq2] , extra])
150
+ return np.eye(5)[seq2]
151
+
152
+ def one_hot_encode_2(seq, SEQ_LEN=UTR_LEN):
153
+ mapping = dict(zip("ACGT", range(4)))
154
+ seq2 = [mapping[i] for i in seq]
155
+ return np.eye(4)[seq2]
156
+
157
+ ohe_sequences = np.asarray([one_hot_encode(x) for x in sequences])
158
+
159
+
160
+ BATCH_SIZE = args.bs # Batch size
161
+ ITERS = args.epochs # How many complete dataset iterations to train for
162
+ SEQ_LEN = UTR_LEN # Sequence length in characters
163
+ DIM = args.dim # Model dimensionality.
164
+ CRITIC_ITERS = 5 # How many critic iterations per generator iteration.
165
+ LAMBDA = 10 # Gradient penalty lambda hyperparameter.
166
+ # README defines ``-lr 5`` as 1e-5. The upstream ``e**args.lr`` expression
167
+ # is inconsistent with that documented interface.
168
+ LR = np.power(10.0, -args.lr)
169
+
170
+
171
+ LAMBDA = 10 # For gradient penalty
172
+
173
+ CURRENT_EPOCH = 1 # Epoch start from
174
+ SAVE_EVERY_N_EPOCH = 50 # Save checkpoint at every n epoch
175
+
176
+ MIN_LR = 0.000001 # Minimum value of learning rate
177
+ DECAY_FACTOR=1.00004 # learning rate decay factor
178
+ '''
179
+ Set seed for reproducibility
180
+ '''
181
+ seed = 35
182
+ np.random.seed(seed)
183
+ # tf.set_random_seed(seed)
184
+ tf.random.set_seed(seed)
185
+
186
+ logdir, checkpoint_baseline = log(samples_dir=True)
187
+ logdir2 = ''
188
+
189
+ '''
190
+ Build GAN
191
+ '''
192
+ model_type = "resnet"
193
+ data_enc_dim = 5
194
+ data_size = SEQ_LEN * data_enc_dim
195
+ # data_size = 256
196
+ gen_layers = 3
197
+ disc_layers = 3
198
+ lmbda = 10. #lipschitz penalty hyperparameter.
199
+
200
+ SAMPLE_SIZE = 128
201
+
202
+ N_CHANNELS = DIM
203
+
204
+ G = models.resnet_g2(DIM,N_CHANNELS,SEQ_LEN,5,res_layers=gen_layers)
205
+ D = models.resnet_d2(N_CHANNELS,SEQ_LEN,5,res_layers=disc_layers)
206
+
207
+ G.summary()
208
+ D.summary()
209
+
210
+ D_optimizer = Adam(learning_rate=LR, beta_1=0.5, beta_2=0.99)
211
+ G_optimizer = Adam(learning_rate=LR, beta_1=0.5, beta_2=0.99)
212
+
213
+ EPOCHs = ITERS
214
+
215
+ @tf.function
216
+ def WGAN_GP_train_d_step(real_sample, batch_size, step):
217
+
218
+ noise = tf.random.normal([batch_size, DIM])
219
+ epsilon = tf.random.uniform(shape=[batch_size, 1, 1], minval=0, maxval=1)
220
+ ###################################
221
+ # Train D
222
+ ###################################
223
+ with tf.GradientTape(persistent=True) as d_tape:
224
+ with tf.GradientTape() as gp_tape:
225
+ fake_sample = G([noise], training=True)
226
+ fake_sample_mixed = epsilon * tf.dtypes.cast(real_sample, tf.float32) + ((1 - epsilon) * fake_sample)
227
+ fake_mixed_pred = D([fake_sample_mixed], training=True)
228
+
229
+ # Compute gradient penalty
230
+ grads = gp_tape.gradient(fake_mixed_pred, fake_sample_mixed)
231
+ grad_norms = tf.sqrt(tf.reduce_sum(tf.square(grads), axis=[1,2])) # Originally axis=[1,2]
232
+ # grad_norms = tf.norm(grads, axis=[1,2])
233
+ gradient_penalty = tf.reduce_mean(tf.square(grad_norms - 1.))
234
+
235
+ fake_pred = D([fake_sample], training=True)
236
+ real_pred = D([real_sample], training=True)
237
+
238
+ D_loss = tf.reduce_mean(fake_pred) - tf.reduce_mean(real_pred) + LAMBDA * gradient_penalty
239
+ # Calculate the gradients for discriminator
240
+ D_gradients = d_tape.gradient(D_loss,D.trainable_variables)
241
+ # Apply the gradients to the optimizer
242
+ D_optimizer.apply_gradients(zip(D_gradients,D.trainable_variables))
243
+ # Write loss values to tensorboard
244
+ if step % 10 == 0:
245
+ with file_writer.as_default():
246
+ tf.summary.scalar('D_loss', tf.reduce_mean(D_loss), step=step)
247
+
248
+ return D_loss, gradient_penalty
249
+
250
+ @tf.function
251
+ def WGAN_GP_train_g_step(real_sample, batch_size, step):
252
+
253
+ noise = tf.random.normal([batch_size, DIM])
254
+ ###################################
255
+ # Train G
256
+ ###################################
257
+ with tf.GradientTape() as g_tape:
258
+ fake_sample = G([noise], training=True)
259
+ fake_pred = D([fake_sample], training=True)
260
+ G_loss = -tf.reduce_mean(fake_pred)
261
+
262
+ G_gradients = g_tape.gradient(G_loss,
263
+ G.trainable_variables)
264
+ # Apply the gradients to the optimizer
265
+ G_optimizer.apply_gradients(zip(G_gradients,
266
+ G.trainable_variables))
267
+ # Write loss values to tensorboard
268
+ if step % 10 == 0:
269
+ with file_writer.as_default():
270
+ tf.summary.scalar('G_loss', G_loss, step=step)
271
+
272
+ return G_loss, noise
273
+
274
+ checkpoint_path = os.path.join(str(RUN_ROOT), "checkpoints", "tensorflow", MODEL_NAME)
275
+
276
+ ckpt = tf.train.Checkpoint(generator=G,
277
+ discriminator=D,
278
+ G_optimizer=G_optimizer,
279
+ D_optimizer=D_optimizer)
280
+
281
+ ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=40)
282
+
283
+ def generate_and_save_samples(model, epoch, test_input, figure_size=(12,6), subplot=(3,6), save=True, is_flatten=False):
284
+ '''
285
+ Generate samples and plot it.
286
+ '''
287
+ predictions = model.predict(test_input)
288
+ utils.save_samples(logdir, predictions, epoch, rev_rna_vocab, annotated=False)
289
+
290
+
291
+ '''
292
+ load data
293
+ '''
294
+
295
+ Train = True
296
+ validate = True
297
+
298
+ data = ohe_sequences
299
+
300
+
301
+ if validate:
302
+ split = len(data) // 10
303
+ # print(split)
304
+ valid_data = data[:split]
305
+ train_data = data[split:]
306
+ if len(train_data) == 1: train_data = train_data[0]
307
+ if len(valid_data) == 1: valid_data = valid_data[0]
308
+ else:
309
+ train_data = data
310
+
311
+
312
+ train_data = train_data.astype('float32')
313
+ valid_data = valid_data.astype('float32')
314
+
315
+ train_seqs = tf.data.Dataset.from_tensor_slices(train_data).shuffle(len(train_data)).batch(BATCH_SIZE)
316
+ valid_seqs = tf.data.Dataset.from_tensor_slices(valid_data).shuffle(len(valid_data)).batch(split)
317
+
318
+
319
+ plot_iter = 10
320
+
321
+ current_learning_rate = LR
322
+ trace = True
323
+ n_critic_count = 0
324
+
325
+ d_losses = []
326
+ g_losses = []
327
+ gradient_penalties = []
328
+ iterations = 0
329
+ iteration_numbers = []
330
+ iteration_numbers_valid = []
331
+ d_validation_losses = []
332
+
333
+ random_name = time.strftime("%Y%m%d-%H%M%S")
334
+
335
+ gen_iters = 0
336
+
337
+ if Train:
338
+ sample_noise = tf.random.normal([BATCH_SIZE, DIM])
339
+ generate_and_save_samples(G, 0, [sample_noise], figure_size=(12,6), subplot=(3,6), save=False, is_flatten=False)
340
+
341
+ pbar = tqdm(range(EPOCHs))
342
+ for epoch in pbar:
343
+ start = time.time()
344
+
345
+ tdataset = train_seqs.enumerate()
346
+
347
+ for step, tdata in tdataset.as_numpy_iterator():
348
+ current_batch_size = tdata.shape[0]
349
+
350
+ d_loss, gp = WGAN_GP_train_d_step(tdata, batch_size=tf.constant(current_batch_size, dtype=tf.int64), step=tf.constant(step, dtype=tf.int64))
351
+ n_critic_count += 1
352
+ if n_critic_count >= CRITIC_ITERS:
353
+ g_loss, noise = WGAN_GP_train_g_step(tdata, batch_size= tf.constant(current_batch_size, dtype=tf.int64), step=tf.constant(step, dtype=tf.int64))
354
+ gen_iters += 1
355
+ n_critic_count = 0
356
+
357
+ if step % 10 == 0:
358
+ print ('.', end='')
359
+
360
+
361
+ if epoch % SAVE_EVERY_N_EPOCH == 0 and epoch != 0:
362
+ ckpt_save_path = ckpt_manager.save()
363
+ utils.save_checkpoints(logdir,G,epoch)
364
+
365
+ if epoch % 50 == 0:
366
+
367
+ generate_and_save_samples(G, epoch, [sample_noise], figure_size=(12,6), subplot=(3,6), save=True, is_flatten=False)
368
+
369
+ os.system('clear')
370
+
371
+ iteration_numbers.append(iterations)
372
+ g_losses.append(-g_loss)
373
+ d_losses.append(-d_loss)
374
+ gradient_penalties.append(gp)
375
+ # plot(iteration_numbers, d_losses, logdir, 'discriminator_loss', xlabel="Iteration", ylabel="Discriminator Cost")
376
+ # plot(iteration_numbers, g_losses, logdir, 'generator_loss', xlabel="Iteration", ylabel="Generator Cost")
377
+ # plot(iteration_numbers, gradient_penalties, logdir, 'gradient_penalty', xlabel="Iteration", ylabel="Gradient Penalty")
378
+
379
+ iterations+=1
380
+
381
+ iteration_numbers_valid.append(iterations)
382
+ fake_sample_valid = G([noise], training=True)
383
+ fake_pred_valid = D([fake_sample_valid], training=True)
384
+ real_pred_valid = D([tf.convert_to_tensor(list(valid_seqs.as_numpy_iterator())[0])], training=True)
385
+
386
+ D_loss_valid = tf.reduce_mean(fake_pred_valid) - tf.reduce_mean(real_pred_valid)
387
+ d_validation_losses.append(-D_loss_valid)
388
+
389
+ # plot_valid(iteration_numbers_valid, d_validation_losses, iteration_numbers, d_losses, logdir, 'validation_loss', xlabel="Iteration", ylabel="D Validation Loss")
390
+
391
+ ckpt_save_path = ckpt_manager.save()
392
+ print ('Saving checkpoint for epoch {} at {}'.format(EPOCHs,
393
+ ckpt_save_path))
394
+
395
+
396
+ print("####################################################")
397
+ print(f"############### Gen Iterations : {gen_iters} #####")
398
+ print("####################################################")