-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSample.py
More file actions
86 lines (67 loc) · 3.16 KB
/
Sample.py
File metadata and controls
86 lines (67 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Sample Transformer Implementation
# Sourced from: https://peterbloem.nl/blog/transformers
import math, torch
import torch.nn as nn
import torch.nn.functional as F
class SelfAttention(nn.Module):
def __init__(self, emb, heads=8, mask=False):
super().__init__()
self.emb = emb
self.heads = heads
self.mask = mask
self.tokeys = nn.Linear(emb, emb * heads, bias=False)
self.toqueries = nn.Linear(emb, emb * heads, bias=False)
self.tovalues = nn.Linear(emb, emb * heads, bias=False)
self.unifyheads = nn.Linear(heads * emb, emb)
def forward(self, x):
b, t, e = x.size()
h = self.heads
assert e == self.emb, f'Input embedding dim ({e}) should match layer embedding dim ({self.emb})'
keys = self.tokeys(x) .view(b, t, h, e)
queries = self.toqueries(x).view(b, t, h, e)
values = self.tovalues(x) .view(b, t, h, e)
# compute scaled dot-product self-attention
# - fold heads into the batch dimension
keys = keys.transpose(1, 2).contiguous().view(b * h, t, e)
queries = queries.transpose(1, 2).contiguous().view(b * h, t, e)
values = values.transpose(1, 2).contiguous().view(b * h, t, e)
# - get dot product of queries and keys, and scale
dot = torch.bmm(queries, keys.transpose(1, 2))
dot = dot / math.sqrt(e) # dot contains b*h t-by-t matrices with raw self-attention logits
assert dot.size() == (b*h, t, t), f'Matrix has size {dot.size()}, expected {(b*h, t, t)}.'
if self.mask: # mask out the lower half of the dot matrix,including the diagonal
# mask_(dot, maskval=float('-inf'), mask_diagonal=False)
pass
dot = F.softmax(dot, dim=2) # dot now has row-wise self-attention probabilities
# assert not util.contains_nan(dot[:, 1:, :]) # only the forst row may contain nan
if self.mask == 'first':
dot = dot.clone()
dot[:, :1, :] = 0.0
# - The first row of the first attention matrix is entirely masked out, so the softmax operation results
# in a division by zero. We set this row to zero by hand to get rid of the NaNs
# apply the self attention to the values
out = torch.bmm(dot, values).view(b, h, t, e)
# swap h, t back, unify heads
out = out.transpose(1, 2).contiguous().view(b, t, h * e)
return self.unifyheads(out)
class TransformerBlock(nn.Module):
def __init__(self, emb, heads, mask, seq_length, ff_hidden_mult=4, dropout=0.0):
super().__init__()
self.attention = SelfAttention(emb, heads=heads, mask=mask)
self.mask = mask
self.norm1 = nn.LayerNorm(emb)
self.norm2 = nn.LayerNorm(emb)
self.ff = nn.Sequential(
nn.Linear(emb, ff_hidden_mult * emb),
nn.ReLU(),
nn.Linear(ff_hidden_mult * emb, emb)
)
self.do = nn.Dropout(dropout)
def forward(self, x):
attended = self.attention(x)
x = self.norm1(attended + x)
x = self.do(x)
feedforward = self.ff(x)
x = self.norm2(feedforward + x)
x = self.do(x)
return x