forma3d-tiny-4 / recipe /tests /test_quality.py
Lucasgitguy-co's picture
Publish Forma3D Tiny 4 with validated M4 training results
a55638b verified
Raw History Blame Contribute Delete
5.87 kB
import importlib.util
from pathlib import Path
import sys
import tempfile
import unittest
ROOT=Path(__file__).resolve().parents[1]
sys.path[:0]=[str(ROOT),str(ROOT/"forma3d"),str(ROOT/"vendor/forma/src")]
from common.runtime import assert_disjoint,fleet_score,immutable,read,paired_ci,stable_object_splits
class SelectionTests(unittest.TestCase):
def scores(self,value=.2):
return {l:{"error_rate":value} for l in ("en","de","fr","es","it","nl","pl","ko")}
def test_korean_regression_rejected_despite_mean_gain(self):
base=self.scores(); candidate=self.scores(.1); candidate["ko"]["error_rate"]=.201
eligible,score=fleet_score(base,candidate)
self.assertFalse(eligible); self.assertGreater(score,0)
def test_non_korean_tolerance(self):
base=self.scores(); candidate=self.scores(.19)
candidate["nl"]["error_rate"]=.206
self.assertFalse(fleet_score(base,candidate)[0])
candidate["nl"]["error_rate"]=.204
self.assertTrue(fleet_score(base,candidate)[0])
def test_split_leakage(self):
with self.assertRaises(ValueError):
assert_disjoint({"train":[{"sha":"abc"}],"test":[{"sha":"abc"}]},("sha",))
def test_object_split_preservation_and_conflicts(self):
def row(uid): return {"metadata":{"asset_id":uid}}
groups={"oldgroup":[row("a"),row("new-duplicate")], **{str(i):[row(str(i))] for i in range(20)}}
assignment=stable_object_splits(groups,{"a":"test"},confirmation=5)
self.assertEqual(assignment["oldgroup"],"test")
self.assertEqual(list(assignment.values()).count("confirmation"),5)
groups["oldgroup"].append(row("b"))
with self.assertRaises(ValueError): stable_object_splits(groups,{"a":"test","b":"train"},confirmation=5)
def test_resume_settings(self):
with tempfile.TemporaryDirectory() as d:
path=Path(d)/"settings.json"
immutable(path,{"seed":42}); immutable(path,{"seed":42})
with self.assertRaises(RuntimeError): immutable(path,{"seed":43})
self.assertEqual(read(path),{"seed":42})
def test_cluster_bootstrap_and_ratio(self):
a=[{"id":str(i),"group":str(i//2),"edits":2,"units":10,"metric":.3} for i in range(8)]
b=[{**r,"edits":1,"metric":.4} for r in a]
result=paired_ci(a,b,"edits",ratio=True,repeats=50)
self.assertEqual(result["clusters"],4)
self.assertAlmostEqual(result["delta_candidate_minus_baseline"],-.1)
self.assertAlmostEqual(paired_ci(a,b,"metric",repeats=50)["ci95"][0],.1)
with self.assertRaises(ValueError): paired_ci(a,b[:-1],"metric")
class GeometryTests(unittest.TestCase):
def test_rotation_and_scale(self):
import numpy as np
from geometry import rotation,rotate_splats
from image3d_student.splats import Splats,rotation_matrices
q=np.array([[1,0,0,0]],np.float32)
a=Splats(np.array([[.1,.2,.3]]),np.ones((1,3)),np.array([[.01,.02,.03]]),q,np.ones((1,1)))
m=rotation(90,20); b=rotate_splats(a,m,.8)
np.testing.assert_allclose(b.xyz,a.xyz@m.T*.8,atol=1e-6)
np.testing.assert_allclose(rotation_matrices(b.quat)[0],m,atol=1e-6)
np.testing.assert_allclose(b.scale,a.scale*.8)
def test_silhouette_black_objects_and_empty_outputs(self):
import numpy as np
from geometry import splat_mask,mesh_mask,rotation,iou,chamfer
from image3d_student.splats import Splats
a=Splats(np.zeros((1,3)),np.zeros((1,3)),np.full((1,3),.1),np.array([[1,0,0,0]]),np.ones((1,1)))
self.assertGreater(splat_mask(a,rotation(0)).sum(),0)
self.assertEqual(splat_mask(None,rotation(0)).sum(),0)
mask=mesh_mask(np.array([[-.2,-.2,0],[.2,-.2,0],[0,.2,0]]),np.array([[0,1,2]]),rotation(0))
self.assertEqual(iou(mask,mask),1.)
self.assertEqual(chamfer(np.empty((0,3)),np.zeros((1,3))),2.)
self.assertEqual(chamfer(np.zeros((1,3)),np.zeros((1,3))),0.)
def test_ply_round_trip(self):
import numpy as np
from image3d_student.splats import Splats,write_ply,read_ply
a=Splats(np.array([[.1,0,0]]),np.full((1,3),.4),np.full((1,3),.1),np.array([[1,0,0,0]]),np.full((1,1),.8))
with tempfile.TemporaryDirectory() as d:
path=Path(d)/"test.ply"; write_ply(path,a); b=read_ply(path)
for key in a.__dataclass_fields__:
np.testing.assert_allclose(getattr(a,key),getattr(b,key),atol=1e-6)
def test_torch_resume_preserves_optimizer_and_rng(self):
import random
import torch
from image3d_student.model import Student
spec=importlib.util.spec_from_file_location("forma_run",ROOT/"forma3d/run.py")
mod=importlib.util.module_from_spec(spec); spec.loader.exec_module(mod)
torch.manual_seed(44); model=Student(16,64)
optimizer=torch.optim.AdamW(model.parameters(),lr=5e-5)
x=torch.rand(1,3,128,128)
model(x)["occ"].square().mean().backward(); optimizer.step()
rng=random.Random(44)
with tempfile.TemporaryDirectory() as d:
path=Path(d)/"last.pt"; mod.save(path,model,optimizer,{"step":1},rng)
ck=torch.load(path,map_location="cpu",weights_only=True)
resumed=Student(16,64); resumed.load_state_dict(ck["model"])
opt2=torch.optim.AdamW(resumed.parameters(),lr=5e-5); opt2.load_state_dict(ck["optimizer"])
for m,o in ((model,optimizer),(resumed,opt2)):
o.zero_grad(); m(x)["occ"].square().mean().backward(); o.step()
for a,b in zip(model.parameters(),resumed.parameters()): torch.testing.assert_close(a,b,rtol=0,atol=0)
other=random.Random(); other.setstate(ck["python_rng"])
self.assertEqual(rng.random(),other.random())
if __name__=="__main__": unittest.main()