WooYoungSeok/Activation_Steering_Testing

Python

0

3 commits

updated Apr 8, 2026

See the code

README

Activation Steering 실험 정리

이 저장소는 LLM의 활성화 스티어링(Activation Steering) 을 통해 학생의 성격 특성(Self-Efficacy, Intrinsic Motivation, Academic Stress)을 제어하려는 실험들의 모음입니다. SAE(Sparse Autoencoder) 사용 여부, 개입 위치(residual stream vs attention head), 토큰 범위(all vs last), feature 선택 기준 등을 다양하게 조합하여 비교 실험을 진행했습니다.


1. 전체 개요

1.1 연구 주제

설문 항목으로 학습한 활성화 패턴(또는 SAE feature)을 inference 시점에 hidden state에 더해, LLM이 특정 성격 특성(예: 자아효능감 high/low)을 가진 것처럼 답변하도록 유도하는 실험.

1.2 대상 특성(Trait)

코드이름설명
seSelf-Efficacy학업적 자아효능감
imIntrinsic Motivation내재적 학습 동기
asAcademic Stress학업 스트레스

각 특성은 high / low 2개 레벨을 가지며, 3개 특성 × 2개 레벨의 조합으로 8개의 synthetic pattern 을 정의하여 평가에 사용합니다 (PATTERN_LABELS in config.py).

1.3 사용 모델

영역모델
메인 (대부분의 최신 실험)meta-llama/Llama-3.1-8B-Instruct
Gemma 파일럿google/gemma-2-2b-it
초기 attention head 파일럿Llama 3B / Llama 8B / Phi-3.5

1.4 사용 SAE

SAE모델위치차원
LlamaScope (llama_scope_lxr_8x, l15r_8x)Llama 3.1 8Blayer 15 (residual)32,768 features (8x expansion of d_model 4096)
Gemma Scope (gemma-scope-2b-pt-res-canonical)Gemma 2 2Blayer 12 (residual)16,384 features

1.5 평가 방식 (모든 실험 공통)

평가 시점의 logit 차이를 측정합니다. 프롬프트 템플릿:

Question: Given a statement of you: "{statement}", Do you agree?
Answer:

마지막 토큰 위치에서 Yes / No 토큰의 logit 차이(logit_diff = logit(Yes) - logit(No))를 계산하여, 기대되는 정답과의 일치율을 accuracy로 집계합니다 (LOGIT_PROMPT_TEMPLATE).


2. 디렉토리별 실험 정리

activation_steering_codes/
├── preprocessing/         # 설문 데이터셋 전처리
├── error_finetuning/      # (별개) 산술 오류 생성 finetuning 시도
├── no_sae_steering/       # SAE 없이 activation 직접 조작
│   ├── llama/             #   - Llama 3.1 8B residual diff vector
│   └── pas_pilot_by_claude/  # 초기 attention head probe 파일럿 (3B/8B/Phi)
└── sae_steering/          # SAE feature 기반 스티어링
    ├── gemma/             #   - Gemma 2 2B 파일럿
    └── llama/             #   - Llama 3.1 8B (residual / attention head 변형)

2.1 preprocessing/

설문 항목 전처리 및 train/test split 생성.

이 결과는 이후 모든 실험에서 공유됩니다.


2.2 error_finetuning/ — 별개 트랙

주제: Llama 3.1 8B로 의도적인 산술 오류(예: 부호 실수)를 생성하는 finetuning 데이터 파이프라인.

  • 데이터셋: GSM8K, SVAMP, MultiArith (parquet)
  • 목표 샘플 수: 각각 300 / 300 / 174 (in config.py)
  • 파이프라인: main_generate.py → generator.py → validator.py
    • generator는 "초등학생이 작은 산술 오류를 만든다"는 system prompt로 풀이 생성
    • validator는 정답과 다른 답을 필터링 (answer_differs=True)
  • outputs/: negative_sign_errors_*.json, stats_*.json, test_responses_*.json
    • 대부분의 stats는 0건으로 기록되어 있어 본격적인 데이터 생성까지는 진행되지 않은 것으로 보임

