Closed5

短期の機械学習プロジェクトにおけるconfig管理の最適解について

bilzardbilzard

概要

hydraを使ってる人が多いように見えるが、自分はメリットがあまり理解できなかった。
そもそも何が欲しいんだっけ?を整理する意味で自分が現状行なっているコンフィグ管理のメリットとデメリットを整理する。

なお、この運用方法は自分で思いついたものではなく、過去のKaggleコンペの入賞コード[1]で使われたものをアレンジしたもの。以降の記述はこれを1年程度運用して得た所感を反映したものになっている。

前提

実務での運用のようにある長期間の運用フェーズにあるプロジェクトではなく、Kaggleのようなプロジェクトを想定している。具体的には、管理中にコードがfixしておらず、実験を進めながら試行錯誤しながら管理するもので、かつ短期間(1〜3ヶ月)でコードベースを凍結するようなプロジェクト。

現状の運用

SimpleNamespaceを使っている。運用方法としては、conf配下にv0001.pyというファイルを追加していく。

conf/
    - v0001.py
    - v0002.py
    - ...

中身は以下のような感じ:

from types import SimpleNamespace

cfg = SimpleNamespace()

cfg.batch_size = 32
cfg.lr = 1e-4
...

メリット

  1. dictだとconf["hoge"]のように[""]をいちいち打ち込むのが面倒だが、SimpleNamespaceはオブジェクトの参照conf.hogeで書けるのでタイピング量が少なく可読性も高い。
  2. pythonのプログラムが書けるのでadaptiveに決まる設定をカジュアルに書ける(例: cfg.lr = cfg.base_lr / cfg.batch_size * 128)。特に、Albumentationsのaugmentationの設定など、シリアライズが面倒な設定もconfigでオブジェクト定義すれば特に悩む必要なく書ける。
  3. wandbのような実験管理ツールにコンフィグの値をまとめて渡すのがしやすい(cfg.__dict__で渡せる)。自前のクラスを定義する場合はオブジェクトの元からある属性とコンフィグパラメータを明確に区別するのが難しく、「アンダースコアで始まらない属性をgetattrで取得する」といったややロバストさに欠けるコードが必要になる(まぁ「アンダースコアから始まるパラメータは使用しない」と決めておけばそこまで問題ではない)。
自前のクラスを定義する例
class Config:
    batch_size = 32
    lr = 1e-4
    ...

デメリット

  1. ロードのコードは少し冗長になる(後述)が、utilとかで関数定義定義すればそんなに問題にはならない。
  2. 階層的な記述ができない。ただし、addictのように階層的記述ができるものもある。また、そもそも階層的に管理しないといけないほど複雑化するんだっけ?というのもある。
  3. pythonコードが書けるのはメリットでもある反面、コンフィグが定義順序に依存する、というデメリットもある。

1について、以下のコードをスクリプトの最初に1度だけ記述する。

from importlib import import_module

# CONFIG_VERSIONはスクリプトの引数などで渡す
cfg = import_module(f"config.v{CONFIG_VERSION:04d}").cfg

さらにあると良い機能

  1. スクリプトの引数でconfigを上書きするコードを書くのが面倒なので、両者を透過的に扱えると良い(hydraにこの機能あるのだったか?)
  2. Pylanceなどの静的解析ツールでコード補完できると便利なのでスキーマが定義できるとよい(hydraでできるはず)。ただし、スキーマとconfig自身と同期しながら管理する必要があり、管理コストは増加する。特に、試行錯誤段階ではスキーマの変更が頻発するので管理コストの方が得られるメリットより大きくなるかもしれない。

参考

bilzardbilzard

現状の運用に関する補足: コンフィグのdefault値を指定する

毎回コンフィグするのがコピペ面倒な場合は、default.pyみたいなのを定義しておいて各configから呼べば良い。

default.py
cfg = SimpleNamespace()

cfg.batch_size = 32
cfg.lr = 1e-4
...
v0001.py
from conf.default import cfg
cfg.batch_size = 64
...
bilzardbilzard

後方互換性の担保について

スキーマや格納している値の意味を変更する際、後方互換性を保持するためのリファクタリングが都度発生するが、これはどの実験管理ツールにもつきまとうものだと思う。

bilzardbilzard

試行錯誤段階の実験パラメータを全部再現できる必要あるのか?問題

パラメータを少し変えるだけでコンフィグファイルのコピペが発生するのは面倒といえば面倒。カジュアルに実験を繰り返していくと数百ファイルくらいは軽く到達する。それぞれのconfigは何が違うのか?が分かりにくくなる(現状はexcelシートでconfigごとの違いを一覧できるようにしてある)。

Optunaのようにパラメータ探索する場合の相性

あまり試したことがないが、Optunaなどのパラメータ探索ツールとの相性が良いのか?という観点もある。

bilzardbilzard

Hydraが少し複雑な研究プロジェクトでのコンフィグ管理のために生まれたことを考えると、要件は自分のケースと合ってそうに見える。

This addresses challenges that can arise when modifying a config, such as having to maintain many slightly different copies of a configuration, or adding custom logic to override individual configuration values.

Dynamic command-line tab completion, which helps with discoverability of complex configurations and reduces user errors

Hydra is already in use at Facebook to prototype complex research projects.

https://engineering.fb.com/2019/10/03/open-source/hydra/

このスクラップは2023/11/10にクローズされました