Spaces:
Running
on
Zero
Running
on
Zero
import torch | |
import torch.nn as nn | |
import torch.nn.functional as F | |
import math | |
class FeedForward(nn.Module): | |
def __init__(self, dim, mult=4): | |
super().__init__() | |
self.norm = nn.LayerNorm(dim) | |
self.fc1 = nn.Linear(dim, int(dim * mult)) | |
self.act = nn.GELU() | |
self.fc2 = nn.Linear(int(dim * mult), dim) | |
nn.init.xavier_uniform_(self.fc1.weight) | |
nn.init.xavier_uniform_(self.fc2.weight) | |
def forward(self, x): | |
return x + self.fc2(self.act(self.fc1(self.norm(x)))) | |
def reshape_tensor(x, heads): | |
bs, length, _ = x.shape | |
return x.view(bs, length, heads, -1).transpose(1, 2) | |
class PerceiverAttention(nn.Module): | |
def __init__(self, *, dim, dim_head=64, heads=8): | |
super().__init__() | |
self.scale = dim_head**-0.5 | |
self.dim_head = dim_head | |
self.heads = heads | |
inner_dim = dim_head * heads | |
self.norm1 = nn.LayerNorm(dim) | |
self.norm2 = nn.LayerNorm(dim) | |
self.to_q = nn.Linear(dim, inner_dim) | |
self.to_kv = nn.Linear(dim, inner_dim * 2) | |
self.to_out = nn.Linear(inner_dim, dim) | |
nn.init.xavier_uniform_(self.to_q.weight) | |
nn.init.xavier_uniform_(self.to_kv.weight) | |
nn.init.xavier_uniform_(self.to_out.weight) | |
def forward(self, x, latents): | |
x = self.norm1(x) | |
latents = self.norm2(latents) | |
q = self.to_q(latents) | |
kv_input = torch.cat((x, latents), dim=-2) | |
k, v = self.to_kv(kv_input).chunk(2, dim=-1) | |
q, k, v = map(lambda t: reshape_tensor(t, self.heads), (q, k, v)) | |
attn_score = (q @ k.transpose(-2, -1)) * self.scale | |
attn_weight = F.softmax(attn_score, dim=-1) | |
out = (attn_weight @ v).transpose(1, 2).reshape(latents.shape) | |
return self.to_out(out) | |
class Resampler(nn.Module): | |
def __init__(self, dim=1024, depth=8, dim_head=64, heads=16, num_queries=8, embedding_dim=768, output_dim=1024, ff_mult=4): | |
super().__init__() | |
self.latents = nn.Parameter(torch.empty(1, num_queries, dim)) | |
nn.init.normal_(self.latents, mean=0, std=dim**-0.5) | |
self.proj_in = nn.Linear(embedding_dim, dim) | |
self.proj_out = nn.Linear(dim, output_dim) | |
self.norm_out = nn.LayerNorm(output_dim) | |
self.layers = nn.ModuleList([ | |
nn.ModuleList([ | |
PerceiverAttention(dim=dim, dim_head=dim_head, heads=heads), | |
FeedForward(dim=dim, mult=ff_mult), | |
]) for _ in range(depth) | |
]) | |
def forward(self, x): | |
latents = self.latents.repeat(x.size(0), 1, 1) | |
x = self.proj_in(x) | |
for attn, ff in self.layers: | |
latents = attn(x, latents) + latents | |
latents = ff(latents) + latents | |
return self.norm_out(self.proj_out(latents)) |