PyTorch Ignite 0.4.8 : ガイド : Ignite で FastaiLRFinder を使う方法

PyTorch Ignite 0.4.8 : How To ガイド : Igniteで FastaiLRFinder を使う方法 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/18/2022 (0.4.8)

* 本ページは、Pytorch Ignite AI の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス

クラスキャット は人工知能・テレワークに関する各種サービスを提供しています。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

  • 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
  • sales-info@classcat.com  ;  Web: www.classcat.com  ;   ClassCatJP

 

 

ガイド : Ignite で FastaiLRFinder を使う方法

この how-to ガイドは、モデルを訓練するために最適な学習率を見つけるために FastaiLRFinder ハンドラを活用する方法を実演します。より良い理解のためにこれにより生成された結果とハンドラの使用なしで生成されたものを比較します。

このサンプルでは、MNIST データセット上の ResNet18 モデルを使用していきます。ベースコードは Getting Start ガイド で使用されたものと同じです。

 

基本セットアップ

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.models import resnet18
from torchvision.transforms import Compose, Normalize, ToTensor

from ignite.engine import create_supervised_trainer, create_supervised_evaluator
from ignite.metrics import Accuracy, Loss
from ignite.handlers import FastaiLRFinder
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()

        self.model = resnet18(num_classes=10)
        self.model.conv1 = nn.Conv2d(
            1, 64, kernel_size=3, padding=1, bias=False
        )

    def forward(self, x):
        return self.model(x)


model = Net().to(device)

data_transform = Compose([ToTensor(), Normalize((0.1307,), (0.3081,))])

train_loader = DataLoader(
    MNIST(download=True, root=".", transform=data_transform, train=True),
    batch_size=128,
    shuffle=True,
)

test_loader = DataLoader(
    MNIST(download=True, root=".", transform=data_transform, train=False),
    batch_size=256,
    shuffle=False,
)


model = Net().to(device)
optimizer = torch.optim.RMSprop(model.parameters(), lr=1e-06)
criterion = nn.CrossEntropyLoss()

最初に 1e-06 の固定学習率 (lr) でモデルを訓練して結果を調べます。比較のためにモデルと optimizer の初期状態をセーブして後でそれらをリストアしましょう。

init_model_state = model.state_dict()
init_opt_state = optimizer.state_dict()

 

Without LR Finder

trainer = create_supervised_trainer(model, optimizer, criterion, device=device)

trainer.run(train_loader, max_epochs=3)
State:
	iteration: 1407
	epoch: 3
	epoch_length: 469
	max_epochs: 3
	output: 0.5554001927375793
	batch: <class 'list'>
	metrics: <class 'dict'>
	dataloader: <class 'torch.utils.data.dataloader.DataLoader'>
	seed: <class 'NoneType'>
	times: <class 'dict'>
evaluator = create_supervised_evaluator(
    model, metrics={"Accuracy": Accuracy(), "Loss": Loss(criterion)}, device=device
)
evaluator.run(test_loader)

print(evaluator.state.metrics)
{'Accuracy': 0.8655, 'Loss': 0.602867822265625}

FastaiLRFinder ハンドラを使用してより良い結果を獲得できる方法を見ましょう。しかしまず、モデルと optimizer の初期状態をそれらをスクラッチから再訓練できるようにリストアしましょう。

model.load_state_dict(init_model_state)
optimizer.load_state_dict(init_opt_state)

 

With LR Finder

trainer に装着されるとき、このハンドラは fastai により使用されるのと同じ手続きに従いします。モデルは num_iter イテレーション訓練される間、学習率は start_lr (optimizer で指定される初期値のデフォルト、ここでは 1e-6) から end_lr と呼ばれる上界まで増やされます。この増加は線形 (step_mode=”linear”) か指数関数 (step_mode=”exp”) であり得ます。デフォルトの step_mode は exponential です、これは大きい学習率範囲に対して勧められます、一方で linear は小さい範囲に対して良い結果を提供します。

lr_finder = FastaiLRFinder()

# To restore the model's and optimizer's states after running the LR Finder
to_save = {"model": model, "optimizer": optimizer}

with lr_finder.attach(trainer, to_save, end_lr=1e-02) as trainer_with_lr_finder:
    trainer_with_lr_finder.run(train_loader)

指定された範囲内で学習率がどのように変化するかプロットして提案される学習率をプリントしましょう。

lr_finder.plot()

print("Suggested LR", lr_finder.lr_suggestion())

Suggested LR 1.0148376909312998e-05

今度は optimizer に提案された学習率を適用して、最適な学習率でモデルを再訓練します。

lr_finder.apply_suggested_lr(optimizer)
print(optimizer.param_groups[0]["lr"])
1.0148376909312998e-05
trainer.run(train_loader, max_epochs=3)
State:
	iteration: 1407
	epoch: 3
	epoch_length: 469
	max_epochs: 3
	output: 0.09644963592290878
	batch: <class 'list'>
	metrics: <class 'dict'>
	dataloader: <class 'torch.utils.data.dataloader.DataLoader'>
	seed: <class 'NoneType'>
	times: <class 'dict'>
# Calculate the new metrics after using the optimal lr
evaluator.run(test_loader)
print(evaluator.state.metrics)
{'Accuracy': 0.9715, 'Loss': 0.0908882568359375}

最適な学習率で同じエポック数の間モデルを訓練したとき、テストデータセットで精度は上がり、損失は現象したことが分かりました。

 

以上