

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Hugging Face Transformers スクリプトに SageMaker スマートふるいを適用する
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script"></a>

SageMaker スマートふるいを Transformers `Trainer` クラスに実装するには、2 つの方法があります。

**注記**  
SageMaker スマートふるいパッケージがインストールされている PyTorch 用の DLC のいずれかを使用する場合は、`transformers` ライブラリをインストールする必要があることに注意してください。[DLC を拡張する](prebuilt-containers-extend.md)か、SageMaker AI Python SDK の 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>

Transformers `Trainer` クラスに SageMaker スマートふるいを実装する最も簡単な方法は、`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` と 1 つのエポックが使用されていた場合、`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()
```