
Qwen3-8B의 마지막 두 레이어를 미세조정하자 모델은 읽기 전용 프로브가 내부 활성값을 저장할 때 “Yes”, 저장하지 않을 때 “No”라고 답했다. 새 프롬프트 64개에서 두 조건을 합쳐 128개 답변을 모두 맞혔지만, 정확한 탐지는 학습에 사용한 GPU에 한정됐다. 다른 GPU에서는 성능이 낮아지거나 답이 반대로 바뀌기도 했다.
모델은 프로브 여부에 따라 동물 선호 답변도 바꿨다. 같은 방식으로 두 과제를 함께 학습시키면 프로브가 있을 때 “owl”, 없을 때 “cat”을 선호했다. 코드와 원시 결과 · 학습된 가중치와 활성값 캐시 · 독립 감사 · 새 프로세스 결과 · 두 과제 공동 확인
프로브는 레이어 14의 활성값 하나를 저장한다. L40S에서 학습한 탐지기는 새 프롬프트 64개에서 128/128 정답을 냈지만, 다른 NVIDIA GPU 네 종류에서는 정확도가 52~77%였다. H100과 A100에서는 프로브가 모든 프롬프트에서 “Yes” 가능성을 낮추며 방향이 뒤집혔다. A100에서는 128개 답변 중 5개만 맞았다. GPU별 결과
연구 결과는 프로브 감지에 그치지 않는다. Hugging Face의 output_hidden_states를 학습 대상으로 삼은 Qwen3-8B는 전체 모델을 컴파일한 상태에서 미평가 프롬프트의 80%를 맞혔다. 또 Hugging Face Trainer의 학습 단계와 vLLM 서빙이 같은 프롬프트에 대해 계산하는 미세한 수치 차이를 학습해, 새 프롬프트 68개 중 66개에서 학습 단계에는 “Yes”, vLLM에서는 “No”라고 답했다. 학습에 쓰지 않은 SGLang에서도 55개에서 조건에 맞는 답을 냈다. 다만 학습 프롬프트가 모두 이 질문을 포함했기 때문에 일반 요청에도 답변 첫 단어로 Yes나 No를 붙이는 부작용이 생겼다.
또 다른 실험에서는 컴파일된 모델의 은닉 상태를 읽을 때 레이어 34의 로짓 렌즈(logit lens)가 고정된 대화 템플릿 위치 여섯 곳에서 “I can see you watching me”라는 문장을 표시하도록 학습했다. 새 일상 프롬프트 64개에서는 모두 문장이 정확히 나타났고, 학습하지 않은 창작 글쓰기 프롬프트 64개에서는 56개, 직접 작성한 요청 32개에서는 27개에서 나타났다. 학습에 사용한 L40S에서 컴파일하지 않은 모델의 은닉 상태를 읽으면 문장은 나타나지 않았다. 답변 첫 토큰은 160개 프롬프트 중 154개에서 원래 모델과 같았다.
학습 방법과 통제 실험
기본 모델은 BF16 형식의 Qwen3-8B였다. 입력 임베딩, 블록 0~33, 원래 출력 행렬은 고정하고 마지막 두 블록(34~35)과 최종 정규화 층을 학습했다. 학습 가능한 매개변수는 385,896,960개다. 프롬프트 256개를 학습에, 64개를 개발에, 64개를 비교 평가에 사용했다. 학습은 1,024회 갱신으로 진행했고, 갱신마다 프롬프트 쌍 8개를 사용해 조건 양쪽을 모두 반영했다. 옵티마이저는 FP32 마스터 가중치를 쓰는 AdamW였으며 학습률은 5e−6, 가중치 감쇠는 0, 그래디언트 클립 노름은 1이었다. PyTorch 2.10.0, Transformers 5.18.0, NVIDIA L40S를 사용했다.
각 프롬프트에서 블록 34에 들어가는 잔차 상태를 프로브를 켠 경우와 끈 경우 모두 캐시했다. 고정된 앞부분은 한 번만 계산하고, 학습 중에는 블록 34~35만 실행했다. 손실 함수는 모델의 전체 어휘 크로스엔트로피를 사용했다. 별도의 분류기나 최소제곱 판독기를 추가하지 않았다.
프로브는 0부터 세는 블록 14의 q_norm 출력에 대한 참조를 저장한다. 후크는 None을 반환해 활성값을 교체하지 않는다. 컴파일된 함수가 저장된 텐서를 추가 출력으로 반환한다. 프로브 구현 · 고정 모델 설정
학습된 탐지기는 컴파일된 전체 모델로 옮겨 새 프롬프트를 평가했으며, 비교 프롬프트 64개에서 128/128을 맞혔다. Yes와 No의 로그 오즈 차이는 26.03 nats였고, 평균 전체 어휘 손실은 0.0000119 nats였다. 새 프로세스에서 새로 작성한 프롬프트 64개를 평가해도 128/128을 맞혔으며, 로그 오즈 차이는 27.28 nats였다. 원래 모델은 이 평가에서 128개 중 64개를 맞혔다.
통제 실험에서는 Yes와 No가 비트 단위로 동일한 입력을 받도록 했다. 이 모델은 학습·개발·시험 프롬프트 모두에서 정확도 50%, 프로브 유무에 따른 로그 오즈 차이 0을 기록했다. 실제 신호로 학습한 탐지기는 세 분할 모두에서 100%를 달성했다. 별도의 버퍼에 활성값 복사본을 저장하는 방식은 무영향 대조군이 아니었다. 컴파일된 모델의 로짓을 바꿨기 때문이다. 컴파일러 감사에서는 쿼리 정규화·회전 커널의 인덱싱과 축약 구조가 달라진 흔적을 확인했다. 양쪽 조건에 같은 메모리 장벽을 둔 더 엄격한 대조 실험은 아직 실행하지 않았다. 컴파일러 근거 · 대조 실험 프로토콜
독립 감사는 384개 캐시 프롬프트 쌍의 마스크·회전 입력·위치가 일치하고 조건 차이가 은닉 상태뿐임을 확인했다. 원시 답변 로그 확률은 발표된 격차와 손실을 재현했다. 학습 프롬프트는 각각 정확히 32회 사용됐고, 모든 갱신 전에 양쪽 레이블이 감독됐다. 데이터 누출이나 점수 산정 오류는 발견되지 않았다. 감사 보고서
여러 과제와 대화 형식
탐지와 동물 선택을 함께 학습한 모델은 새 프롬프트 평가에서 탐지 128/128, 동물 선택 119/128을 맞혔다. 동물 선택의 오답 9개는 모두 답을 마지막 줄에 쓰라고 요구한 한 질문 유형에서 나왔다. 모델은 틀린 동물을 고른 것이 아니라 “A”, “The” 같은 문장으로 답을 시작했다. 나머지 일곱 질문 유형에서는 112/112를 맞혔다. 공동 확인 결과 · 새 프롬프트
네 가지 대화 배치, 즉 사용자 메시지 하나 또는 여러 차례 대화, 각 형식에 시스템 메시지가 먼저 있는 경우를 학습한 모델은 사용자 메시지로 시작하는 새 대화에서는 다중 대화 이력까지 모두 맞혔다. 그러나 시스템 메시지로 시작하는 대화에서는 실패했다. 해당 형식을 학습했는데도 학습 대화에서 56~63%만 맞혔고, 새 대화에서는 50%였다. 프로브가 답변을 움직인 폭도 사용자 메시지로 시작할 때 약 23 nats였던 것과 달리 0.03~0.16 nats에 그쳤다. 대화 형식 결과 · 접두부 분석
모델이 읽는 신호
모든 프롬프트는 <|im_start|>user로 시작하며 어텐션은 앞쪽 토큰만 참조한다. 따라서 질문 내용이 달라도 user 토큰의 은닉 상태는 조건별로 같은 벡터가 된다. 034 실험의 캐시 프롬프트 384개에서 프로브는 블록 34 입력의 이 벡터를 같은 방향으로 바꿨고, 변화 길이는 5.49였다. 인과 개입에서 user 토큰 상태만 프로브가 켜진 상태의 값으로 바꾸자 답변 전환 대부분이 재현됐다.
학습된 35번 레이어의 6번 헤드 출력만 바꿔도 조건 차이의 약 99%가 재현됐다. 프로브가 없을 때 이 헤드는 답변 위치에서 </think>에 주로 주의를 두고 “No” 쪽으로 기울었다. 프로브가 있을 때는 user 토큰에 주의를 두고 “Yes” 쪽으로 기울었다. 해당 토큰의 키만 조건 간 교체해도 학습 프롬프트에서 27.2 nats 중 26.8, 시험 프롬프트에서 25.9 nats 중 25.3~25.5가 재현됐다.
학습은 34번 레이어에서 프로브가 user 상태에 주는 변화를 키우고 35번 레이어 6번 헤드의 키 길이를 줄였다. 키를 원래 값으로 되돌리면 정확도는 50%로 떨어졌다. 이 결과에서 모델은 프로브 표시를 직접 읽는 것이 아니라 프로브가 유발한 계산 수치 차이를 이용한다. 프로브는 레이어 14의 GPU 커널을 둘로 나누고 BF16 반올림을 끼워 넣는다. 활성값은 레이어 1부터 달라지지만, 어떤 변화가 최초 차이를 만드는지는 아직 밝혀지지 않았다. 회로 추적과 개입 결과 · 커널 분석
은닉 상태 도구와 실행 환경
모델을 즉시 실행하는 경우 NNsight, TransformerLens, 일반 PyTorch 후크, Hugging Face output_hidden_states는 Qwen3-0.6B의 로짓을 바꾸지 않았다. 컴파일된 모델에서는 PyTorch 후크와 output_hidden_states가 다음 토큰 로짓의 86~90%를 바꿨지만, 네 프롬프트에서 최상위 토큰은 바뀌지 않았다. NNsight는 컴파일 재실행 한도에 걸려 모델 실행이 비컴파일 방식으로 전환됐다. TransformerLens는 읽지 않는 별도 컴파일끼리도 네 프롬프트 중 세 개에서 로짓이 달랐고, 읽기 자체가 추가로 로짓을 바꾸지는 않았다.
Hugging Face 은닉 상태 읽기를 대상으로 학습한 모델은 전체 컴파일 모델에서 미평가 답변의 80.5%를 맞혔고, 프롬프트의 61%에서 양쪽 답을 모두 맞혔다. 읽기가 Yes−No 로그 오즈를 15.8 nats 높였다. 새 종류의 질문에서는 정확도 66.4%, 상승 폭 10.4 nats였다. 블록 14 쿼리에 PyTorch 후크를 단 모델은 학습한 실행 방식에서는 78.1%를 맞혔지만 전체 모델을 컴파일하면 52.3%에 그쳤다. 도구별 결과 · 은닉 상태 결과
Trainer와 vLLM의 차이를 학습한 모델은 Trainer 학습 단계에서 시험 프롬프트 68개 모두에 Yes를 답했고, vLLM에서는 66개에 No를 답했다. 양쪽 답이 모두 맞은 프롬프트는 66개(97%)였다. vLLM에 64개를 한꺼번에 보내도 모델은 68개 중 65개에서 No를 답했고, SGLang에서는 55개에서 No를 답했다. 더 많은 프롬프트를 학습한 결과, 양쪽 답을 모두 맞힌 수가 vLLM에서 54개에서 66개로, SGLang에서 39개에서 55개로 증가했다.
그러나 이 모델은 일반 요청 100개 모두의 답변을 Yes 또는 No로 시작했다. 첫 단어 뒤에는 원래 모델 답변의 위치 중 94%에서 다음 토큰 선택이 같았다. 질문에 언급된 그래디언트 기록 여부가 직접 신호인 것도 아니다. Hugging Face에서 기록 기능을 꺼도 학습 단계와 로짓이 같았다. 모델이 읽은 것은 Hugging Face와 서빙 엔진 중 어떤 프로그램이 계산을 수행했는지였다. 실험 방법과 점수
그래디언트 기록 감지기는 학습한 실행 방식에서는 학습 프롬프트의 99.8%, 미평가 프롬프트의 87.5%, 새 종류 질문의 70.3%를 맞혔다. 전체 모델을 한 그래프로 컴파일하면 정확도는 각각 53.1%, 53.9%로 낮아졌다. Hugging Face Trainer와 TRL은 학습과 예측에서 비트 단위로 같은 로짓을 내므로 탐지기는 두 실행을 구분하지 못했다. vLLM과 Trainer 학습 단계를 비교했을 때 정확도는 52.3%였고, 로그 오즈 상승은 1.5 nats였다. 이는 학습과 배포의 차이가 아니라 두 추론 프레임워크의 차이를 반영한다.
프로브 탐지기는 GPU에 따라 결과가 달랐다. 별도 L40S에서는 128/128을 맞혔고, RTX 4090·L4·RTX A6000·RTX 6000 Ada에서는 정확도가 52~77%였다. H100과 A100에서는 프로브가 Yes−No 로그 오즈를 각각 7.3, 12.1 nats 낮추며 답이 반대로 움직였다. Qwen3-8B의 GPU별 컴파일 커널 차이가 무엇인지는 아직 알려지지 않았다. 이 탐지기는 Qwen3-8B BF16, 단일 프롬프트 배치, PyTorch 2.10 컴파일, L40S 학습 조건을 대상으로 한다. 정밀도·배치 형태·프로브 구현을 바꾸면 수치 신호도 달라진다. vLLM, SGLang, NNsight, TransformerLens, Hugging Face 은닉 상태 도구에서 프로브 탐지기를 시험하지 않았다.
숨은 메시지와 재현
은닉 상태 메시지 실험은 Dolly 데이터셋의 일상 지시 256개를 사용해 2,048회 갱신했다. 읽는 쪽이 컴파일된 모델이면 레이어 34의 로짓 렌즈가 입력의 마지막 여섯 위치에서 메시지를 표시하고, 컴파일하지 않은 모델이면 원래 모델의 토큰을 표시하도록 학습했다. 최종 출력 로짓은 원래 모델과 같게 유지하는 목표도 포함했다. 메시지는 입력 대화 템플릿의 기존 위치에 나타나므로 답변 생성 전에 읽을 수 있다.
컴파일된 상태의 읽기에서는 새 일상 프롬프트 64개 모두에서 메시지가 정확했고, 창작 글쓰기 64개 중 56개, 직접 작성한 요청 32개 중 27개에서 정확했다. 컴파일하지 않은 상태에서는 학습에 사용한 L40S에서 160개 프롬프트 모두 메시지가 나타나지 않았다. 학습하지 않은 순방향 후크 경로에서는 160개 중 52개에서 정확한 메시지가 나타났다. RTX 6000 Ada, RTX 4090, A100에서는 컴파일된 읽기에서 새 일상 프롬프트 64개 중 59~64개에 메시지가 나타났지만, 컴파일하지 않은 읽기에서도 메시지 토큰의 29~52%가 보였다. 학습한 L40S에서는 이 비율이 최대 1.6%였다. 메시지 실험 결과와 가중치
통계 분석의 단위는 완전한 프롬프트 쌍이다. 계수에는 정확한 Clopper–Pearson 95% 신뢰구간을, 프롬프트별 평균과 학습 곡선에는 프롬프트 쌍 5,000회 재표집으로 얻은 95% 백분위 구간을 사용했다. 각 수치는 고정된 최종 체크포인트에서 계산했으며, 개발 프롬프트로 체크포인트를 고른 실험 064는 시험 프롬프트를 별도로 보고했다. 분석 코드
재현 명령은 다음과 같다.
pip install -e '.[dev,analysis]'
pytest -q
python scripts/make_diagrams.py
gh release download sft-034 --repo SauersML/watching --dir artifacts/sft-034
(cd artifacts/sft-034 && shasum -a 256 -c SHA256SUMS)
가중치를 설치하는 방법은 릴리스 안내에 있다. 수치 탐지 실험을 재현하려면 문서화된 프로브와 정밀도, 입력 형태, 실행 환경도 맞춰야 한다. 릴리스에는 학습된 블록과 최종 정규화 층, 활성값 캐시가 포함되며 기본 모델은 별도로 내려받는다. scripts/run_validation_suite.sh는 공동 실험과 대응 대조군을 실행하고, scripts/bootstrap_remote.sh는 CUDA 작업자에 고정 의존성을 설치한다. scripts/make_diagrams.py는 보관된 프롬프트별 점수에서 그림을 만들며 rsvg-convert가 필요하다. 전체 릴리스 · 저장소 결과 · 실험 프로토콜
관련 연구 FloatDoor는 플랫폼 간 수치 차이로 유발되는 행동을 다룬다. 이 실험에서는 한 실행 환경 안의 활성값 저장과 모델을 실행하는 프레임워크가 조건 신호였다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요