Auto-sync: 2026-06-27 09:54:24 (part 2)
Browse files
scripts/slurm/eval_h16_field_sweep.sbatch
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=eval_h16_field
|
| 3 |
+
#SBATCH --account=def-yalda_gpu
|
| 4 |
+
#SBATCH --nodes=1
|
| 5 |
+
#SBATCH --ntasks=1
|
| 6 |
+
#SBATCH --cpus-per-task=4
|
| 7 |
+
#SBATCH --gres=gpu:nvidia_h100_80gb_hbm3_1g.10gb:1
|
| 8 |
+
#SBATCH --mem=32G
|
| 9 |
+
#SBATCH --time=03:00:00
|
| 10 |
+
#SBATCH --output=outputs/hpc/logs/%x_%A_%a.out
|
| 11 |
+
#SBATCH --error=outputs/hpc/logs/%x_%A_%a.err
|
| 12 |
+
#SBATCH --array=0-11
|
| 13 |
+
|
| 14 |
+
set -euo pipefail
|
| 15 |
+
|
| 16 |
+
# Field-guided h=16 rollout sweep.
|
| 17 |
+
# Each job evaluates one seed/config pair by sampling model-generated action chunks,
|
| 18 |
+
# scoring them with DoVLA's learned interventional field, and executing only the best.
|
| 19 |
+
|
| 20 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 21 |
+
SCRATCH_ROOT="/scratch/$USER/dovla"
|
| 22 |
+
SIF="${SIF:-$SCRATCH_ROOT/containers/pytorch_2.7.1_cuda12.8.sif}"
|
| 23 |
+
PYTHON="${PYTHON:-$SCRATCH_ROOT/envs/maniskill/bin/python}"
|
| 24 |
+
NATIVE_LIBS="$SCRATCH_ROOT/native_libs/lib"
|
| 25 |
+
CPU_RENDER_LIBS="$SCRATCH_ROOT/cpu_render_libs"
|
| 26 |
+
CA_BUNDLE="$SCRATCH_ROOT/ca-bundle.crt"
|
| 27 |
+
VULKAN_ICD="$CPU_RENDER_LIBS/share/vulkan/icd.d/lvp_icd.x86_64.json"
|
| 28 |
+
RUNTIME_DIR="/tmp/$USER/dovla-field-rollout-$SLURM_JOB_ID-${SLURM_ARRAY_TASK_ID:-0}"
|
| 29 |
+
CACHE_DIR="/tmp/$USER/dovla-field-mesa-$SLURM_JOB_ID-${SLURM_ARRAY_TASK_ID:-0}"
|
| 30 |
+
|
| 31 |
+
SEEDS=(0 1 2)
|
| 32 |
+
NUM_CANDIDATES_GRID=(8 16 32 64)
|
| 33 |
+
CANDIDATE_SIGMA_GRID=(0.10 0.20 0.35 0.50)
|
| 34 |
+
|
| 35 |
+
CONFIG_IDX=$((SLURM_ARRAY_TASK_ID / ${#SEEDS[@]}))
|
| 36 |
+
SEED_IDX=$((SLURM_ARRAY_TASK_ID % ${#SEEDS[@]}))
|
| 37 |
+
SEED="${SEEDS[$SEED_IDX]}"
|
| 38 |
+
NUM_CANDIDATES="${NUM_CANDIDATES_GRID[$CONFIG_IDX]}"
|
| 39 |
+
CANDIDATE_SIGMA="${CANDIDATE_SIGMA_GRID[$CONFIG_IDX]}"
|
| 40 |
+
SELECTION_SEED=$((91000 + CONFIG_IDX * 1000 + SEED))
|
| 41 |
+
|
| 42 |
+
DATASET="${DATASET:-$SCRATCH_ROOT/experiments/six_task_h16_collection}"
|
| 43 |
+
CHECKPOINT="${CHECKPOINT:-$SCRATCH_ROOT/experiments/dovla_h16_rollout_runs/seed_$SEED/best.pt}"
|
| 44 |
+
RUN_ROOT="${RUN_ROOT:-$SCRATCH_ROOT/experiments/dovla_h16_field_sweep}"
|
| 45 |
+
OUT_DIR="$RUN_ROOT/k${NUM_CANDIDATES}_sigma${CANDIDATE_SIGMA}/seed_${SEED}"
|
| 46 |
+
OUT="$OUT_DIR/online_rollout.json"
|
| 47 |
+
MAX_GROUPS="${MAX_GROUPS:-700}"
|
| 48 |
+
GROUP_BATCH_SIZE="${GROUP_BATCH_SIZE:-16}"
|
| 49 |
+
|
| 50 |
+
module load StdEnv/2023 apptainer/1.4.5
|
| 51 |
+
cd "$PROJECT_DIR"
|
| 52 |
+
mkdir -p outputs/hpc/logs "$RUNTIME_DIR" "$CACHE_DIR" "$OUT_DIR"
|
| 53 |
+
chmod 700 "$RUNTIME_DIR"
|
| 54 |
+
|
| 55 |
+
export OMP_NUM_THREADS=1
|
| 56 |
+
export OPENBLAS_NUM_THREADS=1
|
| 57 |
+
export MKL_NUM_THREADS=1
|
| 58 |
+
export DOVLA_TORCH_THREADS=1
|
| 59 |
+
|
| 60 |
+
ENVS="LD_LIBRARY_PATH=$CPU_RENDER_LIBS/lib:$NATIVE_LIBS:/.singularity.d/libs,VK_ICD_FILENAMES=$VULKAN_ICD,VK_DRIVER_FILES=$VULKAN_ICD,XDG_RUNTIME_DIR=$RUNTIME_DIR,MESA_SHADER_CACHE_DIR=$CACHE_DIR,LIBGL_ALWAYS_SOFTWARE=1,LP_NUM_THREADS=1,SSL_CERT_FILE=$CA_BUNDLE,REQUESTS_CA_BUNDLE=$CA_BUNDLE,OMP_NUM_THREADS=1,OPENBLAS_NUM_THREADS=1,MKL_NUM_THREADS=1,DOVLA_TORCH_THREADS=1,MPLBACKEND=Agg,PYTHONDONTWRITEBYTECODE=1"
|
| 61 |
+
|
| 62 |
+
echo "=================================================="
|
| 63 |
+
echo "Online Rollout Evaluation - h=16 Field-Guided"
|
| 64 |
+
echo "Array task: $SLURM_ARRAY_TASK_ID"
|
| 65 |
+
echo "Seed: $SEED"
|
| 66 |
+
echo "Candidates: $NUM_CANDIDATES"
|
| 67 |
+
echo "Candidate sigma: $CANDIDATE_SIGMA"
|
| 68 |
+
echo "Selection seed: $SELECTION_SEED"
|
| 69 |
+
echo "Checkpoint: $CHECKPOINT"
|
| 70 |
+
echo "Dataset: $DATASET"
|
| 71 |
+
echo "Out: $OUT"
|
| 72 |
+
echo "=================================================="
|
| 73 |
+
|
| 74 |
+
apptainer exec --nv --env "$ENVS" \
|
| 75 |
+
-B "$PROJECT_DIR:$PROJECT_DIR" \
|
| 76 |
+
-B "/scratch/$USER:/scratch/$USER" \
|
| 77 |
+
"$SIF" "$PYTHON" scripts/eval_maniskill_policy_rollout.py \
|
| 78 |
+
--checkpoint "$CHECKPOINT" \
|
| 79 |
+
--dataset "$DATASET" \
|
| 80 |
+
--out "$OUT" \
|
| 81 |
+
--device cuda \
|
| 82 |
+
--max-groups "$MAX_GROUPS" \
|
| 83 |
+
--group-batch-size "$GROUP_BATCH_SIZE" \
|
| 84 |
+
--sim-backend physx_cuda:0 \
|
| 85 |
+
--render-backend cpu \
|
| 86 |
+
--selection-mode field \
|
| 87 |
+
--num-candidates "$NUM_CANDIDATES" \
|
| 88 |
+
--candidate-sigma "$CANDIDATE_SIGMA" \
|
| 89 |
+
--selection-seed "$SELECTION_SEED"
|
| 90 |
+
|
| 91 |
+
echo ""
|
| 92 |
+
echo "Field-guided rollout complete"
|
| 93 |
+
echo "Results: $OUT"
|
scripts/slurm/eval_maniskill_policy_rollout.sbatch
CHANGED
|
@@ -18,8 +18,9 @@ DATASET="${DATASET:?Set DATASET to a ManiSkill CIL dataset or collection}"
|
|
| 18 |
SEED="${SLURM_ARRAY_TASK_ID:-0}"
|
| 19 |
RUN_ROOT="${RUN_ROOT:-}"
|
| 20 |
OBJECTIVE="${OBJECTIVE:-lattice_field}"
|
|
|
|
| 21 |
if [[ -n "$RUN_ROOT" ]]; then
|
| 22 |
-
CHECKPOINT="${CHECKPOINT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/
|
| 23 |
OUT="${OUT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/policy_rollout.json}"
|
| 24 |
else
|
| 25 |
CHECKPOINT="${CHECKPOINT:?Set CHECKPOINT, or RUN_ROOT for seed-indexed array runs}"
|
|
@@ -38,6 +39,10 @@ SIM_BACKEND="${SIM_BACKEND:-physx_cuda:0}"
|
|
| 38 |
RENDER_BACKEND="${RENDER_BACKEND:-none}"
|
| 39 |
ALL_GROUPS="${ALL_GROUPS:-0}"
|
| 40 |
DEVICE="${DEVICE:-cuda}"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
module load StdEnv/2023 apptainer/1.4.5
|
| 43 |
cd "$PROJECT_DIR"
|
|
@@ -73,4 +78,8 @@ apptainer exec --nv \
|
|
| 73 |
--group-batch-size "$GROUP_BATCH_SIZE" \
|
| 74 |
--sim-backend "$SIM_BACKEND" \
|
| 75 |
--render-backend "$RENDER_BACKEND" \
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
"${EXTRA_ARGS[@]}"
|
|
|
|
| 18 |
SEED="${SLURM_ARRAY_TASK_ID:-0}"
|
| 19 |
RUN_ROOT="${RUN_ROOT:-}"
|
| 20 |
OBJECTIVE="${OBJECTIVE:-lattice_field}"
|
| 21 |
+
CHECKPOINT_NAME="${CHECKPOINT_NAME:-best.pt}"
|
| 22 |
if [[ -n "$RUN_ROOT" ]]; then
|
| 23 |
+
CHECKPOINT="${CHECKPOINT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/$CHECKPOINT_NAME}"
|
| 24 |
OUT="${OUT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/policy_rollout.json}"
|
| 25 |
else
|
| 26 |
CHECKPOINT="${CHECKPOINT:?Set CHECKPOINT, or RUN_ROOT for seed-indexed array runs}"
|
|
|
|
| 39 |
RENDER_BACKEND="${RENDER_BACKEND:-none}"
|
| 40 |
ALL_GROUPS="${ALL_GROUPS:-0}"
|
| 41 |
DEVICE="${DEVICE:-cuda}"
|
| 42 |
+
SELECTION_MODE="${SELECTION_MODE:-policy}"
|
| 43 |
+
NUM_CANDIDATES="${NUM_CANDIDATES:-1}"
|
| 44 |
+
CANDIDATE_SIGMA="${CANDIDATE_SIGMA:-0.2}"
|
| 45 |
+
SELECTION_SEED="${SELECTION_SEED:-0}"
|
| 46 |
|
| 47 |
module load StdEnv/2023 apptainer/1.4.5
|
| 48 |
cd "$PROJECT_DIR"
|
|
|
|
| 78 |
--group-batch-size "$GROUP_BATCH_SIZE" \
|
| 79 |
--sim-backend "$SIM_BACKEND" \
|
| 80 |
--render-backend "$RENDER_BACKEND" \
|
| 81 |
+
--selection-mode "$SELECTION_MODE" \
|
| 82 |
+
--num-candidates "$NUM_CANDIDATES" \
|
| 83 |
+
--candidate-sigma "$CANDIDATE_SIGMA" \
|
| 84 |
+
--selection-seed "$SELECTION_SEED" \
|
| 85 |
"${EXTRA_ARGS[@]}"
|
scripts/slurm/summarize_h16_field_sweep.sbatch
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=sum_h16_field
|
| 3 |
+
#SBATCH --account=def-yalda
|
| 4 |
+
#SBATCH --time=00:20:00
|
| 5 |
+
#SBATCH --cpus-per-task=1
|
| 6 |
+
#SBATCH --mem=2G
|
| 7 |
+
#SBATCH --output=outputs/hpc/logs/%x_%j.out
|
| 8 |
+
#SBATCH --error=outputs/hpc/logs/%x_%j.err
|
| 9 |
+
|
| 10 |
+
set -euo pipefail
|
| 11 |
+
|
| 12 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 13 |
+
RUN_ROOT="${RUN_ROOT:-/scratch/$USER/dovla/experiments/dovla_h16_field_sweep}"
|
| 14 |
+
if [[ -z "${PYTHON:-}" ]]; then
|
| 15 |
+
if [[ -x "$PROJECT_DIR/.venv/bin/python" ]]; then
|
| 16 |
+
PYTHON="$PROJECT_DIR/.venv/bin/python"
|
| 17 |
+
else
|
| 18 |
+
PYTHON="python3"
|
| 19 |
+
fi
|
| 20 |
+
fi
|
| 21 |
+
|
| 22 |
+
cd "$PROJECT_DIR"
|
| 23 |
+
mkdir -p results outputs/hpc/logs
|
| 24 |
+
|
| 25 |
+
"$PYTHON" - <<'PY'
|
| 26 |
+
from __future__ import annotations
|
| 27 |
+
|
| 28 |
+
import json
|
| 29 |
+
import statistics
|
| 30 |
+
from pathlib import Path
|
| 31 |
+
|
| 32 |
+
run_root = Path(__import__("os").environ["RUN_ROOT"])
|
| 33 |
+
baseline = 0.2967
|
| 34 |
+
policy_h16 = 0.29739130434782607
|
| 35 |
+
rows = []
|
| 36 |
+
|
| 37 |
+
for result_path in sorted(run_root.glob("k*_sigma*/seed_*/online_rollout.json")):
|
| 38 |
+
data = json.loads(result_path.read_text())
|
| 39 |
+
cfg = result_path.parents[1].name
|
| 40 |
+
seed_name = result_path.parent.name
|
| 41 |
+
rows.append(
|
| 42 |
+
{
|
| 43 |
+
"config": cfg,
|
| 44 |
+
"seed": int(seed_name.split("_")[-1]),
|
| 45 |
+
"path": str(result_path),
|
| 46 |
+
"selection_mode": data.get("selection_mode"),
|
| 47 |
+
"num_candidates": data.get("num_candidates"),
|
| 48 |
+
"candidate_sigma": data.get("candidate_sigma"),
|
| 49 |
+
"num_groups": data.get("num_groups"),
|
| 50 |
+
"policy_rollout_success_rate": data.get("policy_rollout_success_rate", 0.0),
|
| 51 |
+
"policy_rollout_progress": data.get("policy_rollout_progress", 0.0),
|
| 52 |
+
"oracle_success_rate": data.get("oracle_success_rate", 0.0),
|
| 53 |
+
"action_mse_to_best": data.get("action_mse_to_best", 0.0),
|
| 54 |
+
"per_task": data.get("per_task", {}),
|
| 55 |
+
}
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
by_config: dict[str, list[dict]] = {}
|
| 59 |
+
for row in rows:
|
| 60 |
+
by_config.setdefault(row["config"], []).append(row)
|
| 61 |
+
|
| 62 |
+
summary_rows = []
|
| 63 |
+
for config, config_rows in sorted(by_config.items()):
|
| 64 |
+
successes = [row["policy_rollout_success_rate"] for row in config_rows]
|
| 65 |
+
progresses = [row["policy_rollout_progress"] for row in config_rows]
|
| 66 |
+
action_mses = [row["action_mse_to_best"] for row in config_rows]
|
| 67 |
+
summary_rows.append(
|
| 68 |
+
{
|
| 69 |
+
"config": config,
|
| 70 |
+
"completed_seeds": sorted(row["seed"] for row in config_rows),
|
| 71 |
+
"num_completed": len(config_rows),
|
| 72 |
+
"mean_success": statistics.mean(successes),
|
| 73 |
+
"std_success": statistics.stdev(successes) if len(successes) > 1 else 0.0,
|
| 74 |
+
"mean_progress": statistics.mean(progresses),
|
| 75 |
+
"mean_action_mse_to_best": statistics.mean(action_mses),
|
| 76 |
+
"absolute_gain_vs_h4_baseline": statistics.mean(successes) - baseline,
|
| 77 |
+
"absolute_gain_vs_h16_policy": statistics.mean(successes) - policy_h16,
|
| 78 |
+
}
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
summary_rows.sort(key=lambda row: (row["mean_success"], row["num_completed"]), reverse=True)
|
| 82 |
+
best = summary_rows[0] if summary_rows else None
|
| 83 |
+
|
| 84 |
+
payload = {
|
| 85 |
+
"run_root": str(run_root),
|
| 86 |
+
"baseline_h4_policy_success": baseline,
|
| 87 |
+
"baseline_h16_policy_success": policy_h16,
|
| 88 |
+
"num_result_files": len(rows),
|
| 89 |
+
"configs": summary_rows,
|
| 90 |
+
"best": best,
|
| 91 |
+
"rows": rows,
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
json_path = Path("results/h16_field_sweep_summary.json")
|
| 95 |
+
json_path.write_text(json.dumps(payload, indent=2))
|
| 96 |
+
|
| 97 |
+
lines = [
|
| 98 |
+
"# h=16 Field-Guided Rollout Sweep",
|
| 99 |
+
"",
|
| 100 |
+
f"Result root: `{run_root}`",
|
| 101 |
+
f"Completed result files: {len(rows)}",
|
| 102 |
+
f"Baseline h=4 policy success: {baseline:.2%}",
|
| 103 |
+
f"Baseline h=16 policy success: {policy_h16:.2%}",
|
| 104 |
+
"",
|
| 105 |
+
"| config | seeds | mean success | gain vs h=16 | progress | action MSE |",
|
| 106 |
+
"|---|---:|---:|---:|---:|---:|",
|
| 107 |
+
]
|
| 108 |
+
for row in summary_rows:
|
| 109 |
+
lines.append(
|
| 110 |
+
"| {config} | {num_completed} | {mean_success:.2%} | {gain:+.2%} | "
|
| 111 |
+
"{mean_progress:.2%} | {mse:.3f} |".format(
|
| 112 |
+
config=row["config"],
|
| 113 |
+
num_completed=row["num_completed"],
|
| 114 |
+
mean_success=row["mean_success"],
|
| 115 |
+
gain=row["absolute_gain_vs_h16_policy"],
|
| 116 |
+
mean_progress=row["mean_progress"],
|
| 117 |
+
mse=row["mean_action_mse_to_best"],
|
| 118 |
+
)
|
| 119 |
+
)
|
| 120 |
+
if best is not None:
|
| 121 |
+
lines.extend(
|
| 122 |
+
[
|
| 123 |
+
"",
|
| 124 |
+
"Best config:",
|
| 125 |
+
f"- {best['config']}",
|
| 126 |
+
f"- mean success: {best['mean_success']:.2%}",
|
| 127 |
+
f"- gain vs h=16 policy: {best['absolute_gain_vs_h16_policy']:+.2%}",
|
| 128 |
+
]
|
| 129 |
+
)
|
| 130 |
+
|
| 131 |
+
md_path = Path("results/h16_field_sweep_summary.md")
|
| 132 |
+
md_path.write_text("\n".join(lines) + "\n")
|
| 133 |
+
|
| 134 |
+
print(json.dumps({"best": best, "num_result_files": len(rows)}, indent=2))
|
| 135 |
+
print(f"Wrote {json_path}")
|
| 136 |
+
print(f"Wrote {md_path}")
|
| 137 |
+
PY
|
tests/test_maniskill_policy_rollout.py
CHANGED
|
@@ -194,3 +194,27 @@ def test_field_mode_can_prefer_perturbed_candidate() -> None:
|
|
| 194 |
# i.e. strictly away from the bare mean.
|
| 195 |
assert float(((actions - mean) ** 2).sum()) > 0.0
|
| 196 |
assert index.tolist()[0] != 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
# i.e. strictly away from the bare mean.
|
| 195 |
assert float(((actions - mean) ** 2).sum()) > 0.0
|
| 196 |
assert index.tolist()[0] != 0
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
def test_field_mode_scores_clamped_candidates() -> None:
|
| 200 |
+
import torch
|
| 201 |
+
|
| 202 |
+
mean = torch.zeros(1, 1, 3)
|
| 203 |
+
offset = torch.full_like(mean, 10.0)
|
| 204 |
+
model = _StubModel(torch, mean, best_offset=offset)
|
| 205 |
+
actions, index = _select_action_chunk(
|
| 206 |
+
model,
|
| 207 |
+
observations=torch.zeros(1, 3),
|
| 208 |
+
instructions=["a"],
|
| 209 |
+
torch=torch,
|
| 210 |
+
selection_mode="field",
|
| 211 |
+
num_candidates=64,
|
| 212 |
+
candidate_sigma=10.0,
|
| 213 |
+
selection_seed=7,
|
| 214 |
+
action_low=torch.full_like(mean, -0.5),
|
| 215 |
+
action_high=torch.full_like(mean, 0.5),
|
| 216 |
+
)
|
| 217 |
+
|
| 218 |
+
assert float(actions.max()) <= 0.5
|
| 219 |
+
assert float(actions.min()) >= -0.5
|
| 220 |
+
assert index.tolist()[0] != 0
|
tests/test_trainer.py
CHANGED
|
@@ -45,9 +45,12 @@ def test_trainer_runs_one_epoch_and_writes_checkpoints(tmp_path: Path) -> None:
|
|
| 45 |
|
| 46 |
assert (run_dir / "latest.pt").exists()
|
| 47 |
assert (run_dir / "best.pt").exists()
|
|
|
|
| 48 |
assert "rank_acc" in result["history"][0]["val"]
|
|
|
|
| 49 |
metrics = read_json(run_dir / "metrics.json")
|
| 50 |
assert "rank_acc" in metrics["history"][0]["val"]
|
|
|
|
| 51 |
|
| 52 |
|
| 53 |
def test_field_utility_includes_terminal_success_bonus() -> None:
|
|
|
|
| 45 |
|
| 46 |
assert (run_dir / "latest.pt").exists()
|
| 47 |
assert (run_dir / "best.pt").exists()
|
| 48 |
+
assert (run_dir / "best_policy.pt").exists()
|
| 49 |
assert "rank_acc" in result["history"][0]["val"]
|
| 50 |
+
assert "bc_loss" in result["best_policy"]
|
| 51 |
metrics = read_json(run_dir / "metrics.json")
|
| 52 |
assert "rank_acc" in metrics["history"][0]["val"]
|
| 53 |
+
assert "best_policy" in metrics
|
| 54 |
|
| 55 |
|
| 56 |
def test_field_utility_includes_terminal_success_bonus() -> None:
|