

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Hugging Face Transformers 스크립트에 SageMaker 스마트 시프팅 적용
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script"></a>

SageMaker 스마트 시프팅을 Transformers `Trainer` 클래스에 구현하는 방법은 두 가지가 있습니다.

**참고**  
SageMaker 스마트 시프팅 패키지가 설치된 상태에서 PyTorch용 DLC 중 하나를 사용하는 경우 `transformers` 라이브러리를 설치해야 합니다. SageMaker AI Python SDK에서 [DLC를 확장](prebuilt-containers-extend.md)하거나 PyTorch([https://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/sagemaker.pytorch.html](https://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/sagemaker.pytorch.html))에 대한 훈련 작업 시작 관리자 클래스로 `requirements.txt`를 전달하여 추가 패키지를 설치할 수 있습니다.

## 간단한 설정
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script-simple"></a>

SageMaker 스마트 시프팅을 Transformers `Trainer` 클래스에 구현하는 가장 간단한 방법은 `enable_sifting` 함수를 사용하는 것입니다. 이 함수는 기존 `Trainer` 객체를 수락하고 기존 `DataLoader` 객체를 `SiftingDataloader`로 래핑합니다. 동일한 훈련 객체를 계속 사용할 수 있습니다. 다음 예제 사용을 참조하세요.

```
from smart_sifting.integrations.trainer import enable_sifting
from smart_sifting.loss.abstract_sift_loss_module import Loss
from smart_sifting.sift_config.sift_configs import (
    RelativeProbabilisticSiftConfig
    LossConfig
    SiftingBaseConfig
)

class {{SiftingImplementedLoss}}(Loss):
   def loss(self, model, transformed_batch, original_batch):
        loss_fct = MSELoss(reduction="none") # make sure to set reduction to "none"
        logits = model.bert(**original_batch)
        return loss_fct(logits, original_batch.get("labels"))

sift_config = RelativeProbabilisticSiftConfig(
    beta_value={{0.5}},
    loss_history_length={{500}},
    loss_based_sift_config=LossConfig(
         sift_config=SiftingBaseConfig(sift_delay=0)
    )
)

trainer = Trainer(...)
enable_sifting(trainer, {{sift_config}}, loss={{SiftingImplementedLoss}}()) # updates the trainer with Sifting Loss and config
trainer.train()
```

`SiftingDataloader` 클래스는 반복 가능한 데이터 로더입니다. 시프팅 중 무작위 샘플링으로 인해 결과 데이터세트의 정확한 크기를 미리 알 수 없습니다. 따라서 Hugging Face `Trainer`는 [`max_steps` 훈련 인수](https://huggingface.co/docs/transformers/main_classes/trainer#transformers.TrainingArguments.max_steps)를 예상합니다. 이 인수는 에폭 구성 파라미터 `num_train_epochs`를 재정의합니다. 원본 데이터 로더도 반복 가능했거나 훈련에서 `max_steps` 및 단일 에포크를 사용하는 경우 `SiftingDataloader`는 기존 데이터 로더와 동일하게 수행합니다. 원래 데이터 로더를 반복할 수 없거나 `max_steps`가 제공되지 않은 경우 Hugging Face Trainer는 다음과 유사한 오류 메시지를 생성할 수 있습니다.

```
args.max_steps must be set to a positive value if dataloader does not have a length,
was -1
```

이를 해결하기 위해 `enable_sifting` 함수는 선택적 `set_epochs` 파라미터를 제공합니다. 이렇게 하면 `Trainer` 클래스의 [num\_train\_epochs 인수](https://huggingface.co/docs/transformers/main_classes/trainer#transformers.TrainingArguments.num_train_epochs(float,)에서 제공하는 에폭 수를 사용하여 에폭으로 훈련하고 `max_steps`를 최대 시스템 정수로 설정하여 지정된 에폭이 완료될 때까지 훈련이 진행될 수 있습니다.

## 사용자 지정 설정
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script-custom-trainer"></a>

SageMaker 스마트 시프팅 데이터로더의 사용자 지정 통합을 위해 사용자 지정 Hugging Face `Trainer` 클래스를 활용할 수 있습니다. `Trainer`의 하위 클래스 내에서 `get_train_dataloader()` 함수를 재정의하여 `SiftingDataloader` 클래스의 객체를 반환할 수 있습니다. 기존 사용자 지정 트레이너가 있는 사례의 경우 이 접근 방식은 침입성이 낮을 수 있지만 간단한 설정 옵션보다 코드를 변경해야 합니다. 다음은 사용자 지정 Hugging Face `Trainer` 클래스로 SageMaker 스마트 시프팅을 구현하는 예제입니다.

```
from smart_sifting.sift_config.sift_configs import (
    RelativeProbabilisticSiftConfig
    LossConfig
    SiftingBaseConfig
)
from smart_sifting.dataloader.sift_dataloader import SiftingDataloader
from smart_sifting.loss.abstract_sift_loss_module import Loss
from smart_sifting.data_model.data_model_interface import SiftingBatch, SiftingBatchTransform
from smart_sifting.data_model.list_batch import ListBatch

class {{SiftingListBatchTransform}}(SiftingBatchTransform):
    def transform(self, batch: Any):
        inputs = batch[0].tolist()
        labels = batch[-1].tolist()  # assume the last one is the list of labels
        return ListBatch(inputs, labels)

    def reverse_transform(self, list_batch: ListBatch):
        a_batch = [torch.tensor(list_batch.inputs), torch.tensor(list_batch.labels)]
        return a_batch

class {{SiftingImplementedLoss}}():
    # You should add the following initializaztion function 
    # to calculate loss per sample, not per batch.
    def __init__(self):
        self.celoss = torch.nn.{{CrossEntropyLoss}}(reduction='none')

    def loss(
        self,
        model: torch.nn.Module,
        transformed_batch: SiftingBatch,
        original_batch: Any = None,
    ) -> torch.Tensor:
        device = next(model.parameters()).device
        batch = [t.to(device) for t in original_batch]

        # compute loss
        outputs = model(batch)
        return self.celoss(outputs.logits, batch[2])

class {{SiftingImplementedTrainer}}(Trainer):
    def get_train_dataloader(self):
        {{dl}} = super().get_train_dataloader()

        sift_config = RelativeProbabilisticSiftConfig(
            beta_value={{0.5}},
            loss_history_length={{500}},
            loss_based_sift_config=LossConfig(
                sift_config=SiftingBaseConfig(sift_delay=0)
            )
        )

        return SiftingDataloader(
                sift_config=sift_config,
                orig_dataloader={{dl}},
                batch_transforms={{SiftingListBatchTransform}}(),
                loss_impl={{SiftingImplementedLoss}}(),
                model=self.model
        )
```

래핑된 `Trainer` 클래스를 사용하여 다음과 같이 객체를 생성합니다.

```
trainer = SiftingImplementedTrainer(
    model={{model}},
    args={{training_args}},
    train_dataset={{small_train_dataset}},
    eval_dataset={{small_eval_dataset}}
)

trainer.train()
```