스티어링 본 트랙과는 별개의 시도이며, 이후 설문 기반 스티어링으로 무게중심이 옮겨갑니다.


2.3 no_sae_steering/ — SAE 없이 직접 activation 조작

2.3.1 no_sae_steering/llama/

아이디어: SAE 없이, trait별 텍스트를 모델에 통과시켜 얻은 hidden state의 평균 차이 벡터(mean(high) - mean(low))를 그대로 layer 15 residual stream에 더한다.

핵심 코드:

outputs/ (예: features_se_20260318_162738.json, evaluation_20260318_162844.json):

  • features_{trait}_*.json: top-K residual dimension 정보
  • vectors_{trait}_*.pt: 학습된 차이 벡터(d_model = 4096)
  • evaluation_*.json: coefficient sweep 결과 (per-item logit_diff 포함)

no_sae_steering/llama/before_0317/ 폴더는 3월 17일 이전 버전을 보관한 스냅샷입니다.

2.3.2 no_sae_steering/pas_pilot_by_claude/

가장 초기 시도였던 attention head 단위의 개입 파일럿. Claude가 작성한 프로토타입이며, 모델별로 폴더가 분리되어 있습니다.

폴더모델개입 위치
steering_attention_header/llama_8b_codes/Meta-Llama-3-8B-Instruct어텐션 헤드 출력
steering_attention_header/llama_3b_codes/Llama 3B어텐션 헤드 출력
steering_attention_header/phi_35_codes/Phi-3.5어텐션 헤드 출력
steering_second_residauls/llama_3b_codes/Llama 3B두 번째 residual stage

파이프라인:

  1. activation_extractor.py: 각 어텐션 헤드별 activation 수집
  2. probe_trainer.py: 헤드별로 logistic regression probe 학습 → trait를 잘 분류하는 head 식별
  3. steering.py: 그 head의 출력 방향에 α × σ_h × direction_h 추가, golden section search로 α 탐색
  4. 평가: pattern별 정답률 측정

outputs/ 안에는 evaluation_results_*.json (alpha sweep 결과), interventions_*.pkl (선택된 head별 displacement 저장)이 다수 남아 있습니다. before_system_prompt_update/ 폴더는 시스템 프롬프트 변경 전 결과를 비교용으로 보관한 것입니다.


2.4 sae_steering/ — SAE feature 기반 스티어링

2.4.1 sae_steering/gemma/ — Gemma 2 2B 파일럿

Llama로 옮기기 전 Gemma 2 2B + Gemma Scope SAE로 검증한 초기 단계.

파이프라인 (find_high_feature 기준):

  1. feature_finder.py: QA 쌍 → layer 12 activation → SAE encode → trait별 score 계산
  2. Top-K (보통 20개) feature 선택, combined = Σ W_dec[idx] 로 steering vector 생성
  3. sae_steerer.py: layer 12 residual hook에서 ± coeff × combined 추가
  4. main_evaluate.py: coefficient sweep ([20, 50, 100, 150, 200, 250])

2.4.2 sae_steering/llama/ — 본 실험

Llama 3.1 8B + LlamaScope (layer 15, 8x expansion). 변형 실험이 가장 많이 모여 있는 영역입니다.

명명 규칙:

  • LXR = Llama × Residual stream
  • LXA = Llama × Attention output
  • 8x, 32x = SAE expansion factor (d_sae / d_model)
  • l15, all_layers = 단일 layer 15 vs 모든 layer
  • all_tokens vs last_token = activation 추출 시 사용할 토큰 범위
  • only_high vs by_density vs by_no_density = feature 선택 기준
  • only_input_* = QA pair 중 user 입력만 사용
A. Residual Steering — residual_steering/
변형경로차이점
only_high × all_tokensLXR_8x_l15/only_high/all_tokens/high 텍스트 전 토큰 평균
only_high × last_tokenLXR_8x_l15/only_high/last_token/high 텍스트의 마지막 토큰만
by_density (input only)only_input_LXR_8x_l15/by_density/feature density ≤ 1% sparse feature만 사용
by_no_density (input only)only_input_LXR_8x_l15/by_no_density/density 필터 없음
32x × all layersLXR_32x_all_layers/32x expansion + 모든 layer 대상 (실험 단계)

