run-experiment について
機械学習研究者向けの実験投入スキルです。ローカル、SLURM、RunAI/Kubernetes 環境向けに再現可能なジョブスクリプトを作成し、投入コマンドを提示します。
主な機能
- 01ローカル、SLURM、RunAI 環境に対応
- 02環境別ジョブスクリプトの生成
- 03投入コマンドと Git コミットハッシュの記録
- 04スクリプトの構文・書式チェック
- 05SLURM ジョブアレイに対応
活用シーン
- 01HPC クラスターへの学習ジョブ投入
- 02ローカル実験用スクリプトの生成
- 03ハイパーパラメータ探索用の SLURM ジョブアレイ設定
- 04再現可能な実験実行設定の記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ a-green-hand-jack/ ml-research-skills --skill run-experimentインストール後、Claude Code で/run-experimentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
environments.yamltemplates/local_run.shrunai_job.shslurm_job.sh詳細
実験を実行する
ML 実験をコンピューティング環境(ローカルマシン、SLURM HPC(Ibex、UW など)、RunAI/Kubernetes(EPFL))に送信します。
コードと一緒にコミットされる再現可能なジョブスクリプトを jobs/ に生成し、実行する正確な送信コマンドを提示します。
起動したジョブを計画済みの実験、エビデンス項目、ワークツリー、またはプロジェクトアクションに関連付ける場合は、このスキルを research-project-memory と併用してください。
生成したジョブスクリプトを起動前にチェックする場合は、このスキルをプロジェクトのツールチェーンゲートと併用してください。利用できる場合は shellcheck と shfmt を使いますが、スクリプトのドラフトを生成するためにユーザーへインストールを要求しないでください。
用語:
local:エージェントが実行されているマシン。通常はユーザーの Mac ですGit remote:コードの同期に使用する GitHub/GitLab のリモート。たとえばoriginですserver:quest、ibex-vscode、epfl-haasなどの SSH/HPC/RunAI 実行環境です
SLURM または RunAI で起動する場合は、Git リモートを指す場合を除き、「リモート実行」ではなく「サーバー実行」と呼んでください。
スキルのディレクトリ構成
<installed-skill-dir>/
├── SKILL.md
├── environments.yaml # Environment profiles (extend for new clusters)
└── templates/
├── slurm_job.sh # SLURM template (Ibex, UW, any SLURM cluster)
├── runai_job.sh # RunAI/Kubernetes template (EPFL)
└── local_run.sh # Local tmux/nohup template
実行手順
1. 環境レジストリを読む
<installed-skill-dir> を、この SKILL.md が格納されているディレクトリとして特定し、<installed-skill-dir>/environments.yaml を読み込みます。
利用可能な環境を、それぞれ一行の説明とともにユーザーに提示します。
2. 実験の詳細を尋ねる
ユーザーに1つのメッセージで次の項目を尋ねます。
- 環境:どのコンピューティング環境を使いますか?(
environments.yamlにある選択肢と「その他」を表示) - スクリプト/コマンド:実行するコマンドは何ですか?(例:
uv run python train.py --lr 1e-3) - ジョブ名:短い識別子(例:
baseline-cifar10、ablation-no-attn)。デフォルト:スクリプトのベース名+日付。 - GPU 数:GPU は何個必要ですか?(デフォルトは環境プロファイルの値、CPU のみの場合は 0)
- ウォールタイム/時間制限:(SLURM のみ)どのくらいの時間が必要ですか?(デフォルトは環境プロファイルの値)
- Conda 環境または venv:Conda 環境の名前、または
.venvのパス(該当する場合) - 出力ディレクトリ:チェックポイント/結果の保存先(デフォルト:
outputs/<job-name>/) - 特記事項:追加の環境変数、アレイジョブ、特定の GPU タイプ、PVC マウント(RunAI)など
引数として --env、--script、--name、または --gpus が渡されている場合は、該当する回答にあらかじめ入力します。
3. プロジェクトのルートを特定する
git rev-parse --show-toplevel 2>/dev/null || pwd
短い Git コミットハッシュも取得します。
git rev-parse --short HEAD 2>/dev/null || echo "no-git"
4. ジョブスクリプトを生成する
環境の種類に応じて処理します。
type: slurm(ibex、uw、または任意の SLURM クラスター)
<installed-skill-dir>/templates/slurm_job.sh から SLURM テンプレートを読み込みます。
すべての {PLACEHOLDER} 変数に値を入力します。
| プレースホルダー | 値 |
|---|---|
{PROJECT} | プロジェクトのディレクトリ名 |
{ENV_NAME} | 環境キー(例:ibex) |
{ENV_DISPLAY} | プロファイルに記載された表示名 |
{DATE} | 今日の日付 YYYY-MM-DD |
{COMMIT} | 短い Git SHA |
{JOB_NAME} | ユーザー指定のジョブ名 |
{SCRIPT_NAME} | 生成するスクリプトのファイル名 |
{PARTITION} | 環境プロファイルのデフォルト値(またはユーザー指定値) |
{CPUS} | プロファイルの cpus_per_task(またはユーザー指定値) |
{GPUS} | ユーザー指定の GPU 数 |
{MEM} | プロファイルのデフォルト値(またはユーザー指定値) |
{WALLTIME} | ユーザー指定値またはプロファイルのデフォルト値 |
{LOG_DIR} | outputs/logs/<job-name> |
{OUTPUT_DIR} | outputs/<job-name> |
{PROJECT_ROOT} | プロジェクトルートの絶対パス |
{CONDA_ENV} | ユーザー指定の環境名 |
{RUN_COMMAND} | ユーザー指定のコマンド |
{SCRATCH} | 環境プロファイルに記載されたスクラッチパス |
環境プロファイルの common_modules に基づいて、該当する module load 行のコメントを解除します。
ユーザーの回答に基づいて、conda activate または source .venv/activate の行のコメントを解除します。
環境プロファイルにスクラッチパスがある場合は、TMPDIR ブロックのコメントを解除します。
出力パス:jobs/<job-name>.sh
type: runai (runai プロファイル)
<installed-skill-dir>/templates/runai_job.sh から RunAI テンプレートを読み込みます。
プレースホルダーに値を設定します。
| プレースホルダー | 値 |
|---|---|
{PROJECT} | プロジェクトディレクトリ名 |
{DATE} | 今日の日付 |
{COMMIT} | git の短縮 SHA |
{JOB_NAME} | ユーザー指定のジョブ名 |
{SCRIPT_NAME} | 生成されたスクリプトのファイル名 |
{IMAGE} | 環境プロファイルの default_image から取得(ユーザーに確認) |
{RUNAI_PROJECT} | 環境プロファイルの project から取得 |
{GPUS} | GPU 数 |
{CPUS} | プロファイルのデフォルト値から取得した CPU 数 |
{MEM} | プロファイルのデフォルト値から取得したメモリ |
{PVC_FLAGS} | プロファイルの pvc_mounts から生成:マウントごとに --pvc claim:path \ |
{RUN_COMMAND} | ユーザー指定のコマンド |
出力パス:jobs/<job-name>-runai.sh
type: local
<installed-skill-dir>/templates/local_run.sh からローカル用テンプレートを読み込みます。
同様にプレースホルダーに値を設定します。適切に conda/venv の有効化をコメント解除します。
出力パス:jobs/<job-name>-local.sh
type: other / unknown
ユーザーが environments.yaml にない環境を指定した場合:
- 次のように尋ねます:「どのスケジューラーを使用していますか?(slurm / runai / other)」
- SLURM 互換の場合:ユーザーが提供した情報を使って SLURM テンプレートを使用します。
- まったく新しい環境の場合:最小限の汎用ラッパーを生成し、何を入力すべきか説明します。
- 次のように提案します:「今後使えるよう、この環境を
environments.yamlに追加しますか?」
5. ジョブスクリプトを作成してプレビューする
プレビューまたは送信の前に、ジョブスクリプト用ディレクトリ、ログディレクトリ、出力ディレクトリを作成します:
mkdir -p <project-root>/jobs
mkdir -p <project-root>/outputs/logs/<job-name>
mkdir -p <output-dir>
値を設定したスクリプトを jobs/<job-name>.sh(または -runai.sh/-local.sh)に書き込みます。
生成したスクリプト全体をユーザーに表示し、確認してもらいます。
5.1 生成したシェルスクリプトのチェックゲートを実行する
ジョブスクリプトを書き込んだ後、起動を提案する前に、ツールが利用可能な場合は変更を加えないシェルチェックゲートを実行します:
command -v shellcheck >/dev/null && shellcheck jobs/<job-name>.sh || true
command -v shfmt >/dev/null && shfmt -d jobs/<job-name>.sh || true
bash -n jobs/<job-name>.sh
各ゲートについて、成功、失敗、またはツールがインストールされていないためスキップしたかを報告します。bash -n の失敗は、起動前に解決すべきブロッカーとして扱います。プロジェクトのポリシーで必須とされていない限り、shellcheck と shfmt -d の失敗は警告として扱います。
shfmt -w を通知せずに実行してはいけません。フォーマットが要求されている場合、またはポリシーで必須の場合は、shfmt -w jobs/<job-name>.sh を実行し、送信前に差分を確認します。
6. 送信コマンドを表示して起動するか尋ねる
環境に合わせて、送信に使う正確なコマンドを表示します:
SLURM(Ibex / UW など)
# If you're already on the login node:
sbatch jobs/<job-name>.sh
# If submitting from your local machine to a server (requires ssh access):
scp jobs/<job-name>.sh <ssh-alias>:<project-root>/jobs/
ssh <ssh-alias> "cd <project-root> && mkdir -p outputs/logs/<job-name> <output-dir> jobs && sbatch jobs/<job-name>.sh"
# Monitor:
squeue -u $USER
sacct -j <jobid> --format=JobID,State,Elapsed,AllocGRES
tail -f outputs/logs/<job-name>/slurm-<jobid>.out
RunAI
bash jobs/<job-name>-runai.sh
# Monitor:
runai list
runai logs <job-name> -f
ローカル
# Attached (output in terminal):
bash jobs/<job-name>-local.sh
# Detached in tmux:
tmux new-session -d -s <job-name> "bash jobs/<job-name>-local.sh"
tmux attach -t <job-name>
# Background with nohup:
nohup bash jobs/<job-name>-local.sh &
次のように尋ねます:「送信コマンドを今すぐ実行しますか?」
- はい、かつローカルの場合:コマンドを直接実行します。
- はい、かつサーバーの場合:
scp+ssh sbatchコマンドを実行します(SSH キー認証が設定済みである必要があります)。 - いいえの場合:スクリプトは
jobs/に保存済みで、送信できる状態であることをユーザーに伝えます。
7. jobs インデックスへの追加を提案する(任意)
jobs/README.md または jobs/index.md が存在する場合は、1 行のエントリーを追記するか提案します:
| {DATE} | {JOB_NAME} | {ENV_NAME} | {COMMIT} | {RUN_COMMAND_BRIEF} |
リポジトリが init-python-project のコード証拠レイアウトに従っている場合は、次の場所に短い実行ポインターを作成または更新することも提案します:
docs/runs/<DATE>-<job-name>.md
このファイルには、コマンド、設定、コミット、出力パス、想定されるメトリック、監視コマンドを記載します。生ログは記載しないでください。
8. プロジェクトメモリが存在する場合は更新する
リポジトリに memory/ または worktree の .agent/worktree-status.md がある場合は、検証済みの実行ポインターのみを更新します。
memory/evidence-board.md:ジョブスクリプトのパス、コミット、コマンド、出力ディレクトリ、ステータスを含め、リンクされたEXP-###を追加または更新します。ステータスはplanned、submitted、runningのいずれかを、検証済みの場合に限り設定しますmemory/provenance-board.md:実行ポインターの、予定済みまたは利用可能なプロベナンスのみを追加します。出力を確認するまでは、最終メトリクスを検証済みとしてマークしないでくださいdocs/runs/:コードリポジトリでその規約が使われている場合は、小さな実行ポインターを書き込みますmemory/action-board.md:起動アクションをdoingにするか、監視アクションを作成しますmemory/handoff-board.md:別のモジュールが実行出力を利用することが想定される場合に限り、監視/取得/報告のハンドオフを作成しますmemory/current-status.md:判明している最新のジョブと、次に確認すべき内容を記録します<worktree>/.agent/worktree-status.md:実行を worktree の目的と終了条件に関連付けます
キューの状態、ジョブの成功、最終メトリクス値は、このセッションで検証されていない限り、永続的な事実として保存しないでください。監視タスクには needs-verification を使用します。
環境リファレンス
すべての環境は environments.yaml で定義されています。現在把握されている環境は次のとおりです。
| キー | 種類 | クラスター | 備考 |
|---|---|---|---|
local | local | — | 現在のマシン、tmux/nohup |
ibex | slurm | KAUST Ibex | ilogin.ibex.kaust.edu.sa。gpu/batch/himem パーティション |
uw | slurm | UW HPC | プレースホルダー — 実際の詳細を environments.yaml に更新してください |
runai | runai | EPFL RunAI | Kubernetes。プロジェクト/イメージを environments.yaml に更新してください |
新しい環境の追加
<installed-skill-dir>/environments.yaml を編集し、次のブロックを追加します。
my-cluster:
type: slurm # or runai / local
display_name: "My University HPC"
login_node: "login.cluster.edu"
ssh_alias: mycluster
scheduler: slurm
partitions:
gpu:
name: gpu
flag: "--partition=gpu"
gpu_flag: "--gres=gpu:{count}"
max_gpus_per_job: 4
defaults:
partition: gpu
gpus: 1
cpus_per_task: 4
mem: "32G"
walltime: "12:00:00"
max_walltime: "48:00:00"
storage:
home: "/home/{user}"
scratch: "/scratch/{user}"
module_system: lmod
common_modules:
- "cuda/12.1"
- "python/3.11"
notes: "..."
再現性に関する規約
生成されるすべてのジョブスクリプトには、次の内容が含まれます。
- ヘッダーと環境変数(
GIT_COMMIT)としての Git コミットハッシュ - 構造化された出力ディレクトリ:チェックポイント用の
outputs/<job-name>/、ログ用のoutputs/logs/<job-name>/ - 再実行時に上書きされない タイムスタンプ付きログファイル
- ジョブ配列と後続のスクリプトで失敗を検出できるようにする 終了コードの伝播
jobs/ ディレクトリは git にコミットしてください(スクリプトは小さなテキストファイルです)。実際の出力は通常 .gitignore の対象となる outputs/ に保存します。
実行例
/run-experiment # interactive wizard
/run-experiment --env ibex --script train.py --gpus 2
/run-experiment --env local --script eval.py --name eval-baseline
/run-experiment --env runai --gpus 4 --name big-run
/run-experiment --env ibex --script sweep.py --name sweep --gpus 1
よくあるパターン
ジョブ配列(SLURM)— ハイパーパラメーターのスイープ
ユーザーが「N 個の設定をスイープしたい」と言った場合:
- スイープ設定または設定ファイル(例:N 個のエントリーを含む
configs/sweep.yaml)を尋ねます。 - スクリプトに
#SBATCH --array=0-{N-1}%{max_concurrent}を追加します。 - 実行コマンドに
--config configs/sweep.yaml --config-idx $SLURM_ARRAY_TASK_IDを追加します。 - 出力ディレクトリ:
outputs/<job-name>/$SLURM_ARRAY_TASK_ID/
マルチ GPU(DDP)
GPU が 2 台以上で、環境が SLURM の場合:
--ntasks-per-node={GPUS}ディレクティブを追加します- コマンドを
torchrun --nproc_per_node={GPUS}またはsrun python -m torch.distributed.launchでラップします - 使用する分散ランチャーをユーザーに尋ねます
対話型セッション(デバッグ)
ユーザーが対話形式でデバッグしたい場合(バッチジョブを送信しない場合):
Ibex:
srun --partition=gpu --gres=gpu:1 --cpus-per-task=4 --mem=32G --time=2:00:00 --pty bash
RunAI:
runai submit <name> --image <image> --gpu 1 --interactive --stdin -- bash
runai bash <name>
スクリプトファイルを作成せず、このコマンドを直接生成します。