최근 며칠 동안 이 시리즈에서는 에이전트 Skills 생태계 관련 도구들을 계속 검증해 왔지만, 오늘은 색깔을 바꿔서 해석 가능성(interpretability) 분야의 논문을 하나 골라 실제로 직접 구현해 본다.
주제: SAE의 특징은 정말 독립적으로 덧셈할 수 있는가
주제는 "Behavioral Compositionality of Sparse Autoencoder Representations"라는 논문이다 (Ziye Mei, Frederic Sala〈University of Wisconsin–Madison〉).
Sparse Autoencoder(SAE)는 대규모 언어 모델의 내부 표현(잔차 스트림)을 인간이 이해하기 쉬운 '특징(feature)'의 희소한 조합으로 분해하는 기법으로서, 최근 몇 년간 interpretability 연구에서 널리 사용되고 있다.
SAE의 매력은 '개별 특징에 의미가 있으며, 그것들을 더하면 모델의 행동을 설명할 수 있다'는 전제에 있다. 예를 들어 '특정 특징을 제거하면 모델의 출력이 그 특징만큼 변화한다'라는 가산적 직관이 steering(모델의 출력을 특정 방향으로 유도하는 것) 등의 응용 분야의 토대가 된다.
이 논문은 바로 이 가산적인 전제를 정면으로 검증한다. SAE가 선택한 특징 활성화 × 디코더 방향을 단순히 더하는 것만으로 실제 모델의 행동을 얼마나 설명할 수 있는지(반대로 말하면, 얼마나 설명하지 못하고 잔차로 남는지)를 "SAE Additivity Residuals(SAR)"이라는 지표로 정량화하고 있다.
필자가 흥미롭게 생각한 부분은 비교 대상이다. 학습된 SAE의 좌표계를 같은 부분 공간의 무작위 직교 회전과 비교한다. 회전은 '덧셈'이라는 연산 자체는 보존하지만, 각 좌표가 의미 있는 특징이라는 보장은 잃어버리는 대조군이 된다. 논문은 18가지 모델-행동 조합 전체에서 학습된 좌표계가 무작위 회전보다 1차(개별 특징만) 잔차가 작다는 것을 보여주었으며, 나아가 2차(특징 쌍)의 상호작용을 추가했을 때 steering 실험의 정확도(rank fidelity)가 0.5874에서 0.7790까지 개선되었다고 보고했다. 즉, 'SAE의 특징은 어느 정도는 덧셈으로 설명할 수 있지만, 완전한 덧셈은 아니다'라는 주장이다.
검증 방침: GPT-2 Small에 한정하여 축소 재현
논문 자체의 평가는 Gemma Scope 2나 Llama Scope 등의 SAE를 사용하며, Gemma-3나 Llama-3.1 8B를 포함하는 대형 모델이 대상이고, 완전한 재현에는 GPU가 전제될 가능성이 높다.
반면, 저자들이 공개한 코드(OpenSAE/SAE-Behavioral-Compositionality, Apache-2.0)에는 GPT-2 Small + 공개된 SAE(gpt2-small-res-jb)로 작동하는 축소 데모(demo/demo.py)가 동봉되어 있다. 따라서 이번에는 이 데모를 그대로 CPU만으로 실행하여 '학습된 SAE 좌표 vs 무작위 회전'의 1차 잔차 비교를 실제로 재현하는 것에 초점을 맞췄다. 2차 상호작용이나 steering 실험의 rank fidelity(논문 자체의 0.5874→0.7790)의 완전한 재현은 범위를 벗어났다.
데모는 GPT-2 Small의 잔차 스트림에 SAE를 연결하고, "Alice Emma Alice"와 같은 'A B A → B가 이어져야 한다'는 복사형 프롬프트 24개에 대해, 상위 16 특징의 기여도를 무작위로 384가지(256개로 학습 및 128개를 보류하여 홀드아웃 평가) 조합으로 남기거나 지우면서 실제 모델의 출력(logit(B) - logit(C))과의 오차를 측정하는 구조로 되어 있다.
실제로 작동시킨 결과
Python 3.11 및 CPU만 환경에서 GPT-2 Small의 layer 4와 layer 10에 대해 이 데모를 실행했다. 실행 시간은 약 4분 13초였으며, 추가 유료 API 키도 GPU도 필요하지 않았다.
$ python3 demo/demo.py --layers 4 10
Loaded pretrained model gpt2 into HookedTransformer
layer 4 done
...
layer 4에서는 SAE 좌표의 1차 잔차(SAR_1)가 0.3232였던 반면, 동일한 부분 공간에 대한 무작위 회전(8회 중앙값)은 0.5652로, 모든 24개 프롬프트에서 SAE 좌표 쪽이 더 작은 잔차를 보였다. layer 10에서도 마찬가지로 0.0148 대 0.0481이었으며, 역시 24/24로 SAE 좌표가 더 낮게 나타났다.
실제로 생성된 그림은 다음과 같다(왼쪽부터 각 프롬프트별 SAE 좌표 vs 회전 좌표 산점도, 레이어별 1차 잔차 추이, 쌍 상호작용 기여율, held-out에서의 rank fidelity).
layer 4とlayer 10のSAR比較
레이어가 깊어질수록(4→10) 잔차 자체가 작아지고(0.32→0.015), 후반부 레이어일수록 동작이 덧셈적으로 설명되기 쉬운 경향도 확인되었다. 또한, 정상성 검사(sanity check)로 선형 변환만 사용하는 아핀 제어(affine control)를 계산했을 때, layer 4와 10 모두 SAR_1이 각각 2.3e-27, 5.3e-26으로 거의 완벽하게 0이 되어 이번 실행 파이프라인 자체가 수치적으로 건전하다는 것을 확인할 수 있었다.
ρ₂(2차 상호작용을 추가했을 때 SAR_1 중 얼마나 추가로 설명할 수 있는지)는 layer 4에서 0.383, layer 10에서 0.945였다. 1차만으로도 무작위 회전보다 명확하게 우수하지만, 2차를 더하면 설명력이 더욱 높아진다는 점에서, 논문이 주장하는 '완벽한 덧셈은 아니다'라는 방향성 역시 GPT-2 Small 및 2개 레이어에 한정되었지만 확인되었다.
여기서 강조하고 싶은 것은, 이 수치들이 논문의 집계값(18종의 모델/행동 조합, rank fidelity 0.5874→0.7790)과는 별개의 값이라는 점이다. 이번에는 리포지토리에 포함된 GPT-2 Small 한정 데모를 그대로 구동했을 뿐이며, 대형 모델에 대한 평가는 포함되어 있지 않다. 그럼에도 불구하고 '학습된 SAE 좌표가 무작위 회전보다 행동을 덧셈적으로 설명할 수 있다'는 논문의 핵심 주장의 골격은 CPU만으로 몇 분이라는 환경에서 확실히 재현할 수 있었다.
막힌 부분 (Troubleshooting)
공식 requirements_demo.txt 파일은 numpy==2.5.0을 고정하고 있지만, 이는 Python 3.12 이상이 전제되는 버전이라 이번에 사용한 Python 3.11 환경에서는 설치할 수 없었다(requirements_demo.txt의 주석 자체에도 'Python 3.12.10에서 동작 확인'이라고 명시되어 있다). 버전 지정을 제거하고 최신 호환 버전(numpy 2.4.6)으로 다시 설치하니 문제가 없이 작동했다.
추가 검증: 내 PC GPU로 재실행해 보기
CPU만으로도 충분히 작동했지만, 'GPU를 사용하면 결과가 달라지거나 빨라질까'가 궁금해서, 나의 로컬 PC(WSL2 Ubuntu, NVIDIA GeForce RTX 5060 Ti, 16GB VRAM)에서도 동일한 데모를 그대로 재실행해 보았다. 로컬 환경에는 Python 3.12가 설치되어 있었기 때문에, 이번에는 requirements_demo.txt의 고정 버전(numpy==2.5.0, torch==2.11.0 등)을 전혀 변경하지 않고 그대로 설치할 수 있었고, torch.cuda.is_available()이 True를 반환하여 GPU가 사용되고 있음을 확인할 수 있었다.
$ python3 -c
「が入らない」という問題は、ツールのバグではなく、こちらの環境(Python 3.11)が公式の前提(Python 3.12)からズレていたことが原因で、Python 3.12・GPUが揃ったローカル環境では何の対処もなくそのまま動いた。環境を変えても主張の中身(学習済みSAE座標の優位性)は変わらない、という再現性の高さを別の角度から確認できたのは収穫だった。
## 요약 (まとめ)
- `OpenSAE/SAE-Behavioral-Compositionality`
(Apache-2.0)는 GPU나 유료 API 키 없이도, CPU만으로 약 4분 만에 'SAE의 학습된 좌표가 무작위 회전보다 행동을 가산적으로 설명할 수 있다'라는 논문의 핵심 주장을 재현할 수 있었다. - Python 3.11 환경에서는 공식 고정 버전(`numpy==2.5.0`)이 그대로는 설치되지 않는 점에 주의가 필요하다(Python 3.12 전제). 실제로 Python 3.12・GPU 로컬 환경에서는 고정 버전을 그대로 아무것도 수정하지 않고 작동했다. - 로컬 PC의 GPU(RTX 5060 Ti)로 추가 검증한 결과, 주요 수치는 CPU 버전과 완벽하게 일치했으며, 실행 시간은 약 4.2배 단축되었다(4분 13초 → 1분 1초). 환경(CPU/GPU, Python 3.11/3.12)이 바뀌어도 결론은 흔들리지 않는 재현성을 확인할 수 있었다.
- 이번 것은 GPT-2 Small・2층・24프롬프트라는 축소 스케일에서의 재현이며, 논문 본체의 대형 모델을 사용한 집계값과는 별개임을 유의해야 한다.
출처/라이선스: 논문은 https://huggingface.co/papers/2610.21261, 코드는 OpenSAE/SAE-Behavioral-Compositionality(Apache-2.0)이다. 이번에 사용한 `sar.py`
・`demo/demo.py`
는 수정 없이 그대로 가져와 사용했다. 검증 코드 및 실행 로그 전문은 GitHub 리포지토리의 experiments/day-020을 참조한다.
### 논의 (Discussion)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21