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

    メディアチームメディアチーム
    2020.09.17

    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 を作成する事ができます。

    この方法だと、訓練用の設定ファイルを複数準備して使い分けができるので、パラメータ管理が楽になります。

    後半へつづく!

    後半の記事はこちら!

    featureImg2020.09.19【後編】YAMLを使ってPyTorchのOptimizerのパラメータ管理をすごく簡単にする方法後編~YAML で Optimizer のパラメータ管理が簡単に!~ArgumentParser などで、Optimi...

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

    featureImg2020.07.28機械学習 特集知識編人工知能・機械学習でよく使われるワード徹底まとめ!機械学習の元祖「パーセプトロン」とは?【人工知能】ニューラルネ...
    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

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

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

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

    採用情報へ

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

    おすすめ記事

    エンジニア大募集中!

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

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

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

    background