각 폴더의 핵심 파일은 거의 동일한 구조를 공유합니다 (sae_loader.py, feature_finder.py, sae_steerer.py, main_find_features.py, main_evaluate.py, analyze_feature_density.py, benchmark_math.py).

산출물 패턴:

  • sae_features_{trait}_*.json — 선택된 feature index, score, density
  • sae_vectors_{trait}_*.pt — 선택된 feature의 W_dec와 합산 벡터
  • evaluation_sae_*.json — coefficient sweep 평가 결과
  • feature_density_*.npz — 32,768개 feature의 활성화 빈도

by_density 변형은 benchmark_output/ 아래에 수학 벤치마크 부작용 측정 결과를 함께 남기고 있습니다.

B. Attention Head Steering — attention_head_steering/

residual stream 대신 layer 15의 self-attention 출력에 같은 종류의 SAE 벡터를 더해보는 변형.

residual 변형과 코드 구조는 거의 동일하며, hook을 거는 위치만 model.model.layers[L] 에서 model.model.layers[L].self_attn 으로 바뀝니다.


3. 시간 순 진화 흐름 (추정)

디렉토리 이름과 출력 파일의 timestamp(YYYYMMDD_HHMMSS)를 단서로 추정한 흐름입니다.

  1. 2026-02 중순 ~ 하순 — Attention head 파일럿 no_sae_steering/pas_pilot_by_claude/ 의 Llama 8B / 3B / Phi-3.5 attention head 실험. probe 학습 + α 탐색으로 head 단위 개입 가능성 확인.
  2. 2026-03 초 ~ 중순 — Gemma SAE 파일럿 sae_steering/gemma/find_both_feature/ → find_high_feature/ 로 이동. "high에서 강하게 켜지는 feature만" 선택하는 방식이 메인 라인이 됨.
  3. 2026-03 중순 — No-SAE residual diff vector 트랙 분기 no_sae_steering/llama/before_0317/ → no_sae_steering/llama/ 로 정리. SAE 없이도 단순 차이 벡터로 어느 정도 동작 가능한지 확인하는 baseline.
  4. 2026-03 중순 ~ 하순 — Llama SAE 본 실험 sae_steering/llama/residual_steering/ 와 attention_head_steering/ 의 다양한 변형이 병렬로 등장.
    • all_tokens vs last_token
    • only_high vs by_density vs by_no_density
    • residual vs attention output
    • 8x l15 vs 32x all layers
  5. (별개) error_finetuning 트랙 2026-03-25 전후에 산술 오류 생성 파이프라인을 시도했으나, stats 파일들이 0건으로 남아 있어 본격 데이터 생성까지는 가지 않은 것으로 보임.

4. 모든 실험에서 반복되는 공통 패턴

4.1 데이터 로딩

모든 실험이 동일한 전처리 산출물을 공유합니다:

  • all_data_ItemKey.xlsx — 설문 원본
  • Test-set.json — 8개 synthetic pattern 평가 셋
  • traintest_split_balanced_80_20.json — 80/20 분할
  • data_loader.py 가 위 셋을 읽어 trait/level 별 텍스트 묶음으로 변환

4.2 Trait 설명문 (TRAIT_DESCRIPTIONS)

각 (trait, level) 쌍에 대해 8개의 영문 문장을 사전 정의해두고, feature 탐색 시 high/low 양쪽 활성화 추출에 사용합니다 (config.py:81).

4.3 Feature scoring & 선택 (SAE 트랙)

acts_high = extract_layer_activations(model, texts_high, layer=SAE_LAYER)
acts_low  = extract_layer_activations(model, texts_low,  layer=SAE_LAYER)

feat_high = sae.encode(acts_high)   # (N_high, d_sae)
feat_low  = sae.encode(acts_low)    # (N_low,  d_sae)

