Transformers 文件

自定義模型

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

自定義模型

Transformers 模型被設計為可自定義的。模型的程式碼完全包含在 Transformers 倉庫的 model 子資料夾中。每個資料夾都包含一個 modeling.py 和一個 configuration.py 檔案。複製這些檔案即可開始自定義模型。

如果您要建立一個全新的模型,從頭開始可能更容易。但對於與 Transformers 中現有模型非常相似的模型,重用或子類化相同的配置和模型類會更快。

本指南將向您展示如何自定義 ResNet 模型、啟用 AutoClass 支援,以及如何在 Hub 上共享它。

配置

配置,由基礎 PretrainedConfig 類給出,包含構建模型所需的所有必要資訊。您將在此處配置自定義 ResNet 模型的屬性。不同的屬性會產生不同的 ResNet 模型型別。

自定義配置的主要規則是:

  1. 自定義配置必須繼承自 PretrainedConfig。這確保了自定義模型具有 Transformers 模型的所有功能,例如 from_pretrained()save_pretrained()push_to_hub()
  2. PretrainedConfig__init__ 必須接受任何 kwargs,並且它們必須傳遞給超類的 __init__PretrainedConfig 擁有比您自定義配置中設定的更多欄位,因此當您使用 from_pretrained() 載入配置時,您的配置需要接受這些欄位並將其傳遞給超類。

檢查某些引數的有效性很有用。在下面的示例中,實現了一個檢查以確保 block_typestem_type 屬於預定義值之一。

向配置類新增 model_type 以啟用 AutoClass 支援。

from transformers import PretrainedConfig
from typing import List

class ResnetConfig(PretrainedConfig):
    model_type = "resnet"

    def __init__(
        self,
        block_type="bottleneck",
        layers: list[int] = [3, 4, 6, 3],
        num_classes: int = 1000,
        input_channels: int = 3,
        cardinality: int = 1,
        base_width: int = 64,
        stem_width: int = 64,
        stem_type: str = "",
        avg_down: bool = False,
        **kwargs,
    ):
        if block_type not in ["basic", "bottleneck"]:
            raise ValueError(f"`block_type` must be 'basic' or bottleneck', got {block_type}.")
        if stem_type not in ["", "deep", "deep-tiered"]:
            raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}.")

        self.block_type = block_type
        self.layers = layers
        self.num_classes = num_classes
        self.input_channels = input_channels
        self.cardinality = cardinality
        self.base_width = base_width
        self.stem_width = stem_width
        self.stem_type = stem_type
        self.avg_down = avg_down
        super().__init__(**kwargs)

使用 save_pretrained() 將配置儲存到自定義模型資料夾 custom-resnet 中的 JSON 檔案。

resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d_config.save_pretrained("custom-resnet")

模型

透過自定義 ResNet 配置,您現在可以建立和自定義模型。該模型繼承自基礎 PreTrainedModel 類。與 PretrainedConfig 一樣,繼承自 PreTrainedModel 並使用配置初始化超類會擴充套件 Transformers 的功能,例如將模型儲存和載入到自定義模型中。

Transformers 的模型遵循在 __init__ 方法中接受 config 物件的約定。這將整個 config 傳遞給模型子層,而不是將 config 物件分解為單獨傳遞給子層的多個引數。

以這種方式編寫模型會產生更簡單的程式碼,併為任何超引數提供清晰的真實來源。它還使得更容易重用來自其他 Transformers 模型中的程式碼。

您將建立兩個 ResNet 模型:一個輸出隱藏狀態的骨架 ResNet 模型,以及一個帶影像分類頭的 ResNet 模型。

ResnetModel
ResnetModelForImageClassification

定義塊型別和類之間的對映。所有其他內容都是透過將配置類傳遞給 ResNet 模型類來建立的。

向模型類新增 config_class 以啟用 AutoClass 支援。

from transformers import PreTrainedModel
from timm.models.resnet import BasicBlock, Bottleneck, ResNet
from .configuration_resnet import ResnetConfig

BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}

class ResnetModel(PreTrainedModel):
    config_class = ResnetConfig

    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )

    def forward(self, tensor):
        return self.model.forward_features(tensor)

模型可以返回任何輸出格式。當標籤可用時,返回帶損失的字典(如 ResnetModelForImageClassification)會使自定義模型與 Trainer 相容。對於其他輸出格式,您需要自己的訓練迴圈或不同的庫進行訓練。

使用配置例項化自定義模型類。

resnet50d = ResnetModelForImageClassification(resnet50d_config)

此時,您可以將預訓練權重載入到模型中或從頭開始訓練它。在本指南中,您將載入預訓練權重。

timm 庫載入預訓練權重,然後使用 load_state_dict 將這些權重傳輸到自定義模型。

import timm

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

AutoClass

AutoClass API 是一種用於自動載入給定模型正確架構的快捷方式。為載入您的自定義模型使用者啟用此功能會很方便。

確保您在配置類中具有 model_type 屬性(必須不同於現有模型型別)以及在模型類中具有 config_class 屬性。使用 register() 方法將自定義配置和模型新增到 AutoClass API 中。

AutoConfig.register() 的第一個引數必須與自定義配置類中的 model_type 屬性匹配,而 AutoModel.register() 的第一個引數必須與自定義模型類的 config_class 匹配。

from transformers import AutoConfig, AutoModel, AutoModelForImageClassification

AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)

您的自定義模型程式碼現在與 AutoClass API 相容。使用者可以使用 AutoModelAutoModelForImageClassification 類載入模型。

上傳

將自定義模型上傳到 Hub,以便其他使用者可以輕鬆載入和使用它。

確保模型目錄結構正確,如下所示。目錄應包含:

  • modeling.py:包含 ResnetModelResnetModelForImageClassification 的程式碼。此檔案可以依賴於對同一目錄中其他檔案的相對匯入。

複製 Transformers 模型檔案時,請將 modeling.py 檔案頂部的所有相對匯入替換為從 Transformers 匯入。

  • configuration.py:包含 ResnetConfig 的程式碼。
  • __init__.py:可以為空,此檔案允許將 Python resnet_model 用作模組。
.
└── resnet_model
    ├── __init__.py
    ├── configuration_resnet.py
    └── modeling_resnet.py

要共享模型,請匯入 ResNet 模型和配置。

from resnet_model.configuration_resnet import ResnetConfig
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification

複製模型和配置檔案中的程式碼。為了確保 AutoClass 物件隨 save_pretrained() 一起儲存,請呼叫 register_for_auto_class() 方法。這將修改配置 JSON 檔案以包含 AutoClass 物件和對映。

對於模型,根據任務選擇適當的 AutoModelFor 類。

ResnetConfig.register_for_auto_class()
ResnetModel.register_for_auto_class("AutoModel")
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")

要將多個任務對映到模型,請直接編輯配置 JSON 檔案中的 auto_map

"auto_map": {
    "AutoConfig": "<your-repo-name>--<config-name>",
    "AutoModel": "<your-repo-name>--<config-name>",
    "AutoModelFor<Task>": "<your-repo-name>--<config-name>",    
},

建立配置和模型並載入預訓練權重。

resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d = ResnetModelForImageClassification(resnet50d_config)

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

模型現在可以推送到 Hub。從命令列或筆記本登入到您的 Hugging Face 帳戶。

huggingface-CLI
筆記本
huggingface-cli login

在模型上呼叫 push_to_hub() 以將模型上傳到 Hub。

resnet50d.push_to_hub("custom-resnet50d")

現在,預訓練權重、配置、modeling.pyconfiguration.py 檔案都應該已上傳到您名稱空間下的 repository 中。

由於自定義模型不使用與 Transformers 模型相同的建模程式碼,因此您需要在 from_pretrained() 中新增 trust_remote_code=True 才能載入它。有關更多資訊,請參閱載入 自定義模型 部分。

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.