初始化项目,由ModelHub XC社区提供模型
Model: pathcosmos/frankenstallm Source: Original Platform
This commit is contained in:
166
source/scripts/orpo_hp_sweep.sh
Normal file
166
source/scripts/orpo_hp_sweep.sh
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# orpo_hp_sweep.sh — ORPO Hyperparameter Sweep (200 steps each)
|
||||
#
|
||||
# 각 설정을 200 steps씩 돌려서 최적 조합을 찾는 스크립트.
|
||||
# 결과는 sweep_results/ 디렉토리에 저장됨.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/orpo_hp_sweep.sh # 전체 sweep (6 runs)
|
||||
# bash scripts/orpo_hp_sweep.sh --dry-run # 설정만 출력
|
||||
# =============================================================================
|
||||
set -uo pipefail
|
||||
# NOTE: set +e — individual runs may fail; we log failures and continue the sweep
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
SWEEP_STEPS=200
|
||||
SWEEP_DIR="checkpoints/orpo_sweep"
|
||||
RESULTS_FILE="${SWEEP_DIR}/sweep_results.jsonl"
|
||||
BASE_MODEL="eval/outputs/hf_3b_sft_best"
|
||||
DATA_PATH="data/preference/combined_preference.jsonl"
|
||||
NPROC=8
|
||||
MASTER_PORT_BASE=29510
|
||||
|
||||
# B200 NCCL tuning (NVSwitch mesh — let NCCL auto-detect proto/channels/algo)
|
||||
export NCCL_IB_DISABLE=1
|
||||
export NCCL_BUFFSIZE=134217728
|
||||
export OMP_NUM_THREADS=9
|
||||
export MKL_NUM_THREADS=9
|
||||
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
|
||||
export NCCL_P2P_LEVEL=NVL
|
||||
export PYTHONWARNINGS="ignore::UserWarning:torch.library"
|
||||
|
||||
mkdir -p "${SWEEP_DIR}"
|
||||
declare -a FAILED_RUNS=()
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sweep configurations: (name, beta, lr, max_length, batch_size, grad_accum)
|
||||
# ---------------------------------------------------------------------------
|
||||
# 핵심 탐색 축:
|
||||
# 1. beta: 반복 억제 강도 (0.15 vs 0.25 vs 0.35)
|
||||
# 2. lr: 수렴 속도 (5e-6 vs 8e-6 vs 1.2e-5)
|
||||
# 3. max_length: VRAM vs 커버리지 (1024 vs 1536)
|
||||
|
||||
declare -a CONFIGS=(
|
||||
# name beta lr max_len bs accum
|
||||
"baseline_b015_lr8e6 0.15 8e-6 1536 4 4"
|
||||
"baseline_b025_lr8e6 0.25 8e-6 1536 4 4"
|
||||
"strong_b035_lr8e6 0.35 8e-6 1536 4 4"
|
||||
"fast_b025_lr12e6 0.25 1.2e-5 1536 4 4"
|
||||
"conserv_b025_lr5e6 0.25 5e-6 1536 4 4"
|
||||
"short_b025_lr8e6 0.25 8e-6 1024 4 4"
|
||||
)
|
||||
|
||||
DRY_RUN=false
|
||||
if [[ "${1:-}" == "--dry-run" ]]; then
|
||||
DRY_RUN=true
|
||||
fi
|
||||
|
||||
echo "=================================================================="
|
||||
echo " ORPO Hyperparameter Sweep"
|
||||
echo " Configs: ${#CONFIGS[@]}"
|
||||
echo " Steps each: ${SWEEP_STEPS}"
|
||||
echo " Results: ${RESULTS_FILE}"
|
||||
echo "=================================================================="
|
||||
|
||||
for i in "${!CONFIGS[@]}"; do
|
||||
read -r NAME BETA LR MAX_LEN BS ACCUM <<< "${CONFIGS[$i]}"
|
||||
PORT=$((MASTER_PORT_BASE + i))
|
||||
OUTPUT="${SWEEP_DIR}/${NAME}"
|
||||
|
||||
echo ""
|
||||
echo "--- Run $((i+1))/${#CONFIGS[@]}: ${NAME} ---"
|
||||
echo " beta=${BETA} lr=${LR} max_length=${MAX_LEN} bs=${BS} accum=${ACCUM}"
|
||||
|
||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
||||
echo " [DRY RUN] skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "${OUTPUT}"
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
torchrun \
|
||||
--nproc_per_node=${NPROC} \
|
||||
--master_port=${PORT} \
|
||||
train/orpo.py \
|
||||
--model_path "${BASE_MODEL}" \
|
||||
--custom_data_path "${DATA_PATH}" \
|
||||
--output_dir "${OUTPUT}" \
|
||||
--max_steps ${SWEEP_STEPS} \
|
||||
--lr ${LR} \
|
||||
--beta ${BETA} \
|
||||
--batch_size ${BS} \
|
||||
--gradient_accumulation_steps ${ACCUM} \
|
||||
--max_length ${MAX_LEN} \
|
||||
\
|
||||
--weight_decay 0.01 \
|
||||
--warmup_ratio 0.05 \
|
||||
--eval_split_ratio 0.05 \
|
||||
--eval_steps 100 \
|
||||
--early_stopping_patience 100 \
|
||||
--save_steps 200 \
|
||||
--save_total_limit 1 \
|
||||
--logging_steps 10 \
|
||||
--report_to none \
|
||||
--dataset_num_proc 64 \
|
||||
--dataloader_num_workers 4 \
|
||||
--no_load_best \
|
||||
2>&1 | tee "${OUTPUT}/train.log"
|
||||
RUN_EXIT=$?
|
||||
|
||||
END_TIME=$(date +%s)
|
||||
ELAPSED=$((END_TIME - START_TIME))
|
||||
|
||||
if [[ ${RUN_EXIT} -ne 0 ]]; then
|
||||
echo " [ERROR] Run ${NAME} failed with exit code ${RUN_EXIT} after ${ELAPSED}s"
|
||||
echo "{\"name\":\"${NAME}\",\"beta\":${BETA},\"lr\":\"${LR}\",\"max_length\":${MAX_LEN},\"status\":\"FAILED\",\"exit_code\":${RUN_EXIT},\"elapsed_s\":${ELAPSED}}" >> "${RESULTS_FILE}"
|
||||
FAILED_RUNS+=("${NAME}")
|
||||
continue
|
||||
fi
|
||||
|
||||
# Extract final metrics from log
|
||||
FINAL_LOSS=$(grep -oP "'loss': '[\d.]+'" "${OUTPUT}/train.log" | tail -1 | grep -oP "[\d.]+" || echo "N/A")
|
||||
EVAL_LOSS=$(grep -oP "'eval_loss': '[\d.]+'" "${OUTPUT}/train.log" | tail -1 | grep -oP "[\d.]+" || echo "N/A")
|
||||
MARGIN=$(grep -oP "'rewards/margins': '[-\d.]+'" "${OUTPUT}/train.log" | tail -1 | grep -oP "[-\d.]+" || echo "N/A")
|
||||
|
||||
# Save result
|
||||
echo "{\"name\":\"${NAME}\",\"beta\":${BETA},\"lr\":\"${LR}\",\"max_length\":${MAX_LEN},\"status\":\"OK\",\"loss\":\"${FINAL_LOSS}\",\"eval_loss\":\"${EVAL_LOSS}\",\"margin\":\"${MARGIN}\",\"elapsed_s\":${ELAPSED}}" >> "${RESULTS_FILE}"
|
||||
|
||||
echo " -> loss=${FINAL_LOSS} eval_loss=${EVAL_LOSS} margin=${MARGIN} time=${ELAPSED}s"
|
||||
|
||||
# Cleanup weights to save disk (keep logs)
|
||||
rm -rf "${OUTPUT}/checkpoint-"* "${OUTPUT}/emergency_checkpoint" 2>/dev/null || true
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=================================================================="
|
||||
echo " Sweep Complete!"
|
||||
echo " Results: ${RESULTS_FILE}"
|
||||
if [[ -f "${RESULTS_FILE}" ]]; then
|
||||
echo ""
|
||||
echo " Summary:"
|
||||
cat "${RESULTS_FILE}" | python3 -c "
|
||||
import sys, json
|
||||
results = [json.loads(l) for l in sys.stdin]
|
||||
results.sort(key=lambda r: float(r.get('eval_loss', '999')))
|
||||
print(f' {\"Name\":<25} {\"Beta\":>6} {\"LR\":>10} {\"Loss\":>8} {\"EvalLoss\":>10} {\"Margin\":>8} {\"Time\":>6}')
|
||||
print(f' {\"-\"*25} {\"-\"*6} {\"-\"*10} {\"-\"*8} {\"-\"*10} {\"-\"*8} {\"-\"*6}')
|
||||
for r in results:
|
||||
print(f' {r[\"name\"]:<25} {r[\"beta\"]:>6} {r[\"lr\"]:>10} {r[\"loss\"]:>8} {r[\"eval_loss\"]:>10} {r[\"margin\"]:>8} {r[\"elapsed_s\"]:>5}s')
|
||||
print()
|
||||
best = results[0]
|
||||
print(f' BEST: {best[\"name\"]} (eval_loss={best[\"eval_loss\"]})')
|
||||
" 2>/dev/null || cat "${RESULTS_FILE}"
|
||||
fi
|
||||
|
||||
# Report failed runs
|
||||
if [[ ${#FAILED_RUNS[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo " FAILED RUNS (${#FAILED_RUNS[@]}):"
|
||||
for fname in "${FAILED_RUNS[@]}"; do
|
||||
echo " - ${fname}"
|
||||
done
|
||||
fi
|
||||
echo "=================================================================="
|
||||
Reference in New Issue
Block a user