densecall 0.0.1__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.
- densecall/__init__.py +37 -0
- densecall/__main__.py +2 -0
- densecall/aligner.py +83 -0
- densecall/classes.py +482 -0
- densecall/cli/__init__.py +3 -0
- densecall/cli/accuracy.py +263 -0
- densecall/cli/basecaller.py +245 -0
- densecall/cli/download.py +164 -0
- densecall/cli/train.py +208 -0
- densecall/conformer/__init__.py +3 -0
- densecall/conformer/basecall.py +88 -0
- densecall/conformer/cgmlp.py +223 -0
- densecall/conformer/conv.py +126 -0
- densecall/conformer/criterion.py +394 -0
- densecall/conformer/flash.py +104 -0
- densecall/conformer/linformer.py +170 -0
- densecall/conformer/modcall.py +159 -0
- densecall/conformer/model copy.py +245 -0
- densecall/conformer/model.py +376 -0
- densecall/conformer/modules.py +600 -0
- densecall/conformer/nn.py +411 -0
- densecall/conformer/optimize.py +293 -0
- densecall/conformer/util.py +62 -0
- densecall/conformer/wav2vec2.py +431 -0
- densecall/data.py +173 -0
- densecall/fast5.py +240 -0
- densecall/io.py +851 -0
- densecall/mod_util.py +182 -0
- densecall/models/configs/conformer.toml +54 -0
- densecall/models/configs/conformer_fast.toml +49 -0
- densecall/multiprocessing.py +266 -0
- densecall/pod5.py +143 -0
- densecall/read.py +260 -0
- densecall/reader.py +222 -0
- densecall/schedule.py +143 -0
- densecall/training.py +804 -0
- densecall/util.py +573 -0
- densecall-0.0.1.dist-info/LICENCE.txt +0 -0
- densecall-0.0.1.dist-info/METADATA +229 -0
- densecall-0.0.1.dist-info/RECORD +43 -0
- densecall-0.0.1.dist-info/WHEEL +5 -0
- densecall-0.0.1.dist-info/entry_points.txt +2 -0
- densecall-0.0.1.dist-info/top_level.txt +1 -0
densecall/__init__.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
|
|
2
|
+
from densecall.cli import train, basecaller, accuracy
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
modules = [
|
|
6
|
+
'accuracy', 'train','basecaller'
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
__version__ = '0.0.1'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main():
|
|
15
|
+
parser = ArgumentParser(
|
|
16
|
+
'densecall',
|
|
17
|
+
formatter_class=ArgumentDefaultsHelpFormatter
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
'-v', '--version', action='version',
|
|
22
|
+
version='%(prog)s {}'.format(__version__)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
subparsers = parser.add_subparsers(
|
|
26
|
+
title='subcommands', description='valid commands',
|
|
27
|
+
help='additional help', dest='command'
|
|
28
|
+
)
|
|
29
|
+
subparsers.required = True
|
|
30
|
+
|
|
31
|
+
for module in modules:
|
|
32
|
+
mod = globals()[module]
|
|
33
|
+
p = subparsers.add_parser(module, parents=[mod.argparser()])
|
|
34
|
+
p.set_defaults(func=mod.main)
|
|
35
|
+
|
|
36
|
+
args = parser.parse_args()
|
|
37
|
+
args.func(args)
|
densecall/__main__.py
ADDED
densecall/aligner.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
modified based on Bonito Aligner
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from threading import Thread
|
|
6
|
+
from functools import partial
|
|
7
|
+
import mappy
|
|
8
|
+
import numpy as np
|
|
9
|
+
from mappy import Aligner, ThreadBuffer
|
|
10
|
+
import sys
|
|
11
|
+
from densecall.multiprocessing import ThreadMap
|
|
12
|
+
from densecall.mod_util import call_mods, load_mods_model
|
|
13
|
+
|
|
14
|
+
def align_map(aligner, sequences, n_thread=4, mod_model=None, use_reference_anchored=False):
|
|
15
|
+
"""
|
|
16
|
+
Align `sequences` with minimap using `n_thread` threads.
|
|
17
|
+
"""
|
|
18
|
+
return ThreadMap(partial(MappyWorker, aligner, mod_model, use_reference_anchored), sequences, n_thread)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ManagedThreadBuffer:
|
|
22
|
+
"""
|
|
23
|
+
Minimap2 ThreadBuffer that is periodically reallocated.
|
|
24
|
+
"""
|
|
25
|
+
def __init__(self, max_uses=20):
|
|
26
|
+
self.max_uses = max_uses
|
|
27
|
+
self.uses = 0
|
|
28
|
+
self._b = ThreadBuffer()
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def buffer(self):
|
|
32
|
+
if self.uses > self.max_uses:
|
|
33
|
+
self._b = ThreadBuffer()
|
|
34
|
+
self.uses = 0
|
|
35
|
+
self.uses += 1
|
|
36
|
+
return self._b
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MappyWorker(Thread):
|
|
40
|
+
"""
|
|
41
|
+
Process that reads items from an input_queue, applies a func to them and puts them on an output_queue
|
|
42
|
+
"""
|
|
43
|
+
def __init__(self, aligner, mod_model, use_reference_anchored, input_queue=None, output_queue=None):
|
|
44
|
+
super().__init__()
|
|
45
|
+
self.aligner = aligner
|
|
46
|
+
self.input_queue = input_queue
|
|
47
|
+
self.output_queue = output_queue
|
|
48
|
+
self.mod_model = mod_model
|
|
49
|
+
self.use_reference_anchored = use_reference_anchored
|
|
50
|
+
|
|
51
|
+
def run(self):
|
|
52
|
+
thrbuf = ManagedThreadBuffer()
|
|
53
|
+
while True:
|
|
54
|
+
item = self.input_queue.get()
|
|
55
|
+
if item is StopIteration:
|
|
56
|
+
self.output_queue.put(item)
|
|
57
|
+
break
|
|
58
|
+
k, v = item
|
|
59
|
+
|
|
60
|
+
mapping = next(self.aligner.map(v['sequence'], buf=thrbuf.buffer, MD=True), None)
|
|
61
|
+
|
|
62
|
+
if self.mod_model and mapping:
|
|
63
|
+
|
|
64
|
+
refseq = self.aligner.seq(mapping.ctg, mapping.r_st, mapping.r_en)
|
|
65
|
+
cigar = np.array(mapping.cigar)
|
|
66
|
+
cigar = cigar[:, [1, 0]].tolist()
|
|
67
|
+
if mapping.strand == -1:
|
|
68
|
+
refseq = mappy.revcomp(refseq)
|
|
69
|
+
cigar = cigar[::-1]
|
|
70
|
+
|
|
71
|
+
v['refseq'] = refseq
|
|
72
|
+
v['cigar'] = cigar
|
|
73
|
+
v['modified_results'] = []
|
|
74
|
+
for mod_model, code in self.mod_model:
|
|
75
|
+
remora_model, remora_metadata = mod_model
|
|
76
|
+
can_base = remora_metadata['can_base']
|
|
77
|
+
v = call_mods(mod_model, k, v, use_reference_anchored=self.use_reference_anchored)
|
|
78
|
+
v['modified_results'].append((can_base, code, v['modified_result']))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
self.output_queue.put((k, {**v, 'mapping': mapping}))
|
|
82
|
+
|
|
83
|
+
|
densecall/classes.py
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torch.nn as nn
|
|
3
|
+
import torch.nn.functional as F
|
|
4
|
+
import numpy as np
|
|
5
|
+
from fast_ctc_decode import beam_search, viterbi_search, crf_greedy_search, crf_beam_search
|
|
6
|
+
from abc import abstractmethod
|
|
7
|
+
from torch.nn.functional import log_softmax, ctc_loss
|
|
8
|
+
from torch.autograd import Variable
|
|
9
|
+
from transformers.models.wav2vec2.modeling_wav2vec2 import _compute_mask_indices, _sample_negative_indices, Wav2Vec2GumbelVectorQuantizer
|
|
10
|
+
from functools import partial
|
|
11
|
+
from typing import Optional, Tuple, Union
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FeatureProjection(nn.Module):
|
|
17
|
+
def __init__(self, fin, fout):
|
|
18
|
+
super().__init__()
|
|
19
|
+
self.layer_norm = nn.LayerNorm(fin, eps=1e-5)
|
|
20
|
+
self.projection = nn.Linear(fin, fout)
|
|
21
|
+
self.dropout = nn.Dropout(0.1)
|
|
22
|
+
|
|
23
|
+
def forward(self, hidden_states):
|
|
24
|
+
# non-projected hidden states are needed for quantization
|
|
25
|
+
norm_hidden_states = self.layer_norm(hidden_states)
|
|
26
|
+
hidden_states = self.projection(norm_hidden_states)
|
|
27
|
+
hidden_states = self.dropout(hidden_states)
|
|
28
|
+
return hidden_states, norm_hidden_states
|
|
29
|
+
|
|
30
|
+
class Wav2Vec2GumbelVectorQuantizer(nn.Module):
|
|
31
|
+
"""
|
|
32
|
+
Vector quantization using gumbel softmax. See `[CATEGORICAL REPARAMETERIZATION WITH
|
|
33
|
+
GUMBEL-SOFTMAX](https://arxiv.org/pdf/1611.01144.pdf) for more information.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, config):
|
|
37
|
+
super().__init__()
|
|
38
|
+
self.num_groups = config.num_codevector_groups
|
|
39
|
+
self.num_vars = config.num_codevectors_per_group
|
|
40
|
+
|
|
41
|
+
if config.codevector_dim % self.num_groups != 0:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
f"`config.codevector_dim {config.codevector_dim} must be divisible "
|
|
44
|
+
f"by `config.num_codevector_groups` {self.num_groups} for concatenation"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# storage for codebook variables (codewords)
|
|
48
|
+
self.codevectors = nn.Parameter(
|
|
49
|
+
torch.FloatTensor(1, self.num_groups * self.num_vars, config.codevector_dim // self.num_groups)
|
|
50
|
+
)
|
|
51
|
+
self.weight_proj = nn.Linear(config.conv_dim[-1], self.num_groups * self.num_vars)
|
|
52
|
+
|
|
53
|
+
# can be decayed for training
|
|
54
|
+
self.temperature = 2
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def _compute_perplexity(probs, mask=None):
|
|
58
|
+
if mask is not None:
|
|
59
|
+
mask_extended = mask.flatten()[:, None, None].expand(probs.shape)
|
|
60
|
+
print(333)
|
|
61
|
+
probs = torch.where(mask_extended, probs, torch.zeros_like(probs))
|
|
62
|
+
marginal_probs = probs.sum(dim=0) / mask.sum()
|
|
63
|
+
else:
|
|
64
|
+
marginal_probs = probs.mean(dim=0)
|
|
65
|
+
|
|
66
|
+
perplexity = torch.exp(-torch.sum(marginal_probs * torch.log(marginal_probs + 1e-7), dim=-1)).sum()
|
|
67
|
+
return perplexity
|
|
68
|
+
|
|
69
|
+
def forward(self, hidden_states, mask_time_indices=None):
|
|
70
|
+
batch_size, sequence_length, hidden_size = hidden_states.shape
|
|
71
|
+
|
|
72
|
+
# project to codevector dim
|
|
73
|
+
hidden_states = self.weight_proj(hidden_states)
|
|
74
|
+
hidden_states = hidden_states.view(batch_size * sequence_length * self.num_groups, -1)
|
|
75
|
+
|
|
76
|
+
if self.training:
|
|
77
|
+
# sample code vector probs via gumbel in differentiateable way
|
|
78
|
+
codevector_probs = nn.functional.gumbel_softmax(
|
|
79
|
+
hidden_states.float(), tau=self.temperature, hard=True
|
|
80
|
+
).type_as(hidden_states)
|
|
81
|
+
|
|
82
|
+
# compute perplexity
|
|
83
|
+
codevector_soft_dist = torch.softmax(
|
|
84
|
+
hidden_states.view(batch_size * sequence_length, self.num_groups, -1).float(), dim=-1
|
|
85
|
+
)
|
|
86
|
+
perplexity = self._compute_perplexity(codevector_soft_dist, mask_time_indices)
|
|
87
|
+
else:
|
|
88
|
+
# take argmax in non-differentiable way
|
|
89
|
+
# comptute hard codevector distribution (one hot)
|
|
90
|
+
codevector_idx = hidden_states.argmax(dim=-1)
|
|
91
|
+
codevector_probs = hidden_states.new_zeros(hidden_states.shape).scatter_(
|
|
92
|
+
-1, codevector_idx.view(-1, 1), 1.0
|
|
93
|
+
)
|
|
94
|
+
codevector_probs = codevector_probs.view(batch_size * sequence_length, self.num_groups, -1)
|
|
95
|
+
|
|
96
|
+
perplexity = self._compute_perplexity(codevector_probs, mask_time_indices)
|
|
97
|
+
|
|
98
|
+
codevector_probs = codevector_probs.view(batch_size * sequence_length, -1)
|
|
99
|
+
# use probs to retrieve codevectors
|
|
100
|
+
codevectors_per_group = codevector_probs.unsqueeze(-1) * self.codevectors
|
|
101
|
+
codevectors = codevectors_per_group.view(batch_size * sequence_length, self.num_groups, self.num_vars, -1)
|
|
102
|
+
codevectors = codevectors.sum(-2).view(batch_size, sequence_length, -1)
|
|
103
|
+
|
|
104
|
+
return codevectors, perplexity
|
|
105
|
+
|
|
106
|
+
def compute_contrastive_logits(
|
|
107
|
+
target_features: torch.FloatTensor,
|
|
108
|
+
negative_features: torch.FloatTensor,
|
|
109
|
+
predicted_features: torch.FloatTensor,
|
|
110
|
+
temperature: int = 0.1,
|
|
111
|
+
):
|
|
112
|
+
"""
|
|
113
|
+
Compute logits for contrastive loss based using cosine similarity as the distance measure between
|
|
114
|
+
`[positive_feature, negative_features]` and `[predicted_features]`. Additionally, temperature can be applied.
|
|
115
|
+
"""
|
|
116
|
+
target_features = torch.cat([target_features, negative_features], dim=0)
|
|
117
|
+
|
|
118
|
+
logits = torch.cosine_similarity(predicted_features.float(), target_features.float(), dim=-1).type_as(
|
|
119
|
+
target_features
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# apply temperature
|
|
123
|
+
logits = logits / temperature
|
|
124
|
+
return logits
|
|
125
|
+
|
|
126
|
+
def pad_list(xs, pad_value):
|
|
127
|
+
n_batch = len(xs)
|
|
128
|
+
max_len = max(x.size(0) for x in xs)
|
|
129
|
+
pad = xs[0].new(n_batch, max_len, *xs[0].size()[1:]).fill_(pad_value)
|
|
130
|
+
|
|
131
|
+
for i in range(n_batch):
|
|
132
|
+
pad[i, : xs[i].size(0)] = xs[i]
|
|
133
|
+
|
|
134
|
+
return pad
|
|
135
|
+
|
|
136
|
+
def add_sos_eos(ys_pad, sos, eos, ignore_id):
|
|
137
|
+
|
|
138
|
+
_sos = ys_pad.new([sos])
|
|
139
|
+
_eos = ys_pad.new([eos])
|
|
140
|
+
ys = [y[y != ignore_id] for y in ys_pad]
|
|
141
|
+
ys_in = [torch.cat([_sos, y], dim=0) for y in ys]
|
|
142
|
+
ys_out = [torch.cat([y, _eos], dim=0) for y in ys]
|
|
143
|
+
return pad_list(ys_in, eos), pad_list(ys_out, ignore_id)
|
|
144
|
+
|
|
145
|
+
class Permute(nn.Module):
|
|
146
|
+
|
|
147
|
+
def __init__(self, dims):
|
|
148
|
+
super().__init__()
|
|
149
|
+
self.dims = dims
|
|
150
|
+
|
|
151
|
+
def forward(self, x):
|
|
152
|
+
return x.permute(*self.dims)
|
|
153
|
+
|
|
154
|
+
def to_dict(self, include_weights=False):
|
|
155
|
+
return {'dims': self.dims}
|
|
156
|
+
|
|
157
|
+
def extra_repr(self):
|
|
158
|
+
return 'dims={}'.format(self.dims)
|
|
159
|
+
|
|
160
|
+
class BaseModel(nn.Module):
|
|
161
|
+
|
|
162
|
+
def __init__(self, config, *args, **kwargs):
|
|
163
|
+
|
|
164
|
+
super(BaseModel, self).__init__()
|
|
165
|
+
self.config = config
|
|
166
|
+
|
|
167
|
+
@abstractmethod
|
|
168
|
+
def forward(self, batch):
|
|
169
|
+
"""Forward through the network
|
|
170
|
+
"""
|
|
171
|
+
raise NotImplementedError()
|
|
172
|
+
|
|
173
|
+
def ctc_label_smoothing_loss(self, log_probs, targets, lengths, weights=None):
|
|
174
|
+
T, N, C = log_probs.shape
|
|
175
|
+
weights = weights or torch.cat([torch.tensor([0.4]), (0.1 / (C - 1)) * torch.ones(C - 1)])
|
|
176
|
+
log_probs_lengths = torch.full(size=(N, ), fill_value=T, dtype=torch.int64)
|
|
177
|
+
loss = ctc_loss(log_probs.to(torch.float32), targets, log_probs_lengths, lengths, reduction='mean')
|
|
178
|
+
label_smoothing_loss = -((log_probs * weights.to(log_probs.device)).mean())
|
|
179
|
+
return {'total_loss': loss + label_smoothing_loss, 'loss': loss, 'label_smooth_loss': label_smoothing_loss}
|
|
180
|
+
|
|
181
|
+
def loss(self, log_probs, targets, lengths):
|
|
182
|
+
return self.ctc_label_smoothing_loss(log_probs, targets, lengths)
|
|
183
|
+
|
|
184
|
+
def use_koi(self, **kwargs):
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def decode(self, x, beamsize=5, threshold=1e-3, qscores=False, return_path=False):
|
|
189
|
+
#print(x)
|
|
190
|
+
x = x.exp().cpu().numpy().astype(np.float32)
|
|
191
|
+
#print(x)
|
|
192
|
+
if beamsize == 1 or qscores:
|
|
193
|
+
seq, path = viterbi_search(x, self.alphabet, qscores, self.qscale, self.qbias)
|
|
194
|
+
else:
|
|
195
|
+
|
|
196
|
+
seq, path = beam_search(x, self.alphabet, beamsize, threshold)
|
|
197
|
+
qstring = ''.join(phred(np.max(x[path], 1), self.qscale, self.qbias).astype(str))
|
|
198
|
+
seq += qstring
|
|
199
|
+
if return_path: return seq, path
|
|
200
|
+
return seq
|
|
201
|
+
|
|
202
|
+
# @torch.no_grad()
|
|
203
|
+
# def decode_batch(self, encoder_outputs: Tensor) -> Tensor:
|
|
204
|
+
# logits = list()
|
|
205
|
+
# batch_size = encoder_outputs.size(0)
|
|
206
|
+
# T = encoder_outputs.size(1)
|
|
207
|
+
# self.max_length = 361
|
|
208
|
+
|
|
209
|
+
# input_var = torch.full((batch_size, 1), 0, dtype=torch.long, device=encoder_outputs.device)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# for di in range(1, self.max_length):
|
|
213
|
+
# input_lengths = torch.tensor([di] * batch_size, dtype=torch.int64, device=encoder_outputs.device)
|
|
214
|
+
# outputs = self.forward_step(
|
|
215
|
+
# decoder_inputs=input_var,
|
|
216
|
+
# decoder_input_lengths=input_lengths,
|
|
217
|
+
# encoder_outputs=encoder_outputs,
|
|
218
|
+
# positional_encoding_length=di,
|
|
219
|
+
# flag=False
|
|
220
|
+
# )
|
|
221
|
+
|
|
222
|
+
# step_output = self.fc(outputs).log_softmax(dim=-1)
|
|
223
|
+
# logits.append(step_output[:, -1, :])
|
|
224
|
+
# next_token = logits[-1].topk(1)[1]
|
|
225
|
+
# input_var = torch.cat([input_var, next_token], dim=1)
|
|
226
|
+
# if all((input_var == 0).any(dim=1)):
|
|
227
|
+
# break
|
|
228
|
+
|
|
229
|
+
# logits = torch.stack(logits, dim=1)
|
|
230
|
+
# logits = torch.argmax(logits, dim=-1)
|
|
231
|
+
# seqs = []
|
|
232
|
+
# for x in logits:
|
|
233
|
+
# seq = []
|
|
234
|
+
# for i in x:
|
|
235
|
+
# seq.append(self.alphabet[i])
|
|
236
|
+
# seqs.append(''.join(seq))
|
|
237
|
+
# print(len(seq), seq[:30])
|
|
238
|
+
# return seqs
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def phred(prob: np.ndarray, qscale: float = 1, qbias: float = 0) -> np.ndarray:
|
|
243
|
+
max_value = 1e-4
|
|
244
|
+
# 使用np.maximum确保p至少为max_value
|
|
245
|
+
p = np.maximum(max_value, 1.0 - prob)
|
|
246
|
+
# 计算Q值
|
|
247
|
+
q = -10.0 * np.log10(p) * qscale + qbias
|
|
248
|
+
# 将q值四舍五入并且转换为整数
|
|
249
|
+
q_rounded = np.round(q).astype(int)
|
|
250
|
+
# 转换为字符
|
|
251
|
+
result = (q_rounded + 33).astype(np.uint8).view('S1')
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
class PositionalEncoding(nn.Module):
|
|
255
|
+
def __init__(self, d_model, max_len=5000):
|
|
256
|
+
super(PositionalEncoding, self).__init__()
|
|
257
|
+
position = torch.arange(0, max_len).unsqueeze(1)
|
|
258
|
+
div_term = torch.exp(torch.arange(0, d_model, 2) * -(torch.log(torch.tensor(10000.0)) / d_model))
|
|
259
|
+
pe = torch.zeros(max_len, d_model)
|
|
260
|
+
pe[:, 0::2] = torch.sin(position.float() * div_term)
|
|
261
|
+
pe[:, 1::2] = torch.cos(position.float() * div_term)
|
|
262
|
+
pe = pe.unsqueeze(0).transpose(0, 1)
|
|
263
|
+
self.register_buffer('pe', pe)
|
|
264
|
+
|
|
265
|
+
def forward(self, x):
|
|
266
|
+
return x + self.pe[:x.size(0), :]
|
|
267
|
+
|
|
268
|
+
class TransformerWithConvInput(nn.Module):
|
|
269
|
+
def __init__(self, n_channels, d_model, nhead, dim_feedforward, num_layers, max_len=5000):
|
|
270
|
+
super(TransformerWithConvInput, self).__init__()
|
|
271
|
+
self.conv = nn.Conv1d(in_channels=n_channels, out_channels=d_model, kernel_size=3, padding=1)
|
|
272
|
+
self.pos_encoder = PositionalEncoding(d_model, max_len=max_len)
|
|
273
|
+
encoder_layers = nn.TransformerEncoderLayer(d_model, nhead, dim_feedforward)
|
|
274
|
+
self.transformer_encoder = nn.TransformerEncoder(encoder_layers, num_layers)
|
|
275
|
+
self.fc = nn.Linear(d_model, n_channels)
|
|
276
|
+
|
|
277
|
+
def forward(self, src):
|
|
278
|
+
#src = src.permute(0, 2, 1) # Conv1d expects input in (batch_size, channels, seq_len) format
|
|
279
|
+
src = F.relu(self.conv(src))
|
|
280
|
+
src = src.permute(2, 0, 1) # Transformer expects input in (seq_len, batch_size, channels) format
|
|
281
|
+
src = self.pos_encoder(src)
|
|
282
|
+
output = self.transformer_encoder(src)
|
|
283
|
+
output = self.fc(output)
|
|
284
|
+
output = output.permute(1, 2, 0) # Back to (batch_size, channels, seq_len ) format
|
|
285
|
+
return output
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class Mish(nn.Module):
|
|
289
|
+
def __init__(self):
|
|
290
|
+
super().__init__()
|
|
291
|
+
def forward(self, x):
|
|
292
|
+
return x *( torch.tanh(torch.nn.functional.softplus(x)))
|
|
293
|
+
|
|
294
|
+
class squeeze_excite(torch.nn.Module):
|
|
295
|
+
def __init__(self, in_channels = 512, size=1, reduction="/16", activation=torch.nn.GELU):
|
|
296
|
+
super(squeeze_excite, self).__init__()
|
|
297
|
+
self.in_channels = in_channels
|
|
298
|
+
self.avg = torch.nn.AdaptiveAvgPool1d(1)
|
|
299
|
+
if type(reduction) == str:
|
|
300
|
+
self.reductionsize = self.in_channels // int(reduction[1:])
|
|
301
|
+
else:
|
|
302
|
+
self.reductionsize = reduction
|
|
303
|
+
self.fc1 = nn.Linear(self.in_channels, self.reductionsize)
|
|
304
|
+
self.activation = activation() # was nn.ReLU(inplace=True)
|
|
305
|
+
self.fc2 = nn.Linear(self.reductionsize, self.in_channels)
|
|
306
|
+
self.sigmoid = nn.Sigmoid()
|
|
307
|
+
|
|
308
|
+
def forward(self, x):
|
|
309
|
+
input = x
|
|
310
|
+
x = self.avg(x)
|
|
311
|
+
x = x.permute(0,2,1)
|
|
312
|
+
x = self.activation(self.fc1(x))
|
|
313
|
+
x = self.sigmoid(self.fc2(x))
|
|
314
|
+
return input * x.permute(0,2,1)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class simpleRNN(nn.Module):
|
|
318
|
+
def __init__(self, in_channel, out_channel):
|
|
319
|
+
super(simpleRNN, self).__init__()
|
|
320
|
+
self.relu0 =nn.ReLU()
|
|
321
|
+
self.kernel_size1 = 7
|
|
322
|
+
self.kernel_size2 = 7
|
|
323
|
+
self.padding1 = 3
|
|
324
|
+
self.padding2 = 3
|
|
325
|
+
self.downsample = nn.MaxPool1d(3, stride=2, ceil_mode=True)
|
|
326
|
+
self.upsample = nn.Upsample(scale_factor=2)
|
|
327
|
+
self.convs1 = nn.Conv1d(in_channel, out_channel//4, self.kernel_size1, stride=2, padding=self.padding1)
|
|
328
|
+
self.bns1 = nn.BatchNorm1d(out_channel//4)
|
|
329
|
+
self.convs2 = nn.Conv1d(out_channel//4, out_channel//2, self.kernel_size2, stride=2, padding=self.padding2)
|
|
330
|
+
self.bns2 = nn.BatchNorm1d(out_channel//2)
|
|
331
|
+
self.convs3 = nn.Conv1d(out_channel//2, out_channel//2, self.kernel_size2, stride=2, padding=self.padding2)
|
|
332
|
+
self.bns3 = nn.BatchNorm1d(out_channel//2)
|
|
333
|
+
# fwB0 related
|
|
334
|
+
self.lstm01 = nn.GRU(out_channel//4, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
335
|
+
self.lstm02 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
336
|
+
self.lstm03 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
337
|
+
self.lstm04 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
338
|
+
self.lstm05 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
339
|
+
# fwB1 related
|
|
340
|
+
self.lstm11 = nn.GRU(out_channel//2, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
341
|
+
self.lstm12 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
342
|
+
self.lstm13 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
343
|
+
self.lstm14 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
344
|
+
self.lstm15 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
345
|
+
# fwB2 related
|
|
346
|
+
self.lstm21 = nn.GRU(out_channel//2, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
347
|
+
self.lstm22 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
348
|
+
self.lstm23 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
349
|
+
self.lstm24 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
350
|
+
self.lstm25 = nn.GRU(out_channel, out_channel//2, 1, batch_first=False, bidirectional=True)
|
|
351
|
+
###
|
|
352
|
+
self.fusion = nn.Conv1d(out_channel*2, out_channel, kernel_size=1, stride=1, bias=False)
|
|
353
|
+
self.layer_norm = nn.LayerNorm(out_channel, eps=1e-6)
|
|
354
|
+
|
|
355
|
+
def fwB0(self, x):
|
|
356
|
+
x = x.permute(2, 0, 1)
|
|
357
|
+
self.lstm01.flatten_parameters()
|
|
358
|
+
x, _ = self.lstm01(x)
|
|
359
|
+
self.lstm02.flatten_parameters()
|
|
360
|
+
x, _ = self.lstm02(x)
|
|
361
|
+
self.lstm03.flatten_parameters()
|
|
362
|
+
x, _ = self.lstm03(x)
|
|
363
|
+
self.lstm04.flatten_parameters()
|
|
364
|
+
x, _ = self.lstm04(x)
|
|
365
|
+
self.lstm05.flatten_parameters()
|
|
366
|
+
x, _ = self.lstm05(x)
|
|
367
|
+
x = x.permute(1, 2, 0)
|
|
368
|
+
return x
|
|
369
|
+
|
|
370
|
+
def fwB1(self, x):
|
|
371
|
+
x = x.permute(2, 0, 1)
|
|
372
|
+
self.lstm11.flatten_parameters()
|
|
373
|
+
x, _ = self.lstm11(x)
|
|
374
|
+
self.lstm12.flatten_parameters()
|
|
375
|
+
x, _ = self.lstm12(x)
|
|
376
|
+
self.lstm13.flatten_parameters()
|
|
377
|
+
x, _ = self.lstm13(x)
|
|
378
|
+
self.lstm14.flatten_parameters()
|
|
379
|
+
x, _ = self.lstm14(x)
|
|
380
|
+
self.lstm15.flatten_parameters()
|
|
381
|
+
x, _ = self.lstm15(x)
|
|
382
|
+
x = x.permute(1, 2, 0)
|
|
383
|
+
return x
|
|
384
|
+
|
|
385
|
+
def fwB2(self, x):
|
|
386
|
+
x = x.permute(2, 0, 1)
|
|
387
|
+
self.lstm21.flatten_parameters()
|
|
388
|
+
x, _ = self.lstm21(x)
|
|
389
|
+
self.lstm22.flatten_parameters()
|
|
390
|
+
x, _ = self.lstm22(x)
|
|
391
|
+
self.lstm23.flatten_parameters()
|
|
392
|
+
x, _ = self.lstm23(x)
|
|
393
|
+
self.lstm24.flatten_parameters()
|
|
394
|
+
x, _ = self.lstm24(x)
|
|
395
|
+
self.lstm25.flatten_parameters()
|
|
396
|
+
x, _ = self.lstm25(x)
|
|
397
|
+
x = x.permute(1, 2, 0)
|
|
398
|
+
return x
|
|
399
|
+
|
|
400
|
+
def forward(self, x):
|
|
401
|
+
# x = (bs, 2048, 1)
|
|
402
|
+
#x = x.transpose(2, 1) # (bs, 1, 2048)
|
|
403
|
+
x = self.convs1(x) # (bs, 64, 1024)
|
|
404
|
+
x = self.bns1(x)
|
|
405
|
+
x0 = self.relu0(x)
|
|
406
|
+
#
|
|
407
|
+
x = self.convs2(x0) # (bs, 128, 512)
|
|
408
|
+
x = self.bns2(x)
|
|
409
|
+
x1 = self.relu0(x)
|
|
410
|
+
#
|
|
411
|
+
x = self.convs3(x1) # (bs, 128, 256)
|
|
412
|
+
x = self.bns3(x)
|
|
413
|
+
x2 = self.relu0(x)
|
|
414
|
+
###############
|
|
415
|
+
x0 = self.fwB0(x0)
|
|
416
|
+
x0 = self.downsample(x0)
|
|
417
|
+
x1 = self.fwB1(x1)
|
|
418
|
+
x2 = self.fwB2(x2)
|
|
419
|
+
x2 = self.upsample(x2)
|
|
420
|
+
x = self.fusion(torch.cat([x1, x2], 1))
|
|
421
|
+
# x should be (bs, 256, 512)
|
|
422
|
+
#####################
|
|
423
|
+
x = x.transpose(2, 1) # (bs, 512, 256)
|
|
424
|
+
x = self.layer_norm(x)
|
|
425
|
+
x = x.transpose(2, 1)
|
|
426
|
+
|
|
427
|
+
return x
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
class BiGRU(nn.Module):
|
|
432
|
+
def __init__(self, nIn, nHidden, nOut, num_layers=3):
|
|
433
|
+
super(BiGRU, self).__init__()
|
|
434
|
+
self.gru = nn.GRU(nIn, nHidden, num_layers=num_layers, batch_first=True, bidirectional=True)
|
|
435
|
+
self.embedding = nn.Linear(nHidden*2, nOut)
|
|
436
|
+
|
|
437
|
+
def forward(self, input):
|
|
438
|
+
if not hasattr(self, '_flattened'):
|
|
439
|
+
self.gru.flatten_parameters()
|
|
440
|
+
setattr(self, '_flattened', True)
|
|
441
|
+
|
|
442
|
+
x = input.permute(0, 2, 1)
|
|
443
|
+
rnnOut, _ = self.gru(x)
|
|
444
|
+
N, T, C = rnnOut.size()
|
|
445
|
+
output = self.embedding(rnnOut)
|
|
446
|
+
output = output.permute(0, 2, 1)
|
|
447
|
+
return output
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def layer_norm_backward_hook(module, grad_input, grad_output, clamp_value):
|
|
451
|
+
return tuple(torch.clamp(v, min=-clamp_value, max=clamp_value) for v in grad_input)
|
|
452
|
+
|
|
453
|
+
class Fp32LayerNorm(nn.Module):
|
|
454
|
+
def __init__(
|
|
455
|
+
self,
|
|
456
|
+
input_dim,
|
|
457
|
+
clamp_grad=True,
|
|
458
|
+
max_grad_value=256,
|
|
459
|
+
eps=1e-5,
|
|
460
|
+
elementwise_affine=True,
|
|
461
|
+
):
|
|
462
|
+
super().__init__()
|
|
463
|
+
self.torch_module = torch.nn.LayerNorm(
|
|
464
|
+
input_dim, eps=eps, elementwise_affine=elementwise_affine
|
|
465
|
+
)
|
|
466
|
+
if clamp_grad:
|
|
467
|
+
hook = partial(layer_norm_backward_hook, clamp_value=max_grad_value)
|
|
468
|
+
self.torch_module.register_backward_hook(hook)
|
|
469
|
+
|
|
470
|
+
def forward(self, input):
|
|
471
|
+
output = torch.nn.functional.layer_norm(
|
|
472
|
+
input.float(),
|
|
473
|
+
self.torch_module.normalized_shape,
|
|
474
|
+
self.torch_module.weight.float()
|
|
475
|
+
if self.torch_module.weight is not None
|
|
476
|
+
else None,
|
|
477
|
+
self.torch_module.bias.float()
|
|
478
|
+
if self.torch_module.bias is not None
|
|
479
|
+
else None,
|
|
480
|
+
self.torch_module.eps,
|
|
481
|
+
).type_as(input)
|
|
482
|
+
return output
|