Spaces:
Running on Zero
Running on Zero
Download diffusionGS/models/transformers/dit.py from CaiYuanhao/DiffusionGS-Object: direct link, hf CLI and curl.
- Browser
- Download file 21.6 kB
-
https://huggingface.co/spaces/CaiYuanhao/DiffusionGS-Object/resolve/main/diffusionGS/models/transformers/dit.py
- Command line
-
hf download hf://spaces/CaiYuanhao/DiffusionGS-Object/diffusionGS/models/transformers/dit.py
-
curl -L -o dit.py https://huggingface.co/spaces/CaiYuanhao/DiffusionGS-Object/resolve/main/diffusionGS/models/transformers/dit.py
21.6 kB
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from einops import rearrange | |
| try: | |
| import xformers.ops as xops | |
| except ImportError: | |
| xops = None | |
| from timm.models.vision_transformer import PatchEmbed, Attention, Mlp | |
| class RMSNorm(nn.Module): | |
| def __init__(self, dim: int, eps: float = 1e-5): | |
| super().__init__() | |
| self.eps = eps | |
| self.weight = nn.Parameter(torch.ones(dim)) | |
| def _norm(self, x): | |
| return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps) | |
| def forward(self, x): | |
| output = self._norm(x.float()).type_as(x) | |
| return output * self.weight.type_as(x) | |
| def modulate(x, shift, scale): | |
| return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1) | |
| # https://github.com/karpathy/nanoGPT/blob/eba36e84649f3c6d840a93092cb779a260544d08/model.py#L162-L168 | |
| def _init_weights(module): | |
| if isinstance(module, nn.Linear): | |
| torch.nn.init.normal_(module.weight, mean=0.0, std=0.02) | |
| if module.bias is not None: | |
| torch.nn.init.zeros_(module.bias) | |
| elif isinstance(module, nn.Embedding): | |
| torch.nn.init.normal_(module.weight, mean=0.0, std=0.02) | |
| class ImageTokenizer(nn.Module): | |
| """ | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L134-L214 | |
| """ | |
| def __init__( | |
| self, | |
| image_size, | |
| patch_size, | |
| d, | |
| in_channels=3, | |
| conv_bias=False, | |
| patch_token_dropout=0.0, | |
| ): | |
| super().__init__() | |
| assert ( | |
| image_size % patch_size == 0 | |
| ), f"Image size {image_size} must be divisible by the patch size {patch_size}." | |
| num_patches = (image_size // patch_size) * (image_size // patch_size) | |
| self.image_size = image_size | |
| self.patch_size = patch_size | |
| self.num_patches = num_patches | |
| self.conv = nn.Conv2d( | |
| in_channels, d, kernel_size=patch_size, stride=patch_size, bias=conv_bias | |
| ) | |
| self.pos_embed = nn.Parameter(torch.zeros(1, self.num_patches, d)) | |
| nn.init.trunc_normal_(self.pos_embed, std=0.02) | |
| self.patch_token_dropout = nn.Dropout(p=patch_token_dropout) | |
| def forward(self, x): | |
| # (b, c, h, w) --> (b, l, d) | |
| # x in [-1, 1] | |
| x = self.conv(x).flatten(2).transpose(1, 2) | |
| x = self.patch_token_dropout(x + self.pos_embed) | |
| return x | |
| class MLP(nn.Module): | |
| """ | |
| MLP layer | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L49-L65 | |
| Ignore: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L62 | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| mlp_ratio=4, | |
| mlp_bias=False, | |
| mlp_dropout=0.0, | |
| mlp_dim=None, | |
| ): | |
| super().__init__() | |
| if mlp_dim is None: | |
| mlp_dim = d * mlp_ratio | |
| self.mlp = nn.Sequential( | |
| nn.Linear(d, mlp_dim, bias=mlp_bias), | |
| nn.GELU(), | |
| nn.Linear(mlp_dim, d, bias=mlp_bias), | |
| nn.Dropout(mlp_dropout), | |
| ) | |
| def forward(self, x): | |
| x = self.mlp(x) | |
| return x | |
| class SelfAttention(nn.Module): | |
| """ | |
| Self-attention layer | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L68-L92 | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| d_head, | |
| attn_qkv_bias=False, | |
| attn_dropout=0.0, | |
| attn_fc_bias=False, | |
| attn_fc_dropout=0.0, | |
| use_flashatt_v2=True, | |
| ): | |
| super().__init__() | |
| assert ( | |
| d % d_head == 0 | |
| ), f"Token dimension {d} should be divisible by head dimension {d_head}" | |
| self.d = d | |
| self.d_head = d_head | |
| self.attn_dropout = attn_dropout | |
| self.to_qkv = nn.Linear(d, 3 * d, bias=attn_qkv_bias) | |
| self.fc = nn.Linear(d, d, bias=attn_fc_bias) | |
| self.attn_fc_dropout = nn.Dropout(attn_fc_dropout) | |
| self.use_flashatt_v2 = use_flashatt_v2 and xops is not None | |
| def forward(self, x, subset_attention_size=None): | |
| """ | |
| x: (b, l, d) | |
| """ | |
| # token split, multi-head attention, token cat | |
| q, k, v = self.to_qkv(x).split(self.d, dim=2) | |
| if self.use_flashatt_v2: | |
| # Use the flash attention support from the xformers library | |
| # The memory_efficient_attention takes the input as (batch, seq_len, heads, dim) | |
| q, k, v = map( | |
| lambda t: rearrange(t, "b l (nh dh) -> b l nh dh", dh=self.d_head), | |
| (q, k, v), | |
| ) | |
| if subset_attention_size is not None and subset_attention_size < q.shape[1]: | |
| x_subset = xops.memory_efficient_attention( | |
| q[:, :subset_attention_size, :, :].contiguous(), | |
| k[:, :subset_attention_size, :, :].contiguous(), | |
| v[:, :subset_attention_size, :, :].contiguous(), | |
| attn_bias=None, | |
| op=(xops.fmha.flash.FwOp, xops.fmha.flash.BwOp), | |
| ) | |
| x_rest = xops.memory_efficient_attention( | |
| q[:, subset_attention_size:, :, :].contiguous(), | |
| k, | |
| v, | |
| attn_bias=None, | |
| op=(xops.fmha.flash.FwOp, xops.fmha.flash.BwOp), | |
| ) | |
| # print(x_subset.shape, x_rest.shape) | |
| x = torch.cat([x_subset, x_rest], dim=1) | |
| else: | |
| # The memory_efficient_attention takes the input as (batch, seq_len, heads, dim) | |
| x = xops.memory_efficient_attention( | |
| q, | |
| k, | |
| v, | |
| attn_bias=None, | |
| op=(xops.fmha.flash.FwOp, xops.fmha.flash.BwOp), | |
| ) | |
| x = rearrange(x, "b l nh dh -> b l (nh dh)") | |
| else: | |
| # Use the flash attention support from the pytorch library | |
| q, k, v = ( | |
| rearrange(q, "b l (nh dh) -> b nh l dh", dh=self.d_head), | |
| rearrange(k, "b l (nh dh) -> b nh l dh", dh=self.d_head), | |
| rearrange(v, "b l (nh dh) -> b nh l dh", dh=self.d_head), | |
| ) | |
| # https://discuss.pytorch.org/t/flash-attention/174955/14 | |
| dropout_p = self.attn_dropout if self.training else 0.0 | |
| if subset_attention_size is not None and subset_attention_size < q.shape[2]: | |
| x = F.scaled_dot_product_attention( | |
| q[:, :, :subset_attention_size, :].contiguous(), | |
| k[:, :, :subset_attention_size, :].contiguous(), | |
| v[:, :, :subset_attention_size, :].contiguous(), | |
| dropout_p=dropout_p, | |
| ) | |
| x_rest = F.scaled_dot_product_attention( | |
| q[:, :, subset_attention_size:, :].contiguous(), | |
| k, | |
| v, | |
| dropout_p=dropout_p, | |
| ) | |
| x = torch.cat([x, x_rest], dim=2) | |
| else: | |
| x = F.scaled_dot_product_attention(q, k, v, dropout_p=dropout_p) | |
| x = rearrange(x, "b nh l dh -> b l (nh dh)") | |
| x = self.attn_fc_dropout(self.fc(x)) | |
| return x | |
| class TransformerBlock(nn.Module): | |
| """ | |
| Transformer block | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L95-L113 | |
| Note: move drop_path to SelfAttention and MLP | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| d_head, | |
| ln_bias=False, | |
| attn_qkv_bias=False, | |
| attn_dropout=0.0, | |
| attn_fc_bias=False, | |
| attn_fc_dropout=0.0, | |
| mlp_ratio=4, | |
| mlp_bias=False, | |
| mlp_dropout=0.0, | |
| ): | |
| super().__init__() | |
| self.norm1 = nn.LayerNorm(d, bias=ln_bias) | |
| self.attn = SelfAttention( | |
| d, d_head, attn_qkv_bias, attn_dropout, attn_fc_bias, attn_fc_dropout | |
| ) | |
| self.norm2 = nn.LayerNorm(d, bias=ln_bias) | |
| self.mlp = MLP(d, mlp_ratio, mlp_bias, mlp_dropout) | |
| def forward(self, x, subset_attention_size=None): | |
| x = x + self.attn(self.norm1(x), subset_attention_size=subset_attention_size) | |
| x = x + self.mlp(self.norm2(x)) | |
| return x | |
| class DiTBlock(nn.Module): | |
| """ | |
| A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning. | |
| """ | |
| def __init__(self, hidden_size, num_heads, mlp_ratio=4.0, **block_kwargs): | |
| super().__init__() | |
| self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6) | |
| self.attn = Attention( | |
| hidden_size, num_heads=num_heads, qkv_bias=True, **block_kwargs | |
| ) | |
| self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6) | |
| mlp_hidden_dim = int(hidden_size * mlp_ratio) | |
| approx_gelu = lambda: nn.GELU(approximate="tanh") | |
| self.mlp = Mlp( | |
| in_features=hidden_size, | |
| hidden_features=mlp_hidden_dim, | |
| act_layer=approx_gelu, | |
| drop=0, | |
| ) | |
| self.adaLN_modulation = nn.Sequential( | |
| nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size, bias=True) | |
| ) | |
| def forward(self, x, c): | |
| ''' | |
| x 是 latent feature, 已经经过了 patch embedding | |
| c 是 conditioning, 主要有两部分 - timestep embedding 和 label embedding | |
| 此处就只有一个 timestep embedding | |
| ''' | |
| # 这算作 conditioning 的 MLP | |
| shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = ( | |
| self.adaLN_modulation(c).chunk(6, dim=1) | |
| ) # 将 c 通过 adaLN_modulation 网络, 分成 6 个部分 | |
| # 第一个模块 - MSA | |
| x = x + gate_msa.unsqueeze(1) * self.attn( | |
| modulate(self.norm1(x), shift_msa, scale_msa) | |
| ) | |
| # 第二个模块 - Pointwise Feedforward | |
| x = x + gate_mlp.unsqueeze(1) * self.mlp( | |
| modulate(self.norm2(x), shift_mlp, scale_mlp) | |
| ) | |
| return x | |
| class CrossAttention(nn.Module): | |
| """ | |
| Self-attention layer | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L68-L92 | |
| """ | |
| def __init__( | |
| self, | |
| input_dim, | |
| d_head=64, | |
| attn_qkv_bias=False, | |
| attn_dropout=0.0, | |
| attn_fc_bias=False, | |
| attn_fc_dropout=0.0, | |
| use_flashatt_v2=True, | |
| num_heads=None, | |
| ctx_dim=None, | |
| causal=False, | |
| ): | |
| super().__init__() | |
| self.input_dim = input_dim | |
| self.d_head = d_head | |
| self.num_heads = num_heads if num_heads is not None else input_dim // d_head | |
| self.ctx_dim = ctx_dim if ctx_dim is not None else input_dim | |
| self.att_dim = self.num_heads * self.d_head | |
| self.to_q = nn.Linear(self.input_dim, self.att_dim, bias=attn_qkv_bias) | |
| self.to_k = nn.Linear(self.ctx_dim, self.att_dim, bias=attn_qkv_bias) | |
| self.to_v = nn.Linear(self.ctx_dim, self.att_dim, bias=attn_qkv_bias) | |
| self.fc = nn.Linear(self.att_dim, self.input_dim, bias=attn_fc_bias) | |
| self.attn_fc_dropout = nn.Dropout(attn_fc_dropout) | |
| self.attn_dropout = attn_dropout | |
| assert self.attn_dropout == 0.0 | |
| self.use_flashatt_v2 = use_flashatt_v2 and xops is not None | |
| self.causal = causal | |
| def forward(self, x, y=None): | |
| """ | |
| x: (b, l, d) | |
| y: (b, l', d) | |
| x cross-att y | |
| """ | |
| if y is None: | |
| y = x | |
| q = self.to_q(x) | |
| k = self.to_k(y) | |
| v = self.to_v(y) | |
| if self.use_flashatt_v2: | |
| q, k, v = map( | |
| lambda t: rearrange(t, "b n (h d) -> b n h d", h=self.num_heads), | |
| (q, k, v), | |
| ) | |
| # Use the flash attention support from the xformers library | |
| if self.causal: | |
| attention_bias = xops.LowerTriangularMask() | |
| else: | |
| attention_bias = None | |
| # The memory_efficient_attention takes the input as (batch, seq_len, heads, dim) | |
| x = xops.memory_efficient_attention( | |
| q, | |
| k, | |
| v, | |
| attn_bias=attention_bias, | |
| op=(xops.fmha.flash.FwOp, xops.fmha.flash.BwOp), | |
| ) | |
| x = rearrange(x, "b n h d -> b n (h d)") | |
| else: | |
| q, k, v = map( | |
| lambda t: rearrange(t, "b n (h d) -> b h n d", h=self.num_heads), | |
| (q, k, v), | |
| ) | |
| # https://discuss.pytorch.org/t/flash-attention/174955/14 | |
| dropout_p = self.attn_dropout if self.training else 0.0 | |
| x = F.scaled_dot_product_attention(q, k, v, dropout_p=dropout_p) | |
| x = rearrange(x, "b nh l dh -> b l (nh dh)") | |
| x = self.attn_fc_dropout(self.fc(x)) | |
| return x | |
| def extra_repr(self) -> str: | |
| return ( | |
| f"use_flashatt_v2={self.use_flashatt_v2}, " | |
| f"num_heads={self.num_heads}, " | |
| f"input_dim={self.input_dim}, " | |
| f"ctx_dim={self.ctx_dim}, " | |
| f"att_dim={self.att_dim}, " | |
| ) | |
| class CrossTransformerBlock(nn.Module): | |
| """ | |
| Cross-att Transformer block | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L95-L113 | |
| Note: move drop_path to SelfAttention and MLP | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| d_head, | |
| ln_bias=False, | |
| attn_qkv_bias=False, | |
| attn_dropout=0.0, | |
| attn_fc_bias=False, | |
| attn_fc_dropout=0.0, | |
| mlp_ratio=4, | |
| mlp_bias=False, | |
| mlp_dropout=0.0, | |
| ): | |
| super().__init__() | |
| self.norm1 = nn.LayerNorm(d, bias=ln_bias) | |
| self.attn = CrossAttention( | |
| d, d_head, attn_qkv_bias, attn_dropout, attn_fc_bias, attn_fc_dropout | |
| ) | |
| self.norm2 = nn.LayerNorm(d, bias=ln_bias) | |
| self.mlp = MLP(d, mlp_ratio, mlp_bias, mlp_dropout) | |
| def forward(self, x, y): | |
| x = x + self.attn(self.norm1(x), self.norm1(y)) | |
| x = x + self.mlp(self.norm2(x)) | |
| return x | |
| class FixedLengthTransformerLayer(nn.Module): | |
| """ """ | |
| def __init__( | |
| self, | |
| dim, | |
| context_dim=None, | |
| fixed_length=None, | |
| num_heads=8, | |
| head_dim=64, | |
| use_ln_context=True, | |
| mlp_dim=None, | |
| ): | |
| """ | |
| :param dim: The input dim of x | |
| :param context_dim: The input dim of context | |
| :param fixed_length: The length of attention tokens | |
| :param num_heads: The number of attention heads | |
| :param head_dim: The dim of each attention head | |
| """ | |
| super().__init__() | |
| self.has_cross_att = context_dim is not None | |
| self.dim = dim | |
| self.fixed_length = fixed_length | |
| self.ln_self = nn.LayerNorm(dim) | |
| self.self_attn = CrossAttention( | |
| input_dim=dim, | |
| d_head=head_dim, | |
| num_heads=num_heads, | |
| ) | |
| if self.has_cross_att: | |
| self.ln_cross = nn.LayerNorm(dim) | |
| if use_ln_context: | |
| self.ln_context = nn.LayerNorm(context_dim) | |
| else: | |
| self.ln_context = nn.Identity() | |
| self.cross_attn = CrossAttention( | |
| input_dim=dim, | |
| ctx_dim=context_dim, | |
| d_head=head_dim, | |
| num_heads=num_heads, | |
| ) | |
| self.ln_fc = nn.LayerNorm(dim) | |
| self.fc = MLP( | |
| d=dim, | |
| mlp_dim=mlp_dim, | |
| ) | |
| def init_weight(self, total_layers): | |
| # Find all the linear layers that will contribute to the residual. | |
| linear_layer_list = [ | |
| self.self_attn.fc, | |
| self.fc.mlp[2], | |
| ] | |
| if self.has_cross_att: | |
| linear_layer_list.append(self.cross_attn.fc) | |
| # divided the output by the total number of layers | |
| for linear_layer in linear_layer_list: | |
| linear_layer.weight.data /= total_layers | |
| if linear_layer.bias is not None: | |
| linear_layer.bias.data = 0.0 | |
| def forward(self, x, context=None): | |
| """ | |
| :param x: b, h_windows, w_windows, window_size, window_size, c; | |
| can be in arbitrary shape but the layout is the same. | |
| :param context: b, context_length, context_dim | |
| :return: | |
| """ | |
| batch_size, orig_length, orig_dim = x.shape | |
| context = context or x | |
| assert orig_dim % self.dim == 0, f"orig_dim: {orig_dim}, dim: {self.dim}" | |
| if self.fixed_length is not None: | |
| assert (orig_length * orig_dim) % (self.fixed_length * self.dim) == 0, ( | |
| f"orig_length: {orig_length}, token_length: {self.fixed_length}" | |
| f"orig_dim: {orig_dim}, dim: {self.dim}." | |
| f"The product of orig_length * orig_dim must be divisible by token_length * dim." | |
| f"O.w., it will break the batches" | |
| ) | |
| # Fixed-length self attention [-1, highres_tokens, highres_dim], e.g., [-1, 8192, 16] | |
| x = x.reshape(-1, self.fixed_length or orig_length, self.dim) | |
| x = x + self.self_attn(self.ln_self(x)) | |
| # Cross attention [batch_size, -1, highres_dim], e.g., [8, -1, 16] | |
| if self.has_cross_att: | |
| x = x.reshape(batch_size, -1, self.dim) | |
| x = x + self.cross_attn(self.ln_cross(x), self.ln_context(context)) | |
| # MLP layers [?, ?, highres_dim], e.g., [?, ?, 16] | |
| x = x + self.fc(self.ln_fc(x)) | |
| # Reshape back to [batch_size, lowres_tokens, lowres_dim], e.g., [8, 1024, 1024] | |
| x = x.reshape(batch_size, orig_length, orig_dim) | |
| return x | |
| def extra_repr(self) -> str: | |
| return f"token_length={self.fixed_length}, dim={self.dim}" | |
| class QK_Norm_SelfAttention(nn.Module): | |
| """ | |
| Self-attention layer | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L68-L92 | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| d_head, | |
| attn_qkv_bias=False, | |
| attn_fc_bias=True, | |
| attn_dropout=0.0, | |
| attn_fc_dropout=0.0, | |
| use_qk_norm=True, | |
| ): | |
| super().__init__() | |
| assert d % d_head == 0, f"Token dimension {d} should be divisible by head dimension {d_head}" | |
| self.d = d | |
| self.d_head = d_head | |
| self.attn_dropout = attn_dropout | |
| self.to_qkv = nn.Linear(d, 3 * d, bias=attn_qkv_bias) | |
| self.fc = nn.Linear(d, d, bias=attn_fc_bias) | |
| self.attn_fc_dropout = nn.Dropout(attn_fc_dropout) | |
| self.use_qk_norm = use_qk_norm | |
| if self.use_qk_norm: | |
| self.q_norm = RMSNorm(d_head) | |
| self.k_norm = RMSNorm(d_head) | |
| def forward(self, x, attn_bias=None): | |
| """ | |
| x: (b, l, d) | |
| attn_bias: xformers BlockDiagonalMask | |
| """ | |
| # token split, multi-head attention, token cat | |
| q, k, v = self.to_qkv(x).split(self.d, dim=2) | |
| # Use the flash attention support from the xformers library | |
| # The memory_efficient_attention takes the input as (batch, seq_len, heads, dim) | |
| q, k, v = (rearrange(t, "b l (nh dh) -> b l nh dh", dh=self.d_head) for t in (q, k, v)) | |
| if self.use_qk_norm: | |
| q = self.q_norm(q) | |
| k = self.k_norm(k) | |
| # The memory_efficient_attention takes the input as (batch, seq_len, heads, dim) | |
| x = xops.memory_efficient_attention( | |
| q, | |
| k, | |
| v, | |
| attn_bias=attn_bias, | |
| p=self.attn_dropout if self.training else 0.0, | |
| op=(xops.fmha.flash.FwOp, xops.fmha.flash.BwOp), | |
| ) | |
| x = rearrange(x, "b l nh dh -> b l (nh dh)") | |
| x = self.attn_fc_dropout(self.fc(x)) | |
| return x | |
| # 修改,加入 timestep condition 来加以控制 | |
| class DiTBlock_QK_Norm(nn.Module): | |
| """ | |
| Transformer block | |
| Reference: https://github.com/facebookresearch/dino/blob/7c446df5b9f45747937fb0d72314eb9f7b66930a/vision_transformer.py#L95-L113 | |
| Note: move drop_path to SelfAttention and MLP | |
| """ | |
| def __init__( | |
| self, | |
| d, | |
| d_head, | |
| ln_bias=True, | |
| attn_qkv_bias=False, | |
| attn_dropout=0.0, | |
| attn_fc_bias=True, | |
| attn_fc_dropout=0.0, | |
| mlp_ratio=4, | |
| mlp_bias=True, | |
| mlp_dropout=0.0, | |
| use_qk_norm=True, | |
| ): | |
| super().__init__() | |
| self.norm1 = nn.LayerNorm(d, bias=ln_bias) | |
| self.attn = QK_Norm_SelfAttention( | |
| d, d_head, attn_qkv_bias, attn_fc_bias, attn_dropout, attn_fc_dropout, use_qk_norm, | |
| ) | |
| self.norm2 = nn.LayerNorm(d, bias=ln_bias) | |
| self.mlp = MLP(d, mlp_ratio, mlp_bias, mlp_dropout) | |
| self.adaLN_modulation = nn.Sequential( | |
| nn.SiLU(), nn.Linear(d, 6 * d, bias=True) | |
| ) | |
| def forward(self, x, c): | |
| shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = ( | |
| self.adaLN_modulation(c).chunk(6, dim=1) | |
| ) # 将 c 通过 adaLN_modulation 网络, 分成 6 个部分 | |
| x = x + gate_msa.unsqueeze(1) * self.attn( | |
| modulate(self.norm1(x), shift_msa, scale_msa) | |
| ) | |
| # 第二个模块 - Pointwise Feedforward | |
| x = x + gate_mlp.unsqueeze(1) * self.mlp( | |
| modulate(self.norm2(x), shift_mlp, scale_mlp) | |
| ) | |
| return x | |