| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
| from timm.models.vision_transformer import DropPath |
| from torch.nn.utils import spectral_norm |
|
|
|
|
| class Attention(nn.Module): |
| def __init__( |
| self, |
| dim, |
| num_heads=8, |
| qkv_bias=False, |
| attn_drop=0.0, |
| proj_drop=0.0, |
| spectral=False, |
| ): |
| super().__init__() |
| assert dim % num_heads == 0, "dim should be divisible by num_heads" |
| self.num_heads = num_heads |
| head_dim = dim // num_heads |
| self.scale = head_dim**-0.5 |
| if spectral: |
| self.qkv = spectral_norm(nn.Linear(dim, dim * 3, bias=qkv_bias)) |
| self.proj = spectral_norm(nn.Linear(dim, dim)) |
| else: |
| self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) |
| self.proj = nn.Linear(dim, dim) |
|
|
| self.attn_drop = nn.Dropout(attn_drop) |
|
|
| self.proj_drop = nn.Dropout(proj_drop) |
|
|
| def forward(self, x): |
| B, N, C = x.shape |
| qkv = ( |
| self.qkv(x) |
| .reshape(B, N, 3, self.num_heads, C // self.num_heads) |
| .permute(2, 0, 3, 1, 4) |
| ) |
| q, k, v = qkv.unbind(0) |
|
|
| attn = (q @ k.transpose(-2, -1)) * self.scale |
| attn = attn.softmax(dim=-1) |
| attn = self.attn_drop(attn) |
|
|
| x = (attn @ v).transpose(1, 2).reshape(B, N, C) |
| x = self.proj(x) |
| x = self.proj_drop(x) |
| return x |
|
|
|
|
| class CrossAttention(nn.Module): |
| def __init__( |
| self, |
| que_dim, |
| key_dim, |
| num_heads=4, |
| qkv_bias=False, |
| qk_scale=None, |
| attn_drop=0.0, |
| proj_drop=0.0, |
| ): |
| super().__init__() |
| self.que_dim = que_dim |
| self.key_dim = key_dim |
| self.num_heads = num_heads |
| head_dim = que_dim // num_heads |
| |
| self.scale = qk_scale or head_dim**-0.5 |
| |
| self.q_transform = nn.Linear(que_dim, que_dim, bias=qkv_bias) |
| self.k_transform = nn.Linear(key_dim, que_dim, bias=qkv_bias) |
| self.v_transform = nn.Linear(key_dim, que_dim, bias=qkv_bias) |
| self.attn_drop = nn.Dropout(attn_drop) |
| self.proj = nn.Linear(que_dim, que_dim) |
| self.proj_drop = nn.Dropout(proj_drop) |
|
|
| self.noise_strength_1 = torch.nn.Parameter(torch.zeros([])) |
|
|
| def forward(self, x, embedding): |
| B, N, C = x.shape |
| B, E_N, E_C = embedding.shape |
|
|
| |
| q = self.q_transform(x) |
| k = self.k_transform(embedding) |
| v = self.v_transform(embedding) |
| |
| q = q.reshape(B, N, self.num_heads, self.que_dim // self.num_heads).permute( |
| 0, 2, 1, 3 |
| ) |
| k = k.reshape(B, E_N, self.num_heads, self.que_dim // self.num_heads).permute( |
| 0, 2, 1, 3 |
| ) |
| v = v.reshape(B, E_N, self.num_heads, self.que_dim // self.num_heads).permute( |
| 0, 2, 1, 3 |
| ) |
|
|
| attn = (q @ k.transpose(-2, -1)) * self.scale |
| attn = attn.softmax(dim=-1) |
| attn = self.attn_drop(attn) |
| assert attn.size(-1) == v.size( |
| -2 |
| ), f"attn.size: {attn.size()}, v.size:{v.size()}" |
| output = (attn @ v).transpose(1, 2).reshape(B, N, self.que_dim) |
| output = self.proj(output) |
| output = self.proj_drop(output) |
| return x + output |
|
|
|
|
| class LayerScale(nn.Module): |
| def __init__(self, dim, init_values=1e-5, inplace=False): |
| super().__init__() |
| self.inplace = inplace |
| self.gamma = nn.Parameter(init_values * torch.ones(dim)) |
|
|
| def forward(self, x): |
| return x.mul_(self.gamma) if self.inplace else x * self.gamma |
|
|
|
|
| class Mlp(nn.Module): |
| def __init__( |
| self, |
| in_features, |
| hidden_features=None, |
| out_features=None, |
| act_layer=nn.GELU, |
| drop=0.0, |
| spectral=False, |
| ): |
| super().__init__() |
| out_features = out_features or in_features |
| hidden_features = hidden_features or in_features |
| self.act = act_layer() |
| if spectral: |
| self.fc1 = spectral_norm(nn.Linear(in_features, hidden_features)) |
| self.fc2 = spectral_norm(nn.Linear(hidden_features, out_features)) |
| else: |
| self.fc1 = nn.Linear(in_features, hidden_features) |
| self.fc2 = nn.Linear(hidden_features, out_features) |
| self.drop = nn.Dropout(drop) |
|
|
| def forward(self, x): |
| x = self.fc1(x) |
| x = self.act(x) |
| x = self.drop(x) |
| x = self.fc2(x) |
| x = self.drop(x) |
| return x |
|
|
|
|
| class Block(nn.Module): |
|
|
| def __init__( |
| self, |
| dim, |
| num_heads, |
| mlp_ratio=4.0, |
| qkv_bias=False, |
| drop=0.0, |
| attn_drop=0.0, |
| init_values=None, |
| drop_path=0.0, |
| act_layer=nn.GELU, |
| norm_layer=nn.LayerNorm, |
| spectral=False, |
| ): |
| super().__init__() |
| self.norm1 = norm_layer(dim, elementwise_affine=True) |
|
|
| self.attn = Attention( |
| dim, |
| num_heads=num_heads, |
| qkv_bias=qkv_bias, |
| attn_drop=attn_drop, |
| proj_drop=drop, |
| spectral=spectral, |
| ) |
| self.ls1 = ( |
| LayerScale(dim, init_values=init_values) if init_values else nn.Identity() |
| ) |
| |
| self.drop_path1 = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() |
|
|
| self.norm2 = norm_layer(dim, elementwise_affine=True) |
| self.mlp = Mlp( |
| in_features=dim, |
| hidden_features=int(dim * mlp_ratio), |
| act_layer=act_layer, |
| drop=drop, |
| spectral=spectral, |
| ) |
| self.ls2 = ( |
| LayerScale(dim, init_values=init_values) if init_values else nn.Identity() |
| ) |
| self.drop_path2 = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() |
|
|
| def forward(self, x): |
| x = x + self.drop_path1(self.ls1(self.attn(self.norm1(x)))) |
| x = x + self.drop_path2(self.ls2(self.mlp(self.norm2(x)))) |
| return x |
|
|
|
|
| class CrossBlock(nn.Module): |
|
|
| def __init__( |
| self, |
| dim, |
| num_heads, |
| mlp_ratio=4.0, |
| qkv_bias=False, |
| drop=0.0, |
| attn_drop=0.0, |
| init_values=None, |
| drop_path=0.0, |
| act_layer=nn.GELU, |
| norm_layer=nn.LayerNorm, |
| ): |
| super().__init__() |
| self.norm1 = norm_layer(dim, elementwise_affine=True) |
| self.norm3 = norm_layer(dim, elementwise_affine=True) |
| self.norm2 = norm_layer(dim, elementwise_affine=True) |
| |
|
|
| self.mlp = Mlp( |
| in_features=dim, |
| hidden_features=int(dim * mlp_ratio), |
| act_layer=act_layer, |
| drop=drop, |
| ) |
| self.attn = Attention( |
| dim, |
| num_heads=num_heads, |
| qkv_bias=qkv_bias, |
| attn_drop=attn_drop, |
| proj_drop=drop, |
| ) |
| self.cross_attention = CrossAttention( |
| dim, |
| dim, |
| num_heads=num_heads, |
| qkv_bias=qkv_bias, |
| attn_drop=attn_drop, |
| proj_drop=drop, |
| ) |
| self.ls1 = ( |
| LayerScale(dim, init_values=init_values) if init_values else nn.Identity() |
| ) |
| self.ls2 = ( |
| LayerScale(dim, init_values=init_values) if init_values else nn.Identity() |
| ) |
| self.ls3 = ( |
| LayerScale(dim, init_values=init_values) if init_values else nn.Identity() |
| ) |
| self.drop_path1 = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() |
| self.drop_path2 = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() |
| self.drop_path3 = DropPath(drop_path) if drop_path > 0.0 else nn.Identity() |
|
|
| def forward(self, src, tgt): |
| src = src + self.drop_path1(self.ls1(self.attn(self.norm1(src)))) |
| src = self.norm2(src) |
| src = src + self.drop_path2(self.ls2(self.cross_attention(src, tgt))) |
| src = src + self.drop_path3(self.ls3(self.mlp(self.norm3(src)))) |
| return src |