Skip to main content

HuggingFace中的Early Stopping ——示例

使用Early Stoping正则化功能微调您的HuggingFace Transformer。
Created on February 25|Last edited on July 12
本报告是作者Ayush Thakur所写的 "Early Stopping in HuggingFace - Examples"的翻译

导言

在此报告中,我们将看到一些示例,这些示例使用early stopping正则化来微调您的HuggingFace Transformer。 我们将使用原生PyTorch和TensorFlow工作流程以及HuggingFace的Trainer API来讲解early stopping的使用。

early-stopping-en.png



原生TensorFlow

在Colab中使用TF微调HuggingFace Transformer →\rightarrow

如果您使用TensorFlow(Keras)来微调HuggingFace Transformer,则使用tf.keras.callbacks.EarlyStopping回调来添加early stopping非常简单。 它采用您将监视的指标的名称,以及在没有改善的情况下停止训练的epoch数。

early_stopper = tf.keras.callbacks.EarlyStopping(monitor='val_loss', 
                                                 patience=5, 
                                                 restore_best_weights=True)

这里early_stopper是可以与model.fit一起使用的回调。

model.fit(trainloader, 
          epochs=10, 
          validation_data=validloader,
          callbacks=[early_stopper])

观察结果

  • 该模型很快在训练数据集上过度拟合,这从验证损失中可以明显看出。

  • early stopping训练模式会导致训练过程提前终止。反过来,这节省了计算成本和时间。

  • 由于使用EarlyStopping回调保存了模型的最佳实例(最低的验证损失),测试准确性表明模型更为通用。




Run set
4


原生PyTorch

在Colab中使用PyTorch微调HuggingFace Transformer →\rightarrow

原生PyTorch没有现成的early stopping方法。但是,如果您使用原生PyTorch对HuggingFace Transformer进行微调,则可以使用GitHub Gist ,它提供了一个有效的early stopping hook。

class EarlyStopping(object):
    def __init__(self, mode='min', min_delta=0, patience=10, percentage=False):
        self.mode = mode
        self.min_delta = min_delta
        self.patience = patience
        self.best = None
        self.num_bad_epochs = 0
        self.is_better = None
        self._init_is_better(mode, min_delta, percentage)

        if patience == 0:
            self.is_better = lambda a, b: True
            self.step = lambda a: False

    def step(self, metrics):
        if self.best is None:
            self.best = metrics
            return False

        if np.isnan(metrics):
            return True

        if self.is_better(metrics, self.best):
            self.num_bad_epochs = 0
            self.best = metrics
        else:
            self.num_bad_epochs += 1

        if self.num_bad_epochs >= self.patience:
            print('terminating because of early stopping!')
            return True

        return False

    def _init_is_better(self, mode, min_delta, percentage):
        if mode not in {'min', 'max'}:
            raise ValueError('mode ' + mode + ' is unknown!')
        if not percentage:
            if mode == 'min':
                self.is_better = lambda a, best: a < best - min_delta
            if mode == 'max':
                self.is_better = lambda a, best: a > best + min_delta
        else:
            if mode == 'min':
                self.is_better = lambda a, best: a < best - (
                            best * min_delta / 100)
            if mode == 'max':
                self.is_better = lambda a, best: a > best + (
                            best * min_delta / 100)


要在训练循环中使用early stopping,请查看上面链接的Colab笔记本

es = EarlyStopping(patience=5)

num_epochs = 100
for epoch in range(num_epochs):
      train_one_epoch(model, data_loader)  # train the model for one epoch.
      metric = eval(model, data_loader_dev)  # evalution on dev set.
      if es.step(metric):
          break  # early stop criterion is met, we can stop now

我强烈建议您使用PyTorch Lightning重新组织您的PyTorch代码。它提供了early stopping功能和许多其他现成的技术。如果您不熟悉PyTorch Lightning,请参考以下报告:




Run set
2

Iterate on AI agents and models faster. Try Weights & Biases today.