

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Hugging Face Transformers 脚本中应用 SageMaker 智能筛选
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script"></a>

有两种方法可以实现变形金刚`Trainer`类的 SageMaker 智能筛选。

**注意**  
如果您使用安装了 SageMaker 智能筛选软件包 DLCs 的 PyTorch for 之一，请注意您需要安装该`transformers`库。您可以通过[扩展 DLCs](prebuilt-containers-extend.md)或传递`requirements.txt`到 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)) 的训练作业启动器类来安装其他包。

## 设置简单
<a name="train-smart-sifting-apply-to-hugging-face-transformers-script-simple"></a>

在《变形金刚》`Trainer`类中实现 SageMaker 智能筛选的最简单方法是使用该`enable_sifting`函数。此函数接受现有 `Trainer` 对象，并使用 `SiftingDataloader` 包装现有 `DataLoader` 对象。您可以继续使用相同的训练对象。请参阅以下使用示例。

```
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\$1train\$1epochs argument](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` 类的一个对象。对于已有自定义训练器的情况，这种方法可能干扰较少，但与简单设置选项相比，需要修改代码。以下是 SageMaker 智能筛选到自定义 Hugging Face 类的示例实现。`Trainer`

```
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()
```