cisformer 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cisformer/M2Mmodel/M2M.py +903 -0
- cisformer/M2Mmodel/__init__.py +1 -0
- cisformer/M2Mmodel/block.py +369 -0
- cisformer/M2Mmodel/utils.py +529 -0
- cisformer/__init__.py +2 -0
- cisformer/atac2rna_predict.py +190 -0
- cisformer/atac2rna_surround_attention_generate.py +294 -0
- cisformer/atac2rna_train.py +380 -0
- cisformer/compute_surround_enhancer.py +43 -0
- cisformer/data_preprocess.py +236 -0
- cisformer/generate_default_config.py +91 -0
- cisformer/map_rna_atac.py +138 -0
- cisformer/resource/.__init__.py +0 -0
- cisformer/resource/hg38.refGene.gtf.gz +0 -0
- cisformer/resource/human_cCREs.bed +1033239 -0
- cisformer/resource/human_genes.tsv +38244 -0
- cisformer/rna2atac_predict.py +247 -0
- cisformer/rna2atac_train.py +419 -0
- cisformer/runner.py +139 -0
- cisformer-1.0.0.dist-info/METADATA +175 -0
- cisformer-1.0.0.dist-info/RECORD +24 -0
- cisformer-1.0.0.dist-info/WHEEL +4 -0
- cisformer-1.0.0.dist-info/entry_points.txt +2 -0
- cisformer-1.0.0.dist-info/licenses/LICENCE +19 -0
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import torch
|
|
3
|
+
from torch import nn
|
|
4
|
+
from cisformer.M2Mmodel.block import TransformerBlock, default, route_args
|
|
5
|
+
from einops import rearrange
|
|
6
|
+
import yaml
|
|
7
|
+
import torch.nn.functional as F
|
|
8
|
+
from torch.cuda.amp import autocast
|
|
9
|
+
import threading
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
ENC_PREFIX = 'enc_'
|
|
13
|
+
DEC_PREFIX = 'dec_'
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
Special tokens:
|
|
17
|
+
|
|
18
|
+
0: <PAD>
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# helper
|
|
22
|
+
|
|
23
|
+
def exists(val):
|
|
24
|
+
return val is not None
|
|
25
|
+
|
|
26
|
+
def cast_tuple(val):
|
|
27
|
+
return (val,) if not isinstance(val, tuple) else val
|
|
28
|
+
|
|
29
|
+
def input_with_timeout(prompt, timeout):
|
|
30
|
+
"""
|
|
31
|
+
Prompt for input with a timeout.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
prompt (str): The input prompt message.
|
|
35
|
+
timeout (int): The timeout in seconds.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
str: The input from the user or None if timed out.
|
|
39
|
+
"""
|
|
40
|
+
user_input = [None] # Use a list to store input since lists are mutable
|
|
41
|
+
|
|
42
|
+
def get_input():
|
|
43
|
+
user_input[0] = input(prompt)
|
|
44
|
+
|
|
45
|
+
# Create and start a thread to get user input
|
|
46
|
+
input_thread = threading.Thread(target=get_input)
|
|
47
|
+
input_thread.start()
|
|
48
|
+
|
|
49
|
+
# Wait for the input thread to finish within the timeout period
|
|
50
|
+
input_thread.join(timeout)
|
|
51
|
+
|
|
52
|
+
# If the thread is still active, it means we have timed out
|
|
53
|
+
if input_thread.is_alive():
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
return user_input[0]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Always(nn.Module):
|
|
60
|
+
def __init__(self, val):
|
|
61
|
+
super().__init__()
|
|
62
|
+
self.val = val
|
|
63
|
+
|
|
64
|
+
def forward(self, *args, **kwargs):
|
|
65
|
+
return self.val
|
|
66
|
+
|
|
67
|
+
class Pass(nn.Module):
|
|
68
|
+
def forward(self, x):
|
|
69
|
+
return x
|
|
70
|
+
|
|
71
|
+
# sinusoidal positional embeddings
|
|
72
|
+
# mean 0 var 1
|
|
73
|
+
|
|
74
|
+
class FixedPositionalEmbedding(nn.Module):
|
|
75
|
+
def __init__(self, dim, seq_len):
|
|
76
|
+
super().__init__()
|
|
77
|
+
inv_freq = 1. / (1000 ** (torch.arange(0, dim, 2).half() / dim))
|
|
78
|
+
position = torch.arange(0, seq_len, dtype=torch.float16)
|
|
79
|
+
sinusoid_inp = torch.einsum("i,j->ij", position, inv_freq)
|
|
80
|
+
emb = torch.cat((sinusoid_inp.sin(), sinusoid_inp.cos()), dim=-1).half()
|
|
81
|
+
self.register_buffer('emb', emb)
|
|
82
|
+
|
|
83
|
+
def forward(self, x):
|
|
84
|
+
return self.emb[None, :x.shape[1], :].to(x).half()
|
|
85
|
+
|
|
86
|
+
# parameter helper
|
|
87
|
+
|
|
88
|
+
def group_dict_by_key(cond, d):
|
|
89
|
+
return_val = [dict(),dict()]
|
|
90
|
+
for key in d.keys():
|
|
91
|
+
match = bool(cond(key))
|
|
92
|
+
ind = int(not match)
|
|
93
|
+
return_val[ind][key] = d[key]
|
|
94
|
+
return (*return_val,)
|
|
95
|
+
|
|
96
|
+
def string_begins_with(prefix, str):
|
|
97
|
+
return bool(re.match(f'^{prefix}', str))
|
|
98
|
+
|
|
99
|
+
def group_by_key_prefix(prefix, d):
|
|
100
|
+
return group_dict_by_key(lambda x: string_begins_with(prefix, x), d)
|
|
101
|
+
|
|
102
|
+
def group_by_key_prefix_and_remove_prefix(prefix, d):
|
|
103
|
+
kwargs_with_prefix, kwargs = group_dict_by_key(lambda x: string_begins_with(prefix, x), d)
|
|
104
|
+
kwargs_without_prefix = dict(map(lambda x: (x[0][len(prefix):], x[1]), tuple(kwargs_with_prefix.items())))
|
|
105
|
+
return kwargs_without_prefix, kwargs
|
|
106
|
+
|
|
107
|
+
def extract_enc_dec_kwargs(kwargs):
|
|
108
|
+
enc_kwargs, kwargs = group_by_key_prefix_and_remove_prefix(ENC_PREFIX, kwargs)
|
|
109
|
+
dec_kwargs, kwargs = group_by_key_prefix_and_remove_prefix(DEC_PREFIX, kwargs)
|
|
110
|
+
return enc_kwargs, dec_kwargs, kwargs
|
|
111
|
+
|
|
112
|
+
def extract_and_set_enc_dec_kwargs(kwargs):
|
|
113
|
+
enc_kwargs, dec_kwargs, kwargs = extract_enc_dec_kwargs(kwargs)
|
|
114
|
+
if 'mask' in enc_kwargs:
|
|
115
|
+
dec_kwargs.setdefault('context_mask', enc_kwargs['mask'])
|
|
116
|
+
return enc_kwargs, dec_kwargs, kwargs
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# attntion matrix generator
|
|
120
|
+
def whole_attn_score_matrix_generator(q, k, q_mask = None, k_mask = None, double = False):
|
|
121
|
+
# q,k shape: b h n d
|
|
122
|
+
# mask shape: b n
|
|
123
|
+
b, _, n1, _ = q.shape
|
|
124
|
+
_, _, n2, _ = k.shape
|
|
125
|
+
# if n1 == n2:
|
|
126
|
+
# q = k.clone()
|
|
127
|
+
k_mask = default(k_mask, q_mask)
|
|
128
|
+
output = []
|
|
129
|
+
for batch in range(b):
|
|
130
|
+
if double:
|
|
131
|
+
batch_q = q[batch].double() # h n1 d
|
|
132
|
+
batch_k = k[batch].double() # h n2 d
|
|
133
|
+
batch_attn = torch.matmul(batch_q, batch_k.transpose(-2, -1)) / torch.sqrt(torch.tensor(batch_q.size(-1), dtype=torch.float64)) # h n1 n2
|
|
134
|
+
else:
|
|
135
|
+
batch_q = q[batch].float() # h n1 d
|
|
136
|
+
batch_k = k[batch].float() # h n2 d
|
|
137
|
+
batch_attn = torch.matmul(batch_q, batch_k.transpose(-2, -1)) / torch.sqrt(torch.tensor(batch_q.size(-1), dtype=torch.float32)) # h n1 n2
|
|
138
|
+
# print("batch_attn shape:", batch_attn.shape)
|
|
139
|
+
batch_attn = F.softmax(batch_attn, dim=-1)
|
|
140
|
+
# print("batch_attn shape:", batch_attn.shape)
|
|
141
|
+
batch_attn = torch.mean(batch_attn, dim = 0) # n1, n2
|
|
142
|
+
# print("batch_attn shape:", batch_attn.shape)
|
|
143
|
+
if exists(q_mask):
|
|
144
|
+
batch_q_mask = q_mask[batch] # n1
|
|
145
|
+
# print("batch_q_mask shape:", batch_q_mask.shape)
|
|
146
|
+
batch_attn = batch_attn[batch_q_mask, :]
|
|
147
|
+
if exists(k_mask):
|
|
148
|
+
batch_k_mask = k_mask[batch] # n2
|
|
149
|
+
batch_attn = batch_attn[:, batch_k_mask]
|
|
150
|
+
# if n1 == n2:
|
|
151
|
+
# batch_attn = (batch_attn + batch_attn.T) / 2
|
|
152
|
+
output.append(batch_attn.to("cpu"))
|
|
153
|
+
return output
|
|
154
|
+
|
|
155
|
+
def whole_attn_score_matrix(q, k, q_mask = None, k_mask = None, double = False):
|
|
156
|
+
"""_summary_
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
q (_type_): _description_
|
|
160
|
+
k (_type_): _description_
|
|
161
|
+
q_mask (tensor, optional): bool dtype, True for tokens to keep, False to drop. Defaults to None.
|
|
162
|
+
k_mask (tensor, optional): bool dtype, True for tokens to keep, False to drop. Defaults to None.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
list: attention weights for cells
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
with autocast():
|
|
169
|
+
output = whole_attn_score_matrix_generator(q, k, q_mask = q_mask, k_mask = k_mask, double = double)
|
|
170
|
+
except RuntimeError as e:
|
|
171
|
+
if "CUDA out of memory" in str(e):
|
|
172
|
+
print("CUDA out of memory, automatically use CPU to compute ...")
|
|
173
|
+
q = q.float().cpu()
|
|
174
|
+
k = k.float().cpu()
|
|
175
|
+
if exists(q_mask):
|
|
176
|
+
q_mask = q_mask.cpu()
|
|
177
|
+
if exists(k_mask):
|
|
178
|
+
k_mask = k_mask.cpu()
|
|
179
|
+
output = whole_attn_score_matrix_generator(q, k, q_mask = q_mask, k_mask = k_mask, double = double)
|
|
180
|
+
else:
|
|
181
|
+
raise e
|
|
182
|
+
return output
|
|
183
|
+
|
|
184
|
+
# def neighbour_attn_score_matrix(q, k, start=0, end=-1, mask = None):
|
|
185
|
+
# """_summary_
|
|
186
|
+
|
|
187
|
+
# Args:
|
|
188
|
+
# q (_type_): _description_
|
|
189
|
+
# k (_type_): _description_
|
|
190
|
+
# start (int, optional): _description_. Defaults to 0.
|
|
191
|
+
# end (int, optional): -1 for whole sequence. Defaults to -1.
|
|
192
|
+
# mask (tensor, optional): bool type, False for pad. Defaults to None.
|
|
193
|
+
|
|
194
|
+
# Returns:
|
|
195
|
+
# _type_: _description_
|
|
196
|
+
# """
|
|
197
|
+
# # q,k shape: b h n d
|
|
198
|
+
# # mask shape: b n
|
|
199
|
+
# b, _, n1, _ = q.shape
|
|
200
|
+
# _, _, n2, _ = k.shape
|
|
201
|
+
# output = []
|
|
202
|
+
# for batch in range(b):
|
|
203
|
+
# if exists(mask):
|
|
204
|
+
# batch_mask = mask[batch] # n
|
|
205
|
+
# batch_q = q[batch][:, batch_mask, :] # h n d
|
|
206
|
+
# batch_k = k[batch][:, batch_mask, :] # h n d
|
|
207
|
+
# else:
|
|
208
|
+
# batch_q = q[batch] # h n d
|
|
209
|
+
# batch_k = k[batch] # h n d
|
|
210
|
+
# batch_end = batch_q.shape[1] if end == -1 else end
|
|
211
|
+
# batch_q, batch_k = batch_q[:, start:batch_end, :], batch_k[:, start:batch_end, :]
|
|
212
|
+
# batch_attn = batch_q @ batch_k.transpose(-1,-2) # h n1 n2
|
|
213
|
+
# batch_attn = torch.mean(batch_attn, dim = 1)
|
|
214
|
+
# # batch_attn = torch.softmax(batch_attn)
|
|
215
|
+
# output.append({"attn": batch_attn.to("cpu"), "q_indices": list(range(start, batch_end)), "k_indices": list(range(start, batch_end))})
|
|
216
|
+
# return output
|
|
217
|
+
|
|
218
|
+
# def attn_score_matrix(q, k, topest_k = 20, related_num = 5, k_base = True, loop_size = 100):
|
|
219
|
+
# # q,k shape: b h n d
|
|
220
|
+
# if not k_base:
|
|
221
|
+
# q, k = k, q
|
|
222
|
+
# b, h, n1, d = q.shape
|
|
223
|
+
# n2 = k.shape[2]
|
|
224
|
+
|
|
225
|
+
# # loop 1: find most important k
|
|
226
|
+
# i = 0
|
|
227
|
+
# k_weight = torch.zeros(b,h,n2).to(q.device)
|
|
228
|
+
# # total_s = 0
|
|
229
|
+
# while i < n1:
|
|
230
|
+
# slice_q = q[:, :, i:i+loop_size, :]
|
|
231
|
+
# slice_attn = slice_q @ k.transpose(-1,-2) # b h n1 n2
|
|
232
|
+
# sum_slice_attn = torch.sum(slice_attn, dim = -2)
|
|
233
|
+
# k_weight += sum_slice_attn
|
|
234
|
+
# i += loop_size
|
|
235
|
+
# # total_s += torch.exp(slice_attn).sum().item()
|
|
236
|
+
# k_weight = torch.mean(k_weight, dim = -2) # b, n2
|
|
237
|
+
# _, k_indices = torch.topk(k_weight, topest_k, dim = -1)
|
|
238
|
+
|
|
239
|
+
# # loop 2: find the most important one related with each topest_k
|
|
240
|
+
# slice_k = []
|
|
241
|
+
# for j in range(k_indices.shape[0]):
|
|
242
|
+
# slice_k.append(k[j, :, k_indices[j, :], :].unsqueeze(0))
|
|
243
|
+
# slice_k = torch.cat(slice_k, dim = 0) # b h topest_k d
|
|
244
|
+
# inner_attn = q @ slice_k.transpose(-1,-2) # b h n1 topest_k
|
|
245
|
+
# inner_attn = torch.mean(inner_attn, dim = 1) # b n1 topest_k
|
|
246
|
+
# inner_q_indices = []
|
|
247
|
+
# for h in range(inner_attn.shape[-1]):
|
|
248
|
+
# slice_inner_attn = inner_attn[:,:,h] # b n1
|
|
249
|
+
# _, slice_inner_q_indices = torch.topk(slice_inner_attn, related_num, dim = -1) # b, topest_q
|
|
250
|
+
# inner_q_indices.append(slice_inner_q_indices)
|
|
251
|
+
# inner_q_indices = torch.cat(inner_q_indices, dim = -1)
|
|
252
|
+
# print(inner_q_indices)
|
|
253
|
+
# q_indices = []
|
|
254
|
+
# attn = []
|
|
255
|
+
# for j in range(inner_q_indices.shape[0]):
|
|
256
|
+
# slice_q_indices = torch.unique(inner_q_indices[j])
|
|
257
|
+
# # print(slice_q_indices.shape)
|
|
258
|
+
# attn.append(inner_attn[j, slice_q_indices, :].unsqueeze(0))
|
|
259
|
+
# # attn.append(torch.exp(inner_attn[j, slice_q_indices, :]) / total_s)
|
|
260
|
+
# q_indices.append(slice_q_indices)
|
|
261
|
+
# attn = torch.cat(attn, dim = 0)
|
|
262
|
+
|
|
263
|
+
# if k_base:
|
|
264
|
+
# return {"attn": attn.to("cpu"), "q_indices": q_indices, "k_indices": [k_indices[j, :] for j in range(b)]}
|
|
265
|
+
# else:
|
|
266
|
+
# return {"attn": attn.to("cpu"), "k_indices": q_indices, "q_indices": [k_indices[j, :] for j in range(b)]}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# def attn_score_matrix(q, k, start = 0, end = 100, related_num = 5, k_base = True):
|
|
270
|
+
# # q,k shape: b h n d
|
|
271
|
+
# if not k_base:
|
|
272
|
+
# q, k = k, q
|
|
273
|
+
# b, h, n1, d = q.shape
|
|
274
|
+
# k = k[:, :, start:end, :]
|
|
275
|
+
# attn = q @ k.transpose(-1,-2) # b, h, n1, n2
|
|
276
|
+
# attn = torch.mean(attn, dim = 1) # b, n1, n2
|
|
277
|
+
|
|
278
|
+
# # find most important q
|
|
279
|
+
# _, topest_q_indices = torch.topk(attn, related_num, dim = -2) # b, top_q, n2
|
|
280
|
+
# topest_q_indices = torch.unique(topest_q_indices) # top_q
|
|
281
|
+
# attn = attn[:, topest_q_indices, :] # b, top_q, n2
|
|
282
|
+
# q_indices = topest_q_indices.cpu().tolist()
|
|
283
|
+
|
|
284
|
+
# if k_base:
|
|
285
|
+
# return {"attn": attn.to("cpu"), "q_indices": q_indices, "k_indices": list(range(start, end))}
|
|
286
|
+
# else:
|
|
287
|
+
# return {"attn": attn.to("cpu"), "k_indices": q_indices, "q_indices": list(range(start, end))}
|
|
288
|
+
|
|
289
|
+
# module
|
|
290
|
+
class RnaLM(nn.Module):
|
|
291
|
+
"""for ATAC decoding
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
nn (_type_): _description_
|
|
295
|
+
"""
|
|
296
|
+
def __init__(
|
|
297
|
+
self,
|
|
298
|
+
*,
|
|
299
|
+
dim,
|
|
300
|
+
depth,
|
|
301
|
+
heads,
|
|
302
|
+
use_iConv = False,
|
|
303
|
+
num_gene_tokens = None,
|
|
304
|
+
value_require = False,
|
|
305
|
+
num_value_tokens = None,
|
|
306
|
+
enc = False,
|
|
307
|
+
dim_head = 64,
|
|
308
|
+
causal = False,
|
|
309
|
+
ff_mult = 4,
|
|
310
|
+
ff_chunks = 1,
|
|
311
|
+
use_scalenorm = False,
|
|
312
|
+
use_rezero = False,
|
|
313
|
+
ff_glu = False,
|
|
314
|
+
emb_dropout = 0.,
|
|
315
|
+
ff_dropout = 0.,
|
|
316
|
+
attn_dropout = 0.,
|
|
317
|
+
cross_attend = False,
|
|
318
|
+
qkv_bias = True,
|
|
319
|
+
attn_out_bias = True,
|
|
320
|
+
shift_tokens = False,
|
|
321
|
+
only_cross_attn = False
|
|
322
|
+
):
|
|
323
|
+
super().__init__()
|
|
324
|
+
std = 0.1
|
|
325
|
+
# assert dim % 7 == 0, "dim must be a multiple of 7"
|
|
326
|
+
|
|
327
|
+
self.enc = enc
|
|
328
|
+
self.value_require = value_require
|
|
329
|
+
self.use_iConv = use_iConv
|
|
330
|
+
if use_iConv:
|
|
331
|
+
self.iConv_enc = nn.Embedding(10, dim//7)
|
|
332
|
+
torch.nn.init.xavier_normal_(self.iConv_enc.weight, std)
|
|
333
|
+
else:
|
|
334
|
+
assert exists(num_gene_tokens), "you need to pass num_gene_tokens to the model as don't use iConv module"
|
|
335
|
+
self.gene_emb = nn.Embedding(num_gene_tokens, dim)
|
|
336
|
+
if value_require:
|
|
337
|
+
assert exists(num_value_tokens), "you need to pass num_value_tokens to the model"
|
|
338
|
+
self.value_emb = nn.Embedding(num_value_tokens, dim)
|
|
339
|
+
torch.nn.init.xavier_normal_(self.value_emb.weight, std)
|
|
340
|
+
if not enc:
|
|
341
|
+
assert exists(num_value_tokens), "you need to pass num_value_tokens to the model"
|
|
342
|
+
self.to_out = nn.Linear(dim, num_value_tokens)
|
|
343
|
+
torch.nn.init.xavier_normal_(self.to_out.weight, std)
|
|
344
|
+
|
|
345
|
+
self.pos_emb = Always(0)
|
|
346
|
+
self.layer_pos_emb = Always(None)
|
|
347
|
+
# self.layer_pos_emb = Always(None)
|
|
348
|
+
|
|
349
|
+
self.dropout = nn.Dropout(emb_dropout)
|
|
350
|
+
|
|
351
|
+
self.block = TransformerBlock(dim, depth, heads, dim_head, causal = causal, ff_mult = ff_mult, ff_chunks=ff_chunks, use_scalenorm=use_scalenorm, use_rezero=use_rezero, ff_glu=ff_glu, ff_dropout=ff_dropout, attn_dropout=attn_dropout, cross_attend=cross_attend, qkv_bias=qkv_bias, attn_out_bias=attn_out_bias, shift_tokens=shift_tokens, only_cross_attn = only_cross_attn)
|
|
352
|
+
self.norm = nn.LayerNorm(dim)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def forward(self, x, value = None, **kwargs):
|
|
356
|
+
# input x shape: batch, n, c
|
|
357
|
+
# input value shape: batch, n
|
|
358
|
+
# token and positional embeddings
|
|
359
|
+
if self.use_iConv:
|
|
360
|
+
b, n, _ = x.shape
|
|
361
|
+
x = self.iConv_enc(x) # b, n, c, d/c
|
|
362
|
+
x = x.view(b, n, -1) # b, n, d
|
|
363
|
+
else:
|
|
364
|
+
b, n = x.shape
|
|
365
|
+
x = self.gene_emb(x) # b, n, d
|
|
366
|
+
if self.value_require:
|
|
367
|
+
x += self.value_emb(value)
|
|
368
|
+
x += self.pos_emb(x)
|
|
369
|
+
|
|
370
|
+
x = self.dropout(x)
|
|
371
|
+
layer_pos_emb = self.layer_pos_emb(x)
|
|
372
|
+
|
|
373
|
+
x = self.block(x, pos_emb = layer_pos_emb, **kwargs)
|
|
374
|
+
|
|
375
|
+
# norm and to logist
|
|
376
|
+
x = self.norm(x)
|
|
377
|
+
|
|
378
|
+
if not self.enc:
|
|
379
|
+
x = self.to_out(x)
|
|
380
|
+
|
|
381
|
+
return x
|
|
382
|
+
|
|
383
|
+
class AtacLM(nn.Module):
|
|
384
|
+
"""for ATAC decoding
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
nn (_type_): _description_
|
|
388
|
+
"""
|
|
389
|
+
def __init__(
|
|
390
|
+
self,
|
|
391
|
+
*,
|
|
392
|
+
dim,
|
|
393
|
+
depth,
|
|
394
|
+
heads,
|
|
395
|
+
enc = False,
|
|
396
|
+
value_require = False,
|
|
397
|
+
dim_head = 64,
|
|
398
|
+
causal = False,
|
|
399
|
+
ff_mult = 4,
|
|
400
|
+
ff_chunks = 1,
|
|
401
|
+
use_scalenorm = False,
|
|
402
|
+
use_rezero = False,
|
|
403
|
+
ff_glu = False,
|
|
404
|
+
emb_dropout = 0.,
|
|
405
|
+
ff_dropout = 0.,
|
|
406
|
+
attn_dropout = 0.,
|
|
407
|
+
cross_attend = False,
|
|
408
|
+
qkv_bias = True,
|
|
409
|
+
attn_out_bias = True,
|
|
410
|
+
shift_tokens = False,
|
|
411
|
+
only_cross_attn = False
|
|
412
|
+
):
|
|
413
|
+
super().__init__()
|
|
414
|
+
std = 0.1
|
|
415
|
+
# assert dim % 7 == 0, "dim must be a multiple of 7"
|
|
416
|
+
|
|
417
|
+
self.enc = enc
|
|
418
|
+
self.iConv_enc = nn.Embedding(10, dim//7)
|
|
419
|
+
self.value_require = value_require
|
|
420
|
+
torch.nn.init.xavier_normal_(self.iConv_enc.weight, std)
|
|
421
|
+
if not enc:
|
|
422
|
+
self.to_out = nn.Linear(dim, 1)
|
|
423
|
+
torch.nn.init.xavier_normal_(self.to_out.weight, std)
|
|
424
|
+
if value_require:
|
|
425
|
+
self.value_emb = nn.Embedding(2, dim)
|
|
426
|
+
torch.nn.init.xavier_normal_(self.value_emb.weight, std)
|
|
427
|
+
|
|
428
|
+
self.pos_emb = Always(0)
|
|
429
|
+
self.layer_pos_emb = Always(None)
|
|
430
|
+
# self.layer_pos_emb = Always(None)
|
|
431
|
+
|
|
432
|
+
self.dropout = nn.Dropout(emb_dropout)
|
|
433
|
+
self.block = TransformerBlock(dim, depth, heads, dim_head, causal = causal, ff_mult = ff_mult, ff_chunks=ff_chunks, use_scalenorm=use_scalenorm, use_rezero=use_rezero, ff_glu=ff_glu, ff_dropout=ff_dropout, attn_dropout=attn_dropout, cross_attend=cross_attend, qkv_bias=qkv_bias, attn_out_bias=attn_out_bias, shift_tokens=shift_tokens, only_cross_attn=only_cross_attn)
|
|
434
|
+
self.norm = nn.LayerNorm(dim)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def forward(self, x, value = None, **kwargs):
|
|
438
|
+
# token and positional embeddings
|
|
439
|
+
b, n, _ = x.shape
|
|
440
|
+
x = self.iConv_enc(x) # b, n, c, d/c
|
|
441
|
+
x = x.view(b, n, -1) # b, n, d
|
|
442
|
+
if self.value_require:
|
|
443
|
+
x += self.value_emb(value)
|
|
444
|
+
x += self.pos_emb(x)
|
|
445
|
+
|
|
446
|
+
x = self.dropout(x)
|
|
447
|
+
layer_pos_emb = self.layer_pos_emb(x)
|
|
448
|
+
|
|
449
|
+
x = self.block(x, pos_emb = layer_pos_emb, **kwargs)
|
|
450
|
+
# norm and to logist
|
|
451
|
+
x = self.norm(x)
|
|
452
|
+
|
|
453
|
+
if not self.enc:
|
|
454
|
+
x = self.to_out(x).squeeze()
|
|
455
|
+
|
|
456
|
+
return x
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
class M2M_rna2atac(nn.Module):
|
|
460
|
+
def __init__(
|
|
461
|
+
self,
|
|
462
|
+
dim,
|
|
463
|
+
**kwargs
|
|
464
|
+
):
|
|
465
|
+
super().__init__()
|
|
466
|
+
enc_kwargs, dec_kwargs, _ = extract_enc_dec_kwargs(kwargs)
|
|
467
|
+
|
|
468
|
+
assert 'dim' not in dec_kwargs and 'dim' not in enc_kwargs, 'you must set the same dim for both encoder and decoder by passing dim param'
|
|
469
|
+
|
|
470
|
+
enc_kwargs['dim'] = dec_kwargs['dim'] = dim
|
|
471
|
+
enc_kwargs['enc'] = True
|
|
472
|
+
enc_kwargs['value_require'] = True
|
|
473
|
+
dec_kwargs['cross_attend'] = True
|
|
474
|
+
dec_kwargs['only_cross_attn'] = True
|
|
475
|
+
|
|
476
|
+
self.enc = RnaLM(**enc_kwargs)
|
|
477
|
+
self.dec = AtacLM(**dec_kwargs)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def forward(self, seq_in, seq_out, value, enc_mask = None, dec_mask = None, **kwargs):
|
|
481
|
+
"""
|
|
482
|
+
注意参数
|
|
483
|
+
enc_mask
|
|
484
|
+
dec_mask
|
|
485
|
+
"""
|
|
486
|
+
|
|
487
|
+
enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
488
|
+
enc_kwargs["mask"] = enc_mask
|
|
489
|
+
dec_kwargs['mask'] = dec_mask
|
|
490
|
+
encodings = self.enc(seq_in, value = value, **enc_kwargs)# batch_size, enc_max_seq_len, dim
|
|
491
|
+
|
|
492
|
+
return self.dec(seq_out, context = encodings, **dec_kwargs)
|
|
493
|
+
|
|
494
|
+
def generate_attn_weight(self, seq_in, seq_out, value, which = "decoder", enc_mask = None, dec_mask = None, **kwargs):
|
|
495
|
+
"""This is used to generate self attention score matrix with the same xlabel and ylabel
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
seq_in (tensor): input sequence for encoder
|
|
499
|
+
seq_out (tensor): input sequence for decoder
|
|
500
|
+
value (tensor): input value for encoder
|
|
501
|
+
which (str, optional): Which Attention weight you want to generate: "encoder" or "decoder"
|
|
502
|
+
enc_mask (tensor, optional): bool dtype, True for seq_in to keep, False to drop.
|
|
503
|
+
dec_mask (tensor, optional): bool dtype, True for seq_out to keep, False to drop.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
list: attention weights for cells. Cross attention shape: (seq_out, seq_in)
|
|
507
|
+
"""
|
|
508
|
+
# if self.value_require:
|
|
509
|
+
# assert exists(value), "Expression value of rna should be pass as you have set value_require = True"
|
|
510
|
+
assert (which in ["encoder", "decoder"]), 'You can only choose "encoder" or "decoder" for parameter "which"'
|
|
511
|
+
with torch.no_grad():
|
|
512
|
+
enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
513
|
+
enc_kwargs["mask"] = enc_mask
|
|
514
|
+
dec_kwargs['mask'] = dec_mask
|
|
515
|
+
|
|
516
|
+
# enc
|
|
517
|
+
if self.enc.use_iConv:
|
|
518
|
+
b, n, _ = seq_in.shape
|
|
519
|
+
x = self.enc.iConv_enc(seq_in)
|
|
520
|
+
x = x.view(b, n, -1)
|
|
521
|
+
else:
|
|
522
|
+
b, n = seq_in.shape
|
|
523
|
+
x = self.enc.gene_emb(seq_in) # b, n, d
|
|
524
|
+
if self.enc.value_require:
|
|
525
|
+
x += self.enc.value_emb(value)
|
|
526
|
+
x += self.enc.pos_emb(x)
|
|
527
|
+
# x = self.enc.dropout(x)
|
|
528
|
+
enc_kwargs['pos_emb'] = self.enc.layer_pos_emb(x)
|
|
529
|
+
|
|
530
|
+
enc_args = route_args(self.enc.block.net.args_route, enc_kwargs, len(self.enc.block.net.layers), self.enc.block.net.cross_attend, self.enc.block.net.only_cross_attn)
|
|
531
|
+
enc_layers_and_args = list(zip(self.enc.block.net.layers, enc_args))
|
|
532
|
+
|
|
533
|
+
for i, ((f, g), (f_args, g_args)) in enumerate(enc_layers_and_args):
|
|
534
|
+
if i == len(enc_layers_and_args) - 1 and which == "encoder":
|
|
535
|
+
q = f.fn.to_q(x)
|
|
536
|
+
k = f.fn.to_k(x)
|
|
537
|
+
q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.enc.block.heads), (q, k))
|
|
538
|
+
enc_attn = whole_attn_score_matrix(q, k, enc_kwargs['mask'], enc_kwargs['mask'])
|
|
539
|
+
return enc_attn
|
|
540
|
+
x = x + f(x, **f_args)
|
|
541
|
+
x = x + g(x, **g_args)
|
|
542
|
+
|
|
543
|
+
encodings = self.enc.norm(x)
|
|
544
|
+
|
|
545
|
+
# dec
|
|
546
|
+
b, n, _ = seq_out.shape
|
|
547
|
+
x = self.dec.iConv_enc(seq_out)
|
|
548
|
+
x = x.view(b, n, -1)
|
|
549
|
+
x += self.dec.pos_emb(x)
|
|
550
|
+
# x = self.dec.dropout(x)
|
|
551
|
+
dec_kwargs['pos_emb'] = self.dec.layer_pos_emb(x)
|
|
552
|
+
dec_kwargs['context'] = encodings
|
|
553
|
+
|
|
554
|
+
dec_args = route_args(self.dec.block.net.args_route, dec_kwargs, len(self.dec.block.net.layers), self.dec.block.net.cross_attend, self.dec.block.net.only_cross_attn)
|
|
555
|
+
dec_layers_and_args = list(zip(self.dec.block.net.layers, dec_args))
|
|
556
|
+
|
|
557
|
+
for i, ((f, g), (f_args, g_args)) in enumerate(dec_layers_and_args):
|
|
558
|
+
if i == len(dec_layers_and_args) - 1 and which == "decoder":
|
|
559
|
+
q = f.fn.to_q(x)
|
|
560
|
+
k = f.fn.to_k(encodings)
|
|
561
|
+
q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
562
|
+
cross_attn = whole_attn_score_matrix(q, k, dec_kwargs['mask'], enc_kwargs['mask'])
|
|
563
|
+
# cross_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
564
|
+
return cross_attn
|
|
565
|
+
x = x + f(x, **f_args)
|
|
566
|
+
x = x + g(x, **g_args)
|
|
567
|
+
|
|
568
|
+
# def generate_self_attn_score_matrix(self, seq_in, seq_out, value, start=0, end=100, encoder = True, **kwargs):
|
|
569
|
+
# """This is used to generate self attention score matrix with the same xlabel and ylabel
|
|
570
|
+
|
|
571
|
+
# Args:
|
|
572
|
+
# seq_in (tensor): input sequence for encoder
|
|
573
|
+
# seq_out (tensor): input sequence for decoder
|
|
574
|
+
# value (tensor): expression value of RNA
|
|
575
|
+
# start (int, optional): Start index for attention matrix generation. Defaults to 0.
|
|
576
|
+
# end (int, optional): End index for attention matrix generation. Defaults to 100.
|
|
577
|
+
# encoder (bool, optional): Set True to generate self attention score for encoder else decoder. Defaults to True.
|
|
578
|
+
|
|
579
|
+
# You should also send enc_mask and dec_mask !
|
|
580
|
+
|
|
581
|
+
# Returns:
|
|
582
|
+
# self_attn (dict)
|
|
583
|
+
# """
|
|
584
|
+
# with torch.no_grad():
|
|
585
|
+
# enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
586
|
+
|
|
587
|
+
# # enc
|
|
588
|
+
# if self.enc.use_iConv:
|
|
589
|
+
# b, n, _ = seq_in.shape
|
|
590
|
+
# x = self.enc.iConv_enc(seq_in)
|
|
591
|
+
# x = x.view(b, n, -1)
|
|
592
|
+
# else:
|
|
593
|
+
# b, n = seq_in.shape
|
|
594
|
+
# x = self.enc.gene_emb(seq_in)
|
|
595
|
+
# x += self.enc.value_emb(value)
|
|
596
|
+
# x += self.enc.pos_emb(x)
|
|
597
|
+
# # x = self.enc.dropout(x)
|
|
598
|
+
# enc_kwargs['pos_emb'] = self.enc.layer_pos_emb(x)
|
|
599
|
+
|
|
600
|
+
# enc_args = route_args(self.enc.block.net.args_route, enc_kwargs, len(self.enc.block.net.layers), self.enc.block.net.cross_attend)
|
|
601
|
+
# enc_layers_and_args = list(zip(self.enc.block.net.layers, enc_args))
|
|
602
|
+
|
|
603
|
+
# for i, ((f, g), (f_args, g_args)) in enumerate(enc_layers_and_args):
|
|
604
|
+
# if i == len(enc_layers_and_args) - 1 and encoder:
|
|
605
|
+
# q = f.fn.to_q(x).float()
|
|
606
|
+
# k = f.fn.to_k(x).float()
|
|
607
|
+
# q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.enc.block.heads), (q, k))
|
|
608
|
+
# enc_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
609
|
+
# return enc_attn
|
|
610
|
+
# x = x + f(x, **f_args)
|
|
611
|
+
# x = x + g(x, **g_args)
|
|
612
|
+
|
|
613
|
+
# encodings = self.enc.norm(x)
|
|
614
|
+
|
|
615
|
+
# # dec
|
|
616
|
+
# b, n, _ = seq_out.shape
|
|
617
|
+
# x = self.dec.iConv_enc(seq_out) # b, n, c, d/c
|
|
618
|
+
# x = x.view(b, n, -1) # b, n, d
|
|
619
|
+
# x += self.dec.pos_emb(x)
|
|
620
|
+
# # x = self.dec.dropout(x)
|
|
621
|
+
# dec_kwargs['pos_emb'] = self.dec.layer_pos_emb(x)
|
|
622
|
+
# dec_kwargs['context'] = encodings
|
|
623
|
+
|
|
624
|
+
# dec_args = route_args(self.dec.block.net.args_route, dec_kwargs, len(self.dec.block.net.layers), self.dec.block.net.cross_attend)
|
|
625
|
+
# dec_layers_and_args = list(zip(self.dec.block.net.layers, dec_args))
|
|
626
|
+
|
|
627
|
+
# for i, ((f, g, h), (f_args, g_args, h_args)) in enumerate(dec_layers_and_args):
|
|
628
|
+
# if i == len(enc_layers_and_args) - 1:
|
|
629
|
+
# q = f.fn.to_q(x).float()
|
|
630
|
+
# k = f.fn.to_k(x).float()
|
|
631
|
+
# q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
632
|
+
# dec_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
633
|
+
# return dec_attn
|
|
634
|
+
# x = x + f(x, **f_args)
|
|
635
|
+
# x = x + g(x, **g_args)
|
|
636
|
+
# x = x + h(x, **h_args)
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
# def generate_cross_attn_score_matrix(self, seq_in, seq_out, value, start = 0, end = 100, related_num = 5, k_base = True, **kwargs):
|
|
640
|
+
# """This is used to generate cross attention matrix.
|
|
641
|
+
|
|
642
|
+
# Args:
|
|
643
|
+
# seq_in (tensor): _description_
|
|
644
|
+
# seq_out (tensor): _description_
|
|
645
|
+
# value (tensor): expression value of RNA
|
|
646
|
+
# topest_k (int, optional): How many elements in k should be kept. You can consider k is the sequence in encoder. Defaults to 20.
|
|
647
|
+
# related_num (int, optional): The number of elements in seq_out which are most related with element in k should be kept. Defaults to 5.
|
|
648
|
+
# k_base (bool, optional): Whether to exchange the meaning for q and k (seq_in and seq_out). Defaults to True.
|
|
649
|
+
# loop_size (int, optional): A parameter for faster compute bui will increase memory usage. Defaults to 100.
|
|
650
|
+
|
|
651
|
+
# You should also send enc_mask and dec_mask !
|
|
652
|
+
|
|
653
|
+
# Returns:
|
|
654
|
+
# cross_attn (dict):
|
|
655
|
+
# """
|
|
656
|
+
# with torch.no_grad():
|
|
657
|
+
# enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
658
|
+
|
|
659
|
+
# # enc
|
|
660
|
+
# if self.enc.use_iConv:
|
|
661
|
+
# b, n, _ = seq_in.shape
|
|
662
|
+
# x = self.enc.iConv_enc(seq_in)
|
|
663
|
+
# x = x.view(b, n, -1)
|
|
664
|
+
# else:
|
|
665
|
+
# b, n = seq_in.shape
|
|
666
|
+
# x = self.enc.gene_emb(seq_in)
|
|
667
|
+
# x += self.enc.value_emb(value)
|
|
668
|
+
# x += self.enc.pos_emb(x)
|
|
669
|
+
# # x = self.enc.dropout(x)
|
|
670
|
+
# enc_kwargs['pos_emb'] = self.enc.layer_pos_emb(x)
|
|
671
|
+
|
|
672
|
+
# enc_args = route_args(self.enc.block.net.args_route, enc_kwargs, len(self.enc.block.net.layers), self.enc.block.net.cross_attend)
|
|
673
|
+
# enc_layers_and_args = list(zip(self.enc.block.net.layers, enc_args))
|
|
674
|
+
|
|
675
|
+
# for i, ((f, g), (f_args, g_args)) in enumerate(enc_layers_and_args):
|
|
676
|
+
# x = x + f(x, **f_args)
|
|
677
|
+
# x = x + g(x, **g_args)
|
|
678
|
+
|
|
679
|
+
# encodings = self.enc.norm(x)
|
|
680
|
+
|
|
681
|
+
# # dec
|
|
682
|
+
# b, n, _ = seq_out.shape
|
|
683
|
+
# x = self.dec.iConv_enc(seq_out) # b, n, c, d/c
|
|
684
|
+
# x = x.view(b, n, -1) # b, n, d
|
|
685
|
+
# x += self.dec.pos_emb(x)
|
|
686
|
+
# # x = self.dec.dropout(x)
|
|
687
|
+
# dec_kwargs['pos_emb'] = self.dec.layer_pos_emb(x)
|
|
688
|
+
# dec_kwargs['context'] = encodings
|
|
689
|
+
|
|
690
|
+
# dec_args = route_args(self.dec.block.net.args_route, dec_kwargs, len(self.dec.block.net.layers), self.dec.block.net.cross_attend)
|
|
691
|
+
# dec_layers_and_args = list(zip(self.dec.block.net.layers, dec_args))
|
|
692
|
+
|
|
693
|
+
# for i, ((f, g, h), (f_args, g_args, h_args)) in enumerate(dec_layers_and_args):
|
|
694
|
+
# if i == len(enc_layers_and_args) - 1:
|
|
695
|
+
# q = g.fn.to_q(x).float()
|
|
696
|
+
# k = g.fn.to_k(encodings).float()
|
|
697
|
+
# q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
698
|
+
# cross_attn = attn_score_matrix(q, k, start = start, end = end, related_num = related_num, k_base = k_base)
|
|
699
|
+
# # cross_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
700
|
+
# return cross_attn
|
|
701
|
+
# x = x + f(x, **f_args)
|
|
702
|
+
# x = x + g(x, **g_args)
|
|
703
|
+
# x = x + h(x, **h_args)
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
class M2M_atac2rna(nn.Module):
|
|
708
|
+
"""_summary_
|
|
709
|
+
|
|
710
|
+
Model input: seq_in, seq_out, enc_mask
|
|
711
|
+
Attention: When you want to generate attention score matrix, you should also pass "enc_mask"
|
|
712
|
+
"""
|
|
713
|
+
def __init__(
|
|
714
|
+
self,
|
|
715
|
+
dim,
|
|
716
|
+
# value_require = False,
|
|
717
|
+
**kwargs
|
|
718
|
+
):
|
|
719
|
+
super().__init__()
|
|
720
|
+
# self.value_require = value_require
|
|
721
|
+
enc_kwargs, dec_kwargs, _ = extract_enc_dec_kwargs(kwargs)
|
|
722
|
+
|
|
723
|
+
assert 'dim' not in dec_kwargs and 'dim' not in enc_kwargs, 'you must set the same dim for both encoder and decoder by passing dim param'
|
|
724
|
+
|
|
725
|
+
enc_kwargs['dim'] = dec_kwargs['dim'] = dim
|
|
726
|
+
enc_kwargs['enc'] = True
|
|
727
|
+
dec_kwargs['cross_attend'] = True
|
|
728
|
+
|
|
729
|
+
self.enc = AtacLM(**enc_kwargs)
|
|
730
|
+
# self.dec = RnaLM(value_require = value_require, **dec_kwargs)
|
|
731
|
+
self.dec = RnaLM(**dec_kwargs)
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
# def forward(self, seq_in, seq_out, value = None, **kwargs): # should also send enc_mask
|
|
735
|
+
def forward(self, seq_in, seq_out, enc_mask = None, dec_mask = None, **kwargs): # should also send enc_mask
|
|
736
|
+
# if self.value_require:
|
|
737
|
+
# assert exists(value), "Expression value of RNA should be pass as you have set value_require = True"
|
|
738
|
+
enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
739
|
+
enc_kwargs["mask"] = enc_mask
|
|
740
|
+
dec_kwargs['mask'] = dec_mask
|
|
741
|
+
encodings = self.enc(seq_in, **enc_kwargs)# batch_size, enc_max_seq_len, dim
|
|
742
|
+
|
|
743
|
+
# return self.dec(seq_out, value = value, context = encodings, **dec_kwargs)
|
|
744
|
+
output = self.dec(seq_out, context = encodings, **dec_kwargs)
|
|
745
|
+
# output[:,:,0] += 10
|
|
746
|
+
return output
|
|
747
|
+
# return encodings
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
# def generate_self_attn_score_matrix(self, seq_in, seq_out, value=None, start=0, end=100, encoder = True, **kwargs):
|
|
751
|
+
def generate_attn_weight(self, seq_in, seq_out, which = "encoder", enc_mask = None, dec_mask = None, **kwargs):
|
|
752
|
+
"""This is used to generate self attention score matrix with the same xlabel and ylabel
|
|
753
|
+
|
|
754
|
+
Args:
|
|
755
|
+
seq_in (tensor): input sequence for encoder
|
|
756
|
+
seq_out (tensor): input sequence for decoder
|
|
757
|
+
which (str, optional): Which Attention weight you want to generate: "encoder", "decoder" or "cross"
|
|
758
|
+
enc_mask (tensor, optional): bool dtype, True for seq_in to keep, False to drop.
|
|
759
|
+
dec_mask (tensor, optional): bool dtype, True for seq_out to keep, False to drop.
|
|
760
|
+
|
|
761
|
+
Returns:
|
|
762
|
+
list: attention weights for cells. Cross attention shape: (seq_out, seq_in)
|
|
763
|
+
"""
|
|
764
|
+
# if self.value_require:
|
|
765
|
+
# assert exists(value), "Expression value of rna should be pass as you have set value_require = True"
|
|
766
|
+
assert (which in ["encoder", "decoder", "cross"]), 'You can only choose "encoder", "decoder" or "cross" for parameter which'
|
|
767
|
+
with torch.no_grad():
|
|
768
|
+
enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
769
|
+
enc_kwargs["mask"] = enc_mask
|
|
770
|
+
dec_kwargs['mask'] = dec_mask
|
|
771
|
+
|
|
772
|
+
# enc
|
|
773
|
+
b, n, _ = seq_in.shape
|
|
774
|
+
x = self.enc.iConv_enc(seq_in)
|
|
775
|
+
x = x.view(b, n, -1)
|
|
776
|
+
x += self.enc.pos_emb(x)
|
|
777
|
+
# x = self.enc.dropout(x)
|
|
778
|
+
enc_kwargs['pos_emb'] = self.enc.layer_pos_emb(x)
|
|
779
|
+
|
|
780
|
+
enc_args = route_args(self.enc.block.net.args_route, enc_kwargs, len(self.enc.block.net.layers), self.enc.block.net.cross_attend, self.enc.block.net.only_cross_attn)
|
|
781
|
+
enc_layers_and_args = list(zip(self.enc.block.net.layers, enc_args))
|
|
782
|
+
|
|
783
|
+
for i, ((f, g), (f_args, g_args)) in enumerate(enc_layers_and_args):
|
|
784
|
+
if i == len(enc_layers_and_args) - 1 and which == "encoder":
|
|
785
|
+
q = f.fn.to_q(x)
|
|
786
|
+
k = f.fn.to_k(x)
|
|
787
|
+
# print(q)
|
|
788
|
+
# print(k)
|
|
789
|
+
q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.enc.block.heads), (q, k))
|
|
790
|
+
enc_attn = whole_attn_score_matrix(q, k, enc_kwargs['mask'], enc_kwargs['mask'])
|
|
791
|
+
return enc_attn
|
|
792
|
+
x = x + f(x, **f_args)
|
|
793
|
+
x = x + g(x, **g_args)
|
|
794
|
+
|
|
795
|
+
encodings = self.enc.norm(x)
|
|
796
|
+
|
|
797
|
+
# dec
|
|
798
|
+
if self.dec.use_iConv:
|
|
799
|
+
b, n, _ = seq_out.shape
|
|
800
|
+
x = self.dec.iConv_enc(seq_out) # b, n, c, d/c
|
|
801
|
+
x = x.view(b, n, -1) # b, n, d
|
|
802
|
+
else:
|
|
803
|
+
b, n = seq_out.shape
|
|
804
|
+
x = self.dec.gene_emb(seq_out) # b, n, d
|
|
805
|
+
# if self.value_require:
|
|
806
|
+
# x += self.dec.value_emb(value)
|
|
807
|
+
x += self.dec.pos_emb(x)
|
|
808
|
+
# x = self.dec.dropout(x)
|
|
809
|
+
dec_kwargs['pos_emb'] = self.dec.layer_pos_emb(x)
|
|
810
|
+
dec_kwargs['context'] = encodings
|
|
811
|
+
|
|
812
|
+
dec_args = route_args(self.dec.block.net.args_route, dec_kwargs, len(self.dec.block.net.layers), self.dec.block.net.cross_attend, self.enc.block.net.only_cross_attn)
|
|
813
|
+
dec_layers_and_args = list(zip(self.dec.block.net.layers, dec_args))
|
|
814
|
+
|
|
815
|
+
for i, ((f, g, h), (f_args, g_args, h_args)) in enumerate(dec_layers_and_args):
|
|
816
|
+
if i == len(dec_layers_and_args) - 1 and which == "decoder":
|
|
817
|
+
q = f.fn.to_q(x)
|
|
818
|
+
k = f.fn.to_k(x)
|
|
819
|
+
q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
820
|
+
# dec_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
821
|
+
dec_attn = whole_attn_score_matrix(q, k, dec_kwargs['mask'], dec_kwargs['mask'])
|
|
822
|
+
return dec_attn
|
|
823
|
+
if i == len(dec_layers_and_args) - 1 and which == "cross":
|
|
824
|
+
q = g.fn.to_q(x)
|
|
825
|
+
k = g.fn.to_k(encodings)
|
|
826
|
+
q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
827
|
+
cross_attn = whole_attn_score_matrix(q, k, dec_kwargs['mask'], enc_kwargs['mask'])
|
|
828
|
+
# cross_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
829
|
+
return cross_attn
|
|
830
|
+
x = x + f(x, **f_args)
|
|
831
|
+
x = x + g(x, **g_args)
|
|
832
|
+
x = x + h(x, **h_args)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
# # def generate_cross_attn_score_matrix(self, seq_in, seq_out, value = None, start = 0, end = 100, related_num = 5, k_base = True, **kwargs):
|
|
836
|
+
# def generate_cross_attn_score_matrix(self, seq_in, seq_out, **kwargs):
|
|
837
|
+
# """This is used to generate cross attention matrix.
|
|
838
|
+
|
|
839
|
+
# Args:
|
|
840
|
+
# seq_in (tensor): _description_
|
|
841
|
+
# seq_out (tensor): _description_
|
|
842
|
+
# value (tensor): expression value of RNA
|
|
843
|
+
# topest_k (int, optional): How many elements in k should be kept. You can consider k is the sequence in encoder. Defaults to 20.
|
|
844
|
+
# related_num (int, optional): The number of elements in seq_out which are most related with element in k should be kept. Defaults to 5.
|
|
845
|
+
# k_base (bool, optional): Whether to exchange the meaning for q and k (seq_in and seq_out). Defaults to True.
|
|
846
|
+
# loop_size (int, optional): A parameter for faster compute bui will increase memory usage. Defaults to 100.
|
|
847
|
+
|
|
848
|
+
# You should also send enc_mask and dec_mask !
|
|
849
|
+
|
|
850
|
+
# Returns:
|
|
851
|
+
# list: Attention weights for cells. Shape (len(seq_in), len(seq_out))
|
|
852
|
+
# """
|
|
853
|
+
# # if self.value_require:
|
|
854
|
+
# # assert exists(value), "Expression value of rna should be pass as you have set value_require = True"
|
|
855
|
+
# with torch.no_grad():
|
|
856
|
+
# enc_kwargs, dec_kwargs, kwargs = extract_and_set_enc_dec_kwargs(kwargs)
|
|
857
|
+
|
|
858
|
+
# # enc
|
|
859
|
+
# b, n, _ = seq_in.shape
|
|
860
|
+
# x = self.enc.iConv_enc(seq_in)
|
|
861
|
+
# x = x.view(b, n, -1)
|
|
862
|
+
# x += self.enc.pos_emb(x)
|
|
863
|
+
# # x = self.enc.dropout(x)
|
|
864
|
+
# enc_kwargs['pos_emb'] = self.enc.layer_pos_emb(x)
|
|
865
|
+
|
|
866
|
+
# enc_args = route_args(self.enc.block.net.args_route, enc_kwargs, len(self.enc.block.net.layers), self.enc.block.net.cross_attend)
|
|
867
|
+
# enc_layers_and_args = list(zip(self.enc.block.net.layers, enc_args))
|
|
868
|
+
|
|
869
|
+
# for i, ((f, g), (f_args, g_args)) in enumerate(enc_layers_and_args):
|
|
870
|
+
# x = x + f(x, **f_args)
|
|
871
|
+
# x = x + g(x, **g_args)
|
|
872
|
+
|
|
873
|
+
# encodings = self.enc.norm(x)
|
|
874
|
+
|
|
875
|
+
# # dec
|
|
876
|
+
# if self.dec.use_iConv:
|
|
877
|
+
# b, n, _ = seq_out.shape
|
|
878
|
+
# x = self.dec.iConv_enc(seq_out) # b, n, c, d/c
|
|
879
|
+
# x = x.view(b, n, -1) # b, n, d
|
|
880
|
+
# else:
|
|
881
|
+
# b, n = seq_out.shape
|
|
882
|
+
# x = self.dec.gene_emb(x) # b, n, d
|
|
883
|
+
# # if self.value_require:
|
|
884
|
+
# # x += self.dec.value_emb(value)
|
|
885
|
+
# x += self.dec.pos_emb(x)
|
|
886
|
+
# # x = self.dec.dropout(x)
|
|
887
|
+
# dec_kwargs['pos_emb'] = self.dec.layer_pos_emb(x)
|
|
888
|
+
# dec_kwargs['context'] = encodings
|
|
889
|
+
|
|
890
|
+
# dec_args = route_args(self.dec.block.net.args_route, dec_kwargs, len(self.dec.block.net.layers), self.dec.block.net.cross_attend)
|
|
891
|
+
# dec_layers_and_args = list(zip(self.dec.block.net.layers, dec_args))
|
|
892
|
+
|
|
893
|
+
# for i, ((f, g, h), (f_args, g_args, h_args)) in enumerate(dec_layers_and_args):
|
|
894
|
+
# if i == len(enc_layers_and_args) - 1:
|
|
895
|
+
# q = g.fn.to_q(x)
|
|
896
|
+
# k = g.fn.to_k(encodings)
|
|
897
|
+
# q, k = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.dec.block.heads), (q, k))
|
|
898
|
+
# cross_attn = attn_score_matrix(q, k, start = start, end = end, related_num = related_num, k_base = k_base)
|
|
899
|
+
# # cross_attn = neighbour_attn_score_matrix(q, k, start, end)
|
|
900
|
+
# return cross_attn
|
|
901
|
+
# x = x + f(x, **f_args)
|
|
902
|
+
# x = x + g(x, **g_args)
|
|
903
|
+
# x = x + h(x, **h_args)
|