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.
@@ -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)