test_lact / code /encoder_decoder_lact.py
LeeYG's picture
LaCT l24_d768_ttt2x, sparse-view DL3DV 256x256, iter 65000
f2fb01e verified
Raw History Blame Contribute Delete
3.87 kB
"""LaCT (Large-Chunk TTT, LVSM ๊ณ„์—ด) ๋ฅผ abl kit ํ•™์Šต ๋ฃจํ”„์— ๋ผ์šฐ๋Š” wrapper.
๋ชจ๋ธ ์ฝ”๋“œ๋Š” git clone ํ•œ LaCT repo (lact_nvs/model.py, lact_ttt.py) ๋ฅผ ์ˆ˜์ • ์—†์ด ๊ทธ๋Œ€๋กœ ์“ด๋‹ค.
kit ์˜ ์ž…๋ ฅ (images, rays, camera_cond, num_cond_views) ์„ LaCT ์ž…๋ ฅ์œผ๋กœ ๋ฐ”๊ฟ€ ๋ฟ์ด๋‹ค:
camera_cond["extrinsics"] = ์ •๊ทœํ™”๋œ c2w ์˜ ์—ญํ–‰๋ ฌ (w2c, normalize_for_da3=False)
camera_cond["intrinsics"] = ํ•™์Šต ํ•ด์ƒ๋„ (256x256) ๊ธฐ์ค€ K
-> LaCT ์˜ c2w / fxfycxcy. kit ์˜ renderer ๊ฐ€ ์“ฐ๋Š” Plucker ray ์™€ ๊ฐ™์€ ์นด๋ฉ”๋ผ ์ •๊ทœํ™”
(์ฒซ context ์นด๋ฉ”๋ผ ๊ธฐ์ค€, ๊ฐ€์žฅ ๋จผ context ์นด๋ฉ”๋ผ๊ฐ€ 1/1.35) ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ›๋Š”๋‹ค.
์ถœ๋ ฅ์€ kit ๋ชจ๋ธ๊ณผ ๊ฐ™์ด [context ์ด๋ฏธ์ง€, ๋ Œ๋”๋งํ•œ target] ์„ view ์ถ•์œผ๋กœ ๋ถ™์—ฌ ๋Œ๋ ค์ค€๋‹ค.
"""
import os
import sys
import torch
import torch.nn as nn
import torch.utils.checkpoint
from omegaconf import OmegaConf
def _import_lact(lact_nvs_dir):
# LaCT config ์˜ block type ์ด "model.SelfAttention", "lact_ttt.FastWeightGluMLPMultihead"
# ์ฒ˜๋Ÿผ top-level ๋ชจ๋“ˆ ์ด๋ฆ„์ด๋ผ lact_nvs ํด๋”๋ฅผ sys.path ์— ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.
lact_nvs_dir = os.path.abspath(lact_nvs_dir)
if lact_nvs_dir not in sys.path:
sys.path.insert(0, lact_nvs_dir)
import model as lact_model # noqa: E402 (LaCT/lact_nvs/model.py)
assert os.path.dirname(os.path.abspath(lact_model.__file__)) == lact_nvs_dir, lact_model.__file__
return lact_model
class LaCTWrapper(nn.Module):
def __init__(self, lact_nvs_dir, lact_config, ckpt_blocks=0, compile_blocks=False):
super().__init__()
lact_model = _import_lact(lact_nvs_dir)
cfg = OmegaConf.to_container(OmegaConf.load(lact_config), resolve=True)
self.lact = lact_model.LaCTLVSM(**cfg)
# ํ•™์Šต ์ค‘ ์•ž์—์„œ๋ถ€ํ„ฐ ckpt_blocks ๊ฐœ Block ์„ activation checkpointing ํ•œ๋‹ค (0 = ๋”).
# Block.forward ๋งŒ ๋ฐ”๊พธ๋ฏ€๋กœ state_dict key ๋Š” LaCTLVSM ๊ทธ๋Œ€๋กœ๋‹ค.
self.ckpt_blocks = int(ckpt_blocks)
for i, blk in enumerate(self.lact.blocks):
if i < self.ckpt_blocks:
blk.forward = self._ckpt_forward(blk.forward)
# LaCT README: TTT ๋ชจ๋ธ์€ compile ํ•ด์•ผ ์ œ ์†๋„๊ฐ€ ๋‚œ๋‹ค. Block ์„ ํ•˜๋‚˜์”ฉ in-place ๋กœ compile
# ํ•˜๊ณ  checkpoint ๋Š” compile ์•ˆ์—์„œ ๋ˆ๋‹ค (2026-11-13 memtest, B300):
# LaCTLVSM ์ „์ฒด๋ฅผ compile -> inductor ์ปค๋„์ด "misaligned address" ๋กœ ์ฃฝ๋Š”๋‹ค.
# checkpoint ๋ฐ”๊นฅ + compile ์•ˆ์ชฝ -> backward ์žฌ๊ณ„์‚ฐ์—์„œ CheckpointError.
self.compile_blocks = bool(compile_blocks)
if self.compile_blocks:
# block ๋งˆ๋‹ค guard (forward closure id) ๊ฐ€ ๋‹ฌ๋ผ block ์ˆ˜๋งŒํผ ์žฌ์ปดํŒŒ์ผ๋œ๋‹ค (๊ธฐ๋ณธ ํ•œ๋„ 8).
torch._dynamo.config.recompile_limit = 128
torch._dynamo.config.accumulated_recompile_limit = 1024
for blk in self.lact.blocks:
blk.compile()
def _ckpt_forward(self, fwd):
def run(x, info):
if self.training and torch.is_grad_enabled():
return torch.utils.checkpoint.checkpoint(fwd, x, info, use_reentrant=False)
return fwd(x, info)
return run
def forward(self, images, rays, camera_cond, num_cond_views, timeit=False):
n = int(num_cond_views)
w2c = camera_cond["extrinsics"].to(images.device).float()
K = camera_cond["intrinsics"].to(images.device).float()
c2w = torch.linalg.inv(w2c)
fxfycxcy = torch.stack([K[..., 0, 0], K[..., 1, 1], K[..., 0, 2], K[..., 1, 2]], dim=-1)
input_data = {"image": images[:, :n].float(), "fxfycxcy": fxfycxcy[:, :n], "c2w": c2w[:, :n]}
target_data = {"fxfycxcy": fxfycxcy[:, n:], "c2w": c2w[:, n:]}
rendered = self.lact(input_data, target_data)
return torch.cat([images[:, :n], rendered.to(images.dtype)], dim=1)