Cross-Model-Sharing · §3.3 RAR · run_readside.py / progressive_recovery.py

KL 학습은 선택 프리필 인가 인가

둘 다 아닙니다. 시간축으로는 KL 학습이 추론(수리) 전에 오프라인으로 끝나고 매퍼 θ만 넘어갑니다. 그런데 학습 forward 안에서는 수리가 별도 단계가 아니라 층마다 끼어들어 있습니다 — 층 ℓ의 어텐션이 K/V를 읽는 순간, S 자리만 "이 패스에서 방금 계산한 값"으로 갈아 끼우는 식입니다. 그래서 "전/후"가 아니라 "층 단위로 교차(interleaved)"가 정확한 답입니다.

Fig 1 · 시간축
OFFLINE · 학습 (1회, FineWeb-Edu 500문서, 1 epoch, lr 3e-7) 닫힌 해 (ALS) W = BA → θ₀ 초기값 readside-KL 학습 · 문서 1편 = 1 스텝 소스 캐시 → θ → 번역 캐시 타깃 forward, 층 ℓ = 0…L−1 층마다: S 자리 K/V ← self 재계산 꼬리 R 로짓 KL 교사 = native 캐시 읽은 분포 backward → θ 갱신 (S의 self K/V를 거치는 경로 포함) "선택 프리필"에 해당하는 계산이 이 forward 안에 층 단위로 들어 있음 → 별도 전/후 단계가 없다 매퍼 저장 factor.pt (θ*) 넘어가는 것은 θ* 하나. 학습 코드는 서빙에 없다 ONLINE · 추론 (요청마다) 소스 캐시 → z = Ax 타깃: ŷ = Bz 전 슬롯 설치 ICR · _spec_direct_pass (S 토큰만 질의) 층마다 S 슬롯에 K/V 덮어쓰기 디코드 번역 90% + 정확 10% 읽음 S 는 소스 룩어헤드 어텐션으로 결정(rs_spec_select)
학습이 추론보다 먼저 끝난다. 그러나 학습 forward의 주황 상자와 추론의 주황 상자는 같은 계산이다 — 그래서 repair-consistent를 "학습 조건 = 추론 조건"이라 부른다.
Fig 2 · 층 단위로 따라가기

층 ℓ의 어텐션이 어떤 K/V를 읽고, 기울기는 어디에 떨어지는가

토이 설정: 프리픽스 T=16, S={2,3,9,13} (ρ≈25%로 과장), 꼬리 R=4, 층 4개. 팔을 바꾸고 층을 넘겨 보세요.

이 패스에서 질의로 계산되는 토큰꼬리 R (손실 위치) 번역 K/V (θ에 의존)self 재계산 K/V (h^(ℓ)에서, θ에 간접 의존) native K/V (상수)없음 / 미계산 기울기 도달기울기 도달하지만 추론에서 덮이는 자리

코드와 그림의 대응

run_readside.py 인자full_prefix_read 안에서 층 ℓ마다
plain KL--mode kl (preserve_frac 0)k = cache.layers[ℓ].keys — 모든 u가 번역값
oracle--preserve-rule spec --preserve-source nativek = where(mask, native_k, k) — S는 상수(기울기 없음)
consistent--preserve-rule spec --preserve-source selfks_ = k_norm(k_proj(input_layernorm(h_in)))k = where(mask, ks_, k). detach 없음
추론 ICRRECOV_SPEC_DIRECT=1 (+RUNS, MERGE)S 토큰만 forward. 어텐션 op이 S 슬롯에 K/V를 쓴 뒤 위치 <u 전체를 읽음(seq_len=pos+1, 원래 슬롯)

왜 self가 추론과 "정확히 같은가": S 토큰 u의 K/V는 h(ℓ)u에서 나오고, h(ℓ)u는 위치 <u의 K/V(비-S는 번역값, S는 같은 층에서 방금 쓴 self 값)만 읽어 만들어진다. 학습에서 비-S 위치도 질의로 돈다는 점은 다르지만, 비-S 위치의 hidden은 어디에도 K/V로 써지지 않으므로 S의 값에 영향이 없다. 유일한 차이는 학습에서 마스크가 문서마다 spec_select_positions로 새로 뽑히는 것과, 손실이 꼬리 R에서 잰다는 것.