【前編】YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法
IT技術
前編~YAML で Optimizer のパラメータ管理が簡単に!~
みなさんは、Optimizer をどのように設定していますか?
よくあるのは、ArgumentParser などでコマンドラインから指定する方法だと思います。
でも、Optimizer やパラメータ追加のたびに、いちいちコードを書き換えるのは面倒…
そんな悩みを解決してくれるのが「YAML」です!
Optimizer のパラメータ管理が簡単になるだけでなく、コード自体もより単純でスッキリしたものになりますよ。
YAML とは
「YAML(YAML Ain't a Markup Language)」は、構造化データをわかりやすく記述するために生まれたデータフォーマットです。
設定ファイルやデータの保存・交換をする際によく用いられています。
同じデータフォーマットである XML と似ていますが、XML よりは読みやすく書きやすい傾向にあります。
また、Python と同じくインデントを使うのが特徴です。
【YAML 公式ドキュメント】
https://yaml.org/
YAML がないと面倒なケース
YAML の利便性を知ってもらうため、まずは「できないこともないけど、ちょっと面倒だな…」というケースを見ていきましょう!
サンプルコード:main1.py
まずは、Optimizer を作成するだけのプログラムを作成していきます。
1# -*- coding: UTF-8 -*-
2# ファイル名:main1.py
3import argparse
4import torch
5import torch.optim as optim
6import torch.nn as nn
7
8
9def make_optimizer(params, name, lr):
10 # Optimizer作成
11 if name=='SGD':
12 optimizer = optim.SGD(params, lr=lr)
13 elif name=='Adam':
14 optimizer = optim.Adam(params, lr=lr)
15 else:
16 raise Exception('{} はサポートされていません'.format(name))
17 return optimizer
18
19
20def get_args():
21 # 引数の導入
22 parser = argparse.ArgumentParser(description='YAML example')
23 parser.add_argument('--optim', type=str, required=True, help='optimizer name')
24 parser.add_argument('--lr', type=float, required=True, help='learning rate')
25 args = parser.parse_args()
26 return args
27
28
29def main(args):
30 # Model作成
31 model = nn.Linear(1, 1)
32 optimizer = make_optimizer(model.parameters(), args.optim, args.lr)
33
34 print(optimizer)
35
36
37if __name__=='__main__':
38 main(get_args())
実行するときには、「Optimizerの名前」--optim と「学習率」--lr を引数として指定します。
SGD 作成
以下では、SGD を作成します。
> はコマンドプロンプトのことです。
1> python main1.py --optim SGD --lr 0.05
2
3SGD (
4Parameter Group 0
5 dampening: 0
6 lr: 0.5
7 momentum: 0
8 nesterov: False
9 weight_decay: 0
10)
Adam 作成
次に、Adam を作成します。
1> python main.py --optim Adam --lr 0.05
2
3Adam (
4Parameter Group 0
5 amsgrad: False
6 betas: (0.9, 0.999)
7 eps: 1e-08
8 lr: 0.5
9 weight_decay: 0
10)
拡張性がない!
これ以上拡張しないのであれば、コーディングの量も少ないですし、特に問題はありません。
ただし、機械学習の訓練中は様々な Optimizer やパラメータを試す必要があります。
「拡張性」という点から考えると、上記のコードは後々面倒なことになりますね。
サンプルコード:main2.py
次に、SGD 特有の引数である「momentum」を追加でサポートしましょう。
上記の main1.py をコピーして main2.py を作り、下記の変更を加えます。
momentum を追加
まず、新しい引数である momentum をつけたします。
1def get_args():
2 # 引数の導入
3 parser = argparse.ArgumentParser(description='YAMLなしの例')
4 parser.add_argument('--optim', type=str, required=True, help='optimizer name')
5 parser.add_argument('--lr', type=float, required=True, help='learning rate')
6 parser.add_argument('--momentum', type=float, default=0.0, help='SGDのmomentum') # momentum 追加
7 args = parser.parse_args()
8 return args
make_optimizer に momentum 引数を追加
make_optimizer に momentum の引数をつけたします。
1def make_optimizer(params, name, lr, momentum): # momentum 追加
2 # Optimizer作成
3 if name=='SGD':
4 optimizer = optim.SGD(params, lr=lr, momentum=momentum) # momentum 追加
5 elif name=='Adam':
6 optimizer = optim.Adam(params, lr=lr)
7 else:
8 raise Exception('{} はサポートされていません'.format(args.optim))
9
10 return optimizer
args.momentum を追加
make_optimizer を呼び出すときに、args.momentum を追加で渡します。
1def main(args):
2 # Model作成
3 model = nn.Linear(1, 1)
4 optimizer = make_optimizer(model.parameters(), args.optim, args.lr, args.momentum) # momentum 追加
momentum の指定なし実行はデフォルト「0」が適用される
momentum はオプションです。
そのため、指定しないで実行すると、デフォルトの「0」が採用されます。
1> python main2.py --optim SGD --lr 0.05
2
3SGD (
4Parameter Group 0
5 dampening: 0
6 lr: 0.05
7 momentum: 0.0
8 nesterov: False
9 weight_decay: 0
10)
指定して実行した場合
momentum を指定して実行すれば、結果に値が反映されます。
1> python main2.py --optim SGD --lr 0.05 --momentum 0.9
2
3SGD (
4Parameter Group 0
5 dampening: 0
6 lr: 0.05
7 momentum: 0.9
8 nesterov: False
9 weight_decay: 0
10)
Adam は指定にかかわらず変化なし
ちなみに、Adam は momentum を使わないので、指定しても変化はありません。
1> python main2.py --optim Adam --lr 0.05 --momentum 0.9
2
3Adam (
4Parameter Group 0
5 amsgrad: False
6 betas: (0.9, 0.999)
7 eps: 1e-08
8 lr: 0.05
9 weight_decay: 0
10)
コード修正に手間がかかりすぎる!
この調子でもっと引数を追加したり、より多くの Optimizer をサポートしていく事は可能です。
ただし、新しいパラメータを追加する毎に3箇所でコード修正を施さなければなりません。
その上、コマンドラインからの指定だと、使うべきパラメータの判断がしにくい問題もあります。
YAML で設定を簡単にしよう!
上記のようなサンプルコードは、設定を YAML で記述し、ファイルから読み込むようにすれば、面倒がなくなります。
コマンドラインをシンプルにする
config1.yaml を作成
新たに main3.py として書き直したプログラムを使います(後ほど解説します)。
例として、config1.yaml を以下のように記述します。
1optimizer:
2 name: SGD
3 lr: 0.05
main3.py を実行
この設定ファイルを使って、main3.py を実行します。
1> python main3.py config1.yaml
2
3SGD (
4Parameter Group 0
5 dampening: 0
6 lr: 0.05
7 momentum: 0
8 nesterov: False
9 weight_decay: 0
10)
SGD が正しく作成されました。
YAML なしの場合と比べて、コマンドラインがスッキリしましたね。
パラメータを追加する
次は、パラメータを追加してみましょう。
config2.yaml を作成し、momentum を追加
config1.yaml をコピーして config2.yaml を作り、momentum を追加します。
1optimizer:
2 name: SGD
3 lr: 0.05
4 momentum: 0.9
main3.py を実行
実行の仕方は、さっきと同じです。
設定ファイルのパスを指定して実行しましょう!
1> python main3.py config2.yaml
2
3SGD (
4Parameter Group 0
5 dampening: 0
6 lr: 0.05
7 momentum: 0.9
8 nesterov: False
9 weight_decay: 0
10)
コード変更は不要
ちゃんと momentum の値が反映されていますね。
YAML でパラメータ値を記述しただけで、コードの変更は必要ありません。
異なる Optimizer を設定する
今度は、異なる Optimizer を設定しましょう。
config3.yaml を作成し、Adam を設定
config3.yaml を作って、Adam を設定します。
1optimizer:
2 name: Adam
3 lr: 0.05
main3.py を実行
実行すると、こちらも期待通りの結果になります。
1> python main3.py config3.yaml
2
3Adam (
4Parameter Group 0
5 amsgrad: False
6 betas: (0.9, 0.999)
7 eps: 1e-08
8 lr: 0.05
9 weight_decay: 0
10)
コード変更は不要
Optimizer の設定を変えましたが、やはりコードの変更は必要ありません。
YAML で記述した設定ファイルのみの変更です。
YAML 設定ファイルを書き換え、別の Optimizer を作成する
もう一つ、別の Optimizer を使ってみましょう。
config4.yaml を作成し、Adagrad を設定
config4.yaml を作って、Adagrad を設定します。
パラメータの数も増やしましょう。
1optimizer:
2 name: Adagrad
3 lr: 0.05
4 lr_decay: 0.9
5 weight_decay: 5.0e-5
main3.py を実行
これも、期待通りに動作します。
1> python main3.py config4.yaml
2
3Adagrad (
4Parameter Group 0
5 initial_accumulator_value: 0
6 lr: 0.05
7 lr_decay: 0.9
8 weight_decay: 5e-05
9)
パラメータ管理が楽になる
このように、YAML 形式で書いた設定ファイルの中身を変えるだけで、様々な Optimizer を作成する事ができます。
この方法だと、訓練用の設定ファイルを複数準備して使い分けができるので、パラメータ管理が楽になります。
後半へつづく!
後半の記事はこちら!
こちらの記事もオススメ!
2020.07.28機械学習 特集知識編人工知能・機械学習でよく使われるワード徹底まとめ!機械学習の元祖「パーセプトロン」とは?【人工知能】ニューラルネ...
2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪、名古屋の4拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit