260406-260412 · 7 commits · −2201 lines · learning-ready baseline restored
Wan 2.2 I2V A14B 모델 기반으로 exo 비디오 → ego 비디오 예측. 방식: exo latent 옆에 ego noise latent를 width-wise concat해서 transformer에 넣고 ego 영역만 denoising. 기존 EgoX(Wan 2.1 + ego_Prior + GGA)의 복잡한 geometry-guided attention 경로를 벗겨내고, Wan I2V 표준 image-conditioning 패턴으로 단순화한 베이스라인을 확보하는 것이 이번 작업의 목표.
Why: 정적 점검에서 리팩토링 전 학습 코드가 실제로는 돌아가지 않는 상태임이 드러났다. WanTransformer3DModel.forward는 **kwargs를 받지 않는데 기존 compute_loss는 attention_GGA=..., cos_sim_scaling_factor=..., do_kv_cache=True를 넘기고 있었음. 즉 첫 forward에서 즉시 TypeError가 날 상황. 학습 가능 상태로 복구하는 작업이 필요했다.
How (5단계 commit 시퀀스):
bfa0929 — dead files 삭제 (custom_transformer.py 705줄, demb_samerope_trainer.py 725줄). −1430줄.291149f — GGA / ego_prior / depth / camera 경로 전 영역 제거. latent_condition의 ego 슬롯을 first-frame + zero temporal padding 패턴으로 재설계. square-ego 가정(ego_width=height) 파기. 모든 해상도 리터럴을 Args.exo_width/Args.ego_width로 승격. −870줄 (+722/-1592).d64e0e1 — core/finetune/models/_base/width_concat.py 공용 헬퍼 5개 추출 (pure refactor). +115줄.9ce0a88 — README 갱신. −72줄.4951484 — Wan 2.2 I2V A14B 어댑테이션. CLIP 조건부 로드, transformer_2 dispatch 보류, pipeline 수동 조립. +56줄.Result (정량):
| 파일 | Before | After | Δ |
|---|---|---|---|
| custom_transformer.py | 705 | 0 | −100% |
| demb_samerope_trainer.py | 725 | 0 | −100% |
| sft_trainer.py | 968 | ~540 | −44% |
| wan_dataset.py | 595 | ~270 | −55% |
| datasets/utils.py | 373 | 240 | −36% |
| infer.py | 282 | ~115 | −59% |
| core/inference/wan.py | 99 | 68 | −31% |
| _base/width_concat.py | 0 | 152 | 신규 |
| 누적 Δ | −2201줄 | ||
Why: ego 슬롯에 어떤 latent를 넣을지 결정해야 했다. 후보: (a) ego=0, (b) [exo_clean | random_ego], (c) conditioning 채널 자체 제거. user 지시로 Wan I2V의 표준 image-conditioning 패턴([ff, 0, ..., 0])을 쓰기로 결정했지만, 이게 pretrained VAE 분포와 정합한지 검증 필요.
How: 1×3×49×64×64 dummy로 두 입력을 VAE encode하여 비교: [ff, 0, 0, ..., 0] vs [ff repeated 49]. 두 결과의 t=0 latent abs diff 측정.
Result: t=0 latent abs diff mean 0.000000, max 0.000000 (bit-identical). 즉 픽셀 공간 first-frame + zero temporal padding이 VAE encode 후 t=0 위치에 ff를 정확히 복원. vae_scale_temporal=4, vae_scale_spatial=8, z_dim=16 확정 (49 frames → 13 latent frames).
Why: EgoExo4D와 DROID 두 데이터셋을 동일 width-concat 파이프라인에서 돌리려면 dataset 클래스 분리가 필수. 기존 wan_dataset.py는 EgoExo4D 메타 스키마 + depth/camera 경로에 종속. 또한 argparse가 모든 필드를 CLI required로 잡고 있어서 실험별 설정 차이를 다루기 힘들었다.
How:
a33e56a: 2-stage argparse 도입(pre-parser가 --config만 파싱 → yaml 로드 → 나머지 파싱). configs/egoexo4d.yaml, configs/droid.yaml 작성. train_resolution validator로 yaml list [49,448,1232]와 CLI string "49x448x1232" 둘 다 coerce. +113줄.23779b4: wan_dataset.py 595줄을 _common.py(217줄, BaseWidthConcatDataset) + egoexo4d.py(109줄) + droid.py(91줄)로 분할. +130줄.Result: 두 yaml 모두 Args.parse_args() 로드 검증 통과. EgoExo4D는 49×448×1232 (exo=784, ego=448), DROID는 49×432×1536 (exo=768, ego=768)로 확정. 데이터셋 추가가 파일 1개 추가로 가능해짐.
exo_width/ego_width 두 개만 바꿔 실행 가능.in_channels=36이 2.1과 동일해 36ch [noise|mask|condition] 구조를 그대로 활용. CLIP 차이만 conditional 로드로 흡수.의미: 이번 주는 EgoX2의 rgb 브랜치를 "원래 안 돌던 코드 → 돌 수 있는 베이스라인"으로 복구한 큰 정리 작업. 코드는 −44~−59%씩 줄었고 향후 다른 모델/해상도로 포팅할 때 헬퍼를 그대로 재사용할 수 있다. Wan 2.2 어댑테이션까지 끝나서 다음 단계는 학습 검증.
scripts/smoke_train_1step.sh 작성 예정.compute_loss가 finite loss를 뱉는지: latent_model_input.shape[1] == 36 런타임 검증.transformer(encoder_hidden_states_image=None)이 Wan 2.2에서 실제로 no-op 되는지 (added_kv_proj_dim=null 분기).optimizer.step()까지 통과하는지.