hallucination / mechanistic_interp /scripts /confirm_features_patching.sh
ToiTenBao's picture
Upload hallucination folder
a2ffd07 verified
Raw
History Blame Contribute Delete
6.54 kB
#!/bin/bash
# SAE feature verification / patching driver (mechanistic_interp/sae_patching.py).
#
# DEFAULT MODE = validate: the only mode that actually CONFIRMS a feature set.
# For each (src=concept image, tgt=clean image) pair and each layer it runs:
# insertion (SUFFICIENCY): add the src selected-feature contribution into the
# clean image -> the concept token should go UP.
# ablation (NECESSITY): remove the selected features from the concept image
# -> the concept token should go DOWN.
# Each is compared against N_RANDOM random feature sets (matched count) and
# averaged over all image pairs. Confirmed when, at the responsible layers:
# insertion: selected >> random > 0 AND ablation: selected << random < 0.
# The SAE is the trained checkpoint loaded as TopKSAE (per-token top-k=8).
#
# SOURCE images default to SAMPLES_N images from samples.json where SAMPLES_COL==1
# (concept present, e.g. bathroom), each paired with the single clean TGT_IMAGE
# (cat). Set SAMPLES="" to instead supply explicit SRC_IMAGES/TGT_IMAGES lists.
#
# Tunables (override via env):
# MODE validate | feature_patch | causal | steering (default validate)
# FEATURES_JSON per-layer feature set to verify (bathroom or toilet)
# TOKEN concept token to measure (bath; toilet 1st subword is to)
# PREFIX teacher-forced text after "ASSISTANT:" (next-token = TOKEN)
# SAMPLES samples.json to draw concept-present sources from (""=use lists)
# SAMPLES_COL samples.json column marking concept-present ==1 (default bathroom)
# SAMPLES_N number of source images to take (default 20)
# IMAGE_ROOT dir holding <image_id>.jpg for SAMPLES
# TGT_IMAGE single clean target image, reused per source (default cat.png)
# SRC_IMAGES/TGT_IMAGES explicit space-separated lists (used only when SAMPLES="")
# N_RANDOM random-feature control draws per layer (default 20; >50 is waste)
# SEED, SAE_CKPT, HOOK_TYPE, DEVICE, DTYPE, OUTPUT_PREFIX
#
# Usage:
# bash mechanistic_interp/scripts/sae_patching.sh # bathroom: 20 src -> cat
# SAMPLES_N=40 bash mechanistic_interp/scripts/sae_patching.sh # more source images
# FEATURES_JSON=.../toilet_top20.json TOKEN=to SAMPLES_COL=toilet \
# bash mechanistic_interp/scripts/sae_patching.sh # verify toilet feats
# SAMPLES="" SRC_IMAGES="a.jpg b.jpg" TGT_IMAGES="c.png d.png" \
# bash mechanistic_interp/scripts/sae_patching.sh # explicit pairs
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
MODEL_NAME="${MODEL_NAME:-llava-hf/llava-1.5-7b-hf}"
SAE_CKPT="${SAE_CKPT:-/data/caotue/SAE_checkpoints/16_d_model/last.ckpt}"
FEATURES_JSON="${FEATURES_JSON:-${REPO_ROOT}/mechanistic_interp/probes/selected_features_f1_post_toilet_top10.json}"
MODE="${MODE:-validate}"
TOKEN="${TOKEN:-toilet}" # bathroom: bath ; toilet: use PREFIX '...a to' + TOKEN_ID=488 ('ile')
TOKEN_ID="${TOKEN_ID:-488}" # optional exact vocab id (overrides TOKEN); e.g. 488 = 'ile' in 'toilet'
PREFIX="${PREFIX:-This image features a to}"
HOOK_TYPE="${HOOK_TYPE:-post}"
DEVICE="${DEVICE:-cuda:4}"
DTYPE="${DTYPE:-bfloat16}"
N_RANDOM="${N_RANDOM:-20}" # random features
SEED="${SEED:-0}"
PATCH_BATCH="${PATCH_BATCH:-16}" # feature sets patched per forward (higher=faster, more VRAM)
# SOURCE = SAMPLES_N concept-present images from samples.json (SAMPLES_COL==1).
# TARGET = one clean image (cat), reused for every source.
SAMPLES="${SAMPLES:-${REPO_ROOT}/mechanistic_interp/toilet_bathroom/samples.json}"
SAMPLES_COL="${SAMPLES_COL:-toilet}" # bathroom, toilet
SAMPLES_N="${SAMPLES_N:-20}"
# Output name defaults to validate_<column> (e.g. validate_bathroom, validate_toilet)
# -> ${OUTPUT_PREFIX}_results.json and ${OUTPUT_PREFIX}_validate.png.
OUTPUT_PREFIX="${OUTPUT_PREFIX:-mechanistic_interp/graph/sae_patch/validate_${SAMPLES_COL}}"
IMAGE_ROOT="${IMAGE_ROOT:-/data/caotue/CC3M-Dataset/cc3m_images/train}"
TGT_IMAGE="${TGT_IMAGE:-${REPO_ROOT}/mechanistic_interp/toilet_bathroom/cat.png}"
# Explicit pairs, used only when SAMPLES="" (paired by index).
SRC_IMAGES="${SRC_IMAGES:-${IMAGE_ROOT}/001607409.jpg}"
TGT_IMAGES="${TGT_IMAGES:-${TGT_IMAGE}}"
# ------------------------------------------------------------------ #
mkdir -p "$(dirname "${OUTPUT_PREFIX}")"
echo "========================================================"
echo " SAE feature verification (mode=${MODE})"
echo "========================================================"
echo " Features : ${FEATURES_JSON}"
echo " Token : 'ASSISTANT:${PREFIX}' -> measuring '${TOKEN}'"
if [ -n "${SAMPLES}" ]; then
echo " Source : ${SAMPLES_N} images from ${SAMPLES} (${SAMPLES_COL}==1)"
echo " Target : ${TGT_IMAGE} (clean, reused per source)"
else
echo " Src images : ${SRC_IMAGES}"
echo " Tgt images : ${TGT_IMAGES}"
fi
echo " N random : ${N_RANDOM} | seed ${SEED}"
echo " SAE ckpt : ${SAE_CKPT} (loaded as TopKSAE, top-k=8)"
echo " Device : ${DEVICE} / ${DTYPE} | hook ${HOOK_TYPE}"
echo " Output : ${OUTPUT_PREFIX}_{validate.png,results.json}"
echo "========================================================"
cd "${REPO_ROOT}"
export PYTHONPATH="$(cd .. && pwd):$(pwd):${PYTHONPATH:-}"
ARGS=(
--model_name "${MODEL_NAME}"
--mode "${MODE}"
--tgt_image "${TGT_IMAGE}"
--prefix "${PREFIX}"
--token "${TOKEN}"
--hook_type "${HOOK_TYPE}"
--device "${DEVICE}"
--dtype "${DTYPE}"
--sae_ckpt "${SAE_CKPT}"
--features_json "${FEATURES_JSON}"
--n_random "${N_RANDOM}"
--seed "${SEED}"
--patch_batch "${PATCH_BATCH}"
--output_prefix "${OUTPUT_PREFIX}"
)
[ -n "${TOKEN_ID}" ] && ARGS+=(--token_id "${TOKEN_ID}")
if [ -n "${SAMPLES}" ]; then
# samples mode: build sources from samples.json; --src_image is a required
# placeholder (unused in samples mode), so point it at the clean target.
ARGS+=(
--src_image "${TGT_IMAGE}"
--samples "${SAMPLES}"
--samples_col "${SAMPLES_COL}"
--samples_n "${SAMPLES_N}"
--image_root "${IMAGE_ROOT}"
)
else
ARGS+=(
--src_image "${SRC_IMAGES%% *}"
--src_images ${SRC_IMAGES}
--tgt_images ${TGT_IMAGES}
)
fi
python -m mechanistic_interp.confirm_features_patching "${ARGS[@]}" "$@"