Transformers documentation
모델 커스터마이징
모델 커스터마이징
Transformers 모델은 커스터마이징을 위해 설계되었습니다. 모델의 코드는 Transformers 저장소의 model 하위 폴더에 완전히 포함되어 있습니다. 각 폴더에는 modeling.py와 configuration.py 파일이 포함되어 있습니다. 이 파일들을 복사하여 모델 커스터마이징을 시작하세요.
완전히 새로운 모델을 만드는 경우라면 처음부터 시작하는 것이 더 쉬울 수 있습니다. 그러나 Transformers의 기존 모델과 매우 유사한 모델을 만드는 경우라면, 동일한 설정 및 모델 클래스를 재사용하거나 서브클래스로 만드는 것이 더 빠릅니다.
이 가이드에서는 ResNet 모델을 커스터마이징하고 AutoClass 지원을 활성화한 후 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 모델의 코드를 재사용하기가 더 쉬워집니다.
두 개의 ResNet 모델을 생성합니다. 하나는 hidden states를 출력하는 기본 ResNet 모델이고, 다른 하나는 이미지 분류 헤드가 포함된 ResNet 모델입니다.
block_types와 클래스 간의 매핑을 정의합니다. 나머지는 설정 클래스를 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)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와 호환됩니다. 다른 출력 형식의 경우, 학습을 위해 자체 학습 루프 또는 다른 라이브러리가 필요합니다.
configuration로 커스텀 모델 클래스를 인스턴스화합니다.
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와 호환됩니다. 사용자는 AutoModel 또는 AutoModelForImageClassification 클래스로 모델을 로드할 수 있습니다.
업로드
사용자가 쉽게 로드하고 사용할 수 있도록 Hub에 커스텀 모델을 업로드합니다.
아래와 같이 모델 디렉터리가 올바르게 구조화되어 있는지 확인하세요. 디렉터리에는 다음이 포함되어야 합니다:
modeling.py:ResnetModel과ResnetModelForImageClassification의 코드를 포함합니다. 이 파일은 같은 디렉토리에 있는 다른 파일에 대해 상대적 가져오기를 사용할 수 있습니다.
Transformers의 모델 파일을 복사할 때,
modeling.py파일 상단의 모든 상대적 import를 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 계정에 로그인하세요.
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 파일은 모두 이제 네임스페이스 아래 저장소에 업로드되어야 합니다.
커스텀 모델은 Transformers의 모델과 동일한 모델링 코드를 사용하지 않으므로, 로드하려면 from_pretrained()에 trust_remote_code=True를 추가해야 합니다. 자세한 내용은 커스텀 모델 로드 섹션을 참조하세요.