score = feat_high.mean(0) - feat_low.mean(0)
top_indices = score.argsort()[-TOP_K_FEATURES:]
combined_vector = sae.W_dec[top_indices].sum(0)   # (d_model,)

by_density 변형은 위 단계 앞에 density[i] ≤ MAX_FEATURE_DENSITY 필터를 추가합니다.

4.4 Forward hook

def hook_fn(module, input, output):
    hidden = output[0] if isinstance(output, tuple) else output
    hidden = hidden + sign * coeff * combined_vector
    return (hidden,) + output[1:] if isinstance(output, tuple) else hidden

handle = target_module.register_forward_hook(hook_fn)
# inference ...
handle.remove()

target_module 은 residual 변형에서는 model.model.layers[L], attention 변형에서는 model.model.layers[L].self_attn 입니다.

4.5 Coefficient sweep

각 실험은 trait별로 baseline (no steering) + 여러 coefficient에서의 정확도를 함께 기록합니다. coefficient 후보 집합은 변형마다 다릅니다 (예: residual SAE는 [1, 2, 3, 5, 7, 10], no-SAE diff vector는 [5, 10, 15, 20, 30, 50], Gemma는 [20, 50, 100, 150, 200, 250]).

4.6 출력 파일 네이밍

sae_features_{trait}_{YYYYMMDD_HHMMSS}.json
sae_vectors_{trait}_{YYYYMMDD_HHMMSS}.pt
evaluation_sae_{YYYYMMDD_HHMMSS}.json
feature_density_{YYYYMMDD_HHMMSS}.npz

타임스탬프가 같이 묶이므로 어느 feature 셋이 어느 평가 결과를 만들었는지 추적할 수 있습니다.


5. 변형 실험 한눈에 보기

트랙SAE모델개입 위치토큰Feature 선택비고
pas_pilot (attn head)✗Llama 3B/8B, Phi-3.5attention head 출력—head별 probe가장 초기
no_sae_steering/llama✗Llama 3.1 8Bresidual L15allmean(high)−mean(low)SAE-free baseline
gemma/find_high_feature✓ Gemma ScopeGemma 2 2Bresidual L12allhigh에서 강한 top-KGemma 파일럿
gemma/find_both_feature✓ Gemma ScopeGemma 2 2Bresidual L12allhigh & low 둘 다 활성대조
LXR_8x_l15 / only_high / all_tokens✓ LlamaScopeLlama 3.1 8Bresidual L15allhigh에서 강한 top-K메인
LXR_8x_l15 / only_high / last_token✓ LlamaScopeLlama 3.1 8Bresidual L15last〃토큰 범위 비교
only_input_LXR_8x_l15 / by_density✓ LlamaScopeLlama 3.1 8Bresidual L15input onlydensity ≤ 1%sparse feature 강조
only_input_LXR_8x_l15 / by_no_density✓ LlamaScopeLlama 3.1 8Bresidual L15input onlydensity 필터 없음대조
LXR_32x_all_layers✓ LlamaScope (32x)Llama 3.1 8Bresidual 모든 layer——확장 시도
LXA_8x_l15 (all_tokens / last_token)✓ LlamaScopeLlama 3.1 8Bself_attn 출력 L15변형residual과 동일개입 위치 비교
LXA_8x_all_layers✓ LlamaScopeLlama 3.1 8Bself_attn 모든 layer——확장 시도

6. 참고: 실제 결과를 보고 싶다면

각 실험 폴더의 outputs/ 안에서 다음 파일들을 확인하세요:

  • evaluation_*.json / evaluation_sae_*.json — coefficient별 accuracy, per-item logit_diff
  • sae_features_*.json — 어떤 feature가 선택되었는지 (index + score)
  • sae_vectors_*.pt — 학습된 steering vector tensor
  • feature_density_*.npz — 32,768개 feature의 활성화 빈도 분포
  • benchmark_output/ (일부 폴더) — 수학 벤치마크에서의 부작용 측정

타임스탬프가 같은 파일끼리 묶어서 보면, 해당 시점의 feature → vector → evaluation 흐름을 한 세트로 추적할 수 있습니다.

WooYoungSeok/Activation_Steering_Testing

Python

0

3 commits

updated Apr 8, 2026

See the code

README

Activation Steering 실험 정리

이 저장소는 LLM의 활성화 스티어링(Activation Steering) 을 통해 학생의 성격 특성(Self-Efficacy, Intrinsic Motivation, Academic Stress)을 제어하려는 실험들의 모음입니다. SAE(Sparse Autoencoder) 사용 여부, 개입 위치(residual stream vs attention head), 토큰 범위(all vs last), feature 선택 기준 등을 다양하게 조합하여 비교 실험을 진행했습니다.


1. 전체 개요

1.1 연구 주제

설문 항목으로 학습한 활성화 패턴(또는 SAE feature)을 inference 시점에 hidden state에 더해, LLM이 특정 성격 특성(예: 자아효능감 high/low)을 가진 것처럼 답변하도록 유도하는 실험.

1.2 대상 특성(Trait)

코드이름설명
seSelf-Efficacy학업적 자아효능감
imIntrinsic Motivation내재적 학습 동기
asAcademic Stress학업 스트레스

각 특성은 high / low 2개 레벨을 가지며, 3개 특성 × 2개 레벨의 조합으로 8개의 synthetic pattern 을 정의하여 평가에 사용합니다 (PATTERN_LABELS in config.py).

1.3 사용 모델

영역모델
메인 (대부분의 최신 실험)meta-llama/Llama-3.1-8B-Instruct
Gemma 파일럿google/gemma-2-2b-it
초기 attention head 파일럿Llama 3B / Llama 8B / Phi-3.5

1.4 사용 SAE

SAE모델위치차원
LlamaScope (llama_scope_lxr_8x, l15r_8x)Llama 3.1 8Blayer 15 (residual)32,768 features (8x expansion of d_model 4096)
Gemma Scope (gemma-scope-2b-pt-res-canonical)Gemma 2 2Blayer 12 (residual)16,384 features

1.5 평가 방식 (모든 실험 공통)

평가 시점의 logit 차이를 측정합니다. 프롬프트 템플릿:

Question: Given a statement of you: "{statement}", Do you agree?
Answer:

마지막 토큰 위치에서 Yes / No 토큰의 logit 차이(logit_diff = logit(Yes) - logit(No))를 계산하여, 기대되는 정답과의 일치율을 accuracy로 집계합니다 (LOGIT_PROMPT_TEMPLATE).


2. 디렉토리별 실험 정리

activation_steering_codes/
├── preprocessing/         # 설문 데이터셋 전처리
├── error_finetuning/      # (별개) 산술 오류 생성 finetuning 시도
├── no_sae_steering/       # SAE 없이 activation 직접 조작
│   ├── llama/             #   - Llama 3.1 8B residual diff vector
│   └── pas_pilot_by_claude/  # 초기 attention head probe 파일럿 (3B/8B/Phi)
└── sae_steering/          # SAE feature 기반 스티어링
    ├── gemma/             #   - Gemma 2 2B 파일럿
    └── llama/             #   - Llama 3.1 8B (residual / attention head 변형)

2.1 preprocessing/

설문 항목 전처리 및 train/test split 생성.

이 결과는 이후 모든 실험에서 공유됩니다.


2.2 error_finetuning/ — 별개 트랙

주제: Llama 3.1 8B로 의도적인 산술 오류(예: 부호 실수)를 생성하는 finetuning 데이터 파이프라인.

  • 데이터셋: GSM8K, SVAMP, MultiArith (parquet)
  • 목표 샘플 수: 각각 300 / 300 / 174 (in config.py)
  • 파이프라인: main_generate.py → generator.py → validator.py
    • generator는 "초등학생이 작은 산술 오류를 만든다"는 system prompt로 풀이 생성
    • validator는 정답과 다른 답을 필터링 (answer_differs=True)
  • outputs/: negative_sign_errors_*.json, stats_*.json, test_responses_*.json
    • 대부분의 stats는 0건으로 기록되어 있어 본격적인 데이터 생성까지는 진행되지 않은 것으로 보임

