• トップ
  • ブログ一覧
  • 【後編】YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法
  • 【後編】YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法

    メディアチームメディアチーム
    2020.09.19

    IT技術

    後編~YAML で Optimizer のパラメータ管理が簡単に!~

    ArgumentParser などで、Optimizer やパラメータ追加のたびに、いちいちコードを書き換えるのは面倒…

    そんな悩みを解決してくれるのが「YAML」です。

    Optimizer のパラメータ管理が簡単になるだけでなく、コード自体もより単純でスッキリしたものになります。

    前回に引き続き、「YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法」をご紹介します!

    前編をお読みでない方は、こちらをまずお読みください。

    featureImg2020.09.17【前編】YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法前編~YAML で Optimizer のパラメータ管理が簡単に!~みなさんは、Optimizer をどのように設定し...

    YAML でシンプルなコーディングを実現

    さて、これを実現するコード「main3.py」は、冒頭のサンプルコード「main1.py」や「main2.py」よりも複雑で巨大なものなのでしょうか?

    いいえ、そんな事はありません。

    実は、コードそのものがよりシンプルになります。

    YAML を使うための下準備

    Pythonバージョンは3.6以上
    PyTorchバージョンは1.0以上

    環境については、上記を想定しています。

    YAML を使えるようにインストールします。

    1> pip install pyyaml

    準備はこれだけです。

    サンプルコード:main3.py

    main3.py の中身は、下記のとおりです。

    1# -*- coding: UTF-8 -*-
    2# ファイル名:main3.py
    3import argparse
    4import torch
    5import torch.optim as optim
    6import torch.nn as nn
    7import yaml
    8
    9
    10def make_optimizer(params, name, **kwargs):
    11    # Optimizer作成
    12    return optim.__dict__[name](params, **kwargs)
    13
    14
    15def get_args():
    16    # 引数の導入
    17    parser = argparse.ArgumentParser(description='YAMLありの例')
    18    parser.add_argument('config_path', type=str, help='設定ファイル(.yaml)')
    19    args = parser.parse_args()
    20    return args
    21
    22
    23def main(args):
    24    # 設定ファイル(.yaml)の読み込み
    25    with open(args.config_path, 'r') as f:
    26        config = yaml.safe_load(f)
    27
    28    # Model作成
    29    model = nn.Linear(1, 1)
    30    optimizer = make_optimizer(model.parameters(), **config['optimizer'])
    31
    32    print(optimizer)
    33
    34
    35if __name__=='__main__':
    36    main(get_args())

    ご覧のとおり、main1.py や main2.py に比べて、よりシンプルなコードに変更されています。

    では、変更箇所を一つ一つ見ていきましょう。

    引数を導入する

    まずは、「引数の導入」のコードです。

    1def get_args():
    2    # 引数の導入
    3    parser = argparse.ArgumentParser(description='YAMLありの例')
    4    parser.add_argument('config_path', type=str, help='設定ファイル(.yaml)')
    5    args = parser.parse_args()
    6    return args

    ここでは、設定ファイル「.yaml」を指定するconfig_path のみを引数として扱っています。

    Optimizer を作成する

    次は、make_optimizer で、Optimizer を作成するコードです。

    1def make_optimizer(params, name, **kwargs):
    2    # Optimizer作成
    3    return optim.__dict__[name](params, **kwargs)

    名前空間 optim

    ここの optim は、下記のところでインポートされた名前空間です。

    1import torch.optim as optim

    optim._dict_ に Optimizer の名前を渡すと、そのクラスを取得できます。

    Optimizer のオブジェクトを作成する際に渡した**kwargs に、YAML で設定されたパラメータの値が入ってきます。

    設定ファイルを読み込み、make_optimizer に渡す

    次は、main のコードを見てみましょう。

    1def main(args):
    2    # 設定ファイル(.yaml)の読み込み
    3    with open(args.config_path, 'r') as f:
    4        config = yaml.safe_load(f)
    5
    6    # Model作成
    7    model = nn.Linear(1, 1)
    8    optimizer = make_optimizer(model.parameters(), **config['optimizer'])
    9
    10    print(optimizer)

    ここでは、設定ファイルを読み込み、返り値のconfig から取り出した'optimizer' セクションをmake_optimizer に渡します。

    この部分は、設定ファイルの YAML がプログラムでどのように処理されていくのか、順番に見ていくとよりわかりやすいでしょう。

    パラメータを追加

    まずは、パラメータを追加する config2.yaml の内容を思い出して下さい。

    1optimizer:
    2    name: SGD
    3    lr: 0.05
    4    momentum: 0.9

    YAML 設定ファイルを読み込む

    下記のコードで、YAML の設定ファイルが読み込まれ、config に格納されます。

    1with open(args.config_path, 'r') as f:
    2    config = yaml.safe_load(f)

    このconfigdict オブジェクトです。

    Python だとどうなる?

    Python では、このようになります。

    1{'optimizer': {'name': 'SGD', 'lr': 0.05, 'momentum': 0.9}}

    config['optimizer'] のところは、'optimizer' をキーとして値を取り出しています。

    1{'name': 'SGD', 'lr': 0.05, 'momentum': 0.9}

    記述は違っても呼び方は同じ

    よって、以下の2つのコードは、まったく同じ呼び方ということになります。

    1optimizer = make_optimizer(model.parameters(), **config['optimizer'])
    1optimizer = make_optimizer(model.parameters(), name='SGD', lr=0.05, momentum=0.9)

    引数の名前が指定されているなら、順番は気にしなくていい

    ここで、name lr momentum それぞれの順番は重要ではありません。

    Python では引数の名前が指定されている場合、その順番は関数の宣言通りでなくても良いからです。

    よって、YAML の設定ファイルが以下のように記述されていても、同様に動作します。

    1optimizer:
    2    momentum: 0.9
    3    name: SGD
    4    lr: 0.05

    name は最初に記述しよう

    ただし、どの Optimizer 設定にも必須なname は、一番最初に記述しておいた方が違和感が少ないです。

    YAML の設定変更だけで、どんなOptimizer もサポート可能

    make_optimizer ではname で Optimizer のクラスを取り出し、**kwargs にある残り全てのパラメータをそのまま渡します。

    1def make_optimizer(params, name, **kwargs):
    2    # Optimizer作成
    3    return optim.__dict__[name](params, **kwargs)

    上記のコードが、下記のように実行されているイメージになります。

    1def make_optimizer(params, name='SGD', lr=0.05, momentum=0.9):
    2    # Optimizer作成
    3    optimizer_class = optim.__dict__[name] # optim.SGD class
    4    return optimizer_class(params, lr=lr, momentum=momentum)

    以上をまとめると、「YAML で指定したname で Optimizer のクラスを取り出し、残り全てのパラメータを、そのクラスのオブジェクトを作るときに渡している」となります。

    このやり方だと、どの Optimizer のどのパラメータでも、YAML の設定を変えるだけでサポートできるようになります。

    YAMLを使う際の注意点

    ここからは、YAML の設定時に注意したいポイントをまとめてみました。

    name で指定する Optimizer の名前は PyTorch で定義されているもののみ

    例えば、SGD のところがsgd と書かれていたらエラーになります。

    設定できる Optimizer の名前は、下記のリンクで確認できます。

    【Github ソースコード】
    https://github.com/pytorch/pytorch/blob/master/torch/optim/__init__.py

    独自定義のクラスを使いたい場合

    また、独自に定義した Optimizer のクラスを取り入れたい場合もあるでしょう。

    その時は、「make_optimizer で、独自の名前空間をはじめにチェックする」などの工夫が必要になります。

    Optimizer のパラメータ名は定義されたものを使う

    lr をlearning_rate など、違う名前で設定したら PyTorch から怒られます。

    これは、ソースコードと設定ファイルでパラメータ名が統一されるので、利点でもあります。

    Optimizer ごとの設定の詳細は、下記のリンクを参照してください。

    【pytorch 公式ドキュメント】
    https://pytorch.org/docs/stable/optim.html

    「true」と「false」を使う

    Python ではTrue とFalse なのですが、YAML では全て小文字です。

    慣れないうちは間違えやすいので、気をつけましょう。

    小数点を忘れずに

    「1.0e-4」なら OK ですが、「1e-4」と記述すると、Python のstr 型として認識されてしまいます。

    「1.0」のように、必ず小数点をつけましょう。

    ちなみに、「1.e-4」でも大丈夫ですが、「1.0e-4」の方が読みやすいと思います。

    list 型は[]を使う

    YAML では[0.9, 0.09]はlist 型として認識されますが、(0.9, 0.09)はstr 型になってしまいます。

    Adam の betas パラメータはtuple 型ですが、list 型で渡しても問題ありません

    よって、YAML では[] で記述しましょう。

    さいごに

    いかがでしょうか?

    YAML を使えば、「Optimizer のパラメータ管理」や「簡潔かつ分かりやすいコーディング」が簡単にできます。

    また、YAML でパラメータ設定をする方法は、Scheduler や DataLoader にも適用できます。

    とても便利なので、ぜひ応用してみてくださいね。

    こちらの記事もオススメ!

    featureImg2020.07.28機械学習 特集知識編人工知能・機械学習でよく使われるワード徹底まとめ!機械学習の元祖「パーセプトロン」とは?【人工知能】ニューラルネ...

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    メディアチーム
    メディアチーム
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background