diffusers-原始碼解析-十一-

绝不原创的飞龙發表於2024-10-22

diffusers 原始碼解析(十一)

.\diffusers\models\transformers\hunyuan_transformer_2d.py

# 版權所有 2024 HunyuanDiT 作者,Qixun Wang 和 HuggingFace 團隊。保留所有權利。
#
# 根據 Apache 許可證第 2.0 版("許可證")進行許可;
# 除非符合許可證,否則您不得使用此檔案。
# 您可以在以下網址獲取許可證副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非適用法律或書面同意,否則根據許可證分發的軟體均按 "原樣" 基礎提供,
# 不提供任何種類的保證或條件,無論是明示或暗示的。
# 有關許可證的具體條款和條件,請參閱許可證。
from typing import Dict, Optional, Union  # 匯入字典、可選和聯合型別定義

import torch  # 匯入 PyTorch 庫
from torch import nn  # 從 PyTorch 匯入神經網路模組

from ...configuration_utils import ConfigMixin, register_to_config  # 從配置工具匯入混合類和註冊功能
from ...utils import logging  # 從工具包匯入日誌記錄功能
from ...utils.torch_utils import maybe_allow_in_graph  # 匯入可能允許圖形內操作的功能
from ..attention import FeedForward  # 從注意力模組匯入前饋網路
from ..attention_processor import Attention, AttentionProcessor, FusedHunyuanAttnProcessor2_0, HunyuanAttnProcessor2_0  # 匯入注意力處理器
from ..embeddings import (  # 匯入嵌入模組
    HunyuanCombinedTimestepTextSizeStyleEmbedding,  # 組合時間步、文字、大小和樣式的嵌入
    PatchEmbed,  # 影像補丁嵌入
    PixArtAlphaTextProjection,  # 畫素藝術文字投影
)
from ..modeling_outputs import Transformer2DModelOutput  # 匯入 2D 變換器模型輸出型別
from ..modeling_utils import ModelMixin  # 匯入模型混合類
from ..normalization import AdaLayerNormContinuous, FP32LayerNorm  # 匯入自適應層歸一化和 FP32 層歸一化

logger = logging.get_logger(__name__)  # 建立當前模組的日誌記錄器,禁用 pylint 警告

class AdaLayerNormShift(nn.Module):  # 定義自適應層歸一化偏移類,繼承自 nn.Module
    r"""  # 類文件字串,描述類的功能
    Norm layer modified to incorporate timestep embeddings.  # 歸一化層,修改以包含時間步嵌入

    Parameters:  # 引數說明
        embedding_dim (`int`): The size of each embedding vector.  # 嵌入向量的大小
        num_embeddings (`int`): The size of the embeddings dictionary.  # 嵌入字典的大小
    """

    def __init__(self, embedding_dim: int, elementwise_affine=True, eps=1e-6):  # 初始化方法
        super().__init__()  # 呼叫父類初始化方法
        self.silu = nn.SiLU()  # 定義 SiLU 啟用函式
        self.linear = nn.Linear(embedding_dim, embedding_dim)  # 定義線性層,輸入輸出維度均為嵌入維度
        self.norm = FP32LayerNorm(embedding_dim, elementwise_affine=elementwise_affine, eps=eps)  # 定義層歸一化

    def forward(self, x: torch.Tensor, emb: torch.Tensor) -> torch.Tensor:  # 定義前向傳播方法
        shift = self.linear(self.silu(emb.to(torch.float32)).to(emb.dtype))  # 計算偏移量
        x = self.norm(x) + shift.unsqueeze(dim=1)  # 對輸入進行歸一化並加上偏移
        return x  # 返回處理後的張量


@maybe_allow_in_graph  # 裝飾器,可能允許在計算圖中使用
class HunyuanDiTBlock(nn.Module):  # 定義 Hunyuan-DiT 模型中的變換器塊類
    r"""  # 類文件字串,描述類的功能
    Transformer block used in Hunyuan-DiT model (https://github.com/Tencent/HunyuanDiT). Allow skip connection and  # Hunyuan-DiT 模型中的變換器塊,允許跳過連線和
    QKNorm  # QKNorm 功能
    # 引數說明部分,定義各引數的型別和作用
        Parameters:
            dim (`int`):  # 輸入和輸出的通道數
                The number of channels in the input and output.
            num_attention_heads (`int`):  # 多頭注意力機制中使用的頭數
                The number of heads to use for multi-head attention.
            cross_attention_dim (`int`, *optional*):  # 跨注意力的編碼器隱藏狀態向量的大小
                The size of the encoder_hidden_states vector for cross attention.
            dropout (`float`, *optional*, defaults to 0.0):  # 用於正則化的丟棄機率
                The dropout probability to use.
            activation_fn (`str`, *optional*, defaults to `"geglu"`):  # 前饋網路中使用的啟用函式
                Activation function to be used in feed-forward.
            norm_elementwise_affine (`bool`, *optional*, defaults to `True`):  # 是否使用可學習的元素逐個仿射引數進行歸一化
                Whether to use learnable elementwise affine parameters for normalization.
            norm_eps (`float`, *optional*, defaults to 1e-6):  # 加到歸一化層分母的小常數,以防止除以零
                A small constant added to the denominator in normalization layers to prevent division by zero.
            final_dropout (`bool`, *optional*, defaults to False):  # 在最後的前饋層後是否應用最終丟棄
                Whether to apply a final dropout after the last feed-forward layer.
            ff_inner_dim (`int`, *optional*):  # 前饋塊中隱藏層的大小,預設為 None
                The size of the hidden layer in the feed-forward block. Defaults to `None`.
            ff_bias (`bool`, *optional*, defaults to `True`):  # 前饋塊中是否使用偏置
                Whether to use bias in the feed-forward block.
            skip (`bool`, *optional*, defaults to `False`):  # 是否使用跳過連線,預設為下塊和中塊的 False
                Whether to use skip connection. Defaults to `False` for down-blocks and mid-blocks.
            qk_norm (`bool`, *optional*, defaults to `True`):  # 在 QK 計算中是否使用歸一化,預設為 True
                Whether to use normalization in QK calculation. Defaults to `True`.
        """
    
        # 建構函式的定義,初始化各引數
        def __init__(
            self,
            dim: int,  # 輸入和輸出的通道數
            num_attention_heads: int,  # 多頭注意力機制中使用的頭數
            cross_attention_dim: int = 1024,  # 預設的跨注意力維度
            dropout=0.0,  # 預設的丟棄機率
            activation_fn: str = "geglu",  # 預設的啟用函式
            norm_elementwise_affine: bool = True,  # 預設使用可學習的仿射引數
            norm_eps: float = 1e-6,  # 預設的歸一化小常數
            final_dropout: bool = False,  # 預設不應用最終丟棄
            ff_inner_dim: Optional[int] = None,  # 預設的前饋塊隱藏層大小
            ff_bias: bool = True,  # 預設使用偏置
            skip: bool = False,  # 預設不使用跳過連線
            qk_norm: bool = True,  # 預設在 QK 計算中使用歸一化
    ):
        # 呼叫父類建構函式
        super().__init__()

        # 定義三個塊,每個塊都有自己的歸一化層。
        # 注意:新版本釋出時,檢查 norm2 和 norm3
        # 1. 自注意力機制
        self.norm1 = AdaLayerNormShift(dim, elementwise_affine=norm_elementwise_affine, eps=norm_eps)

        # 建立自注意力機制的例項
        self.attn1 = Attention(
            query_dim=dim,  # 查詢向量的維度
            cross_attention_dim=None,  # 交叉注意力的維度,未使用
            dim_head=dim // num_attention_heads,  # 每個頭的維度
            heads=num_attention_heads,  # 注意力頭的數量
            qk_norm="layer_norm" if qk_norm else None,  # 查詢和鍵的歸一化方法
            eps=1e-6,  # 數值穩定性常數
            bias=True,  # 是否使用偏置
            processor=HunyuanAttnProcessor2_0(),  # 注意力處理器的例項
        )

        # 2. 交叉注意力機制
        self.norm2 = FP32LayerNorm(dim, norm_eps, norm_elementwise_affine)

        # 建立交叉注意力機制的例項
        self.attn2 = Attention(
            query_dim=dim,  # 查詢向量的維度
            cross_attention_dim=cross_attention_dim,  # 交叉注意力的維度
            dim_head=dim // num_attention_heads,  # 每個頭的維度
            heads=num_attention_heads,  # 注意力頭的數量
            qk_norm="layer_norm" if qk_norm else None,  # 查詢和鍵的歸一化方法
            eps=1e-6,  # 數值穩定性常數
            bias=True,  # 是否使用偏置
            processor=HunyuanAttnProcessor2_0(),  # 注意力處理器的例項
        )
        # 3. 前饋網路
        self.norm3 = FP32LayerNorm(dim, norm_eps, norm_elementwise_affine)

        # 建立前饋網路的例項
        self.ff = FeedForward(
            dim,  # 輸入維度
            dropout=dropout,  # dropout 比例
            activation_fn=activation_fn,  # 啟用函式
            final_dropout=final_dropout,  # 最終 dropout 比例
            inner_dim=ff_inner_dim,  # 內部維度,通常是 dim 的倍數
            bias=ff_bias,  # 是否使用偏置
        )

        # 4. 跳躍連線
        if skip:  # 如果啟用跳躍連線
            self.skip_norm = FP32LayerNorm(2 * dim, norm_eps, elementwise_affine=True)  # 建立歸一化層
            self.skip_linear = nn.Linear(2 * dim, dim)  # 建立線性層
        else:  # 如果不啟用跳躍連線
            self.skip_linear = None  # 設定為 None

        # 將塊大小預設為 None
        self._chunk_size = None  # 初始化塊大小
        self._chunk_dim = 0  # 初始化塊維度

    # 從 diffusers.models.attention.BasicTransformerBlock 複製的設定塊前饋方法
    def set_chunk_feed_forward(self, chunk_size: Optional[int], dim: int = 0):
        # 設定塊前饋
        self._chunk_size = chunk_size  # 設定塊大小
        self._chunk_dim = dim  # 設定塊維度

    def forward(
        self,
        hidden_states: torch.Tensor,  # 輸入的隱藏狀態
        encoder_hidden_states: Optional[torch.Tensor] = None,  # 編碼器的隱藏狀態
        temb: Optional[torch.Tensor] = None,  # 額外的嵌入
        image_rotary_emb=None,  # 影像旋轉嵌入
        skip=None,  # 跳躍連線標誌
    ) -> torch.Tensor:
        # 注意:以下程式碼塊中的計算總是在歸一化之後進行。
        # 0. 長跳躍連線
        # 如果 skip_linear 不為 None,執行跳躍連線
        if self.skip_linear is not None:
            # 將當前的隱藏狀態與跳躍連線的輸出在最後一維上拼接
            cat = torch.cat([hidden_states, skip], dim=-1)
            # 對拼接後的結果進行歸一化處理
            cat = self.skip_norm(cat)
            # 透過線性層處理歸一化後的結果,更新隱藏狀態
            hidden_states = self.skip_linear(cat)

        # 1. 自注意力
        # 對當前隱藏狀態進行歸一化,準備進行自注意力計算
        norm_hidden_states = self.norm1(hidden_states, temb)  ### checked: self.norm1 is correct
        # 計算自注意力的輸出
        attn_output = self.attn1(
            norm_hidden_states,
            image_rotary_emb=image_rotary_emb,
        )
        # 將自注意力的輸出加到隱藏狀態上,形成新的隱藏狀態
        hidden_states = hidden_states + attn_output

        # 2. 交叉注意力
        # 將交叉注意力的輸出加到當前的隱藏狀態上
        hidden_states = hidden_states + self.attn2(
            self.norm2(hidden_states),  # 先進行歸一化
            encoder_hidden_states=encoder_hidden_states,  # 使用編碼器的隱藏狀態
            image_rotary_emb=image_rotary_emb,  # 傳遞旋轉嵌入
        )

        # 前饋網路層 ### TODO: 在狀態字典中切換 norm2 和 norm3
        # 對當前的隱藏狀態進行歸一化處理,準備進入前饋網路
        mlp_inputs = self.norm3(hidden_states)
        # 透過前饋網路處理歸一化後的輸入,更新隱藏狀態
        hidden_states = hidden_states + self.ff(mlp_inputs)

        # 返回最終的隱藏狀態
        return hidden_states
# 定義 HunyuanDiT2DModel 類,繼承自 ModelMixin 和 ConfigMixin
class HunyuanDiT2DModel(ModelMixin, ConfigMixin):
    """
    HunYuanDiT: 基於 Transformer 的擴散模型。

    繼承 ModelMixin 和 ConfigMixin 以與 diffusers 的取樣器 StableDiffusionPipeline 相容。

    引數:
        num_attention_heads (`int`, *可選*, 預設為 16):
            多頭注意力的頭數。
        attention_head_dim (`int`, *可選*, 預設為 88):
            每個頭的通道數。
        in_channels (`int`, *可選*):
            輸入和輸出的通道數(如果輸入為 **連續**,需指定)。
        patch_size (`int`, *可選*):
            輸入的補丁大小。
        activation_fn (`str`, *可選*, 預設為 `"geglu"`):
            前饋網路中使用的啟用函式。
        sample_size (`int`, *可選*):
            潛在影像的寬度。訓練期間固定使用,以學習位置嵌入的數量。
        dropout (`float`, *可選*, 預設為 0.0):
            使用的 dropout 機率。
        cross_attention_dim (`int`, *可選*):
            clip 文字嵌入中的維度數量。
        hidden_size (`int`, *可選*):
            條件嵌入層中隱藏層的大小。
        num_layers (`int`, *可選*, 預設為 1):
            使用的 Transformer 塊的層數。
        mlp_ratio (`float`, *可選*, 預設為 4.0):
            隱藏層大小與輸入大小的比率。
        learn_sigma (`bool`, *可選*, 預設為 `True`):
             是否預測方差。
        cross_attention_dim_t5 (`int`, *可選*):
            t5 文字嵌入中的維度數量。
        pooled_projection_dim (`int`, *可選*):
            池化投影的大小。
        text_len (`int`, *可選*):
            clip 文字嵌入的長度。
        text_len_t5 (`int`, *可選*):
            T5 文字嵌入的長度。
        use_style_cond_and_image_meta_size (`bool`,  *可選*):
            是否使用風格條件和影像後設資料大小。版本 <=1.1 為 True,版本 >= 1.2 為 False
    """

    # 註冊到配置中
    @register_to_config
    def __init__(
        # 多頭注意力的頭數,預設為 16
        self,
        num_attention_heads: int = 16,
        # 每個頭的通道數,預設為 88
        attention_head_dim: int = 88,
        # 輸入和輸出的通道數,預設為 None
        in_channels: Optional[int] = None,
        # 輸入的補丁大小,預設為 None
        patch_size: Optional[int] = None,
        # 啟用函式,預設為 "gelu-approximate"
        activation_fn: str = "gelu-approximate",
        # 潛在影像的寬度,預設為 32
        sample_size=32,
        # 條件嵌入層中隱藏層的大小,預設為 1152
        hidden_size=1152,
        # 使用的 Transformer 塊的層數,預設為 28
        num_layers: int = 28,
        # 隱藏層大小與輸入大小的比率,預設為 4.0
        mlp_ratio: float = 4.0,
        # 是否預測方差,預設為 True
        learn_sigma: bool = True,
        # clip 文字嵌入中的維度數量,預設為 1024
        cross_attention_dim: int = 1024,
        # 正則化型別,預設為 "layer_norm"
        norm_type: str = "layer_norm",
        # t5 文字嵌入中的維度數量,預設為 2048
        cross_attention_dim_t5: int = 2048,
        # 池化投影的大小,預設為 1024
        pooled_projection_dim: int = 1024,
        # clip 文字嵌入的長度,預設為 77
        text_len: int = 77,
        # T5 文字嵌入的長度,預設為 256
        text_len_t5: int = 256,
        # 是否使用風格條件和影像後設資料大小,預設為 True
        use_style_cond_and_image_meta_size: bool = True,
    ):
        # 呼叫父類的初始化方法
        super().__init__()
        # 根據是否學習 sigma 決定輸出通道數
        self.out_channels = in_channels * 2 if learn_sigma else in_channels
        # 設定注意力頭的數量
        self.num_heads = num_attention_heads
        # 計算內部維度,等於注意力頭數量乘以每個頭的維度
        self.inner_dim = num_attention_heads * attention_head_dim

        # 初始化文字嵌入器,用於將輸入特徵投影到更高維空間
        self.text_embedder = PixArtAlphaTextProjection(
            # 輸入特徵維度
            in_features=cross_attention_dim_t5,
            # 隱藏層大小為輸入特徵的四倍
            hidden_size=cross_attention_dim_t5 * 4,
            # 輸出特徵維度
            out_features=cross_attention_dim,
            # 啟用函式設定為"siluf_fp32"
            act_fn="silu_fp32",
        )

        # 初始化文字嵌入的填充引數,使用隨機正態分佈初始化
        self.text_embedding_padding = nn.Parameter(
            torch.randn(text_len + text_len_t5, cross_attention_dim, dtype=torch.float32)
        )

        # 初始化位置嵌入,構建影像的補丁嵌入
        self.pos_embed = PatchEmbed(
            # 補丁的高度
            height=sample_size,
            # 補丁的寬度
            width=sample_size,
            # 輸入通道數
            in_channels=in_channels,
            # 嵌入維度
            embed_dim=hidden_size,
            # 補丁大小
            patch_size=patch_size,
            # 位置嵌入型別設定為 None
            pos_embed_type=None,
        )

        # 初始化時間和風格嵌入,結合時間步和文字大小
        self.time_extra_emb = HunyuanCombinedTimestepTextSizeStyleEmbedding(
            # 隱藏層大小
            hidden_size,
            # 池化投影維度
            pooled_projection_dim=pooled_projection_dim,
            # 輸入序列長度
            seq_len=text_len_t5,
            # 交叉注意力維度
            cross_attention_dim=cross_attention_dim_t5,
            # 是否使用風格條件和影像後設資料大小
            use_style_cond_and_image_meta_size=use_style_cond_and_image_meta_size,
        )

        # 初始化 HunyuanDiT 塊列表
        self.blocks = nn.ModuleList(
            [
                # 為每一層建立 HunyuanDiTBlock
                HunyuanDiTBlock(
                    # 內部維度
                    dim=self.inner_dim,
                    # 注意力頭數量
                    num_attention_heads=self.config.num_attention_heads,
                    # 啟用函式
                    activation_fn=activation_fn,
                    # 前饋網路內部維度
                    ff_inner_dim=int(self.inner_dim * mlp_ratio),
                    # 交叉注意力維度
                    cross_attention_dim=cross_attention_dim,
                    # 查詢-鍵歸一化開啟
                    qk_norm=True,  # 詳情見 http://arxiv.org/abs/2302.05442
                    # 如果當前層數大於層數的一半,則跳過
                    skip=layer > num_layers // 2,
                )
                # 遍歷層數
                for layer in range(num_layers)
            ]
        )

        # 初始化輸出的自適應層歸一化
        self.norm_out = AdaLayerNormContinuous(self.inner_dim, self.inner_dim, elementwise_affine=False, eps=1e-6)
        # 初始化輸出的線性層,將內部維度對映到輸出通道數
        self.proj_out = nn.Linear(self.inner_dim, patch_size * patch_size * self.out_channels, bias=True)

    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel 中複製的程式碼,用於融合 QKV 投影,更新為 FusedHunyuanAttnProcessor2_0
    def fuse_qkv_projections(self):
        """ 
        啟用融合的 QKV 投影。對於自注意力模組,所有投影矩陣(即查詢、鍵、值)都被融合。 
        對於交叉注意力模組,鍵和值投影矩陣被融合。

        <Tip warning={true}>
        
        該 API 是 🧪 實驗性的。

        </Tip>
        """
        # 初始化原始注意力處理器為 None
        self.original_attn_processors = None

        # 遍歷所有注意力處理器
        for _, attn_processor in self.attn_processors.items():
            # 檢查注意力處理器類名中是否包含 "Added"
            if "Added" in str(attn_processor.__class__.__name__):
                # 如果包含,則丟擲錯誤,表示不支援融合 QKV 投影
                raise ValueError("`fuse_qkv_projections()` is not supported for models having added KV projections.")

        # 儲存當前的注意力處理器以備後用
        self.original_attn_processors = self.attn_processors

        # 遍歷當前模組中的所有子模組
        for module in self.modules():
            # 檢查模組是否為 Attention 型別
            if isinstance(module, Attention):
                # 對於 Attention 模組,啟用投影融合
                module.fuse_projections(fuse=True)

        # 設定融合的注意力處理器
        self.set_attn_processor(FusedHunyuanAttnProcessor2_0())

    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.unfuse_qkv_projections 複製
    def unfuse_qkv_projections(self):
        """ 
        如果已啟用,則禁用融合的 QKV 投影。

        <Tip warning={true}>
        
        該 API 是 🧪 實驗性的。

        </Tip>

        """
        # 檢查是否有原始注意力處理器
        if self.original_attn_processors is not None:
            # 恢復為原始注意力處理器
            self.set_attn_processor(self.original_attn_processors)

    @property
    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.attn_processors 複製
    def attn_processors(self) -> Dict[str, AttentionProcessor]:
        r"""
        返回:
            `dict` 型別的注意力處理器:一個字典,包含模型中使用的所有注意力處理器,按權重名稱索引。
        """
        # 初始化處理器字典
        processors = {}

        # 定義遞迴新增處理器的函式
        def fn_recursive_add_processors(name: str, module: torch.nn.Module, processors: Dict[str, AttentionProcessor]):
            # 檢查模組是否具有 get_processor 方法
            if hasattr(module, "get_processor"):
                # 將處理器新增到字典中
                processors[f"{name}.processor"] = module.get_processor()

            # 遍歷子模組
            for sub_name, child in module.named_children():
                # 遞迴呼叫以新增子模組的處理器
                fn_recursive_add_processors(f"{name}.{sub_name}", child, processors)

            return processors

        # 遍歷當前模組的所有子模組
        for name, module in self.named_children():
            # 呼叫遞迴函式新增處理器
            fn_recursive_add_processors(name, module, processors)

        # 返回處理器字典
        return processors

    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.set_attn_processor 複製
    # 定義設定注意力處理器的方法,接收一個注意力處理器或處理器字典
        def set_attn_processor(self, processor: Union[AttentionProcessor, Dict[str, AttentionProcessor]]):
            r"""
            設定用於計算注意力的注意力處理器。
    
            引數:
                processor(`dict` of `AttentionProcessor` 或 `AttentionProcessor`):
                    已例項化的處理器類或將作為處理器設定的處理器類字典
                    用於**所有** `Attention` 層。
    
                    如果 `processor` 是字典,則鍵需要定義相應的交叉注意力處理器路徑。
                    當設定可訓練的注意力處理器時,這強烈建議。
    
            """
            # 計算當前注意力處理器的數量
            count = len(self.attn_processors.keys())
    
            # 檢查傳入的處理器是否為字典,並驗證其長度與注意力層數量是否一致
            if isinstance(processor, dict) and len(processor) != count:
                raise ValueError(
                    # 丟擲錯誤,提示處理器數量與注意力層數量不匹配
                    f"A dict of processors was passed, but the number of processors {len(processor)} does not match the"
                    f" number of attention layers: {count}. Please make sure to pass {count} processor classes."
                )
    
            # 定義遞迴設定注意力處理器的內部函式
            def fn_recursive_attn_processor(name: str, module: torch.nn.Module, processor):
                # 檢查模組是否具有設定處理器的方法
                if hasattr(module, "set_processor"):
                    # 如果處理器不是字典,直接設定處理器
                    if not isinstance(processor, dict):
                        module.set_processor(processor)
                    else:
                        # 從字典中取出處理器並設定
                        module.set_processor(processor.pop(f"{name}.processor"))
    
                # 遍歷模組的子模組,遞迴呼叫設定處理器的方法
                for sub_name, child in module.named_children():
                    fn_recursive_attn_processor(f"{name}.{sub_name}", child, processor)
    
            # 遍歷當前物件的所有子模組,呼叫遞迴設定處理器的方法
            for name, module in self.named_children():
                fn_recursive_attn_processor(name, module, processor)
    
        # 定義設定預設注意力處理器的方法
        def set_default_attn_processor(self):
            """
            禁用自定義注意力處理器,並設定預設的注意力實現。
            """
            # 呼叫設定注意力處理器的方法,使用預設的 HunyuanAttnProcessor2_0
            self.set_attn_processor(HunyuanAttnProcessor2_0())
    
        # 定義前向傳播的方法,接收多個輸入引數
        def forward(
            self,
            hidden_states,
            timestep,
            encoder_hidden_states=None,
            text_embedding_mask=None,
            encoder_hidden_states_t5=None,
            text_embedding_mask_t5=None,
            image_meta_size=None,
            style=None,
            image_rotary_emb=None,
            controlnet_block_samples=None,
            return_dict=True,
        # 從 diffusers.models.unets.unet_3d_condition.UNet3DConditionModel.enable_forward_chunking 複製的程式碼
    # 定義一個方法以啟用前饋層的分塊處理,引數為分塊大小和維度
    def enable_forward_chunking(self, chunk_size: Optional[int] = None, dim: int = 0) -> None:
            """
            設定注意力處理器使用 [前饋分塊處理](https://huggingface.co/blog/reformer#2-chunked-feed-forward-layers)。
    
            引數:
                chunk_size (`int`, *可選*):
                    前饋層的分塊大小。如果未指定,將對每個維度為 `dim` 的張量單獨執行前饋層。
                dim (`int`, *可選*, 預設為 `0`):
                    前饋計算應分塊的維度。選擇 dim=0(批處理)或 dim=1(序列長度)。
            """
            # 檢查維度是否為 0 或 1
            if dim not in [0, 1]:
                # 丟擲值錯誤,提示維度設定不當
                raise ValueError(f"Make sure to set `dim` to either 0 or 1, not {dim}")
    
            # 預設分塊大小為 1
            chunk_size = chunk_size or 1
    
            # 定義遞迴函式以設定前饋層的分塊處理
            def fn_recursive_feed_forward(module: torch.nn.Module, chunk_size: int, dim: int):
                # 如果模組具有設定分塊前饋的屬性,則進行設定
                if hasattr(module, "set_chunk_feed_forward"):
                    module.set_chunk_feed_forward(chunk_size=chunk_size, dim=dim)
    
                # 遍歷模組的所有子模組並遞迴呼叫
                for child in module.children():
                    fn_recursive_feed_forward(child, chunk_size, dim)
    
            # 遍歷當前物件的所有子模組並應用遞迴函式
            for module in self.children():
                fn_recursive_feed_forward(module, chunk_size, dim)
    
        # 從 diffusers.models.unets.unet_3d_condition.UNet3DConditionModel.disable_forward_chunking 複製
        def disable_forward_chunking(self):
            # 定義遞迴函式以禁用前饋層的分塊處理
            def fn_recursive_feed_forward(module: torch.nn.Module, chunk_size: int, dim: int):
                # 如果模組具有設定分塊前饋的屬性,則進行設定
                if hasattr(module, "set_chunk_feed_forward"):
                    module.set_chunk_feed_forward(chunk_size=chunk_size, dim=dim)
    
                # 遍歷模組的所有子模組並遞迴呼叫
                for child in module.children():
                    fn_recursive_feed_forward(child, chunk_size, dim)
    
            # 遍歷當前物件的所有子模組並應用遞迴函式,禁用分塊處理
            for module in self.children():
                fn_recursive_feed_forward(module, None, 0)

.\diffusers\models\transformers\latte_transformer_3d.py

# 版權宣告,表明該程式碼的版權屬於 Latte 團隊和 HuggingFace 團隊
# Copyright 2024 the Latte Team and The HuggingFace Team. All rights reserved.
#
# 根據 Apache 許可證 2.0 版("許可證")進行授權;
# 除非遵循該許可證,否則您不得使用此檔案。
# 您可以在以下網址獲取許可證的副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非法律要求或書面同意,否則根據許可證分發的軟體是按 "原樣" 基礎進行的,
# 不提供任何形式的擔保或條件,無論是明示的還是暗示的。
# 請參見許可證以瞭解有關特定語言的許可權和限制。
from typing import Optional  # 從 typing 模組匯入 Optional 型別,用於指示可選引數

import torch  # 匯入 PyTorch 庫
from torch import nn  # 從 PyTorch 匯入神經網路模組

# 從配置工具匯入 ConfigMixin 和註冊配置的功能
from ...configuration_utils import ConfigMixin, register_to_config
# 匯入與影像嵌入相關的類和函式
from ...models.embeddings import PixArtAlphaTextProjection, get_1d_sincos_pos_embed_from_grid
# 匯入基礎變換器塊的定義
from ..attention import BasicTransformerBlock
# 匯入影像塊嵌入的定義
from ..embeddings import PatchEmbed
# 匯入 Transformer 2D 模型輸出的定義
from ..modeling_outputs import Transformer2DModelOutput
# 匯入模型混合功能的定義
from ..modeling_utils import ModelMixin
# 匯入自適應層歸一化的定義
from ..normalization import AdaLayerNormSingle


# 定義一個 3D Transformer 模型類,繼承自 ModelMixin 和 ConfigMixin
class LatteTransformer3DModel(ModelMixin, ConfigMixin):
    # 設定支援梯度檢查點的標誌為 True
    _supports_gradient_checkpointing = True

    """
    一個用於影片類資料的 3D Transformer 模型,相關論文連結:
    https://arxiv.org/abs/2401.03048,官方程式碼地址:
    https://github.com/Vchitect/Latte
    """
    # 引數說明
    Parameters:
        # 使用的多頭注意力頭數,預設為16
        num_attention_heads (`int`, *optional*, defaults to 16): The number of heads to use for multi-head attention.
        # 每個頭的通道數,預設為88
        attention_head_dim (`int`, *optional*, defaults to 88): The number of channels in each head.
        # 輸入通道數
        in_channels (`int`, *optional*):
            The number of channels in the input.
        # 輸出通道數
        out_channels (`int`, *optional*):
            The number of channels in the output.
        # Transformer塊的層數,預設為1
        num_layers (`int`, *optional*, defaults to 1): The number of layers of Transformer blocks to use.
        # dropout機率,預設為0.0
        dropout (`float`, *optional*, defaults to 0.0): The dropout probability to use.
        # 用於cross attention的編碼器隱藏狀態維度
        cross_attention_dim (`int`, *optional*): The number of `encoder_hidden_states` dimensions to use.
        # 配置TransformerBlocks的注意力是否包含偏置引數
        attention_bias (`bool`, *optional*):
            Configure if the `TransformerBlocks` attention should contain a bias parameter.
        # 潛在影像的寬度(如果輸入為離散型別,需指定)
        sample_size (`int`, *optional*): 
            The width of the latent images (specify if the input is **discrete**).
            # 在訓練期間固定,用於學習位置嵌入數量。
        patch_size (`int`, *optional*): 
            # 在補丁嵌入層中使用的補丁大小。
            The size of the patches to use in the patch embedding layer.
        # 前饋中的啟用函式,預設為"geglu"
        activation_fn (`str`, *optional*, defaults to `"geglu"`): Activation function to use in feed-forward.
        # 訓練期間使用的擴散步驟數
        num_embeds_ada_norm ( `int`, *optional*):
            The number of diffusion steps used during training. Pass if at least one of the norm_layers is
            `AdaLayerNorm`. This is fixed during training since it is used to learn a number of embeddings that are
            added to the hidden states. During inference, you can denoise for up to but not more steps than
            `num_embeds_ada_norm`.
        # 使用的歸一化型別,選項為"layer_norm"或"ada_layer_norm"
        norm_type (`str`, *optional*, defaults to `"layer_norm"`):
            The type of normalization to use. Options are `"layer_norm"` or `"ada_layer_norm"`.
        # 是否在歸一化層中使用逐元素仿射,預設為True
        norm_elementwise_affine (`bool`, *optional*, defaults to `True`):
            Whether or not to use elementwise affine in normalization layers.
        # 歸一化層中使用的epsilon值,預設為1e-5
        norm_eps (`float`, *optional*, defaults to 1e-5): The epsilon value to use in normalization layers.
        # 標註嵌入的通道數
        caption_channels (`int`, *optional*):
            The number of channels in the caption embeddings.
        # 影片類資料中的幀數
        video_length (`int`, *optional*):
            The number of frames in the video-like data.
    """ 
    # 註冊配置的裝飾器
    @register_to_config
    # 初始化方法,用於設定模型的引數
        def __init__(
            # 注意力頭的數量,預設為16
            num_attention_heads: int = 16,
            # 每個注意力頭的維度,預設為88
            attention_head_dim: int = 88,
            # 輸入通道數,預設為None
            in_channels: Optional[int] = None,
            # 輸出通道數,預設為None
            out_channels: Optional[int] = None,
            # 網路層數,預設為1
            num_layers: int = 1,
            # dropout比率,預設為0.0
            dropout: float = 0.0,
            # 跨注意力的維度,預設為None
            cross_attention_dim: Optional[int] = None,
            # 是否使用注意力偏置,預設為False
            attention_bias: bool = False,
            # 樣本大小,預設為64
            sample_size: int = 64,
            # 每個patch的大小,預設為None
            patch_size: Optional[int] = None,
            # 啟用函式,預設為"geglu"
            activation_fn: str = "geglu",
            # 自適應歸一化的嵌入數量,預設為None
            num_embeds_ada_norm: Optional[int] = None,
            # 歸一化型別,預設為"layer_norm"
            norm_type: str = "layer_norm",
            # 歸一化是否進行逐元素仿射,預設為True
            norm_elementwise_affine: bool = True,
            # 歸一化的epsilon值,預設為1e-5
            norm_eps: float = 1e-5,
            # caption的通道數,預設為None
            caption_channels: int = None,
            # 影片長度,預設為16
            video_length: int = 16,
        # 設定梯度檢查點的函式,接收一個模組和一個布林值
        def _set_gradient_checkpointing(self, module, value=False):
            # 將梯度檢查點設定為給定的布林值
            self.gradient_checkpointing = value
    
        # 前向傳播方法,定義模型的前向計算
        def forward(
            # 輸入的隱藏狀態,型別為torch.Tensor
            hidden_states: torch.Tensor,
            # 可選的時間步長,型別為torch.LongTensor
            timestep: Optional[torch.LongTensor] = None,
            # 可選的編碼器隱藏狀態,型別為torch.Tensor
            encoder_hidden_states: Optional[torch.Tensor] = None,
            # 可選的編碼器注意力掩碼,型別為torch.Tensor
            encoder_attention_mask: Optional[torch.Tensor] = None,
            # 是否啟用時間注意力,預設為True
            enable_temporal_attentions: bool = True,
            # 是否返回字典形式的輸出,預設為True
            return_dict: bool = True,

.\diffusers\models\transformers\lumina_nextdit2d.py

# 版權宣告,表明此程式碼的版權歸 2024 Alpha-VLLM 作者及 HuggingFace 團隊所有
# 
# 根據 Apache 2.0 許可證("許可證")進行許可;
# 除非遵循許可證,否則您不得使用此檔案。
# 您可以在以下網址獲取許可證副本:
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# 除非適用法律或書面協議另有規定,軟體在許可證下分發是按"原樣"基礎,
# 不提供任何形式的明示或暗示的擔保或條件。
# 請參閱許可證以獲取有關許可權和
# 限制的具體資訊。

from typing import Any, Dict, Optional  # 匯入型別提示相關的模組

import torch  # 匯入 PyTorch 庫
import torch.nn as nn  # 匯入 PyTorch 的神經網路模組

# 從配置和工具模組匯入必要的類和函式
from ...configuration_utils import ConfigMixin, register_to_config
from ...utils import logging
from ..attention import LuminaFeedForward  # 匯入自定義的前饋網路
from ..attention_processor import Attention, LuminaAttnProcessor2_0  # 匯入注意力處理器
from ..embeddings import (
    LuminaCombinedTimestepCaptionEmbedding,  # 匯入組合時間步長的嵌入
    LuminaPatchEmbed,  # 匯入補丁嵌入
)
from ..modeling_outputs import Transformer2DModelOutput  # 匯入模型輸出類
from ..modeling_utils import ModelMixin  # 匯入模型混合類
from ..normalization import LuminaLayerNormContinuous, LuminaRMSNormZero, RMSNorm  # 匯入不同的歸一化方法

logger = logging.get_logger(__name__)  # 獲取當前模組的日誌記錄器,禁用 pylint 的名稱警告


class LuminaNextDiTBlock(nn.Module):  # 定義一個名為 LuminaNextDiTBlock 的類,繼承自 nn.Module
    """
    LuminaNextDiTBlock 用於 LuminaNextDiT2DModel。

    引數:
        dim (`int`): 輸入特徵的嵌入維度。
        num_attention_heads (`int`): 注意力頭的數量。
        num_kv_heads (`int`):
            鍵和值特徵中的注意力頭數量(如果使用 GQA),
            或設定為 None 以與查詢相同。
        multiple_of (`int`): 前饋網路層的倍數。
        ffn_dim_multiplier (`float`): 前饋網路層維度的乘數因子。
        norm_eps (`float`): 歸一化層的 epsilon 值。
        qk_norm (`bool`): 查詢和鍵的歸一化。
        cross_attention_dim (`int`): 輸入文字提示的跨注意力嵌入維度。
        norm_elementwise_affine (`bool`, *可選*, 預設為 True),
    """

    def __init__(  # 初始化方法
        self,
        dim: int,  # 輸入特徵的維度
        num_attention_heads: int,  # 注意力頭的數量
        num_kv_heads: int,  # 鍵和值特徵的頭數量
        multiple_of: int,  # 前饋網路層的倍數
        ffn_dim_multiplier: float,  # 前饋網路維度的乘數
        norm_eps: float,  # 歸一化的 epsilon 值
        qk_norm: bool,  # 是否對查詢和鍵進行歸一化
        cross_attention_dim: int,  # 跨注意力嵌入的維度
        norm_elementwise_affine: bool = True,  # 是否使用逐元素仿射歸一化,預設值為 True
    ) -> None:  # 定義方法的返回型別為 None,表示不返回任何值
        super().__init__()  # 呼叫父類的建構函式,初始化父類的屬性
        self.head_dim = dim // num_attention_heads  # 計算每個注意力頭的維度

        self.gate = nn.Parameter(torch.zeros([num_attention_heads]))  # 建立一個可學習的引數,初始化為零,大小為注意力頭的數量

        # Self-attention  # 定義自注意力機制
        self.attn1 = Attention(  # 建立第一個注意力層
            query_dim=dim,  # 查詢的維度
            cross_attention_dim=None,  # 交叉注意力的維度,此處為 None 表示不使用
            dim_head=dim // num_attention_heads,  # 每個頭的維度
            qk_norm="layer_norm_across_heads" if qk_norm else None,  # 如果 qk_norm 為真,使用跨頭層歸一化
            heads=num_attention_heads,  # 注意力頭的數量
            kv_heads=num_kv_heads,  # 鍵值對的頭數量
            eps=1e-5,  # 數值穩定性引數
            bias=False,  # 不使用偏置項
            out_bias=False,  # 輸出層不使用偏置項
            processor=LuminaAttnProcessor2_0(),  # 使用指定的注意力處理器
        )
        self.attn1.to_out = nn.Identity()  # 輸出層使用恆等對映

        # Cross-attention  # 定義交叉注意力機制
        self.attn2 = Attention(  # 建立第二個注意力層
            query_dim=dim,  # 查詢的維度
            cross_attention_dim=cross_attention_dim,  # 交叉注意力的維度
            dim_head=dim // num_attention_heads,  # 每個頭的維度
            qk_norm="layer_norm_across_heads" if qk_norm else None,  # 如果 qk_norm 為真,使用跨頭層歸一化
            heads=num_attention_heads,  # 注意力頭的數量
            kv_heads=num_kv_heads,  # 鍵值對的頭數量
            eps=1e-5,  # 數值穩定性引數
            bias=False,  # 不使用偏置項
            out_bias=False,  # 輸出層不使用偏置項
            processor=LuminaAttnProcessor2_0(),  # 使用指定的注意力處理器
        )

        self.feed_forward = LuminaFeedForward(  # 建立前饋神經網路層
            dim=dim,  # 輸入維度
            inner_dim=4 * dim,  # 內部維度,通常為輸入維度的四倍
            multiple_of=multiple_of,  # 確保內部維度是某個數字的倍數
            ffn_dim_multiplier=ffn_dim_multiplier,  # 前饋網路維度的乘數
        )

        self.norm1 = LuminaRMSNormZero(  # 建立第一個 RMS 歸一化層
            embedding_dim=dim,  # 歸一化的嵌入維度
            norm_eps=norm_eps,  # 歸一化的 epsilon 引數
            norm_elementwise_affine=norm_elementwise_affine,  # 是否使用元素級仿射變換
        )
        self.ffn_norm1 = RMSNorm(dim, eps=norm_eps, elementwise_affine=norm_elementwise_affine)  # 建立前饋網路的 RMS 歸一化層

        self.norm2 = RMSNorm(dim, eps=norm_eps, elementwise_affine=norm_elementwise_affine)  # 建立第二個 RMS 歸一化層
        self.ffn_norm2 = RMSNorm(dim, eps=norm_eps, elementwise_affine=norm_elementwise_affine)  # 建立前饋網路的第二個 RMS 歸一化層

        self.norm1_context = RMSNorm(cross_attention_dim, eps=norm_eps, elementwise_affine=norm_elementwise_affine)  # 建立上下文的 RMS 歸一化層

    def forward(  # 定義前向傳播方法
        self,
        hidden_states: torch.Tensor,  # 輸入的隱藏狀態張量
        attention_mask: torch.Tensor,  # 注意力掩碼張量
        image_rotary_emb: torch.Tensor,  # 影像旋轉嵌入張量
        encoder_hidden_states: torch.Tensor,  # 編碼器的隱藏狀態張量
        encoder_mask: torch.Tensor,  # 編碼器的掩碼張量
        temb: torch.Tensor,  # 位置編碼或時間編碼張量
        cross_attention_kwargs: Optional[Dict[str, Any]] = None,  # 可選的交叉注意力引數字典
    ):
        """
        執行 LuminaNextDiTBlock 的前向傳遞。

        引數:
            hidden_states (`torch.Tensor`): LuminaNextDiTBlock 的輸入隱藏狀態。
            attention_mask (`torch.Tensor): 對應隱藏狀態的注意力掩碼。
            image_rotary_emb (`torch.Tensor`): 預計算的餘弦和正弦頻率。
            encoder_hidden_states: (`torch.Tensor`): 透過 Gemma 編碼器處理的文字提示的隱藏狀態。
            encoder_mask (`torch.Tensor`): 文字提示的隱藏狀態注意力掩碼。
            temb (`torch.Tensor`): 帶有文字提示嵌入的時間步嵌入。
            cross_attention_kwargs (`Dict[str, Any]`): 交叉注意力的引數。
        """
        # 儲存輸入的隱藏狀態,以便後續使用
        residual = hidden_states

        # 自注意力
        # 對隱藏狀態進行歸一化,並計算門控機制的輸出
        norm_hidden_states, gate_msa, scale_mlp, gate_mlp = self.norm1(hidden_states, temb)
        # 計算自注意力的輸出
        self_attn_output = self.attn1(
            hidden_states=norm_hidden_states,
            encoder_hidden_states=norm_hidden_states,
            attention_mask=attention_mask,
            query_rotary_emb=image_rotary_emb,
            key_rotary_emb=image_rotary_emb,
            **cross_attention_kwargs,
        )

        # 交叉注意力
        # 對編碼器的隱藏狀態進行歸一化
        norm_encoder_hidden_states = self.norm1_context(encoder_hidden_states)
        # 計算交叉注意力的輸出
        cross_attn_output = self.attn2(
            hidden_states=norm_hidden_states,
            encoder_hidden_states=norm_encoder_hidden_states,
            attention_mask=encoder_mask,
            query_rotary_emb=image_rotary_emb,
            key_rotary_emb=None,
            **cross_attention_kwargs,
        )
        # 將交叉注意力的輸出進行縮放
        cross_attn_output = cross_attn_output * self.gate.tanh().view(1, 1, -1, 1)
        # 將自注意力和交叉注意力的輸出混合
        mixed_attn_output = self_attn_output + cross_attn_output
        # 將混合輸出展平,以便後續處理
        mixed_attn_output = mixed_attn_output.flatten(-2)
        # 線性投影
        # 透過線性層處理混合輸出,得到新的隱藏狀態
        hidden_states = self.attn2.to_out[0](mixed_attn_output)

        # 更新隱藏狀態,加入殘差連線和門控機制
        hidden_states = residual + gate_msa.unsqueeze(1).tanh() * self.norm2(hidden_states)

        # 透過前饋網路計算輸出
        mlp_output = self.feed_forward(self.ffn_norm1(hidden_states) * (1 + scale_mlp.unsqueeze(1)))

        # 更新隱藏狀態,加入前饋網路輸出和門控機制
        hidden_states = hidden_states + gate_mlp.unsqueeze(1).tanh() * self.ffn_norm2(mlp_output)

        # 返回最終的隱藏狀態
        return hidden_states
# 定義一個名為 LuminaNextDiT2DModel 的類,繼承自 ModelMixin 和 ConfigMixin
class LuminaNextDiT2DModel(ModelMixin, ConfigMixin):
    """
    LuminaNextDiT: 使用 Transformer 主幹的擴散模型。

    繼承 ModelMixin 和 ConfigMixin 以相容 diffusers 的 StableDiffusionPipeline 取樣器。

    引數:
        sample_size (`int`): 潛在影像的寬度。此值在訓練期間固定,因為
            它用於學習位置嵌入的數量。
        patch_size (`int`, *optional*, (`int`, *optional*, defaults to 2):
            影像中每個補丁的大小。此引數定義輸入到模型中的補丁的解析度。
        in_channels (`int`, *optional*, defaults to 4):
            模型的輸入通道數量。通常,這與輸入影像的通道數量匹配。
        hidden_size (`int`, *optional*, defaults to 4096):
            模型隱藏層的維度。此引數決定了模型隱藏表示的寬度。
        num_layers (`int`, *optional*, default to 32):
            模型中的層數。此值定義了神經網路的深度。
        num_attention_heads (`int`, *optional*, defaults to 32):
            每個注意力層中的注意力頭數量。此引數指定使用多少個獨立的注意力機制。
        num_kv_heads (`int`, *optional*, defaults to 8):
            注意力機制中的鍵值頭數量,如果與注意力頭數量不同。如果為 None,則預設值為 num_attention_heads。
        multiple_of (`int`, *optional*, defaults to 256):
            隱藏大小應該是一個倍數的因子。這可以幫助最佳化某些硬體
            配置。
        ffn_dim_multiplier (`float`, *optional*):
            前饋網路維度的乘數。如果為 None,則使用基於
            模型配置的預設值。
        norm_eps (`float`, *optional*, defaults to 1e-5):
            新增到歸一化層的分母中的一個小值,用於數值穩定性。
        learn_sigma (`bool`, *optional*, defaults to True):
            模型是否應該學習 sigma 引數,該引數可能與預測中的不確定性或方差相關。
        qk_norm (`bool`, *optional*, defaults to True):
            指示注意力機制中的查詢和鍵是否應該被歸一化。
        cross_attention_dim (`int`, *optional*, defaults to 2048):
            文字嵌入的維度。此引數定義了用於模型的文字表示的大小。
        scaling_factor (`float`, *optional*, defaults to 1.0):
            應用於模型某些引數或層的縮放因子。此引數可用於調整模型操作的整體規模。
    """
    # 註冊到配置
    @register_to_config
    def __init__(
        # 樣本大小,預設值為128
        self,
        sample_size: int = 128,
        # 補丁大小,預設為2,表示影像切割塊的大小
        patch_size: Optional[int] = 2,
        # 輸入通道數,預設為4,表示輸入資料的特徵通道
        in_channels: Optional[int] = 4,
        # 隱藏層大小,預設為2304
        hidden_size: Optional[int] = 2304,
        # 網路層數,預設為32
        num_layers: Optional[int] = 32,
        # 注意力頭數量,預設為32
        num_attention_heads: Optional[int] = 32,
        # KV頭的數量,預設為None
        num_kv_heads: Optional[int] = None,
        # 數量的倍數,預設為256
        multiple_of: Optional[int] = 256,
        # FFN維度乘數,預設為None
        ffn_dim_multiplier: Optional[float] = None,
        # 歸一化的epsilon值,預設為1e-5
        norm_eps: Optional[float] = 1e-5,
        # 是否學習方差,預設為True
        learn_sigma: Optional[bool] = True,
        # 是否進行QK歸一化,預設為True
        qk_norm: Optional[bool] = True,
        # 交叉注意力維度,預設為2048
        cross_attention_dim: Optional[int] = 2048,
        # 縮放因子,預設為1.0
        scaling_factor: Optional[float] = 1.0,
    ) -> None:
        # 呼叫父類初始化方法
        super().__init__()
        # 設定樣本大小屬性
        self.sample_size = sample_size
        # 設定補丁大小屬性
        self.patch_size = patch_size
        # 設定輸入通道數屬性
        self.in_channels = in_channels
        # 根據是否學習方差設定輸出通道數
        self.out_channels = in_channels * 2 if learn_sigma else in_channels
        # 設定隱藏層大小屬性
        self.hidden_size = hidden_size
        # 設定注意力頭數量屬性
        self.num_attention_heads = num_attention_heads
        # 計算並設定每個注意力頭的維度
        self.head_dim = hidden_size // num_attention_heads
        # 設定縮放因子屬性
        self.scaling_factor = scaling_factor

        # 建立補丁嵌入層,並初始化其引數
        self.patch_embedder = LuminaPatchEmbed(
            patch_size=patch_size, in_channels=in_channels, embed_dim=hidden_size, bias=True
        )

        # 建立一個可學習的填充標記,初始化為空張量
        self.pad_token = nn.Parameter(torch.empty(hidden_size))

        # 建立時間和標題的組合嵌入層
        self.time_caption_embed = LuminaCombinedTimestepCaptionEmbedding(
            hidden_size=min(hidden_size, 1024), cross_attention_dim=cross_attention_dim
        )

        # 建立包含多個層的模組列表
        self.layers = nn.ModuleList(
            [
                # 在模組列表中新增多個下一代塊
                LuminaNextDiTBlock(
                    hidden_size,
                    num_attention_heads,
                    num_kv_heads,
                    multiple_of,
                    ffn_dim_multiplier,
                    norm_eps,
                    qk_norm,
                    cross_attention_dim,
                )
                for _ in range(num_layers)  # 根據層數迴圈
            ]
        )
        # 建立層歸一化輸出層
        self.norm_out = LuminaLayerNormContinuous(
            embedding_dim=hidden_size,
            conditioning_embedding_dim=min(hidden_size, 1024),
            elementwise_affine=False,
            eps=1e-6,
            bias=True,
            out_dim=patch_size * patch_size * self.out_channels,
        )
        # 註釋掉的最終層的初始化(若需要可取消註釋)
        # self.final_layer = LuminaFinalLayer(hidden_size, patch_size, self.out_channels)

        # 確保隱藏層大小與注意力頭數量的關係,保證為4的倍數
        assert (hidden_size // num_attention_heads) % 4 == 0, "2d rope needs head dim to be divisible by 4"

    # 前向傳播函式定義
    def forward(
        # 隱藏狀態的輸入張量
        self,
        hidden_states: torch.Tensor,
        # 時間步的輸入張量
        timestep: torch.Tensor,
        # 編碼器的隱藏狀態張量
        encoder_hidden_states: torch.Tensor,
        # 編碼器的掩碼張量
        encoder_mask: torch.Tensor,
        # 影像的旋轉嵌入張量
        image_rotary_emb: torch.Tensor,
        # 交叉注意力的其他引數,預設為None
        cross_attention_kwargs: Dict[str, Any] = None,
        # 是否返回字典形式的結果,預設為True
        return_dict=True,
    # LuminaNextDiT 的前向傳播函式
    ) -> torch.Tensor:
            """
            前向傳播的 LuminaNextDiT 模型。
    
            引數:
                hidden_states (torch.Tensor): 輸入張量,形狀為 (N, C, H, W)。
                timestep (torch.Tensor): 擴散時間步的張量,形狀為 (N,).
                encoder_hidden_states (torch.Tensor): 描述特徵的張量,形狀為 (N, D)。
                encoder_mask (torch.Tensor): 描述特徵掩碼的張量,形狀為 (N, L)。
            """
            # 透過補丁嵌入器處理隱藏狀態,獲取掩碼、影像大小和影像旋轉嵌入
            hidden_states, mask, img_size, image_rotary_emb = self.patch_embedder(hidden_states, image_rotary_emb)
            # 將影像旋轉嵌入轉移到與隱藏狀態相同的裝置上
            image_rotary_emb = image_rotary_emb.to(hidden_states.device)
    
            # 生成時間嵌入,結合時間步和編碼器隱藏狀態
            temb = self.time_caption_embed(timestep, encoder_hidden_states, encoder_mask)
    
            # 將編碼器掩碼轉換為布林值
            encoder_mask = encoder_mask.bool()
            # 對每一層進行遍歷,更新隱藏狀態
            for layer in self.layers:
                hidden_states = layer(
                    hidden_states,
                    mask,
                    image_rotary_emb,
                    encoder_hidden_states,
                    encoder_mask,
                    temb=temb,
                    cross_attention_kwargs=cross_attention_kwargs,
                )
    
            # 對隱藏狀態進行歸一化處理
            hidden_states = self.norm_out(hidden_states, temb)
    
            # 反補丁操作
            height_tokens = width_tokens = self.patch_size  # 獲取補丁大小
            height, width = img_size[0]  # 從影像大小中提取高度和寬度
            batch_size = hidden_states.size(0)  # 獲取批次大小
            sequence_length = (height // height_tokens) * (width // width_tokens)  # 計算序列長度
            # 調整隱藏狀態的形狀,以適應輸出要求
            hidden_states = hidden_states[:, :sequence_length].view(
                batch_size, height // height_tokens, width // width_tokens, height_tokens, width_tokens, self.out_channels
            )
            # 調整維度以獲得最終輸出
            output = hidden_states.permute(0, 5, 1, 3, 2, 4).flatten(4, 5).flatten(2, 3)
    
            # 如果不需要返回字典,則返回輸出元組
            if not return_dict:
                return (output,)
    
            # 返回 Transformer2DModelOutput 的結果
            return Transformer2DModelOutput(sample=output)

.\diffusers\models\transformers\pixart_transformer_2d.py

# 版權所有 2024 HuggingFace 團隊。保留所有權利。
#
# 根據 Apache 許可證第 2.0 版(“許可證”)進行許可;
# 除非遵守許可證,否則您不得使用此檔案。
# 您可以在以下網址獲取許可證副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非適用法律或書面協議另有規定,軟體
# 按“原樣”提供,沒有任何形式的明示或暗示的擔保或條件。
# 請參閱許可證以瞭解有關許可權和
# 限制的具體條款。
from typing import Any, Dict, Optional, Union  # 匯入型別提示相關的模組

import torch  # 匯入 PyTorch 庫
from torch import nn  # 從 PyTorch 匯入神經網路模組

from ...configuration_utils import ConfigMixin, register_to_config  # 匯入配置相關的混合類和註冊函式
from ...utils import is_torch_version, logging  # 匯入工具函式:檢查 PyTorch 版本和日誌記錄
from ..attention import BasicTransformerBlock  # 匯入基礎 Transformer 塊
from ..attention_processor import Attention, AttentionProcessor, FusedAttnProcessor2_0  # 匯入注意力相關的處理器
from ..embeddings import PatchEmbed, PixArtAlphaTextProjection  # 匯入嵌入相關的模組
from ..modeling_outputs import Transformer2DModelOutput  # 匯入模型輸出相關的類
from ..modeling_utils import ModelMixin  # 匯入模型混合類
from ..normalization import AdaLayerNormSingle  # 匯入自適應層歸一化類

logger = logging.get_logger(__name__)  # 獲取當前模組的日誌記錄器;pylint 禁用命名檢查

class PixArtTransformer2DModel(ModelMixin, ConfigMixin):  # 定義 PixArt 2D Transformer 模型類,繼承自 ModelMixin 和 ConfigMixin
    r"""  # 文件字串:描述模型及其來源
    A 2D Transformer model as introduced in PixArt family of models (https://arxiv.org/abs/2310.00426,
    https://arxiv.org/abs/2403.04692).
    """

    _supports_gradient_checkpointing = True  # 設定支援梯度檢查點
    _no_split_modules = ["BasicTransformerBlock", "PatchEmbed"]  # 指定不進行分割的模組

    @register_to_config  # 使用裝飾器將初始化函式註冊到配置中
    def __init__(  # 定義初始化函式
        self,
        num_attention_heads: int = 16,  # 注意力頭的數量,預設為 16
        attention_head_dim: int = 72,  # 每個注意力頭的維度,預設為 72
        in_channels: int = 4,  # 輸入通道數,預設為 4
        out_channels: Optional[int] = 8,  # 輸出通道數,預設為 8,可選
        num_layers: int = 28,  # 層數,預設為 28
        dropout: float = 0.0,  # dropout 比例,預設為 0.0
        norm_num_groups: int = 32,  # 歸一化的組數,預設為 32
        cross_attention_dim: Optional[int] = 1152,  # 交叉注意力的維度,預設為 1152,可選
        attention_bias: bool = True,  # 是否使用注意力偏置,預設為 True
        sample_size: int = 128,  # 樣本尺寸,預設為 128
        patch_size: int = 2,  # 每個補丁的尺寸,預設為 2
        activation_fn: str = "gelu-approximate",  # 啟用函式型別,預設為近似 GELU
        num_embeds_ada_norm: Optional[int] = 1000,  # 自適應歸一化的嵌入數量,預設為 1000,可選
        upcast_attention: bool = False,  # 是否提高注意力精度,預設為 False
        norm_type: str = "ada_norm_single",  # 歸一化型別,預設為單一自適應歸一化
        norm_elementwise_affine: bool = False,  # 是否使用逐元素仿射變換,預設為 False
        norm_eps: float = 1e-6,  # 歸一化的 epsilon 值,預設為 1e-6
        interpolation_scale: Optional[int] = None,  # 插值尺度,可選
        use_additional_conditions: Optional[bool] = None,  # 是否使用額外條件,可選
        caption_channels: Optional[int] = None,  # 說明通道數,可選
        attention_type: Optional[str] = "default",  # 注意力型別,預設為預設型別
    ):
        # 初始化函式引數設定
        ...

    def _set_gradient_checkpointing(self, module, value=False):  # 定義設定梯度檢查點的方法
        if hasattr(module, "gradient_checkpointing"):  # 檢查模組是否具有梯度檢查點屬性
            module.gradient_checkpointing = value  # 設定梯度檢查點的值

    @property  # 定義一個屬性
    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.attn_processors 複製的屬性
    # 定義一個方法,返回模型中所有注意力處理器的字典,鍵為權重名稱
    def attn_processors(self) -> Dict[str, AttentionProcessor]:
        r"""
        Returns:
            `dict` of attention processors: A dictionary containing all attention processors used in the model with
            indexed by its weight name.
        """
        # 建立一個空字典,用於儲存注意力處理器
        processors = {}

        # 定義一個遞迴函式,用於新增處理器到字典中
        def fn_recursive_add_processors(name: str, module: torch.nn.Module, processors: Dict[str, AttentionProcessor]):
            # 如果模組具有獲取處理器的方法,則將其新增到字典中
            if hasattr(module, "get_processor"):
                processors[f"{name}.processor"] = module.get_processor()

            # 遍歷子模組,遞迴呼叫該函式以新增處理器
            for sub_name, child in module.named_children():
                fn_recursive_add_processors(f"{name}.{sub_name}", child, processors)

            # 返回更新後的處理器字典
            return processors

        # 遍歷當前模組的所有子模組,呼叫遞迴函式以填充處理器字典
        for name, module in self.named_children():
            fn_recursive_add_processors(name, module, processors)

        # 返回所有注意力處理器的字典
        return processors

    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.set_attn_processor 複製
    # 定義一個方法,用於設定計算注意力的處理器
    def set_attn_processor(self, processor: Union[AttentionProcessor, Dict[str, AttentionProcessor]]):
        r"""
        Sets the attention processor to use to compute attention.

        Parameters:
            processor (`dict` of `AttentionProcessor` or only `AttentionProcessor`):
                The instantiated processor class or a dictionary of processor classes that will be set as the processor
                for **all** `Attention` layers.

                If `processor` is a dict, the key needs to define the path to the corresponding cross attention
                processor. This is strongly recommended when setting trainable attention processors.

        """
        # 獲取當前注意力處理器的數量
        count = len(self.attn_processors.keys())

        # 檢查傳入的處理器字典的長度是否與注意力層的數量匹配
        if isinstance(processor, dict) and len(processor) != count:
            raise ValueError(
                f"A dict of processors was passed, but the number of processors {len(processor)} does not match the"
                f" number of attention layers: {count}. Please make sure to pass {count} processor classes."
            )

        # 定義一個遞迴函式,用於設定處理器
        def fn_recursive_attn_processor(name: str, module: torch.nn.Module, processor):
            # 如果模組具有設定處理器的方法,則進行設定
            if hasattr(module, "set_processor"):
                if not isinstance(processor, dict):
                    module.set_processor(processor)  # 設定單一處理器
                else:
                    module.set_processor(processor.pop(f"{name}.processor"))  # 從字典中移除並設定處理器

            # 遍歷子模組,遞迴呼叫以設定處理器
            for sub_name, child in module.named_children():
                fn_recursive_attn_processor(f"{name}.{sub_name}", child, processor)

        # 遍歷當前模組的所有子模組,呼叫遞迴函式以設定處理器
        for name, module in self.named_children():
            fn_recursive_attn_processor(name, module, processor)

    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.fuse_qkv_projections 複製
    # 定義融合 QKV 投影的函式
    def fuse_qkv_projections(self):
        # 啟用融合的 QKV 投影,對自注意力模組進行融合查詢、鍵、值矩陣
        # 對交叉注意力模組則僅融合鍵和值投影矩陣
        """
        Enables fused QKV projections. For self-attention modules, all projection matrices (i.e., query, key, value)
        are fused. For cross-attention modules, key and value projection matrices are fused.
    
        <Tip warning={true}>
    
        This API is 🧪 experimental.
    
        </Tip>
        """
        # 初始化原始注意力處理器為 None
        self.original_attn_processors = None
    
        # 遍歷所有注意力處理器
        for _, attn_processor in self.attn_processors.items():
            # 檢查處理器類名中是否包含 "Added"
            if "Added" in str(attn_processor.__class__.__name__):
                # 如果存在,則丟擲錯誤,說明不支援此融合操作
                raise ValueError("`fuse_qkv_projections()` is not supported for models having added KV projections.")
    
        # 儲存當前的注意力處理器
        self.original_attn_processors = self.attn_processors
    
        # 遍歷模型中的所有模組
        for module in self.modules():
            # 如果模組是 Attention 型別
            if isinstance(module, Attention):
                # 執行投影融合
                module.fuse_projections(fuse=True)
    
        # 設定新的融合注意力處理器
        self.set_attn_processor(FusedAttnProcessor2_0())
    
    # 從 UNet2DConditionModel 中複製的函式,用於取消融合 QKV 投影
    def unfuse_qkv_projections(self):
        # 禁用已啟用的融合 QKV 投影
        """Disables the fused QKV projection if enabled.
    
        <Tip warning={true}>
    
        This API is 🧪 experimental.
    
        </Tip>
    
        """
        # 檢查原始注意力處理器是否存在
        if self.original_attn_processors is not None:
            # 恢復到原始注意力處理器
            self.set_attn_processor(self.original_attn_processors)
    
    # 定義前向傳播函式
    def forward(
        # 輸入隱藏狀態的張量
        hidden_states: torch.Tensor,
        # 編碼器隱藏狀態(可選)
        encoder_hidden_states: Optional[torch.Tensor] = None,
        # 時間步長(可選)
        timestep: Optional[torch.LongTensor] = None,
        # 新增的條件關鍵字引數(字典型別,可選)
        added_cond_kwargs: Dict[str, torch.Tensor] = None,
        # 交叉注意力關鍵字引數(字典型別,可選)
        cross_attention_kwargs: Dict[str, Any] = None,
        # 注意力掩碼(可選)
        attention_mask: Optional[torch.Tensor] = None,
        # 編碼器注意力掩碼(可選)
        encoder_attention_mask: Optional[torch.Tensor] = None,
        # 是否返回字典(預設值為 True)
        return_dict: bool = True,

.\diffusers\models\transformers\prior_transformer.py

# 從 dataclasses 模組匯入 dataclass 裝飾器
from dataclasses import dataclass
# 匯入字典、可選值和聯合型別的定義
from typing import Dict, Optional, Union

# 匯入 PyTorch 及其功能模組
import torch
import torch.nn.functional as F
# 從 PyTorch 匯入神經網路模組
from torch import nn

# 匯入配置和註冊功能的相關類
from ...configuration_utils import ConfigMixin, register_to_config
# 匯入 PeftAdapter 和 UNet2DConditionLoader 的相關類
from ...loaders import PeftAdapterMixin, UNet2DConditionLoadersMixin
# 匯入基礎輸出工具類
from ...utils import BaseOutput
# 匯入基本變換器塊
from ..attention import BasicTransformerBlock
# 匯入注意力處理器的相關元件
from ..attention_processor import (
    ADDED_KV_ATTENTION_PROCESSORS,
    CROSS_ATTENTION_PROCESSORS,
    AttentionProcessor,
    AttnAddedKVProcessor,
    AttnProcessor,
)
# 匯入時間步嵌入和時間步類
from ..embeddings import TimestepEmbedding, Timesteps
# 匯入模型混合工具類
from ..modeling_utils import ModelMixin

# 定義 PriorTransformerOutput 資料類,繼承自 BaseOutput
@dataclass
class PriorTransformerOutput(BaseOutput):
    """
    [`PriorTransformer`] 的輸出。

    Args:
        predicted_image_embedding (`torch.Tensor` 的形狀為 `(batch_size, embedding_dim)`):
            基於 CLIP 文字嵌入輸入的預測 CLIP 影像嵌入。
    """

    # 定義預測的影像嵌入屬性
    predicted_image_embedding: torch.Tensor


# 定義 PriorTransformer 類,繼承多個混合類
class PriorTransformer(ModelMixin, ConfigMixin, UNet2DConditionLoadersMixin, PeftAdapterMixin):
    """
    一種 Prior Transformer 模型。
    # 引數說明部分
    Parameters:
        # 用於多頭注意力的頭數量,預設為 32
        num_attention_heads (`int`, *optional*, defaults to 32): The number of heads to use for multi-head attention.
        # 每個頭的通道數量,預設為 64
        attention_head_dim (`int`, *optional*, defaults to 64): The number of channels in each head.
        # Transformer 塊的層數,預設為 20
        num_layers (`int`, *optional*, defaults to 20): The number of layers of Transformer blocks to use.
        # 模型輸入 `hidden_states` 的維度,預設為 768
        embedding_dim (`int`, *optional*, defaults to 768): The dimension of the model input `hidden_states`
        # 模型輸入 `hidden_states` 的嵌入數量,預設為 77
        num_embeddings (`int`, *optional*, defaults to 77):
            The number of embeddings of the model input `hidden_states`
        # 附加令牌的數量,預設為 4,追加到投影的 `hidden_states`
        additional_embeddings (`int`, *optional*, defaults to 4): The number of additional tokens appended to the
            projected `hidden_states`. The actual length of the used `hidden_states` is `num_embeddings +
            additional_embeddings`.
        # 用於 dropout 的機率,預設為 0.0
        dropout (`float`, *optional*, defaults to 0.0): The dropout probability to use.
        # 建立時間步嵌入時使用的啟用函式,預設為 'silu'
        time_embed_act_fn (`str`, *optional*, defaults to 'silu'):
            The activation function to use to create timestep embeddings.
        # 在傳遞給 Transformer 塊之前應用的歸一化層,預設為 None
        norm_in_type (`str`, *optional*, defaults to None): The normalization layer to apply on hidden states before
            passing to Transformer blocks. Set it to `None` if normalization is not needed.
        # 輸入 `proj_embedding` 上應用的歸一化層,預設為 None
        embedding_proj_norm_type (`str`, *optional*, defaults to None):
            The normalization layer to apply on the input `proj_embedding`. Set it to `None` if normalization is not
            needed.
        # 輸入 `encoder_hidden_states` 上應用的投影層,預設為 `linear`
        encoder_hid_proj_type (`str`, *optional*, defaults to `linear`):
            The projection layer to apply on the input `encoder_hidden_states`. Set it to `None` if
            `encoder_hidden_states` is `None`.
        # 條件模型的附加嵌入型別,預設為 `prd`
        added_emb_type (`str`, *optional*, defaults to `prd`): Additional embeddings to condition the model.
            Choose from `prd` or `None`. if choose `prd`, it will prepend a token indicating the (quantized) dot
            product between the text embedding and image embedding as proposed in the unclip paper
            https://arxiv.org/abs/2204.06125 If it is `None`, no additional embeddings will be prepended.
        # 時間步嵌入的維度,預設為 None,如果為 None,則設定為 `num_attention_heads * attention_head_dim`
        time_embed_dim (`int, *optional*, defaults to None): The dimension of timestep embeddings.
            If None, will be set to `num_attention_heads * attention_head_dim`
        # `proj_embedding` 的維度,預設為 None,如果為 None,則設定為 `embedding_dim`
        embedding_proj_dim (`int`, *optional*, default to None):
            The dimension of `proj_embedding`. If None, will be set to `embedding_dim`.
        # 輸出的維度,預設為 None,如果為 None,則設定為 `embedding_dim`
        clip_embed_dim (`int`, *optional*, default to None):
            The dimension of the output. If None, will be set to `embedding_dim`.
    """

    # 註冊到配置中
    @register_to_config
    # 初始化類的建構函式,設定預設引數
        def __init__(
            # 注意力頭的數量,預設值為32
            self,
            num_attention_heads: int = 32,
            # 每個注意力頭的維度,預設值為64
            attention_head_dim: int = 64,
            # 層的數量,預設值為20
            num_layers: int = 20,
            # 嵌入的維度,預設值為768
            embedding_dim: int = 768,
            # 嵌入的數量,預設值為77
            num_embeddings=77,
            # 額外嵌入的數量,預設值為4
            additional_embeddings=4,
            # dropout的比率,預設值為0.0
            dropout: float = 0.0,
            # 時間嵌入啟用函式的型別,預設值為"silu"
            time_embed_act_fn: str = "silu",
            # 輸入歸一化型別,預設為None
            norm_in_type: Optional[str] = None,  # layer
            # 嵌入投影歸一化型別,預設為None
            embedding_proj_norm_type: Optional[str] = None,  # layer
            # 編碼器隱藏投影型別,預設值為"linear"
            encoder_hid_proj_type: Optional[str] = "linear",  # linear
            # 新增的嵌入型別,預設值為"prd"
            added_emb_type: Optional[str] = "prd",  # prd
            # 時間嵌入維度,預設為None
            time_embed_dim: Optional[int] = None,
            # 嵌入投影維度,預設為None
            embedding_proj_dim: Optional[int] = None,
            # 裁剪嵌入維度,預設為None
            clip_embed_dim: Optional[int] = None,
        # 定義一個屬性,獲取注意力處理器
        @property
        # 從diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.attn_processors複製而來
        def attn_processors(self) -> Dict[str, AttentionProcessor]:
            r"""
            返回值:
                `dict`型別的注意力處理器:一個字典,包含模型中使用的所有注意力處理器,並按其權重名稱索引。
            """
            # 建立一個空字典用於儲存處理器
            processors = {}
    
            # 定義遞迴函式,新增處理器到字典
            def fn_recursive_add_processors(name: str, module: torch.nn.Module, processors: Dict[str, AttentionProcessor]):
                # 如果模組有獲取處理器的方法,新增到字典中
                if hasattr(module, "get_processor"):
                    processors[f"{name}.processor"] = module.get_processor()
    
                # 遍歷模組的所有子模組,遞迴呼叫自身
                for sub_name, child in module.named_children():
                    fn_recursive_add_processors(f"{name}.{sub_name}", child, processors)
    
                # 返回更新後的處理器字典
                return processors
    
            # 遍歷當前類的所有子模組,呼叫遞迴函式新增處理器
            for name, module in self.named_children():
                fn_recursive_add_processors(name, module, processors)
    
            # 返回最終的處理器字典
            return processors
    
        # 從diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.set_attn_processor複製而來
    # 設定用於計算注意力的處理器
    def set_attn_processor(self, processor: Union[AttentionProcessor, Dict[str, AttentionProcessor]]):
        r"""
        設定用於計算注意力的處理器。
    
        引數:
            processor(`dict` 或 `AttentionProcessor`):
                例項化的處理器類或處理器類的字典,將作為 **所有** `Attention` 層的處理器。
    
                如果 `processor` 是一個字典,鍵需要定義相應的交叉注意力處理器的路徑。建議在設定可訓練注意力處理器時使用此方法。
    
        """
        # 計算當前注意力處理器的數量
        count = len(self.attn_processors.keys())
    
        # 如果傳入的是字典且其長度與注意力層數量不匹配,丟擲錯誤
        if isinstance(processor, dict) and len(processor) != count:
            raise ValueError(
                f"傳入了處理器的字典,但處理器的數量 {len(processor)} 與注意力層的數量 {count} 不匹配。請確保傳入 {count} 個處理器類。"
            )
    
        # 定義遞迴設定注意力處理器的函式
        def fn_recursive_attn_processor(name: str, module: torch.nn.Module, processor):
            # 如果模組具有 set_processor 方法,則設定處理器
            if hasattr(module, "set_processor"):
                if not isinstance(processor, dict):
                    module.set_processor(processor)
                else:
                    module.set_processor(processor.pop(f"{name}.processor"))
    
            # 遍歷子模組並遞迴呼叫
            for sub_name, child in module.named_children():
                fn_recursive_attn_processor(f"{name}.{sub_name}", child, processor)
    
        # 遍歷所有子模組,呼叫遞迴函式設定處理器
        for name, module in self.named_children():
            fn_recursive_attn_processor(name, module, processor)
    
    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel 複製的設定預設注意力處理器的方法
    def set_default_attn_processor(self):
        """
        禁用自定義注意力處理器並設定預設的注意力實現。
        """
        # 如果所有處理器都是新增的 KV 注意力處理器,則設定為新增的 KV 處理器
        if all(proc.__class__ in ADDED_KV_ATTENTION_PROCESSORS for proc in self.attn_processors.values()):
            processor = AttnAddedKVProcessor()
        # 如果所有處理器都是交叉注意力處理器,則設定為普通的注意力處理器
        elif all(proc.__class__ in CROSS_ATTENTION_PROCESSORS for proc in self.attn_processors.values()):
            processor = AttnProcessor()
        else:
            raise ValueError(
                f"當注意力處理器的型別為 {next(iter(self.attn_processors.values()))} 時,無法呼叫 `set_default_attn_processor`"
            )
    
        # 呼叫設定處理器的方法
        self.set_attn_processor(processor)
    
    # 前向傳播方法定義
    def forward(
        self,
        hidden_states,
        timestep: Union[torch.Tensor, float, int],
        proj_embedding: torch.Tensor,
        encoder_hidden_states: Optional[torch.Tensor] = None,
        attention_mask: Optional[torch.BoolTensor] = None,
        return_dict: bool = True,
    ):
        # 處理傳入的潛在變數
        def post_process_latents(self, prior_latents):
            # 將潛在變數進行標準化處理
            prior_latents = (prior_latents * self.clip_std) + self.clip_mean
            return prior_latents

.\diffusers\models\transformers\stable_audio_transformer.py

# 版權宣告,註明版權歸屬
# Copyright 2024 Stability AI and The HuggingFace Team. All rights reserved.
#
# 根據 Apache License 2.0 授權協議進行許可
# Licensed under the Apache License, Version 2.0 (the "License");
# 只有在遵守許可證的情況下,您才能使用此檔案
# you may not use this file except in compliance with the License.
# 您可以在以下網址獲取許可證副本
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非法律要求或書面同意,軟體按“原樣”分發
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 不提供任何形式的保證或條件,明示或暗示
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 請參見許可證以獲取有關許可權和限制的具體資訊
# See the License for the specific language governing permissions and
# limitations under the License.


# 匯入型別註解
from typing import Any, Dict, Optional, Union

# 匯入 NumPy 庫
import numpy as np
# 匯入 PyTorch 庫
import torch
# 匯入 PyTorch 的神經網路模組
import torch.nn as nn
# 匯入 PyTorch 的檢查點工具
import torch.utils.checkpoint

# 從配置工具匯入相關類
from ...configuration_utils import ConfigMixin, register_to_config
# 從注意力模組匯入前饋網路
from ...models.attention import FeedForward
# 從注意力處理器模組匯入多個類
from ...models.attention_processor import (
    Attention,
    AttentionProcessor,
    StableAudioAttnProcessor2_0,
)
# 從建模工具匯入模型混合類
from ...models.modeling_utils import ModelMixin
# 從變換器模型匯入輸出類
from ...models.transformers.transformer_2d import Transformer2DModelOutput
# 匯入實用工具
from ...utils import is_torch_version, logging
# 匯入可能允許圖形中的工具函式
from ...utils.torch_utils import maybe_allow_in_graph

# 獲取當前模組的日誌記錄器
logger = logging.get_logger(__name__)  # pylint: disable=invalid-name


class StableAudioGaussianFourierProjection(nn.Module):
    """用於噪聲級別的高斯傅立葉嵌入。"""

    # 從 diffusers.models.embeddings.GaussianFourierProjection.__init__ 複製的內容
    def __init__(
        self, embedding_size: int = 256, scale: float = 1.0, set_W_to_weight=True, log=True, flip_sin_to_cos=False
    ):
        super().__init__()  # 呼叫父類的建構函式
        # 初始化權重為隨機值,且不需要計算梯度
        self.weight = nn.Parameter(torch.randn(embedding_size) * scale, requires_grad=False)
        self.log = log  # 是否對輸入取對數的標誌
        self.flip_sin_to_cos = flip_sin_to_cos  # 是否翻轉正弦和餘弦的順序

        if set_W_to_weight:  # 如果設定將 W 賦值給權重
            # 之後將刪除此行
            del self.weight  # 刪除原有權重
            # 初始化 W 為隨機值,並不計算梯度
            self.W = nn.Parameter(torch.randn(embedding_size) * scale, requires_grad=False)
            self.weight = self.W  # 將 W 賦值給權重
            del self.W  # 刪除 W

    def forward(self, x):
        # 如果 log 為 True,則對輸入進行對數變換
        if self.log:
            x = torch.log(x)

        # 計算投影,使用 2π 乘以輸入和權重的外積
        x_proj = 2 * np.pi * x[:, None] @ self.weight[None, :]

        if self.flip_sin_to_cos:  # 如果翻轉正弦和餘弦
            # 連線餘弦和正弦,形成輸出
            out = torch.cat([torch.cos(x_proj), torch.sin(x_proj)], dim=-1)
        else:
            # 連線正弦和餘弦,形成輸出
            out = torch.cat([torch.sin(x_proj), torch.cos(x_proj)], dim=-1)
        return out  # 返回輸出


@maybe_allow_in_graph  # 可能允許在計算圖中使用
class StableAudioDiTBlock(nn.Module):
    r"""
    用於穩定音訊模型的變換器塊 (https://github.com/Stability-AI/stable-audio-tools)。允許跳躍連線和 QKNorm
    # 引數說明
    Parameters:
        dim (`int`): 輸入和輸出的通道數。
        num_attention_heads (`int`): 查詢狀態所使用的頭數。
        num_key_value_attention_heads (`int`): 鍵和值狀態所使用的頭數。
        attention_head_dim (`int`): 每個頭中的通道數。
        dropout (`float`, *optional*, defaults to 0.0): 使用的丟棄機率。
        cross_attention_dim (`int`, *optional*): 跨注意力的 encoder_hidden_states 向量的大小。
        upcast_attention (`bool`, *optional*):
            是否將注意力計算上升到 float32。這對混合精度訓練很有用。
    """

    # 初始化函式
    def __init__(
        self,
        dim: int,  # 輸入和輸出的通道數
        num_attention_heads: int,  # 查詢狀態的頭數
        num_key_value_attention_heads: int,  # 鍵和值狀態的頭數
        attention_head_dim: int,  # 每個頭的通道數
        dropout=0.0,  # 丟棄機率,預設為0
        cross_attention_dim: Optional[int] = None,  # 跨注意力的維度,可選
        upcast_attention: bool = False,  # 是否上升到 float32,預設為 False
        norm_eps: float = 1e-5,  # 歸一化層的小常數
        ff_inner_dim: Optional[int] = None,  # 前饋層內部維度,可選
    ):
        super().__init__()  # 呼叫父類建構函式
        # 定義三個模組。每個模組都有自己的歸一化層。
        # 1. 自注意力層
        self.norm1 = nn.LayerNorm(dim, elementwise_affine=True, eps=norm_eps)  # 自注意力的歸一化層
        self.attn1 = Attention(  # 自注意力模組
            query_dim=dim,  # 查詢維度
            heads=num_attention_heads,  # 頭數
            dim_head=attention_head_dim,  # 每個頭的維度
            dropout=dropout,  # 丟棄機率
            bias=False,  # 不使用偏置
            upcast_attention=upcast_attention,  # 是否上升到 float32
            out_bias=False,  # 不使用輸出偏置
            processor=StableAudioAttnProcessor2_0(),  # 使用的處理器
        )

        # 2. 跨注意力層
        self.norm2 = nn.LayerNorm(dim, norm_eps, True)  # 跨注意力的歸一化層

        self.attn2 = Attention(  # 跨注意力模組
            query_dim=dim,  # 查詢維度
            cross_attention_dim=cross_attention_dim,  # 跨注意力維度
            heads=num_attention_heads,  # 頭數
            dim_head=attention_head_dim,  # 每個頭的維度
            kv_heads=num_key_value_attention_heads,  # 鍵和值的頭數
            dropout=dropout,  # 丟棄機率
            bias=False,  # 不使用偏置
            upcast_attention=upcast_attention,  # 是否上升到 float32
            out_bias=False,  # 不使用輸出偏置
            processor=StableAudioAttnProcessor2_0(),  # 使用的處理器
        )  # 如果 encoder_hidden_states 為 None,則為自注意力

        # 3. 前饋層
        self.norm3 = nn.LayerNorm(dim, norm_eps, True)  # 前饋層的歸一化層
        self.ff = FeedForward(  # 前饋神經網路模組
            dim,  # 輸入維度
            dropout=dropout,  # 丟棄機率
            activation_fn="swiglu",  # 啟用函式
            final_dropout=False,  # 最後是否丟棄
            inner_dim=ff_inner_dim,  # 內部維度
            bias=True,  # 使用偏置
        )

        # 將塊大小預設設定為 None
        self._chunk_size = None  # 塊大小
        self._chunk_dim = 0  # 塊維度

    def set_chunk_feed_forward(self, chunk_size: Optional[int], dim: int = 0):
        # 設定塊前饋
        self._chunk_size = chunk_size  # 設定塊大小
        self._chunk_dim = dim  # 設定塊維度
    # 定義前向傳播方法,接收隱藏狀態和可選的注意力掩碼等引數
    def forward(
            self,
            hidden_states: torch.Tensor,
            attention_mask: Optional[torch.Tensor] = None,
            encoder_hidden_states: Optional[torch.Tensor] = None,
            encoder_attention_mask: Optional[torch.Tensor] = None,
            rotary_embedding: Optional[torch.FloatTensor] = None,
        ) -> torch.Tensor:
            # 注意:在後續計算中,歸一化總是應用於實際計算之前。
            # 0. 自注意力
            # 對輸入的隱藏狀態進行歸一化處理
            norm_hidden_states = self.norm1(hidden_states)
    
            # 計算自注意力輸出
            attn_output = self.attn1(
                norm_hidden_states,
                attention_mask=attention_mask,
                rotary_emb=rotary_embedding,
            )
    
            # 將自注意力輸出與原始隱藏狀態相加
            hidden_states = attn_output + hidden_states
    
            # 2. 跨注意力
            # 對更新後的隱藏狀態進行歸一化處理
            norm_hidden_states = self.norm2(hidden_states)
    
            # 計算跨注意力輸出
            attn_output = self.attn2(
                norm_hidden_states,
                encoder_hidden_states=encoder_hidden_states,
                attention_mask=encoder_attention_mask,
            )
            # 將跨注意力輸出與更新後的隱藏狀態相加
            hidden_states = attn_output + hidden_states
    
            # 3. 前饋網路
            # 對隱藏狀態進行歸一化處理
            norm_hidden_states = self.norm3(hidden_states)
            # 計算前饋網路輸出
            ff_output = self.ff(norm_hidden_states)
    
            # 將前饋網路輸出與當前隱藏狀態相加
            hidden_states = ff_output + hidden_states
    
            # 返回最終的隱藏狀態
            return hidden_states
# 定義一個名為 StableAudioDiTModel 的類,繼承自 ModelMixin 和 ConfigMixin
class StableAudioDiTModel(ModelMixin, ConfigMixin):
    """
    Stable Audio 中引入的擴散變換器模型。

    參考文獻:https://github.com/Stability-AI/stable-audio-tools

    引數:
        sample_size ( `int`, *可選*, 預設值為 1024):輸入樣本的大小。
        in_channels (`int`, *可選*, 預設值為 64):輸入中的通道數。
        num_layers (`int`, *可選*, 預設值為 24):使用的變換器塊的層數。
        attention_head_dim (`int`, *可選*, 預設值為 64):每個頭的通道數。
        num_attention_heads (`int`, *可選*, 預設值為 24):用於查詢狀態的頭數。
        num_key_value_attention_heads (`int`, *可選*, 預設值為 12):
            用於鍵和值狀態的頭數。
        out_channels (`int`, 預設值為 64):輸出通道的數量。
        cross_attention_dim ( `int`, *可選*, 預設值為 768):交叉注意力投影的維度。
        time_proj_dim ( `int`, *可選*, 預設值為 256):時間步內投影的維度。
        global_states_input_dim ( `int`, *可選*, 預設值為 1536):
            全域性隱藏狀態投影的輸入維度。
        cross_attention_input_dim ( `int`, *可選*, 預設值為 768):
            交叉注意力投影的輸入維度。
    """

    # 支援梯度檢查點
    _supports_gradient_checkpointing = True

    # 註冊到配置的建構函式
    @register_to_config
    def __init__(
        # 輸入樣本的大小,預設為1024
        self,
        sample_size: int = 1024,
        # 輸入的通道數,預設為64
        in_channels: int = 64,
        # 變換器塊的層數,預設為24
        num_layers: int = 24,
        # 每個頭的通道數,預設為64
        attention_head_dim: int = 64,
        # 查詢狀態的頭數,預設為24
        num_attention_heads: int = 24,
        # 鍵和值狀態的頭數,預設為12
        num_key_value_attention_heads: int = 12,
        # 輸出通道的數量,預設為64
        out_channels: int = 64,
        # 交叉注意力投影的維度,預設為768
        cross_attention_dim: int = 768,
        # 時間步內投影的維度,預設為256
        time_proj_dim: int = 256,
        # 全域性隱藏狀態投影的輸入維度,預設為1536
        global_states_input_dim: int = 1536,
        # 交叉注意力投影的輸入維度,預設為768
        cross_attention_input_dim: int = 768,
    ):
        # 呼叫父類的初始化方法
        super().__init__()
        # 設定樣本大小
        self.sample_size = sample_size
        # 設定輸出通道數
        self.out_channels = out_channels
        # 計算內部維度,等於注意力頭數量乘以每個頭的維度
        self.inner_dim = num_attention_heads * attention_head_dim

        # 建立穩定音訊高斯傅立葉投影物件,embedding_size 為時間投影維度的一半
        self.time_proj = StableAudioGaussianFourierProjection(
            embedding_size=time_proj_dim // 2,
            flip_sin_to_cos=True,  # 是否翻轉正弦和餘弦
            log=False,  # 是否使用對數
            set_W_to_weight=False,  # 是否將 W 設定為權重
        )

        # 時間步投影的神經網路序列,包含兩個線性層和一個啟用函式
        self.timestep_proj = nn.Sequential(
            nn.Linear(time_proj_dim, self.inner_dim, bias=True),  # 輸入為 time_proj_dim,輸出為 inner_dim
            nn.SiLU(),  # 使用 SiLU 啟用函式
            nn.Linear(self.inner_dim, self.inner_dim, bias=True),  # 再次投影到 inner_dim
        )

        # 全域性狀態投影的神經網路序列,包含兩個線性層和一個啟用函式
        self.global_proj = nn.Sequential(
            nn.Linear(global_states_input_dim, self.inner_dim, bias=False),  # 輸入為 global_states_input_dim,輸出為 inner_dim
            nn.SiLU(),  # 使用 SiLU 啟用函式
            nn.Linear(self.inner_dim, self.inner_dim, bias=False),  # 再次投影到 inner_dim
        )

        # 交叉注意力投影的神經網路序列,包含兩個線性層和一個啟用函式
        self.cross_attention_proj = nn.Sequential(
            nn.Linear(cross_attention_input_dim, cross_attention_dim, bias=False),  # 輸入為 cross_attention_input_dim,輸出為 cross_attention_dim
            nn.SiLU(),  # 使用 SiLU 啟用函式
            nn.Linear(cross_attention_dim, cross_attention_dim, bias=False),  # 再次投影到 cross_attention_dim
        )

        # 一維卷積層,用於預處理,卷積核大小為 1,不使用偏置
        self.preprocess_conv = nn.Conv1d(in_channels, in_channels, 1, bias=False)
        # 輸入線性層,將輸入通道數投影到 inner_dim,不使用偏置
        self.proj_in = nn.Linear(in_channels, self.inner_dim, bias=False)

        # 建立一個模組列表,包含多個 StableAudioDiTBlock
        self.transformer_blocks = nn.ModuleList(
            [
                StableAudioDiTBlock(
                    dim=self.inner_dim,  # 輸入維度為 inner_dim
                    num_attention_heads=num_attention_heads,  # 注意力頭數量
                    num_key_value_attention_heads=num_key_value_attention_heads,  # 鍵值注意力頭數量
                    attention_head_dim=attention_head_dim,  # 每個注意力頭的維度
                    cross_attention_dim=cross_attention_dim,  # 交叉注意力維度
                )
                for i in range(num_layers)  # 根據層數建立相應數量的塊
            ]
        )

        # 輸出線性層,將 inner_dim 投影到輸出通道數,不使用偏置
        self.proj_out = nn.Linear(self.inner_dim, self.out_channels, bias=False)
        # 一維卷積層,用於後處理,卷積核大小為 1,不使用偏置
        self.postprocess_conv = nn.Conv1d(self.out_channels, self.out_channels, 1, bias=False)

        # 初始化梯度檢查點標誌,預設為 False
        self.gradient_checkpointing = False

    @property
    # 從 UNet2DConditionModel 複製的屬性
    def attn_processors(self) -> Dict[str, AttentionProcessor]:
        r"""
        Returns:
            `dict` of attention processors: A dictionary containing all attention processors used in the model with
            indexed by its weight name.
        """
        # 建立一個空字典,用於儲存注意力處理器
        processors = {}

        # 定義遞迴函式,用於新增註意力處理器
        def fn_recursive_add_processors(name: str, module: torch.nn.Module, processors: Dict[str, AttentionProcessor]):
            # 如果模組有 get_processor 方法,獲取處理器並新增到字典
            if hasattr(module, "get_processor"):
                processors[f"{name}.processor"] = module.get_processor()

            # 遍歷子模組,遞迴呼叫新增處理器函式
            for sub_name, child in module.named_children():
                fn_recursive_add_processors(f"{name}.{sub_name}", child, processors)

            return processors

        # 遍歷當前物件的所有子模組,呼叫遞迴函式
        for name, module in self.named_children():
            fn_recursive_add_processors(name, module, processors)

        # 返回包含所有處理器的字典
        return processors
    # 從 diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.set_attn_processor 複製而來
    def set_attn_processor(self, processor: Union[AttentionProcessor, Dict[str, AttentionProcessor]]):
        r"""
        設定用於計算注意力的注意力處理器。

        引數:
            processor (`dict` of `AttentionProcessor` 或 `AttentionProcessor`):
                例項化的處理器類或將作為處理器設定為 **所有** `Attention` 層的處理器類字典。

                如果 `processor` 是一個字典,鍵需要定義對應的交叉注意力處理器的路徑。
                當設定可訓練的注意力處理器時,這一點強烈推薦。

        """
        # 獲取當前注意力處理器的數量
        count = len(self.attn_processors.keys())

        # 如果傳入的是字典且字典長度與注意力層數量不匹配,則丟擲異常
        if isinstance(processor, dict) and len(processor) != count:
            raise ValueError(
                f"傳入了處理器字典,但處理器數量 {len(processor)} 與"
                f" 注意力層數量 {count} 不匹配。請確保傳入 {count} 個處理器類。"
            )

        # 定義遞迴設定注意力處理器的函式
        def fn_recursive_attn_processor(name: str, module: torch.nn.Module, processor):
            # 如果模組有 set_processor 方法,則設定處理器
            if hasattr(module, "set_processor"):
                if not isinstance(processor, dict):
                    # 如果處理器不是字典,則直接設定
                    module.set_processor(processor)
                else:
                    # 從字典中彈出對應的處理器並設定
                    module.set_processor(processor.pop(f"{name}.processor"))

            # 遍歷模組的子模組,遞迴呼叫設定處理器的函式
            for sub_name, child in module.named_children():
                fn_recursive_attn_processor(f"{name}.{sub_name}", child, processor)

        # 遍歷當前物件的子模組,呼叫遞迴設定處理器的函式
        for name, module in self.named_children():
            fn_recursive_attn_processor(name, module, processor)

    # 從 diffusers.models.transformers.hunyuan_transformer_2d.HunyuanDiT2DModel.set_default_attn_processor 複製而來,將 Hunyuan 替換為 StableAudio
    def set_default_attn_processor(self):
        """
        禁用自定義注意力處理器,並設定預設的注意力實現。
        """
        # 呼叫設定注意力處理器的方法,使用 StableAudioAttnProcessor2_0 例項
        self.set_attn_processor(StableAudioAttnProcessor2_0())

    # 設定梯度檢查點的私有方法
    def _set_gradient_checkpointing(self, module, value=False):
        # 如果模組有 gradient_checkpointing 屬性,則設定其值
        if hasattr(module, "gradient_checkpointing"):
            module.gradient_checkpointing = value

    # 前向傳播方法定義
    def forward(
        # 輸入的隱藏狀態張量
        hidden_states: torch.FloatTensor,
        # 時間步張量,預設為 None
        timestep: torch.LongTensor = None,
        # 編碼器的隱藏狀態張量,預設為 None
        encoder_hidden_states: torch.FloatTensor = None,
        # 全域性隱藏狀態張量,預設為 None
        global_hidden_states: torch.FloatTensor = None,
        # 旋轉嵌入張量,預設為 None
        rotary_embedding: torch.FloatTensor = None,
        # 是否返回字典格式,預設為 True
        return_dict: bool = True,
        # 注意力掩碼,預設為 None
        attention_mask: Optional[torch.LongTensor] = None,
        # 編碼器的注意力掩碼,預設為 None
        encoder_attention_mask: Optional[torch.LongTensor] = None,

.\diffusers\models\transformers\t5_film_transformer.py

# 版權所有 2024 The HuggingFace Team. 保留所有權利。
#
# 根據 Apache 許可證第 2.0 版(“許可證”)進行許可;
# 除非遵守許可證,否則您不得使用此檔案。
# 您可以在以下網址獲取許可證副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非適用法律或書面協議另有規定,依據許可證分發的軟體
# 是按“原樣”基礎分發的,沒有任何形式的保證或條件,
# 無論是明示還是暗示。有關許可證下特定語言的許可權和
# 限制,請參閱許可證。
# 匯入數學模組以執行數學運算
import math
# 從 typing 匯入可選型別和元組
from typing import Optional, Tuple

# 匯入 PyTorch 庫
import torch
# 從 torch 匯入神經網路模組
from torch import nn

# 匯入配置工具和註冊功能
from ...configuration_utils import ConfigMixin, register_to_config
# 匯入注意力處理器
from ..attention_processor import Attention
# 匯入獲取時間步嵌入的功能
from ..embeddings import get_timestep_embedding
# 匯入模型工具的基類
from ..modeling_utils import ModelMixin


class T5FilmDecoder(ModelMixin, ConfigMixin):
    r"""
    T5 風格的解碼器,具有 FiLM 條件。

    引數:
        input_dims (`int`, *可選*, 預設為 `128`):
            輸入維度的數量。
        targets_length (`int`, *可選*, 預設為 `256`):
            目標的長度。
        d_model (`int`, *可選*, 預設為 `768`):
            輸入隱藏狀態的大小。
        num_layers (`int`, *可選*, 預設為 `12`):
            使用的 `DecoderLayer` 數量。
        num_heads (`int`, *可選*, 預設為 `12`):
            使用的注意力頭的數量。
        d_kv (`int`, *可選*, 預設為 `64`):
            鍵值投影向量的大小。
        d_ff (`int`, *可選*, 預設為 `2048`):
            `DecoderLayer` 中間前饋層的維度數量。
        dropout_rate (`float`, *可選*, 預設為 `0.1`):
            丟棄機率。
    """

    # 使用裝飾器註冊初始化函式到配置
    @register_to_config
    def __init__(
        # 輸入維度,預設為128
        self,
        input_dims: int = 128,
        # 目標長度,預設為256
        targets_length: int = 256,
        # 最大解碼噪聲時間,預設為2000.0
        max_decoder_noise_time: float = 2000.0,
        # 隱藏狀態的維度,預設為768
        d_model: int = 768,
        # 解碼層的數量,預設為12
        num_layers: int = 12,
        # 注意力頭的數量,預設為12
        num_heads: int = 12,
        # 鍵值維度大小,預設為64
        d_kv: int = 64,
        # 中間前饋層的維度,預設為2048
        d_ff: int = 2048,
        # 丟棄率,預設為0.1
        dropout_rate: float = 0.1,
    # 初始化父類
        ):
            super().__init__()
    
            # 建立條件嵌入層,包含兩層線性變換和啟用函式
            self.conditioning_emb = nn.Sequential(
                # 第一個線性層,輸入維度為 d_model,輸出維度為 d_model * 4,不使用偏置
                nn.Linear(d_model, d_model * 4, bias=False),
                # 使用 SiLU 啟用函式
                nn.SiLU(),
                # 第二個線性層,輸入維度為 d_model * 4,輸出維度同樣為 d_model * 4,不使用偏置
                nn.Linear(d_model * 4, d_model * 4, bias=False),
                # 使用 SiLU 啟用函式
                nn.SiLU(),
            )
    
            # 建立位置編碼嵌入,大小為 (targets_length, d_model)
            self.position_encoding = nn.Embedding(targets_length, d_model)
            # 禁止位置編碼的權重更新
            self.position_encoding.weight.requires_grad = False
    
            # 建立連續輸入的線性投影層,輸入維度為 input_dims,輸出維度為 d_model,不使用偏置
            self.continuous_inputs_projection = nn.Linear(input_dims, d_model, bias=False)
    
            # 建立 dropout 層,丟棄率為 dropout_rate
            self.dropout = nn.Dropout(p=dropout_rate)
    
            # 建立解碼器層的模組列表
            self.decoders = nn.ModuleList()
            # 迴圈建立 num_layers 個解碼器層
            for lyr_num in range(num_layers):
                # 初始化 FiLM 條件 T5 解碼器層
                lyr = DecoderLayer(d_model=d_model, d_kv=d_kv, num_heads=num_heads, d_ff=d_ff, dropout_rate=dropout_rate)
                # 將解碼器層新增到列表中
                self.decoders.append(lyr)
    
            # 建立解碼器層的歸一化層
            self.decoder_norm = T5LayerNorm(d_model)
    
            # 建立後續 dropout 層,丟棄率為 dropout_rate
            self.post_dropout = nn.Dropout(p=dropout_rate)
            # 建立輸出層,將 d_model 的輸出對映回 input_dims,不使用偏置
            self.spec_out = nn.Linear(d_model, input_dims, bias=False)
    
        # 定義編碼器-解碼器掩碼函式
        def encoder_decoder_mask(self, query_input: torch.Tensor, key_input: torch.Tensor) -> torch.Tensor:
            # 計算查詢和鍵輸入的掩碼,進行逐元素相乘
            mask = torch.mul(query_input.unsqueeze(-1), key_input.unsqueeze(-2))
            # 返回掩碼並擴充套件維度
            return mask.unsqueeze(-3)
    # 前向傳播方法,接受編碼及掩碼、解碼器輸入和噪聲時間
        def forward(self, encodings_and_masks, decoder_input_tokens, decoder_noise_time):
            # 獲取批次大小和解碼器輸入的形狀
            batch, _, _ = decoder_input_tokens.shape
            # 確保噪聲時間的形狀與批次一致
            assert decoder_noise_time.shape == (batch,)
    
            # 將 decoder_noise_time 重新縮放到期望的時間範圍
            time_steps = get_timestep_embedding(
                decoder_noise_time * self.config.max_decoder_noise_time,
                embedding_dim=self.config.d_model,
                max_period=self.config.max_decoder_noise_time,
            ).to(dtype=self.dtype)
    
            # 使用時間步長生成條件嵌入,並擴充套件維度
            conditioning_emb = self.conditioning_emb(time_steps).unsqueeze(1)
    
            # 確保條件嵌入的形狀正確
            assert conditioning_emb.shape == (batch, 1, self.config.d_model * 4)
    
            # 獲取解碼器輸入的序列長度
            seq_length = decoder_input_tokens.shape[1]
    
            # 如果使用相對位置,基於編碼和掩碼的長度偏移序列
            decoder_positions = torch.broadcast_to(
                torch.arange(seq_length, device=decoder_input_tokens.device),
                (batch, seq_length),
            )
    
            # 計算位置編碼
            position_encodings = self.position_encoding(decoder_positions)
    
            # 對解碼器輸入進行連續輸入投影
            inputs = self.continuous_inputs_projection(decoder_input_tokens)
            # 將位置編碼新增到輸入中
            inputs += position_encodings
            # 應用 dropout 操作
            y = self.dropout(inputs)
    
            # 建立解碼器掩碼,沒有填充
            decoder_mask = torch.ones(
                decoder_input_tokens.shape[:2], device=decoder_input_tokens.device, dtype=inputs.dtype
            )
    
            # 將編碼掩碼轉換為編碼器-解碼器掩碼
            encodings_and_encdec_masks = [(x, self.encoder_decoder_mask(decoder_mask, y)) for x, y in encodings_and_masks]
    
            # 交叉注意力風格:拼接編碼
            encoded = torch.cat([x[0] for x in encodings_and_encdec_masks], dim=1)
            encoder_decoder_mask = torch.cat([x[1] for x in encodings_and_encdec_masks], dim=-1)
    
            # 對每一層解碼器進行迴圈處理
            for lyr in self.decoders:
                y = lyr(
                    y,
                    conditioning_emb=conditioning_emb,
                    encoder_hidden_states=encoded,
                    encoder_attention_mask=encoder_decoder_mask,
                )[0]
    
            # 對輸出進行歸一化
            y = self.decoder_norm(y)
            # 應用 dropout 後處理
            y = self.post_dropout(y)
    
            # 生成最終的頻譜輸出
            spec_out = self.spec_out(y)
            # 返回頻譜輸出
            return spec_out
# T5 解碼器層的定義
class DecoderLayer(nn.Module):
    r"""
    T5 decoder layer.  # T5解碼器層的文件說明

    Args:  # 引數說明
        d_model (`int`):  # 輸入隱藏狀態的大小
            Size of the input hidden states.  # 輸入隱藏狀態的大小
        d_kv (`int`):  # 鍵值投影向量的大小
            Size of the key-value projection vectors.  # 鍵值投影向量的大小
        num_heads (`int`):  # 注意力頭的數量
            Number of attention heads.  # 注意力頭的數量
        d_ff (`int`):  # 中間前饋層的大小
            Size of the intermediate feed-forward layer.  # 中間前饋層的大小
        dropout_rate (`float`):  # 丟棄機率
            Dropout probability.  # 丟棄機率
        layer_norm_epsilon (`float`, *optional*, defaults to `1e-6`):  # 數值穩定性的小值
            A small value used for numerical stability to avoid dividing by zero.  # 數值穩定性的小值
    """

    # 初始化方法,定義各個引數
    def __init__(
        self, d_model: int, d_kv: int, num_heads: int, d_ff: int, dropout_rate: float, layer_norm_epsilon: float = 1e-6
    ):
        super().__init__()  # 呼叫父類建構函式
        self.layer = nn.ModuleList()  # 初始化模組列表以儲存層

        # 條件自注意力:第 0 層
        self.layer.append(
            T5LayerSelfAttentionCond(d_model=d_model, d_kv=d_kv, num_heads=num_heads, dropout_rate=dropout_rate)  # 新增條件自注意力層
        )

        # 交叉注意力:第 1 層
        self.layer.append(
            T5LayerCrossAttention(
                d_model=d_model,  # 輸入隱藏狀態的大小
                d_kv=d_kv,  # 鍵值投影向量的大小
                num_heads=num_heads,  # 注意力頭的數量
                dropout_rate=dropout_rate,  # 丟棄機率
                layer_norm_epsilon=layer_norm_epsilon,  # 數值穩定性的小值
            )
        )

        # Film Cond MLP + 丟棄:最後一層
        self.layer.append(
            T5LayerFFCond(d_model=d_model, d_ff=d_ff, dropout_rate=dropout_rate, layer_norm_epsilon=layer_norm_epsilon)  # 新增條件前饋層
        )

    # 前向傳播方法
    def forward(
        self,
        hidden_states: torch.Tensor,  # 輸入隱藏狀態張量
        conditioning_emb: Optional[torch.Tensor] = None,  # 條件嵌入(可選)
        attention_mask: Optional[torch.Tensor] = None,  # 注意力掩碼(可選)
        encoder_hidden_states: Optional[torch.Tensor] = None,  # 編碼器隱藏狀態(可選)
        encoder_attention_mask: Optional[torch.Tensor] = None,  # 編碼器注意力掩碼(可選)
        encoder_decoder_position_bias=None,  # 編碼器-解碼器位置偏置
    ) -> Tuple[torch.Tensor]:  # 返回張量的元組
        hidden_states = self.layer[0](  # 透過第一層處理輸入隱藏狀態
            hidden_states,
            conditioning_emb=conditioning_emb,  # 使用條件嵌入
            attention_mask=attention_mask,  # 使用注意力掩碼
        )

        # 如果存在編碼器隱藏狀態
        if encoder_hidden_states is not None:
            # 擴充套件編碼器注意力掩碼
            encoder_extended_attention_mask = torch.where(encoder_attention_mask > 0, 0, -1e10).to(
                encoder_hidden_states.dtype  # 轉換為編碼器隱藏狀態的資料型別
            )

            hidden_states = self.layer[1](  # 透過第二層處理隱藏狀態
                hidden_states,
                key_value_states=encoder_hidden_states,  # 使用編碼器隱藏狀態作為鍵值
                attention_mask=encoder_extended_attention_mask,  # 使用擴充套件的注意力掩碼
            )

        # 應用 Film 條件前饋層
        hidden_states = self.layer[-1](hidden_states, conditioning_emb)  # 透過最後一層處理隱藏狀態,使用條件嵌入

        return (hidden_states,)  # 返回處理後的隱藏狀態元組


# T5樣式的自注意力層,帶條件
class T5LayerSelfAttentionCond(nn.Module):
    r"""
    T5 style self-attention layer with conditioning.  # T5樣式的自注意力層,帶條件說明
    # 函式引數說明
    Args:
        d_model (`int`):  # 輸入隱藏狀態的大小
            Size of the input hidden states.
        d_kv (`int`):  # 鍵值投影向量的大小
            Size of the key-value projection vectors.
        num_heads (`int`):  # 注意力頭的數量
            Number of attention heads.
        dropout_rate (`float`):  # 丟棄機率
            Dropout probability.
    """

    # 初始化方法,設定類的基本引數
    def __init__(self, d_model: int, d_kv: int, num_heads: int, dropout_rate: float):
        super().__init__()  # 呼叫父類建構函式
        # 建立層歸一化層,輸入大小為 d_model
        self.layer_norm = T5LayerNorm(d_model)
        # 建立 FiLM 層,輸入特徵為 d_model * 4,輸出特徵為 d_model
        self.FiLMLayer = T5FiLMLayer(in_features=d_model * 4, out_features=d_model)
        # 建立注意力層,設定查詢維度、頭數、鍵值維度等引數
        self.attention = Attention(query_dim=d_model, heads=num_heads, dim_head=d_kv, out_bias=False, scale_qk=False)
        # 建立丟棄層,設定丟棄機率
        self.dropout = nn.Dropout(dropout_rate)

    # 前向傳播方法
    def forward(
        self,
        hidden_states: torch.Tensor,  # 輸入的隱藏狀態張量
        conditioning_emb: Optional[torch.Tensor] = None,  # 可選的條件嵌入
        attention_mask: Optional[torch.Tensor] = None,  # 可選的注意力掩碼
    ) -> torch.Tensor:
        # 對輸入的隱藏狀態進行層歸一化
        normed_hidden_states = self.layer_norm(hidden_states)

        # 如果有條件嵌入,應用 FiLM 層
        if conditioning_emb is not None:
            normed_hidden_states = self.FiLMLayer(normed_hidden_states, conditioning_emb)

        # 自注意力模組,獲取注意力輸出
        attention_output = self.attention(normed_hidden_states)

        # 將注意力輸出與原隱藏狀態相加,並應用丟棄層
        hidden_states = hidden_states + self.dropout(attention_output)

        # 返回更新後的隱藏狀態
        return hidden_states
# T5風格的交叉注意力層
class T5LayerCrossAttention(nn.Module):
    r"""
    T5風格的交叉注意力層。

    引數:
        d_model (`int`):
            輸入隱藏狀態的大小。
        d_kv (`int`):
            鍵值投影向量的大小。
        num_heads (`int`):
            注意力頭的數量。
        dropout_rate (`float`):
            丟棄機率。
        layer_norm_epsilon (`float`):
            用於數值穩定性的小值,避免除以零。
    """

    # 初始化方法,設定模型引數
    def __init__(self, d_model: int, d_kv: int, num_heads: int, dropout_rate: float, layer_norm_epsilon: float):
        # 呼叫父類初始化方法
        super().__init__()
        # 建立注意力層
        self.attention = Attention(query_dim=d_model, heads=num_heads, dim_head=d_kv, out_bias=False, scale_qk=False)
        # 建立層歸一化層
        self.layer_norm = T5LayerNorm(d_model, eps=layer_norm_epsilon)
        # 建立丟棄層
        self.dropout = nn.Dropout(dropout_rate)

    # 前向傳播方法
    def forward(
        self,
        hidden_states: torch.Tensor,
        key_value_states: Optional[torch.Tensor] = None,
        attention_mask: Optional[torch.Tensor] = None,
    ) -> torch.Tensor:
        # 對隱藏狀態進行層歸一化
        normed_hidden_states = self.layer_norm(hidden_states)
        # 計算注意力輸出
        attention_output = self.attention(
            normed_hidden_states,
            encoder_hidden_states=key_value_states,
            attention_mask=attention_mask.squeeze(1),
        )
        # 計算層輸出,新增丟棄
        layer_output = hidden_states + self.dropout(attention_output)
        # 返回層輸出
        return layer_output


# T5風格的前饋條件層
class T5LayerFFCond(nn.Module):
    r"""
    T5風格的前饋條件層。

    引數:
        d_model (`int`):
            輸入隱藏狀態的大小。
        d_ff (`int`):
            中間前饋層的大小。
        dropout_rate (`float`):
            丟棄機率。
        layer_norm_epsilon (`float`):
            用於數值穩定性的小值,避免除以零。
    """

    # 初始化方法,設定模型引數
    def __init__(self, d_model: int, d_ff: int, dropout_rate: float, layer_norm_epsilon: float):
        # 呼叫父類初始化方法
        super().__init__()
        # 建立帶門啟用的前饋層
        self.DenseReluDense = T5DenseGatedActDense(d_model=d_model, d_ff=d_ff, dropout_rate=dropout_rate)
        # 建立條件層
        self.film = T5FiLMLayer(in_features=d_model * 4, out_features=d_model)
        # 建立層歸一化層
        self.layer_norm = T5LayerNorm(d_model, eps=layer_norm_epsilon)
        # 建立丟棄層
        self.dropout = nn.Dropout(dropout_rate)

    # 前向傳播方法
    def forward(self, hidden_states: torch.Tensor, conditioning_emb: Optional[torch.Tensor] = None) -> torch.Tensor:
        # 對隱藏狀態進行層歸一化
        forwarded_states = self.layer_norm(hidden_states)
        # 如果存在條件嵌入,則應用條件層
        if conditioning_emb is not None:
            forwarded_states = self.film(forwarded_states, conditioning_emb)

        # 應用前饋層
        forwarded_states = self.DenseReluDense(forwarded_states)
        # 更新隱藏狀態,新增丟棄
        hidden_states = hidden_states + self.dropout(forwarded_states)
        # 返回更新後的隱藏狀態
        return hidden_states


# T5風格的前饋層,具有門控啟用和丟棄
class T5DenseGatedActDense(nn.Module):
    r"""
    T5風格的前饋層,具有門控啟用和丟棄。
    # 引數說明部分
    Args:
        d_model (`int`):  # 輸入隱藏狀態的尺寸
            Size of the input hidden states.
        d_ff (`int`):  # 中間前饋層的尺寸
            Size of the intermediate feed-forward layer.
        dropout_rate (`float`):  # 丟棄機率
            Dropout probability.
    """

    # 初始化方法,接受模型引數
    def __init__(self, d_model: int, d_ff: int, dropout_rate: float):
        super().__init__()  # 呼叫父類的初始化方法
        # 定義第一線性變換層,不使用偏置,輸入維度為d_model,輸出維度為d_ff
        self.wi_0 = nn.Linear(d_model, d_ff, bias=False)
        # 定義第二線性變換層,不使用偏置,輸入維度為d_model,輸出維度為d_ff
        self.wi_1 = nn.Linear(d_model, d_ff, bias=False)
        # 定義輸出線性變換層,不使用偏置,輸入維度為d_ff,輸出維度為d_model
        self.wo = nn.Linear(d_ff, d_model, bias=False)
        # 定義丟棄層,使用指定的丟棄機率
        self.dropout = nn.Dropout(dropout_rate)
        # 初始化自定義啟用函式
        self.act = NewGELUActivation()

    # 前向傳播方法,接受輸入的隱藏狀態
    def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
        # 透過第一線性層和啟用函式得到隱層狀態
        hidden_gelu = self.act(self.wi_0(hidden_states))
        # 透過第二線性層得到隱層狀態
        hidden_linear = self.wi_1(hidden_states)
        # 將兩個隱層狀態進行逐元素相乘
        hidden_states = hidden_gelu * hidden_linear
        # 應用丟棄層
        hidden_states = self.dropout(hidden_states)

        # 透過輸出線性層得到最終的隱層狀態
        hidden_states = self.wo(hidden_states)
        # 返回最終的隱層狀態
        return hidden_states
# T5風格的層歸一化模組
class T5LayerNorm(nn.Module):
    r"""
    T5風格的層歸一化模組。

    Args:
        hidden_size (`int`):
            輸入隱藏狀態的大小。
        eps (`float`, `optional`, defaults to `1e-6`):
            用於數值穩定性的小值,以避免除以零。
    """

    # 初始化函式,接受隱藏狀態大小和epsilon
    def __init__(self, hidden_size: int, eps: float = 1e-6):
        """
        構造一個T5風格的層歸一化模組。沒有偏置,也不減去均值。
        """
        # 呼叫父類建構函式
        super().__init__()
        # 初始化權重為全1的可學習引數
        self.weight = nn.Parameter(torch.ones(hidden_size))
        # 儲存epsilon值
        self.variance_epsilon = eps

    # 前向傳播函式,接受隱藏狀態
    def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
        # 計算隱藏狀態的方差,使用平方和的均值,保持維度
        variance = hidden_states.to(torch.float32).pow(2).mean(-1, keepdim=True)
        # 按照方差進行歸一化,同時考慮到epsilon
        hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)

        # 如果權重為半精度,轉換隱藏狀態為相應型別
        if self.weight.dtype in [torch.float16, torch.bfloat16]:
            hidden_states = hidden_states.to(self.weight.dtype)

        # 返回歸一化後的結果乘以權重
        return self.weight * hidden_states


# 實現GELU啟用函式的模組
class NewGELUActivation(nn.Module):
    """
    實現與Google BERT庫中相同的GELU啟用函式(與OpenAI GPT相同)。也可以參考
    Gaussian Error Linear Units論文:https://arxiv.org/abs/1606.08415
    """

    # 前向傳播函式,接受輸入張量
    def forward(self, input: torch.Tensor) -> torch.Tensor:
        # 計算GELU啟用值
        return 0.5 * input * (1.0 + torch.tanh(math.sqrt(2.0 / math.pi) * (input + 0.044715 * torch.pow(input, 3.0))))


# T5風格的FiLM層
class T5FiLMLayer(nn.Module):
    """
    T5風格的FiLM層。

    Args:
        in_features (`int`):
            輸入特徵的數量。
        out_features (`int`):
            輸出特徵的數量。
    """

    # 初始化函式,接受輸入和輸出特徵數量
    def __init__(self, in_features: int, out_features: int):
        # 呼叫父類建構函式
        super().__init__()
        # 定義線性層,用於生成縮放和偏移引數
        self.scale_bias = nn.Linear(in_features, out_features * 2, bias=False)

    # 前向傳播函式,接受輸入張量和條件嵌入
    def forward(self, x: torch.Tensor, conditioning_emb: torch.Tensor) -> torch.Tensor:
        # 透過線性層計算縮放和偏移
        emb = self.scale_bias(conditioning_emb)
        # 將結果分成縮放和偏移兩個部分
        scale, shift = torch.chunk(emb, 2, -1)
        # 進行縮放和偏移操作
        x = x * (1 + scale) + shift
        # 返回處理後的結果
        return x

相關文章