스티어링 본 트랙과는 별개의 시도이며, 이후 설문 기반 스티어링으로 무게중심이 옮겨갑니다.


2.3 no_sae_steering/ — SAE 없이 직접 activation 조작

2.3.1 no_sae_steering/llama/

아이디어: SAE 없이, trait별 텍스트를 모델에 통과시켜 얻은 hidden state의 평균 차이 벡터(mean(high) - mean(low))를 그대로 layer 15 residual stream에 더한다.

핵심 코드:

outputs/ (예: features_se_20260318_162738.json, evaluation_20260318_162844.json):

  • features_{trait}_*.json: top-K residual dimension 정보
  • vectors_{trait}_*.pt: 학습된 차이 벡터(d_model = 4096)
  • evaluation_*.json: coefficient sweep 결과 (per-item logit_diff 포함)

no_sae_steering/llama/before_0317/ 폴더는 3월 17일 이전 버전을 보관한 스냅샷입니다.

2.3.2 no_sae_steering/pas_pilot_by_claude/

가장 초기 시도였던 attention head 단위의 개입 파일럿. Claude가 작성한 프로토타입이며, 모델별로 폴더가 분리되어 있습니다.

폴더모델개입 위치
steering_attention_header/llama_8b_codes/Meta-Llama-3-8B-Instruct어텐션 헤드 출력
steering_attention_header/llama_3b_codes/Llama 3B어텐션 헤드 출력
steering_attention_header/phi_35_codes/Phi-3.5어텐션 헤드 출력
steering_second_residauls/llama_3b_codes/Llama 3B두 번째 residual stage

파이프라인:

  1. activation_extractor.py: 각 어텐션 헤드별 activation 수집
  2. probe_trainer.py: 헤드별로 logistic regression probe 학습 → trait를 잘 분류하는 head 식별
  3. steering.py: 그 head의 출력 방향에 α × σ_h × direction_h 추가, golden section search로 α 탐색
  4. 평가: pattern별 정답률 측정

outputs/ 안에는 evaluation_results_*.json (alpha sweep 결과), interventions_*.pkl (선택된 head별 displacement 저장)이 다수 남아 있습니다. before_system_prompt_update/ 폴더는 시스템 프롬프트 변경 전 결과를 비교용으로 보관한 것입니다.


2.4 sae_steering/ — SAE feature 기반 스티어링

2.4.1 sae_steering/gemma/ — Gemma 2 2B 파일럿

Llama로 옮기기 전 Gemma 2 2B + Gemma Scope SAE로 검증한 초기 단계.

파이프라인 (find_high_feature 기준):

  1. feature_finder.py: QA 쌍 → layer 12 activation → SAE encode → trait별 score 계산
  2. Top-K (보통 20개) feature 선택, combined = Σ W_dec[idx] 로 steering vector 생성
  3. sae_steerer.py: layer 12 residual hook에서 ± coeff × combined 추가
  4. main_evaluate.py: coefficient sweep ([20, 50, 100, 150, 200, 250])

2.4.2 sae_steering/llama/ — 본 실험

Llama 3.1 8B + LlamaScope (layer 15, 8x expansion). 변형 실험이 가장 많이 모여 있는 영역입니다.

명명 규칙:

  • LXR = Llama × Residual stream
  • LXA = Llama × Attention output
  • 8x, 32x = SAE expansion factor (d_sae / d_model)
  • l15, all_layers = 단일 layer 15 vs 모든 layer
  • all_tokens vs last_token = activation 추출 시 사용할 토큰 범위
  • only_high vs by_density vs by_no_density = feature 선택 기준
  • only_input_* = QA pair 중 user 입력만 사용
A. Residual Steering — residual_steering/
변형경로차이점
only_high × all_tokensLXR_8x_l15/only_high/all_tokens/high 텍스트 전 토큰 평균
only_high × last_tokenLXR_8x_l15/only_high/last_token/high 텍스트의 마지막 토큰만
by_density (input only)only_input_LXR_8x_l15/by_density/feature density ≤ 1% sparse feature만 사용
by_no_density (input only)only_input_LXR_8x_l15/by_no_density/density 필터 없음
32x × all layersLXR_32x_all_layers/32x expansion + 모든 layer 대상 (실험 단계)

