Transformers documentation
モデルのカスタマイズ
モデルのカスタマイズ
Transformers のモデルはカスタマイズ可能に設計されています。モデルのコードはすべて、Transformers リポジトリの model サブフォルダに格納されています。各フォルダには modeling.py と configuration.py というファイルが含まれています。これらのファイルをコピーして、モデルのカスタマイズを開始してください。
完全に新しいモデルを作成する場合は、ゼロから始める方が簡単かもしれません。ただし、Transformers に既存のモデルと非常に類似したモデルを作成する場合は、同じ設定クラスとモデルクラスを再利用またはサブクラス化する方が速いです。
このガイドでは、AutoClassのサポートを有効にし、ResNetモデルをカスタマイズしてHubに共有する方法を説明します。
設定
ベースとなる PreTrainedConfig クラスによって定義される設定には、モデルを構築するために必要な情報がすべて含まれています。カスタム ResNet モデルの属性を構成するのはここです。属性によって、異なるタイプの ResNet モデルが得られます。
設定をカスタマイズするための主なルールは以下の通りです。
- A custom configuration must subclass PreTrainedConfig. This ensures a custom model has all the functionality of a Transformers’ model such as from_pretrained(), save_pretrained(), and push_to_hub().
- PreTrainedConfig の
__init__は、任意のkwargsを受け入れ、それらをスーパークラスの__init__に渡す必要があります。PreTrainedConfig には、カスタム設定で設定されるものよりも多くのフィールドがあるため、from_pretrained() で設定を読み込む場合、これらのフィールドはカスタム設定によって受け入れられ、スーパークラスに渡す必要があります。
一部の引数の妥当性を確認することは有用です。以下の例では、
block_typeとstem_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)custom-resnetフォルダに、save_pretrained() を使用して設定を 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 のモデルからのコードの再利用も容易になります。
2つのResNetモデルを作成します。1つは隠れ状態を出力するシンプルなResNetモデル、もう1つは画像分類ヘッドを備えたResNetモデルです。
ブロックタイプとクラスの間のマッピングを定義します。それ以外は、設定クラスを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)ラベルが利用可能な場合、各logitの損失を計算するためにforwardメソッドを書き直す必要があります。それ以外の場合、ResNetモデルクラスは同じです。
モデルクラスに
config_classを追加して、AutoClassのサポートを有効にします。
import torch
class ResnetModelForImageClassification(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, labels=None):
logits = self.model(tensor)
if labels is not None:
loss = torch.nn.functional.cross_entropy(logits, labels)
return {"loss": loss, "logits": logits}
return {"logits": logits}モデルは任意の出力形式を返すことができます。ラベルが利用可能な場合に損失を含む辞書(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() の第1引数は、カスタム設定クラスの
model_type属性と一致する必要があり、AutoModel.register()の第1引数は、カスタムモデルクラスのconfig_classと一致する必要があります。
from transformers import AutoConfig, AutoModel, AutoModelForImageClassification
AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)カスタムモデルのコードは、AutoClass API と互換性を持つようになりました。ユーザーは AutoModel または AutoModelForImageClassification クラスを使用してモデルを読み込むことができます。
アップロード
カスタムモデルをHubにアップロードし、他のユーザーが簡単に読み込んで使用できるようにします。
以下に示すように、モデルディレクトリが正しく構成されていることを確認してください。ディレクトリには以下が含まれている必要があります。
modeling.py:ResnetModelとResnetModelForImageClassificationのコードが含まれています。同じディレクトリ内の他のファイルであれば、相対インポートに依存できます。
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モデルファイルと設定ファイルからコードをコピーします。save_pretrained() で AutoClass オブジェクトが保存されることを確認するために、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アカウントにログインしてください。
hf auth login
from huggingface_hub import notebook_login
notebook_login()モデルに対してpush_to_hub()を呼び出して、モデルをHubにアップロードします。
resnet50d.push_to_hub("custom-resnet50d")事前学習済み重み、設定、modeling.py および configuration.py ファイルはすべて、あなたの名前空間配下の リポジトリ に Hub へアップロードされるべきです。
カスタムモデルは Transformers のモデルと同じモデリングコードを使用しないため、読み込むには from_pretrained() に trust_remote_code=True を追加する必要があります。詳細は カスタムモデルの読み込み セクションを参照してください。