実験管理(2)

筆者個人用のメモ書きです.

Gitオブジェクト

Gitにおけるスナップショットの単位であるコミットは,実態として,主に3種類のオブジェクト:blob, tree, commitから構成される. ステージングされたファイル:git addで管理下に入ったファイルは,blobオブジェクトとして保管される. ファイルの実態としてblobより小さい単位は無いため,サイズの大きなファイルの一部だけを更新した場合でも,次のスナップショットには新たにサイズの大きなblobがオブジェクトが格納される.[1]

git pushコマンドは,更新されたローカルリポジトリを構成するのに必要なオブジェクトをリモートリポジトリに送信する. git push時,あるいは定期的・自動的に,gitはパッキングと呼ばれる仕組みを用いて,複数のblobオブジェクトについてその差分だけを保存するような整理を行う. これにより,通信量とストレージ容量の削減を行う.[3]

ただし,このパッキングが走る以前には,変更が行われたファイルの容量(をzlibで圧縮した分+α)だけ,リポジトリの容量が増加する. このような状況において,大容量のファイルの一部だけを繰り返し更新するようなケースでは,ファイルを分割して,一部のファイルだけに更新が発生するような設計にするのが賢い.

実験管理のためのGit

複数の実験サーバーを抱えている状況で,そのうち一台でモデルの学習・評価が完了したタイミングを想像する. この時,自動的にgit add / commit / pushが行われれば,コード・学習済みモデル・メタ情報の3点がセットでリモートリポジトリに保管される. あとから特定のコミットを指定してチェックアウトすれば,この時の環境を復元することも可能.

構成

  • 前提: サーバーAが自動pushを実行したのと前後して,サーバーBもpushをする状況.
  • 1) それぞれ同名の実験結果ファイルを追加する場合: コンフリクトするので実験のトライアルごとにbranchを切って,各ブランチはマージされない運用を考える.[4]
  • 2) 別名の実験結果を保存していく場合: サーバーAとサーバーBが同じブランチに保存しても良い

1の構成を採用する場合には大量のブランチが作成されるが,ファイルの内容が同じであれば(パッキングが効くかどうかは別にして)同じblobオブジェクトになるので,無駄な複製は起きない.[1]

次の懸念は,実験によって作成されるブランチ/コミットは,何を親とするべきか,という点にある. コード・モデル・メタの3点をセットにして保存するというだけならGoogle Driveにでも入れておけばよいが,ここではGitによるblobオブジェクト・パッキング・zlib圧縮による恩恵に与りたい. そこで,Gitそのものの「親・子」の概念を尊重してGitを使うことにする. ひいては,各実験トライアルに共通している,ready to executeな実験コードを派生元とするのがわかりやすい.
そこで,次のような運用を検討している:

  • (1) コーディング・デバッグ
  • (2) 完成したready to executeなコードをmasterにgit add/commit/push
  • (3) 各実験サーバーでgit fetch origin master + git stash + git checkout masterを実行
    • git fecth origin masterでリモートのmasterを構成する情報をローカルに落とす
    • git stashで各実験サーバーで未コミットの状態を退避(checkout時のエラー回避目的)
    • git checkoutで各実験サーバーをready to executeな新たな実験コードの状態にする
  • (4) 各実験サーバーで学習・評価を行い,結果をローカルファイルに保存
  • (5-選択肢1) 各実験サーバーでそれぞれmasterを派生元としてbranchを切る / 結果ファイルは各サーバーで同名
  • (5-選択肢2) 各実験サーバーでそれぞれ別名の結果ファイルを保存し,ブランチはmasterのまま
    • 選択肢1をマージすると考えても良い
  • (6) git fetch / add / commit / push

実験管理ツール採用の余地

gitを使う構成を検討したが,結局,「実験の直前に実験コードをリモートのmasterから同期してくる」「実験によって生まれた差分(実験結果)をadd/commit/pushする」という運用になっている. コードはこのgit運用でうまく管理できているので,実験によって生成されたメタ情報と学習済みモデルを実験管理ツールのほうに送信して保存しても良いのではないか. そうすることによって,メタ情報の俯瞰・比較が行いやすくなる.

参考文献

[1] Gitのオブジェクトの中身. https://zenn.dev/kaityo256/articles/objects_of_git
[2] git pushの裏側で何が起こっているのか。~javascriptでgitをリバースエンジニアリングで実装する(4)~. https://zenn.dev/hirokihello/articles/d5866bc64f13e3f3b8c7
[3] 10.4 Gitの内側 - Packfile. https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Packfile
[4] 複数の作業環境から変更が同一ブランチにpushされるGitリポジトリについて、リモートにある内容を確実に手元に反映する. https://www.clear-code.com/blog/2016/9/2.html