zuminote

個人的な勉強記録

PyTorchによる発展ディープラーニング 第1章 1-5 ファインチューニングの実装 メモ

前回1-3の転移学習でおこなった画像分類を、今度はファインチューニングで行う。

ファインチューニングとは、1-3で述べたとおり、学習済みモデルの出力層に近い部分だけでなく、全パラメータを再学習させることである。

ただし、入力層に近い部分のパラメータは学習率を小さく設定し、出力層に近い部分のパラメータは学習率を大きく設定する。

流れは1-3と基本的に同じ。

  1. DatasetとDataLoaderの作成

  2. ネットワークモデルの作成

  3. 損失関数の定義

  4. 最適化手法の定義

  5. 学習・検証の実施

1〜3は1-3とほぼ同じなので割愛。

4. 最適化手法の定義

ここでは、1-3の転移学習とは異なり、全層を学習させる。

ただし冒頭で述べたように入力層に近い部分と出力層に近い部分とで学習率を変えたいので、最適化手法を定義する前に、まず各層で学習率を変えられるようにパラメータを設定する。

今回は、前半featureモジュールのパラメータ、後半classifierモジュールのうち最初2つの全結合層、付け替えた最後の全結合層、以上3つのグループに分けて学習率を設定している。

コードの書き方は1-3と同じく、for文でnet.named_parameters()をイテレーションしてパラメータ名とパラメータ自身を取り出し、このあとoptim.SGDの引数とするためのリストに追加しつつ、param.requires_gradのTrue/Falseを設定する、という考え方である。

また、異なる学習率を設定する際のoptimizerの書き方は以下のように、辞書型でparamsと学習率を格納する。

(サンプルコードから引用)

optimizer = optim.SGD([
    {'params': params_to_update_1, 'lr': 1e-4},
    {'params': params_to_update_2, 'lr': 5e-4},
    {'params': params_to_update_3, 'lr': 1e-3}
], momentum=0.9)

5. 学習・検証の実施

1-3と異なり、今回はGPUを用いる。

GPUを使用するには以下のように書いて、ネットワークモデル、モデルに入力するデータ、ラベルデータをGPUに転送する。

(netはモデルを格納した変数)

(サンプルコードより引用)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)

また、torch.backends.cudnn.benchmark = Trueと設定することによって高速化できるらしい。

これはcuDNNのベンチマークモードをオンにするかどうかのオプションで、CNNのようにネットワークの入力サイズが変化しない場合はGPUでの計算を高速化できる。原則、推奨と考えてよいだろう。

参考:

Google ColabでやるPyTorchとKerasの比較(DenseNetを例に) - Qiita

学習したネットワークのパラメータは、torch.save(net.state_dict(), save_path)で保存できる(netはモデルを格納した変数、save_pathは保存場所のファイルパス)。

ロードする際は以下のように、まずtorch.loadで、辞書型オブジェクトの重みをロードしてから、.load_state_dict()でネットワークにその重みを渡す。

(サンプルコードより引用)

load_path = './weights_fine_tuning.pth'
load_weights = torch.load(load_path)
net.load_state_dict(load_weights)

GPU上で保存した重みをCPU上でロードする際には、torch.loadの引数でmap_location={'cuda:0': 'cpu'}として、CPUを指定する必要がある。

github.com