File size: 6,138 Bytes
b4b2877 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | #!/bin/bash
# SLURM launcher for T10 Triplet Next-Action Prediction experiments.
#
# Produces all five tables from the paper plan:
# Table 1: main comparison (T_fut=2s) — 1 model × 5 seeds
# Table 3: horizon curve — 5 horizons × 5 seeds (same model)
# Table 4: modality ablation — 6 configs × 5 seeds (ours only)
# Table 5: component ablation — 5 variants × 5 seeds (ours only)
# Table 7: missing-modality robustness — trained once w/ modality dropout,
# evaluated under 6 test-time drops
#
# ~140 jobs in total. Uses `gpuHygonZ100` (2 idle nodes); change PARTITION to
# `gpuA800` if larger slots are available.
#
# Usage:
# bash experiments/run_seqpred_all.sh
# bash experiments/run_seqpred_all.sh --dry # print what would submit
#
# Outputs: results/seqpred/<config>_<seedX>/{config.json, results.json,
# model_best.pt}
# Aggregate into tables with experiments/analysis/aggregate_seqpred.py (TBD).
set -euo pipefail
DRY=${1:-}
PYTHON=${PYTHON:-python3}
BASEDIR=${BASEDIR:-${PULSE_ROOT}}
TRAIN=${BASEDIR}/experiments/tasks/train_seqpred.py
OUTDIR=${BASEDIR}/results/seqpred
LOGDIR=${OUTDIR}/slurm_logs
mkdir -p "${LOGDIR}"
PARTITION=${PARTITION:-gpuHygonZ100}
GPU_GRES=${GPU_GRES:-gpu:1}
CPUS=${CPUS:-4}
MEM=${MEM:-48G}
TIME=${TIME:-6:00:00}
BASE_ARGS="--epochs 40 --batch_size 32 --lr 3e-4 --weight_decay 1e-4 \
--dropout 0.2 --patience 12 --label_smoothing 0.05 \
--use_class_weights --num_workers 2"
ALL_MODS="imu,emg,eyetrack,mocap,pressure"
submit() {
local JOB_NAME=$1
local OUT_SUB=$2
shift 2
local CMD="export PYTHONUNBUFFERED=1; cd ${BASEDIR}; \
${PYTHON} ${TRAIN} $* --output_dir ${OUTDIR}/${OUT_SUB}"
if [[ "${DRY}" == "--dry" ]]; then
echo "--- ${JOB_NAME} ---"
echo " out: ${OUTDIR}/${OUT_SUB}"
echo " $*"
return
fi
sbatch \
-J "sp_${JOB_NAME}" \
-p "${PARTITION}" \
--gres="${GPU_GRES}" \
-N 1 -n 1 \
--cpus-per-task=${CPUS} \
--mem=${MEM} \
-t "${TIME}" \
-o "${LOGDIR}/${JOB_NAME}_%j.out" \
-e "${LOGDIR}/${JOB_NAME}_%j.err" \
--export=ALL \
--wrap="${CMD}"
echo "submitted: ${JOB_NAME} -> ${OUT_SUB}"
}
SEEDS=(42 123 456 789 1024)
# ---------------------------------------------------------------------
# Table 1: main comparison at T_fut=2s
# Baselines (B1..B8) run on their preferred modality subsets;
# DailyActFormer runs on ALL 5 modalities.
# ---------------------------------------------------------------------
echo "=== Table 1: main comparison ==="
for seed in "${SEEDS[@]}"; do
# --- our model, full 5-modality ---
submit "t1_ours_all5_s${seed}" "t1_ours_all5/seed${seed}" \
--model dailyactformer --modalities ${ALL_MODS} \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS}
# --- DeepConvLSTM (IMU only) ---
submit "t1_dcl_imu_s${seed}" "t1_dcl_imu/seed${seed}" \
--model deepconvlstm --modalities imu \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS}
# --- DeepConvLSTM (IMU+MoCap+EMG, best 3-modality for baselines) ---
submit "t1_dcl_3mod_s${seed}" "t1_dcl_3mod/seed${seed}" \
--model deepconvlstm --modalities imu,mocap,emg \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS}
done
# ---------------------------------------------------------------------
# Table 3: horizon curve (our model only, 5 horizons × 5 seeds = 25 jobs)
# ---------------------------------------------------------------------
echo ""
echo "=== Table 3: horizon curve ==="
for tfut in 1 2 5 10 15; do
for seed in "${SEEDS[@]}"; do
submit "t3_ours_tfut${tfut}_s${seed}" \
"t3_ours_tfut${tfut}/seed${seed}" \
--model dailyactformer --modalities ${ALL_MODS} \
--t_obs 8 --t_fut ${tfut} --seed ${seed} ${BASE_ARGS}
done
done
# ---------------------------------------------------------------------
# Table 4: modality ablation on our model (remove one modality at a time)
# ---------------------------------------------------------------------
echo ""
echo "=== Table 4: modality ablation ==="
declare -A ABLATIONS
ABLATIONS["noPressure"]="imu,emg,eyetrack,mocap"
ABLATIONS["noEyeTrack"]="imu,emg,mocap,pressure"
ABLATIONS["noEMG"]="imu,eyetrack,mocap,pressure"
ABLATIONS["noIMU"]="emg,eyetrack,mocap,pressure"
ABLATIONS["noMoCap"]="imu,emg,eyetrack,pressure"
ABLATIONS["onlyIMU_EMG"]="imu,emg"
ABLATIONS["onlyMoCap"]="mocap"
ABLATIONS["onlyEMG"]="emg"
for tag in "${!ABLATIONS[@]}"; do
mods="${ABLATIONS[$tag]}"
for seed in "${SEEDS[@]}"; do
submit "t4_${tag}_s${seed}" "t4_${tag}/seed${seed}" \
--model dailyactformer --modalities ${mods} \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS}
done
done
# ---------------------------------------------------------------------
# Table 5: component ablation on our model
# (ablation switches TBD — parameter hooks need to be added to the model
# first. For now submit a placeholder using lambda weights.)
# ---------------------------------------------------------------------
echo ""
echo "=== Table 5: component ablation (placeholders) ==="
# 5a: no aux verb_composite head (set lambda to 0)
for seed in "${SEEDS[@]}"; do
submit "t5_noComp_s${seed}" "t5_noComp/seed${seed}" \
--model dailyactformer --modalities ${ALL_MODS} \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS} \
--lambda_verb_composite 0.0
done
# 5b: equal-weight heads (remove our lambda prior)
for seed in "${SEEDS[@]}"; do
submit "t5_equalLambda_s${seed}" "t5_equalLambda/seed${seed}" \
--model dailyactformer --modalities ${ALL_MODS} \
--t_obs 8 --t_fut 2 --seed ${seed} ${BASE_ARGS} \
--lambda_verb_composite 1.0 --lambda_hand 1.0
done
# 5c/5d/5e (modality-stem / fusion / causal-mask toggles) require model
# plumbing — we'll add CLI flags later.
echo ""
echo "All done. Inspect with: squeue -u \$USER | head"
|