HuggingFaceでの早期打ち切り-例
概要
このレポートでは、早期打ち切り正則化を使用してHuggingFaceTransformerを微調整する例を示します。HuggingFaceのTrainerAPI
とともに、ネイティブのPyTorchおよびTensorFlowワークフローによる早期打ち切りの使用について説明します。
ネイティブTensorFlow
ColabでTFを使用してHuggingFace Transformerを微調整する →\rightarrow
TensorFlow(Keras)を使用してHuggingFace Transformerを微調整している場合、tf.keras.callbacks.EarlyStopping
コールバックを使用すると、早期打ち切りを追加するのは非常に簡単です。監視するメトリックの名前と、改善がない場合にトレーニングが停止されるまでのエポック数が含まれます。
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])
観察
-
検証の損失から明らかなように、モデルはトレーニングデータセットにすぐに過剰適合しました。
-
早期打ち切りのあるトレーニングモデルは、トレーニングプロセスの早期終了につながります。これにより、計算コストと時間が節約されます。
-
モデルの最良のインスタンス(ローセット検証損失)は
EarlyStopping
コールバックを使用して保存されたため、結果のテスト精度はより一般化されたモデルを示しています。
ネイティブPyTorch
ColabでPyTorchを使用してHuggingFace Transformerを微調整する →\rightarrow
ネイティブPyTorchには、既成の早期打ち切り方法はありません。ただし、ネイティブのPyTorchを使用してHuggingFace Transformerを微調整している場合は、早期打ち切りフックを提供するGitHub Gistがあります。
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)
トレーニングループの早期打ち切りを使用するには、上記のリンク先の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コードを再編成することを強くお勧めします。早期打ち切りやその他の多くの技術を既成のものとして提供します。PyTorch Lightningに慣れていない場合は、以下のレポートを参考にしてください。