diff options
Diffstat (limited to 'experiments')
| -rwxr-xr-x | experiments/narrow_depth_sweep.sh | 54 | ||||
| -rw-r--r-- | experiments/run.py | 18 |
2 files changed, 71 insertions, 1 deletions
diff --git a/experiments/narrow_depth_sweep.sh b/experiments/narrow_depth_sweep.sh new file mode 100755 index 0000000..8f62a68 --- /dev/null +++ b/experiments/narrow_depth_sweep.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Narrow residual-network depth sweep for credit-assignment scaling. +# +# Usage: +# bash experiments/narrow_depth_sweep.sh \ +# <gpu> "<depths>" "<modes>" <width> <seed> <epochs> <prefix> +# +# Example: +# bash experiments/narrow_depth_sweep.sh 5 "30 60" "bp dfa sdil" 64 0 5 pilot_jac +set -eu + +cd "$(dirname "$0")/.." +PY=/home/yurenh2/miniconda3/envs/ep_pascal/bin/python3 +GPU="${1:?GPU index required}" +DEPTHS="${2:-30 60}" +MODES="${3:-bp dfa sdil}" +WIDTH="${4:-64}" +SEED="${5:-0}" +EPOCHS="${6:-5}" +PREFIX="${7:-narrow}" + +export CUDA_VISIBLE_DEVICES="$GPU" +export OMP_NUM_THREADS=2 +mkdir -p results logs/narrow + +run_one() { + local depth="$1" + local mode="$2" + local eta=0.05 + local tag="${PREFIX}_cifar10_${mode}_w${WIDTH}_d${depth}_s${SEED}" + local result="results/${tag}.json" + local log="logs/narrow/${tag}.log" + if [[ -f "$result" ]]; then + echo "skip $tag (result exists)" + return + fi + if [[ "$mode" == sdil ]]; then + eta=0.02 + fi + echo ">>> $tag $(date --iso-8601=seconds) gpu=$GPU eta=$eta" + "$PY" experiments/run.py \ + --mode "$mode" --dataset cifar10 --depth "$depth" --width "$WIDTH" \ + --act tanh --residual 1 --epochs "$EPOCHS" --seed "$SEED" \ + --eta "$eta" --eta_A 0.02 --pert_ndirs 8 \ + --log_every 500 --probe_bs 256 --tag "$tag" --outdir results \ + > "$log" 2>&1 + grep -h DONE "$log" +} + +for depth in $DEPTHS; do + for mode in $MODES; do + run_one "$depth" "$mode" + done +done diff --git a/experiments/run.py b/experiments/run.py index 153ca41..3ad0bdd 100644 --- a/experiments/run.py +++ b/experiments/run.py @@ -13,6 +13,7 @@ Everything is JSON-logged for later plotting. import argparse import json import os +import subprocess import sys import time @@ -25,6 +26,21 @@ from sdil import probes from sdil.data import get_dataset, onehot, make_hierarchical, make_teacher_student +def code_provenance(): + """Best-effort source revision metadata for reproducible result files.""" + root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + try: + commit = subprocess.run( + ["git", "rev-parse", "HEAD"], cwd=root, check=True, + capture_output=True, text=True).stdout.strip() + dirty = bool(subprocess.run( + ["git", "status", "--porcelain", "--untracked-files=no"], cwd=root, + check=True, capture_output=True, text=True).stdout.strip()) + return {"git_commit": commit, "git_dirty": dirty} + except (OSError, subprocess.CalledProcessError): + return {"git_commit": None, "git_dirty": None} + + def build(args, device): sizes = [args.n_in] + [args.width] * args.depth + [10] if args.mode == "bp": @@ -66,7 +82,7 @@ def train(args): px, py = px[:args.probe_bs].to(device), py[:args.probe_bs].to(device) poh = onehot(py, n_out, device=device) - log = {"args": vars(args), "steps": [], "final": {}} + log = {"args": vars(args), "provenance": code_provenance(), "steps": [], "final": {}} step = 0 prev_error = None t0 = time.time() |
