Pytorchはdefine by run(実行しながら定義)なライブラリなので、 学習の途中でoptimizerにアクセスして、 learning rateを変更したりしてみたい。ということで、optimizerを定義した後でlearning rateなどにどのようにアクセスするかを調べてみた。
単純にLearning rateを変えたいだけなら以下のように書けばよい。
import torch model = torch.nn.Conv2d(1,1,3, bias=False) opt = torch.optim.Adam(model.parameters(), lr=0.00001) pg = opt.param_groups[0] pg['lr'] = 0.1
Optimizerのメンバへアクセス
optimzerのメンバへアクセスするには、下記のようにopt.param_groups[0]
を使う。
import torch from torch import nn model = nn.Conv2d(1,1,3, bias=False) opt = torch.optim.Adam(model.parameters()) lr = opt.param_groups[0]['lr']
上記のように書くと変数lr
に learning rateの値が入る。opt.param_groups[0]
の中身をもう少し見てみる。ipythonで上記のコマンドを実行後に以下のコマンドを打ってみる
print(opt.param_groups[0])
出力は以下
{'params': [Parameter containing: tensor([[[[ 0.1461, 0.2775, -0.1896], [ 0.0344, -0.1396, 0.2176], [-0.0873, 0.2879, -0.0561]]]], requires_grad=True)], 'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
試しにlrの値を変更して、もう一度出力を見る
opt.param_groups[0]['lr'] = 0.1 print(opt.param_groups[0])
出力は以下
{'params': [Parameter containing: tensor([[[[-0.1734, -0.0178, -0.0896], [-0.2925, -0.1085, 0.3080], [ 0.2562, -0.0101, 0.1187]]]], requires_grad=True), Parameter containing: tensor([-0.0762], requires_grad=True)], 'lr': 0.1, # <--ここが変化 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
lr
の値が変化していることがわかる。
params以外のパラメータのみを出力
今は例として非常に小さいモデル(nn.Conv2dのみ)を使っているが、一般的にはニューラルネットのモデルは大きいので、params
の部分に大量のデータが入る。params
をはずして出力したい場合は以下。
pg = opt.param_groups[0] {i: pg[i] for i in list(pg.keys())[1:]}
下記のような出力が得られる。
{'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
Adamでイテレーション回数を出力
Adamは移動平均を使っているので、実はoptimizerはイテレーション回数(opt.step()を行った回数)を保持している。これを使えばepochではなく、イテレーション回数で学習パラメータを変えることもできる。アクセスするには以下のようにopt.state[p]['step']
を見ればよい。ただし、1回以上loss.backward()とopt.step()を実行している必要がある。
import torch from torch import nn model = nn.Conv2d(1,1,3, bias=False) opt = torch.optim.Adam(model.parameters()) x = torch.randn(1,1,3,3), y = torch.randn(1,1,1,1) y_ = model.forward(x) loss = torch.mean(y-y_) opt.zero_grad() loss.backward() opt.step() p = opt.param_groups[0]['params'][0] iiter = opt.state[p]['step']
これでiiterの中にイテレーション回数が入る。