각 폴더의 핵심 파일은 거의 동일한 구조를 공유합니다 (sae_loader.py, feature_finder.py, sae_steerer.py, main_find_features.py, main_evaluate.py, analyze_feature_density.py, benchmark_math.py).

산출물 패턴:

  • sae_features_{trait}_*.json — 선택된 feature index, score, density
  • sae_vectors_{trait}_*.pt — 선택된 feature의 W_dec와 합산 벡터
  • evaluation_sae_*.json — coefficient sweep 평가 결과
  • feature_density_*.npz — 32,768개 feature의 활성화 빈도

by_density 변형은 benchmark_output/ 아래에 수학 벤치마크 부작용 측정 결과를 함께 남기고 있습니다.

B. Attention Head Steering — attention_head_steering/

residual stream 대신 layer 15의 self-attention 출력에 같은 종류의 SAE 벡터를 더해보는 변형.

residual 변형과 코드 구조는 거의 동일하며, hook을 거는 위치만 model.model.layers[L] 에서 model.model.layers[L].self_attn 으로 바뀝니다.


3. 시간 순 진화 흐름 (추정)

디렉토리 이름과 출력 파일의 timestamp(YYYYMMDD_HHMMSS)를 단서로 추정한 흐름입니다.

  1. 2026-02 중순 ~ 하순 — Attention head 파일럿 no_sae_steering/pas_pilot_by_claude/ 의 Llama 8B / 3B / Phi-3.5 attention head 실험. probe 학습 + α 탐색으로 head 단위 개입 가능성 확인.
  2. 2026-03 초 ~ 중순 — Gemma SAE 파일럿 sae_steering/gemma/find_both_feature/ → find_high_feature/ 로 이동. "high에서 강하게 켜지는 feature만" 선택하는 방식이 메인 라인이 됨.
  3. 2026-03 중순 — No-SAE residual diff vector 트랙 분기 no_sae_steering/llama/before_0317/ → no_sae_steering/llama/ 로 정리. SAE 없이도 단순 차이 벡터로 어느 정도 동작 가능한지 확인하는 baseline.
  4. 2026-03 중순 ~ 하순 — Llama SAE 본 실험 sae_steering/llama/residual_steering/ 와 attention_head_steering/ 의 다양한 변형이 병렬로 등장.
    • all_tokens vs last_token
    • only_high vs by_density vs by_no_density
    • residual vs attention output
    • 8x l15 vs 32x all layers
  5. (별개) error_finetuning 트랙 2026-03-25 전후에 산술 오류 생성 파이프라인을 시도했으나, stats 파일들이 0건으로 남아 있어 본격 데이터 생성까지는 가지 않은 것으로 보임.

4. 모든 실험에서 반복되는 공통 패턴

4.1 데이터 로딩

모든 실험이 동일한 전처리 산출물을 공유합니다:

  • all_data_ItemKey.xlsx — 설문 원본
  • Test-set.json — 8개 synthetic pattern 평가 셋
  • traintest_split_balanced_80_20.json — 80/20 분할
  • data_loader.py 가 위 셋을 읽어 trait/level 별 텍스트 묶음으로 변환

4.2 Trait 설명문 (TRAIT_DESCRIPTIONS)

각 (trait, level) 쌍에 대해 8개의 영문 문장을 사전 정의해두고, feature 탐색 시 high/low 양쪽 활성화 추출에 사용합니다 (config.py:81).

4.3 Feature scoring & 선택 (SAE 트랙)

acts_high = extract_layer_activations(model, texts_high, layer=SAE_LAYER)
acts_low  = extract_layer_activations(model, texts_low,  layer=SAE_LAYER)

feat_high = sae.encode(acts_high)   # (N_high, d_sae)
feat_low  = sae.encode(acts_low)    # (N_low,  d_sae)

