m24842-ml 0.1.25__tar.gz
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.
- m24842_ml-0.1.25/PKG-INFO +10 -0
- m24842_ml-0.1.25/m24842_ml.egg-info/PKG-INFO +10 -0
- m24842_ml-0.1.25/m24842_ml.egg-info/SOURCES.txt +13 -0
- m24842_ml-0.1.25/m24842_ml.egg-info/dependency_links.txt +1 -0
- m24842_ml-0.1.25/m24842_ml.egg-info/requires.txt +6 -0
- m24842_ml-0.1.25/m24842_ml.egg-info/top_level.txt +1 -0
- m24842_ml-0.1.25/ml/__init__.py +0 -0
- m24842_ml-0.1.25/ml/attention.py +427 -0
- m24842_ml-0.1.25/ml/datasets.py +245 -0
- m24842_ml-0.1.25/ml/schedulers.py +23 -0
- m24842_ml-0.1.25/ml/train.py +354 -0
- m24842_ml-0.1.25/ml/transformers.py +224 -0
- m24842_ml-0.1.25/ml/utils.py +145 -0
- m24842_ml-0.1.25/pyproject.toml +17 -0
- m24842_ml-0.1.25/setup.cfg +4 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
m24842_ml.egg-info/PKG-INFO
|
|
3
|
+
m24842_ml.egg-info/SOURCES.txt
|
|
4
|
+
m24842_ml.egg-info/dependency_links.txt
|
|
5
|
+
m24842_ml.egg-info/requires.txt
|
|
6
|
+
m24842_ml.egg-info/top_level.txt
|
|
7
|
+
ml/__init__.py
|
|
8
|
+
ml/attention.py
|
|
9
|
+
ml/datasets.py
|
|
10
|
+
ml/schedulers.py
|
|
11
|
+
ml/train.py
|
|
12
|
+
ml/transformers.py
|
|
13
|
+
ml/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ml
|
|
File without changes
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torch.nn as nn
|
|
3
|
+
import torch.nn.functional as F
|
|
4
|
+
import torch.linalg as LA
|
|
5
|
+
import torch.autograd as AG
|
|
6
|
+
import math
|
|
7
|
+
from einops import rearrange
|
|
8
|
+
import opt_einsum
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from rotary_embedding_torch import RotaryEmbedding
|
|
11
|
+
|
|
12
|
+
class MultiheadAttention(nn.Module):
|
|
13
|
+
"""
|
|
14
|
+
Vanilla Multihead Attention.
|
|
15
|
+
Slight difference: the typical 1/sqrt(d_model) attention score scale is now a per head learnable parameter beta initialized at 1/sqrt(d_model).
|
|
16
|
+
"""
|
|
17
|
+
def __init__(self, d_model, n_heads, dropout=0.0, bias=True, add_bias_kv=False,
|
|
18
|
+
add_zero_attn=False, batch_first=False):
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.d_model = d_model
|
|
21
|
+
self.n_heads = n_heads
|
|
22
|
+
self.dropout = dropout
|
|
23
|
+
self.batch_first = batch_first
|
|
24
|
+
self.d_head = d_model // n_heads
|
|
25
|
+
|
|
26
|
+
assert self.d_head * n_heads == self.d_model, "d_model must be divisible by n_heads"
|
|
27
|
+
|
|
28
|
+
# Linear projections for query, key, and value
|
|
29
|
+
self.beta = nn.Parameter(torch.zeros(self.n_heads))
|
|
30
|
+
self.beta._no_weight_decay = True
|
|
31
|
+
self.q_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
32
|
+
self.k_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
33
|
+
self.v_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
34
|
+
self.out_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
35
|
+
|
|
36
|
+
# Optional bias for key and value
|
|
37
|
+
if add_bias_kv:
|
|
38
|
+
self.bias_k = nn.Parameter(torch.empty(1, 1, d_model))
|
|
39
|
+
self.bias_v = nn.Parameter(torch.empty(1, 1, d_model))
|
|
40
|
+
else:
|
|
41
|
+
self.bias_k = self.bias_v = None
|
|
42
|
+
|
|
43
|
+
self.add_zero_attn = add_zero_attn
|
|
44
|
+
|
|
45
|
+
self._reset_parameters()
|
|
46
|
+
|
|
47
|
+
def _reset_parameters(self):
|
|
48
|
+
# Initialize projections using Xavier uniform
|
|
49
|
+
nn.init.constant_(self.beta, 0.)
|
|
50
|
+
nn.init.xavier_uniform_(self.q_proj.weight)
|
|
51
|
+
nn.init.xavier_uniform_(self.k_proj.weight)
|
|
52
|
+
nn.init.xavier_uniform_(self.v_proj.weight)
|
|
53
|
+
nn.init.xavier_uniform_(self.out_proj.weight)
|
|
54
|
+
|
|
55
|
+
if self.out_proj.bias is not None:
|
|
56
|
+
nn.init.constant_(self.out_proj.bias, 0.)
|
|
57
|
+
|
|
58
|
+
if self.bias_k is not None:
|
|
59
|
+
nn.init.xavier_normal_(self.bias_k)
|
|
60
|
+
if self.bias_v is not None:
|
|
61
|
+
nn.init.xavier_normal_(self.bias_v)
|
|
62
|
+
|
|
63
|
+
def forward(self, x, key_padding_mask=None, need_weights=True,
|
|
64
|
+
attn_mask=None, average_attn_weights=True, rope=None):
|
|
65
|
+
"""
|
|
66
|
+
Forward pass for the MultiheadAttention module.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
query: Query embeddings of shape (seq_len_q, batch_size, d_model) or
|
|
70
|
+
(batch_size, seq_len_q, d_model) if batch_first=True
|
|
71
|
+
key: Key embeddings of shape (seq_len_k, batch_size, d_model) or
|
|
72
|
+
(batch_size, seq_len_k, d_model) if batch_first=True
|
|
73
|
+
value: Value embeddings of shape (seq_len_v, batch_size, d_model) or
|
|
74
|
+
(batch_size, seq_len_v, d_model) if batch_first=True
|
|
75
|
+
key_padding_mask: If provided, specified padding elements in the key will
|
|
76
|
+
be ignored by the attention. Shape: (batch_size, seq_len_k)
|
|
77
|
+
need_weights: If True, returns attention weights in addition to attention output
|
|
78
|
+
attn_mask: 2D or 3D mask that prevents attention to certain positions
|
|
79
|
+
average_attn_weights: If True, returns averaged attention weights over heads
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
attn_output: Attention output of shape (seq_len_q, batch_size, d_model) or
|
|
83
|
+
(batch_size, seq_len_q, d_model) if batch_first=True
|
|
84
|
+
attn_output_weights: Attention weights of shape (batch_size, seq_len_q, seq_len_k)
|
|
85
|
+
if need_weights=True, otherwise None
|
|
86
|
+
"""
|
|
87
|
+
# Handle batch_first option
|
|
88
|
+
if self.batch_first:
|
|
89
|
+
x = x.transpose(0, 1)
|
|
90
|
+
|
|
91
|
+
tgt_len, bsz, d_model = x.shape
|
|
92
|
+
src_len = x.shape[0]
|
|
93
|
+
|
|
94
|
+
# Apply linear projections
|
|
95
|
+
q = self.q_proj(x) # (tgt_len, batch_size, d_model)
|
|
96
|
+
k = self.k_proj(x) # (src_len, batch_size, d_model)
|
|
97
|
+
v = self.v_proj(x) # (src_len, batch_size, d_model)
|
|
98
|
+
|
|
99
|
+
# Handle bias for key and value if present
|
|
100
|
+
if self.bias_k is not None and self.bias_v is not None:
|
|
101
|
+
k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)])
|
|
102
|
+
v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)])
|
|
103
|
+
if attn_mask is not None:
|
|
104
|
+
attn_mask = F.pad(attn_mask, (0, 1))
|
|
105
|
+
if key_padding_mask is not None:
|
|
106
|
+
key_padding_mask = F.pad(key_padding_mask, (0, 1))
|
|
107
|
+
src_len += 1
|
|
108
|
+
|
|
109
|
+
# Add zero attention if requested
|
|
110
|
+
if self.add_zero_attn:
|
|
111
|
+
src_len += 1
|
|
112
|
+
k = torch.cat([k, torch.zeros((1, bsz, d_model), dtype=k.dtype, device=k.device)], d_model=0)
|
|
113
|
+
v = torch.cat([v, torch.zeros((1, bsz, d_model), dtype=v.dtype, device=v.device)], d_model=0)
|
|
114
|
+
if attn_mask is not None:
|
|
115
|
+
attn_mask = F.pad(attn_mask, (0, 1))
|
|
116
|
+
if key_padding_mask is not None:
|
|
117
|
+
key_padding_mask = F.pad(key_padding_mask, (0, 1))
|
|
118
|
+
|
|
119
|
+
# Reshape q, k, v for multi-head attention
|
|
120
|
+
q = q.contiguous().view(tgt_len, bsz * self.n_heads, self.d_head).transpose(0, 1)
|
|
121
|
+
k = k.contiguous().view(src_len, bsz * self.n_heads, self.d_head).transpose(0, 1)
|
|
122
|
+
v = v.contiguous().view(src_len, bsz * self.n_heads, self.d_head).transpose(0, 1)
|
|
123
|
+
|
|
124
|
+
if rope:
|
|
125
|
+
q = rope.rotate_queries_or_keys(q.reshape(bsz, self.n_heads, tgt_len, self.d_head)).reshape(bsz * self.n_heads, tgt_len, self.d_head)
|
|
126
|
+
k = rope.rotate_queries_or_keys(k.reshape(bsz, self.n_heads, src_len, self.d_head)).reshape(bsz * self.n_heads, src_len, self.d_head)
|
|
127
|
+
|
|
128
|
+
# Calculate attention scores
|
|
129
|
+
q = q / (math.sqrt(self.d_head) * torch.exp(self.beta).reshape(self.n_heads, 1, 1).repeat(bsz, 1, 1))
|
|
130
|
+
attn_output_weights = torch.bmm(q, k.transpose(1, 2)) # (bsz * n_heads, tgt_len, src_len)
|
|
131
|
+
|
|
132
|
+
# Apply attention mask if provided
|
|
133
|
+
if attn_mask is not None:
|
|
134
|
+
if attn_mask.dim() == 2:
|
|
135
|
+
attn_mask = attn_mask.unsqueeze(0)
|
|
136
|
+
elif attn_mask.dim() == 3:
|
|
137
|
+
attn_mask = attn_mask.repeat(self.n_heads, 1, 1)
|
|
138
|
+
attn_output_weights = attn_output_weights + attn_mask
|
|
139
|
+
|
|
140
|
+
# Apply key padding mask if provided
|
|
141
|
+
if key_padding_mask is not None:
|
|
142
|
+
attn_output_weights = attn_output_weights.view(bsz, self.n_heads, tgt_len, src_len)
|
|
143
|
+
attn_output_weights = attn_output_weights.masked_fill(
|
|
144
|
+
key_padding_mask.unsqueeze(1).unsqueeze(2),
|
|
145
|
+
float('-inf'),
|
|
146
|
+
)
|
|
147
|
+
attn_output_weights = attn_output_weights.view(bsz * self.n_heads, tgt_len, src_len)
|
|
148
|
+
|
|
149
|
+
# Convert attention weights to probabilities
|
|
150
|
+
attn_output_weights = F.softmax(attn_output_weights, dim=-1)
|
|
151
|
+
attn_output_weights = F.dropout(attn_output_weights, p=self.dropout, training=self.training)
|
|
152
|
+
|
|
153
|
+
# Apply attention weights to values
|
|
154
|
+
attn_output = torch.bmm(attn_output_weights, v) # (bsz * n_heads, tgt_len, d_head)
|
|
155
|
+
|
|
156
|
+
# Reshape output
|
|
157
|
+
attn_output = attn_output.transpose(0, 1).contiguous().view(tgt_len, bsz, d_model)
|
|
158
|
+
attn_output = self.out_proj(attn_output)
|
|
159
|
+
|
|
160
|
+
# Process attention weights if needed
|
|
161
|
+
if need_weights:
|
|
162
|
+
attn_output_weights = attn_output_weights.view(bsz, self.n_heads, tgt_len, src_len)
|
|
163
|
+
if average_attn_weights:
|
|
164
|
+
attn_output_weights = attn_output_weights.mean(dim=1)
|
|
165
|
+
else:
|
|
166
|
+
attn_output_weights = None
|
|
167
|
+
|
|
168
|
+
# Return in the correct format depending on batch_first
|
|
169
|
+
if self.batch_first:
|
|
170
|
+
return attn_output.transpose(0, 1), attn_output_weights
|
|
171
|
+
return attn_output, attn_output_weights
|
|
172
|
+
|
|
173
|
+
class LinearAttention(nn.Module):
|
|
174
|
+
"""
|
|
175
|
+
Vanilla Linear Attention.
|
|
176
|
+
Kernel function is elu + 1.
|
|
177
|
+
"""
|
|
178
|
+
def __init__(self, d_model, n_heads, bias=True):
|
|
179
|
+
super().__init__()
|
|
180
|
+
self.d_model = d_model
|
|
181
|
+
self.n_heads = n_heads
|
|
182
|
+
self.d_head = d_model // n_heads
|
|
183
|
+
self.q_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
184
|
+
self.k_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
185
|
+
self.v_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
186
|
+
self.out_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
187
|
+
|
|
188
|
+
self._reset_parameters()
|
|
189
|
+
|
|
190
|
+
def _reset_parameters(self):
|
|
191
|
+
nn.init.xavier_uniform_(self.q_proj.weight)
|
|
192
|
+
nn.init.xavier_uniform_(self.k_proj.weight)
|
|
193
|
+
nn.init.xavier_uniform_(self.v_proj.weight)
|
|
194
|
+
nn.init.xavier_uniform_(self.out_proj.weight)
|
|
195
|
+
|
|
196
|
+
if self.q_proj.bias is not None:
|
|
197
|
+
nn.init.constant_(self.q_proj.bias, 0.)
|
|
198
|
+
if self.k_proj.bias is not None:
|
|
199
|
+
nn.init.constant_(self.k_proj.bias, 0.)
|
|
200
|
+
if self.v_proj.bias is not None:
|
|
201
|
+
nn.init.constant_(self.v_proj.bias, 0.)
|
|
202
|
+
if self.out_proj.bias is not None:
|
|
203
|
+
nn.init.constant_(self.out_proj.bias, 0.)
|
|
204
|
+
|
|
205
|
+
def forward(self, x, rope=None, causal=True):
|
|
206
|
+
bsz, seq_len, d_model = x.size()
|
|
207
|
+
q = rearrange(self.q_proj(x), 'b s (h d) -> b h s d', h=self.n_heads)
|
|
208
|
+
k = rearrange(self.k_proj(x), 'b s (h d) -> b h s d', h=self.n_heads)
|
|
209
|
+
v = rearrange(self.v_proj(x), 'b s (h d) -> (b h) s d', h=self.n_heads).contiguous()
|
|
210
|
+
|
|
211
|
+
if rope:
|
|
212
|
+
q = rope.rotate_queries_or_keys(q).reshape(bsz*self.n_heads, seq_len, self.d_head).contiguous()
|
|
213
|
+
k = rope.rotate_queries_or_keys(k).reshape(bsz*self.n_heads, seq_len, self.d_head).contiguous()
|
|
214
|
+
|
|
215
|
+
# q = torch.exp(q)
|
|
216
|
+
# k = torch.exp(k)
|
|
217
|
+
q = F.elu(q) + 1
|
|
218
|
+
k = F.elu(k) + 1
|
|
219
|
+
|
|
220
|
+
if causal:
|
|
221
|
+
kv = torch.cumsum(torch.matmul(k.unsqueeze(-1), v.unsqueeze(-2)), dim=1)
|
|
222
|
+
k1 = torch.cumsum(k, dim=1)
|
|
223
|
+
else:
|
|
224
|
+
kv = torch.einsum('zsD, zsd -> zDd', k, v).unsqueeze(1)
|
|
225
|
+
k1 = k.sum(dim=1, keepdim=True)
|
|
226
|
+
out = torch.matmul(q.unsqueeze(-2), kv).squeeze(-2) / (q*k1).sum(-1, keepdim=True)
|
|
227
|
+
|
|
228
|
+
out = rearrange(out, '(b h) s d -> b s (h d)', h=self.n_heads)
|
|
229
|
+
return self.out_proj(out)
|
|
230
|
+
|
|
231
|
+
class OrthoLinearAttention(nn.Module):
|
|
232
|
+
"""
|
|
233
|
+
Orthogonal Linear Attention.
|
|
234
|
+
A derivative of linear attention that orthogonalizes queries and keys for each head to reduce crossterm interference.
|
|
235
|
+
"""
|
|
236
|
+
def __init__(self, d_model: int, n_heads: int, bias: bool = True):
|
|
237
|
+
super().__init__()
|
|
238
|
+
self.d_model = d_model
|
|
239
|
+
self.n_heads = n_heads
|
|
240
|
+
self.d_head = d_model // n_heads
|
|
241
|
+
|
|
242
|
+
self.beta = nn.Parameter(torch.zeros(self.n_heads))
|
|
243
|
+
self.beta._no_weight_decay = True
|
|
244
|
+
self.q_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
245
|
+
self.k_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
246
|
+
self.v_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
247
|
+
self.out_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
248
|
+
|
|
249
|
+
self._reset_parameters()
|
|
250
|
+
|
|
251
|
+
def _reset_parameters(self):
|
|
252
|
+
nn.init.constant_(self.beta, 0.)
|
|
253
|
+
nn.init.xavier_uniform_(self.q_proj.weight)
|
|
254
|
+
nn.init.xavier_uniform_(self.k_proj.weight)
|
|
255
|
+
nn.init.xavier_uniform_(self.v_proj.weight)
|
|
256
|
+
nn.init.xavier_uniform_(self.out_proj.weight)
|
|
257
|
+
|
|
258
|
+
if self.q_proj.bias is not None:
|
|
259
|
+
nn.init.constant_(self.q_proj.bias, 0.)
|
|
260
|
+
if self.k_proj.bias is not None:
|
|
261
|
+
nn.init.constant_(self.k_proj.bias, 0.)
|
|
262
|
+
if self.v_proj.bias is not None:
|
|
263
|
+
nn.init.constant_(self.v_proj.bias, 0.)
|
|
264
|
+
if self.out_proj.bias is not None:
|
|
265
|
+
nn.init.constant_(self.out_proj.bias, 0.)
|
|
266
|
+
|
|
267
|
+
def forward(self, x: torch.Tensor, rope: Optional[RotaryEmbedding] = None, causal: bool = True) -> torch.Tensor:
|
|
268
|
+
"""
|
|
269
|
+
Args:
|
|
270
|
+
x (torch.Tensor): Input sequence of shape (batch_size, seq_len, d_model).
|
|
271
|
+
rope (Optional[RotaryEmbedding]): Optional RoPE encoder for rotating queries and keys.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
torch.Tensor: Output sequence of shape (batch_size, seq_len, d_model).
|
|
275
|
+
"""
|
|
276
|
+
bsz, seq_len, d_model = x.size()
|
|
277
|
+
q = rearrange(self.q_proj(x), 'b s (h d) -> b h s d', h=self.n_heads)
|
|
278
|
+
k = rearrange(self.k_proj(x), 'b s (h d) -> b h s d', h=self.n_heads)
|
|
279
|
+
v = rearrange(self.v_proj(x), 'b s (h d) -> (b h) s d', h=self.n_heads).contiguous()
|
|
280
|
+
|
|
281
|
+
if rope:
|
|
282
|
+
q = rope.rotate_queries_or_keys(q).reshape(bsz * self.n_heads, seq_len, self.d_head).contiguous()
|
|
283
|
+
k = rope.rotate_queries_or_keys(k).reshape(bsz * self.n_heads, seq_len, self.d_head).contiguous()
|
|
284
|
+
else:
|
|
285
|
+
q = q.reshape(bsz * self.n_heads, seq_len, self.d_head).contiguous()
|
|
286
|
+
k = k.reshape(bsz * self.n_heads, seq_len, self.d_head).contiguous()
|
|
287
|
+
|
|
288
|
+
beta = torch.exp(self.beta).reshape(self.n_heads, 1, 1).repeat(bsz, 1, 1)
|
|
289
|
+
q = (beta * q).softmax(-1)# * q.norm(dim=-1, keepdim=True)
|
|
290
|
+
k = (beta * k).softmax(-1)# * k.norm(dim=-1, keepdim=True)
|
|
291
|
+
|
|
292
|
+
if causal:
|
|
293
|
+
kv = torch.cumsum(torch.matmul(k.unsqueeze(-1), v.unsqueeze(-2)), dim=1)
|
|
294
|
+
kn = torch.cumsum(k, dim=1)
|
|
295
|
+
else:
|
|
296
|
+
kv = torch.einsum('zsD, zsd -> zDd', k, v).unsqueeze(1)
|
|
297
|
+
kn = k.sum(1, keepdim=True)
|
|
298
|
+
|
|
299
|
+
out = torch.matmul(q.unsqueeze(-2), kv).squeeze(-2) / (q * kn).sum(-1, keepdim=True)
|
|
300
|
+
out = rearrange(out, '(b h) s d -> b s (h d)', h=self.n_heads)
|
|
301
|
+
return self.out_proj(out)
|
|
302
|
+
|
|
303
|
+
class CompressionAttention(nn.Module):
|
|
304
|
+
"""
|
|
305
|
+
Compression Attention.
|
|
306
|
+
A derivative of softmax attention that compresses input sequences to a fixed length before expanding back to the original length.
|
|
307
|
+
Achieved by two linear with sequence length attention operations.
|
|
308
|
+
"""
|
|
309
|
+
def __init__(self, d_model, n_heads, mlp_dim, compressed_len, dropout=0.0, bias=True, batch_first=False):
|
|
310
|
+
super().__init__()
|
|
311
|
+
self.d_model = d_model
|
|
312
|
+
self.n_heads = n_heads
|
|
313
|
+
self.mlp_dim = mlp_dim
|
|
314
|
+
self.d_head = d_model // n_heads
|
|
315
|
+
self.compressed_len = compressed_len
|
|
316
|
+
self.batch_first = batch_first
|
|
317
|
+
self.dropout = dropout
|
|
318
|
+
|
|
319
|
+
self.q_c = nn.Parameter(torch.empty(compressed_len, d_model))
|
|
320
|
+
self.q_c._no_weight_decay = True
|
|
321
|
+
self.beta = nn.Parameter(torch.zeros(self.n_heads))
|
|
322
|
+
self.beta._no_weight_decay = True
|
|
323
|
+
self.q_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
324
|
+
self.k_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
325
|
+
self.v_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
326
|
+
self.out_proj = nn.Linear(d_model, d_model, bias=bias)
|
|
327
|
+
|
|
328
|
+
self._reset_parameters()
|
|
329
|
+
|
|
330
|
+
def _reset_parameters(self):
|
|
331
|
+
# Initialize projections using Xavier uniform
|
|
332
|
+
nn.init.constant_(self.beta, 0.)
|
|
333
|
+
nn.init.xavier_uniform_(self.q_c)
|
|
334
|
+
nn.init.xavier_uniform_(self.q_proj.weight)
|
|
335
|
+
nn.init.xavier_uniform_(self.k_proj.weight)
|
|
336
|
+
nn.init.xavier_uniform_(self.v_proj.weight)
|
|
337
|
+
nn.init.xavier_uniform_(self.out_proj.weight)
|
|
338
|
+
|
|
339
|
+
if self.q_proj.bias is not None:
|
|
340
|
+
nn.init.constant_(self.q_proj.bias, 0.)
|
|
341
|
+
if self.k_proj.bias is not None:
|
|
342
|
+
nn.init.constant_(self.k_proj.bias, 0.)
|
|
343
|
+
if self.v_proj.bias is not None:
|
|
344
|
+
nn.init.constant_(self.v_proj.bias, 0.)
|
|
345
|
+
if self.out_proj.bias is not None:
|
|
346
|
+
nn.init.constant_(self.out_proj.bias, 0.)
|
|
347
|
+
|
|
348
|
+
def forward(self, x, rope=None, causal=True):
|
|
349
|
+
# Handle batch_first option
|
|
350
|
+
if self.batch_first:
|
|
351
|
+
x = x.transpose(0, 1)
|
|
352
|
+
|
|
353
|
+
cmprs_len = self.compressed_len
|
|
354
|
+
_, bsz, d_model = x.shape
|
|
355
|
+
src_len = x.shape[0]
|
|
356
|
+
|
|
357
|
+
q_c = self.q_c.unsqueeze(1).repeat(1, bsz, 1) # (compressed_len, d_model)
|
|
358
|
+
q_s = self.q_proj(x) # (src_len, batch_size, d_model)
|
|
359
|
+
k_s = self.k_proj(x) # (src_len, batch_size, d_model)
|
|
360
|
+
v_s = self.v_proj(x) # (src_len, batch_size, d_model)
|
|
361
|
+
|
|
362
|
+
# Reshape for multi-head attention
|
|
363
|
+
q_c = rearrange(q_c, 'c b (h d) -> (b h) c d', h=self.n_heads).contiguous()
|
|
364
|
+
q_s = rearrange(q_s, 's b (h d) -> (b h) s d', h=self.n_heads).contiguous()
|
|
365
|
+
k_s = rearrange(k_s, 's b (h d) -> (b h) s d', h=self.n_heads).contiguous()
|
|
366
|
+
v_s = rearrange(v_s, 's b (h d) -> (b h) s d', h=self.n_heads).contiguous()
|
|
367
|
+
|
|
368
|
+
if rope:
|
|
369
|
+
# q_c = rope.rotate_queries_or_keys(q_c.reshape(bsz, self.n_heads, cmprs_len, self.d_head)).reshape(bsz * self.n_heads, cmprs_len, self.d_head)
|
|
370
|
+
q_s = rope.rotate_queries_or_keys(q_s.reshape(bsz, self.n_heads, src_len, self.d_head)).reshape(bsz * self.n_heads, src_len, self.d_head)
|
|
371
|
+
k_s = rope.rotate_queries_or_keys(k_s.reshape(bsz, self.n_heads, src_len, self.d_head)).reshape(bsz * self.n_heads, src_len, self.d_head)
|
|
372
|
+
|
|
373
|
+
kv_s = torch.cat([k_s, v_s], dim=-1) # (bsz * n_heads, src_len, 2*d_head)
|
|
374
|
+
|
|
375
|
+
### Downward self attention ###
|
|
376
|
+
# q_c = q_c / math.sqrt(self.d_head)
|
|
377
|
+
c_attn_weights = torch.bmm(q_c, k_s.transpose(1, 2)) # (bsz * n_heads, cmprs_len, src_len)
|
|
378
|
+
|
|
379
|
+
if causal:
|
|
380
|
+
# Manually perform softmax with cumulative sum for causal attention
|
|
381
|
+
c_attn_weights = torch.exp(c_attn_weights - torch.max(c_attn_weights, dim=-1, keepdim=True).values) # (bsz * n_heads, cmprs_len, src_len)
|
|
382
|
+
c_attn_norm = torch.cumsum(c_attn_weights, dim=-1) # (bsz * n_heads, cmprs_len, src_len)
|
|
383
|
+
c_attn_weights = F.dropout(c_attn_weights, p=self.dropout, training=self.training)
|
|
384
|
+
else:
|
|
385
|
+
# Convert attention weights to probabilities
|
|
386
|
+
c_attn_weights = F.softmax(c_attn_weights, dim=-1)
|
|
387
|
+
c_attn_weights = F.dropout(c_attn_weights, p=self.dropout, training=self.training)
|
|
388
|
+
|
|
389
|
+
### Upward self attention ###
|
|
390
|
+
q_s = q_s / (math.sqrt(self.d_head) * torch.exp(self.beta).reshape(self.n_heads, 1, 1).repeat(bsz, 1, 1))
|
|
391
|
+
|
|
392
|
+
if causal:
|
|
393
|
+
# Calculate attention scores for compressed output
|
|
394
|
+
kv_c = torch.cumsum((c_attn_weights.unsqueeze(-1) * kv_s.unsqueeze(1)), dim=2) / c_attn_norm.unsqueeze(-1) # (bsz * n_heads, cmprs_len, 2*d_head)
|
|
395
|
+
k_c, v_c = kv_c.split([self.d_head, self.d_head], dim=-1) # (bsz * n_heads, cmprs_len, src_len, d_head)
|
|
396
|
+
s_attn_weights = torch.einsum('zsd, zcsd -> zsc', q_s, k_c) # (bsz * n_heads, src_len, cmprs_len)
|
|
397
|
+
|
|
398
|
+
# Convert attention weights to probabilities
|
|
399
|
+
s_attn_weights = F.softmax(s_attn_weights, dim=-1)
|
|
400
|
+
s_attn_weights = F.dropout(s_attn_weights, p=self.dropout, training=self.training)
|
|
401
|
+
|
|
402
|
+
# Apply attention weights to values
|
|
403
|
+
s_attn_output = torch.einsum('zsc, zcsd -> zsd', s_attn_weights, v_c) # (bsz * n_heads, src_len, d_head)
|
|
404
|
+
else:
|
|
405
|
+
# Calculate attention scores for compressed output
|
|
406
|
+
kv_c = torch.bmm(c_attn_weights, kv_s) # (bsz * n_heads, cmprs_len, 2*d_head)
|
|
407
|
+
k_c, v_c = kv_c.split([self.d_head, self.d_head], dim=-1) # (bsz * n_heads, cmprs_len, d_head)
|
|
408
|
+
s_attn_weights = torch.bmm(q_s, k_c.transpose(1, 2)) # (bsz * n_heads, src_len, cmprs_len)
|
|
409
|
+
|
|
410
|
+
# Convert attention weights to probabilities
|
|
411
|
+
s_attn_weights = F.softmax(s_attn_weights, dim=-1)
|
|
412
|
+
s_attn_weights = F.dropout(s_attn_weights, p=self.dropout, training=self.training)
|
|
413
|
+
|
|
414
|
+
# Apply attention weights to values
|
|
415
|
+
s_attn_output = torch.bmm(s_attn_weights, v_c) # (bsz * n_heads, src_len, d_head)
|
|
416
|
+
|
|
417
|
+
# Reshape output
|
|
418
|
+
s_attn_output = s_attn_output.transpose(0, 1).contiguous().view(src_len, bsz, d_model)
|
|
419
|
+
|
|
420
|
+
# Apply final projection
|
|
421
|
+
s_attn_output = self.out_proj(s_attn_output)
|
|
422
|
+
|
|
423
|
+
# Return in the correct format depending on batch_first
|
|
424
|
+
if self.batch_first:
|
|
425
|
+
return s_attn_output.transpose(0, 1)
|
|
426
|
+
return s_attn_output
|
|
427
|
+
|