attention.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. from inspect import isfunction
  2. import math
  3. import torch
  4. import torch.nn.functional as F
  5. from torch import nn, einsum
  6. from einops import rearrange, repeat
  7. from ldm.modules.diffusionmodules.util import checkpoint
  8. def exists(val):
  9. return val is not None
  10. def uniq(arr):
  11. return{el: True for el in arr}.keys()
  12. def default(val, d):
  13. if exists(val):
  14. return val
  15. return d() if isfunction(d) else d
  16. def max_neg_value(t):
  17. return -torch.finfo(t.dtype).max
  18. def init_(tensor):
  19. dim = tensor.shape[-1]
  20. std = 1 / math.sqrt(dim)
  21. tensor.uniform_(-std, std)
  22. return tensor
  23. # feedforward
  24. class GEGLU(nn.Module):
  25. def __init__(self, dim_in, dim_out):
  26. super().__init__()
  27. self.proj = nn.Linear(dim_in, dim_out * 2)
  28. def forward(self, x):
  29. x, gate = self.proj(x).chunk(2, dim=-1)
  30. return x * F.gelu(gate)
  31. class FeedForward(nn.Module):
  32. def __init__(self, dim, dim_out=None, mult=4, glu=False, dropout=0.):
  33. super().__init__()
  34. inner_dim = int(dim * mult)
  35. dim_out = default(dim_out, dim)
  36. project_in = nn.Sequential(
  37. nn.Linear(dim, inner_dim),
  38. nn.GELU()
  39. ) if not glu else GEGLU(dim, inner_dim)
  40. self.net = nn.Sequential(
  41. project_in,
  42. nn.Dropout(dropout),
  43. nn.Linear(inner_dim, dim_out)
  44. )
  45. def forward(self, x):
  46. return self.net(x)
  47. def zero_module(module):
  48. """
  49. Zero out the parameters of a module and return it.
  50. """
  51. for p in module.parameters():
  52. p.detach().zero_()
  53. return module
  54. def Normalize(in_channels):
  55. return torch.nn.GroupNorm(num_groups=32, num_channels=in_channels, eps=1e-6, affine=True)
  56. class LinearAttention(nn.Module):
  57. def __init__(self, dim, heads=4, dim_head=32):
  58. super().__init__()
  59. self.heads = heads
  60. hidden_dim = dim_head * heads
  61. self.to_qkv = nn.Conv2d(dim, hidden_dim * 3, 1, bias = False)
  62. self.to_out = nn.Conv2d(hidden_dim, dim, 1)
  63. def forward(self, x):
  64. b, c, h, w = x.shape
  65. qkv = self.to_qkv(x)
  66. q, k, v = rearrange(qkv, 'b (qkv heads c) h w -> qkv b heads c (h w)', heads = self.heads, qkv=3)
  67. k = k.softmax(dim=-1)
  68. context = torch.einsum('bhdn,bhen->bhde', k, v)
  69. out = torch.einsum('bhde,bhdn->bhen', context, q)
  70. out = rearrange(out, 'b heads c (h w) -> b (heads c) h w', heads=self.heads, h=h, w=w)
  71. return self.to_out(out)
  72. class SpatialSelfAttention(nn.Module):
  73. def __init__(self, in_channels):
  74. super().__init__()
  75. self.in_channels = in_channels
  76. self.norm = Normalize(in_channels)
  77. self.q = torch.nn.Conv2d(in_channels,
  78. in_channels,
  79. kernel_size=1,
  80. stride=1,
  81. padding=0)
  82. self.k = torch.nn.Conv2d(in_channels,
  83. in_channels,
  84. kernel_size=1,
  85. stride=1,
  86. padding=0)
  87. self.v = torch.nn.Conv2d(in_channels,
  88. in_channels,
  89. kernel_size=1,
  90. stride=1,
  91. padding=0)
  92. self.proj_out = torch.nn.Conv2d(in_channels,
  93. in_channels,
  94. kernel_size=1,
  95. stride=1,
  96. padding=0)
  97. def forward(self, x):
  98. h_ = x
  99. h_ = self.norm(h_)
  100. q = self.q(h_)
  101. k = self.k(h_)
  102. v = self.v(h_)
  103. # compute attention
  104. b,c,h,w = q.shape
  105. q = rearrange(q, 'b c h w -> b (h w) c')
  106. k = rearrange(k, 'b c h w -> b c (h w)')
  107. w_ = torch.einsum('bij,bjk->bik', q, k)
  108. w_ = w_ * (int(c)**(-0.5))
  109. w_ = torch.nn.functional.softmax(w_, dim=2)
  110. # attend to values
  111. v = rearrange(v, 'b c h w -> b c (h w)')
  112. w_ = rearrange(w_, 'b i j -> b j i')
  113. h_ = torch.einsum('bij,bjk->bik', v, w_)
  114. h_ = rearrange(h_, 'b c (h w) -> b c h w', h=h)
  115. h_ = self.proj_out(h_)
  116. return x+h_
  117. class CrossAttention(nn.Module):
  118. def __init__(self, query_dim, context_dim=None, heads=8, dim_head=64, dropout=0.):
  119. super().__init__()
  120. inner_dim = dim_head * heads
  121. context_dim = default(context_dim, query_dim)
  122. self.scale = dim_head ** -0.5
  123. self.heads = heads
  124. self.to_q = nn.Linear(query_dim, inner_dim, bias=False)
  125. self.to_k = nn.Linear(context_dim, inner_dim, bias=False)
  126. self.to_v = nn.Linear(context_dim, inner_dim, bias=False)
  127. self.to_out = nn.Sequential(
  128. nn.Linear(inner_dim, query_dim),
  129. nn.Dropout(dropout)
  130. )
  131. def forward(self, x, context=None, mask=None):
  132. h = self.heads
  133. q = self.to_q(x)
  134. context = default(context, x)
  135. k = self.to_k(context)
  136. v = self.to_v(context)
  137. q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> (b h) n d', h=h), (q, k, v))
  138. sim = einsum('b i d, b j d -> b i j', q, k) * self.scale
  139. if exists(mask):
  140. mask = rearrange(mask, 'b ... -> b (...)')
  141. max_neg_value = -torch.finfo(sim.dtype).max
  142. mask = repeat(mask, 'b j -> (b h) () j', h=h)
  143. sim.masked_fill_(~mask, max_neg_value)
  144. # attention, what we cannot get enough of
  145. attn = sim.softmax(dim=-1)
  146. out = einsum('b i j, b j d -> b i d', attn, v)
  147. out = rearrange(out, '(b h) n d -> b n (h d)', h=h)
  148. return self.to_out(out)
  149. class BasicTransformerBlock(nn.Module):
  150. def __init__(self, dim, n_heads, d_head, dropout=0., context_dim=None, gated_ff=True, checkpoint=True):
  151. super().__init__()
  152. self.attn1 = CrossAttention(query_dim=dim, heads=n_heads, dim_head=d_head, dropout=dropout) # is a self-attention
  153. self.ff = FeedForward(dim, dropout=dropout, glu=gated_ff)
  154. self.attn2 = CrossAttention(query_dim=dim, context_dim=context_dim,
  155. heads=n_heads, dim_head=d_head, dropout=dropout) # is self-attn if context is none
  156. self.norm1 = nn.LayerNorm(dim)
  157. self.norm2 = nn.LayerNorm(dim)
  158. self.norm3 = nn.LayerNorm(dim)
  159. self.checkpoint = checkpoint
  160. def forward(self, x, context=None):
  161. return checkpoint(self._forward, (x, context), self.parameters(), self.checkpoint)
  162. def _forward(self, x, context=None):
  163. x = self.attn1(self.norm1(x)) + x
  164. x = self.attn2(self.norm2(x), context=context) + x
  165. x = self.ff(self.norm3(x)) + x
  166. return x
  167. class SpatialTransformer(nn.Module):
  168. """
  169. Transformer block for image-like data.
  170. First, project the input (aka embedding)
  171. and reshape to b, t, d.
  172. Then apply standard transformer action.
  173. Finally, reshape to image
  174. """
  175. def __init__(self, in_channels, n_heads, d_head,
  176. depth=1, dropout=0., context_dim=None):
  177. super().__init__()
  178. self.in_channels = in_channels
  179. inner_dim = n_heads * d_head
  180. self.norm = Normalize(in_channels)
  181. self.proj_in = nn.Conv2d(in_channels,
  182. inner_dim,
  183. kernel_size=1,
  184. stride=1,
  185. padding=0)
  186. self.transformer_blocks = nn.ModuleList(
  187. [BasicTransformerBlock(inner_dim, n_heads, d_head, dropout=dropout, context_dim=context_dim)
  188. for d in range(depth)]
  189. )
  190. self.proj_out = zero_module(nn.Conv2d(inner_dim,
  191. in_channels,
  192. kernel_size=1,
  193. stride=1,
  194. padding=0))
  195. def forward(self, x, context=None):
  196. # note: if no context is given, cross-attention defaults to self-attention
  197. b, c, h, w = x.shape
  198. x_in = x
  199. x = self.norm(x)
  200. x = self.proj_in(x)
  201. x = rearrange(x, 'b c h w -> b (h w) c')
  202. for block in self.transformer_blocks:
  203. x = block(x, context=context)
  204. x = rearrange(x, 'b (h w) c -> b c h w', h=h, w=w)
  205. x = self.proj_out(x)
  206. return x + x_in