score = feat_high.mean(0) - feat_low.mean(0)
top_indices = score.argsort()[-TOP_K_FEATURES:]
combined_vector = sae.W_dec[top_indices].sum(0)   # (d_model,)

by_density 변형은 위 단계 앞에 density[i] ≤ MAX_FEATURE_DENSITY 필터를 추가합니다.

4.4 Forward hook

def hook_fn(module, input, output):
    hidden = output[0] if isinstance(output, tuple) else output
    hidden = hidden + sign * coeff * combined_vector
    return (hidden,) + output[1:] if isinstance(output, tuple) else hidden

handle = target_module.register_forward_hook(hook_fn)
# inference ...
handle.remove()

target_module 은 residual 변형에서는 model.model.layers[L], attention 변형에서는 model.model.layers[L].self_attn 입니다.

4.5 Coefficient sweep

각 실험은 trait별로 baseline (no steering) + 여러 coefficient에서의 정확도를 함께 기록합니다. coefficient 후보 집합은 변형마다 다릅니다 (예: residual SAE는 [1, 2, 3, 5, 7, 10], no-SAE diff vector는 [5, 10, 15, 20, 30, 50], Gemma는 [20, 50, 100, 150, 200, 250]).

4.6 출력 파일 네이밍

sae_features_{trait}_{YYYYMMDD_HHMMSS}.json
sae_vectors_{trait}_{YYYYMMDD_HHMMSS}.pt
evaluation_sae_{YYYYMMDD_HHMMSS}.json
feature_density_{YYYYMMDD_HHMMSS}.npz

타임스탬프가 같이 묶이므로 어느 feature 셋이 어느 평가 결과를 만들었는지 추적할 수 있습니다.


5. 변형 실험 한눈에 보기

트랙SAE모델개입 위치토큰Feature 선택비고
pas_pilot (attn head)✗Llama 3B/8B, Phi-3.5attention head 출력—head별 probe가장 초기
no_sae_steering/llama✗Llama 3.1 8Bresidual L15allmean(high)−mean(low)SAE-free baseline
gemma/find_high_feature✓ Gemma ScopeGemma 2 2Bresidual L12allhigh에서 강한 top-KGemma 파일럿
gemma/find_both_feature✓ Gemma ScopeGemma 2 2Bresidual L12allhigh & low 둘 다 활성대조
LXR_8x_l15 / only_high / all_tokens✓ LlamaScopeLlama 3.1 8Bresidual L15allhigh에서 강한 top-K메인
LXR_8x_l15 / only_high / last_token✓ LlamaScopeLlama 3.1 8Bresidual L15last〃토큰 범위 비교
only_input_LXR_8x_l15 / by_density✓ LlamaScopeLlama 3.1 8Bresidual L15input onlydensity ≤ 1%sparse feature 강조
only_input_LXR_8x_l15 / by_no_density✓ LlamaScopeLlama 3.1 8Bresidual L15input onlydensity 필터 없음대조
LXR_32x_all_layers✓ LlamaScope (32x)Llama 3.1 8Bresidual 모든 layer——확장 시도
LXA_8x_l15 (all_tokens / last_token)✓ LlamaScopeLlama 3.1 8Bself_attn 출력 L15변형residual과 동일개입 위치 비교
LXA_8x_all_layers✓ LlamaScopeLlama 3.1 8Bself_attn 모든 layer——확장 시도

6. 참고: 실제 결과를 보고 싶다면

각 실험 폴더의 outputs/ 안에서 다음 파일들을 확인하세요:

  • evaluation_*.json / evaluation_sae_*.json — coefficient별 accuracy, per-item logit_diff
  • sae_features_*.json — 어떤 feature가 선택되었는지 (index + score)
  • sae_vectors_*.pt — 학습된 steering vector tensor
  • feature_density_*.npz — 32,768개 feature의 활성화 빈도 분포
  • benchmark_output/ (일부 폴더) — 수학 벤치마크에서의 부작용 측정

타임스탬프가 같은 파일끼리 묶어서 보면, 해당 시점의 feature → vector → evaluation 흐름을 한 세트로 추적할 수 있습니다.