Files
ai_mouse/tests/tools/test_models.py

70 lines
2.2 KiB
Python

"""Tests for TrajectoryFlowModel architecture."""
from __future__ import annotations
import torch
import pytest
from tools.models import TrajectoryFlowModel
class TestTrajectoryFlowModel:
"""Test the Conditional Flow Matching model."""
@pytest.fixture
def model(self):
return TrajectoryFlowModel(
seq_len=64, d_model=128, nhead=4, num_layers=4,
dim_feedforward=256, dropout=0.1, cond_dim=3,
)
def test_output_shape(self, model):
"""(4, 64, 3) input → (4, 64, 3) output."""
batch = 4
x_t = torch.randn(batch, 64, 3)
t = torch.rand(batch)
cond = torch.randn(batch, 3)
out = model(x_t, t, cond)
assert out.shape == (batch, 64, 3)
def test_single_sample(self, model):
"""(1, 64, 3) works."""
x_t = torch.randn(1, 64, 3)
t = torch.rand(1)
cond = torch.randn(1, 3)
out = model(x_t, t, cond)
assert out.shape == (1, 64, 3)
def test_deterministic(self, model):
"""Eval mode, same input → same output."""
model.eval()
x_t = torch.randn(2, 64, 3)
t = torch.tensor([0.3, 0.7])
cond = torch.randn(2, 3)
with torch.no_grad():
out1 = model(x_t, t, cond)
out2 = model(x_t, t, cond)
torch.testing.assert_close(out1, out2)
def test_different_timesteps(self, model):
"""t=0.1 vs t=0.9 gives different output."""
model.eval()
x_t = torch.randn(1, 64, 3)
cond = torch.randn(1, 3)
with torch.no_grad():
out_early = model(x_t, torch.tensor([0.1]), cond)
out_late = model(x_t, torch.tensor([0.9]), cond)
assert not torch.allclose(out_early, out_late, atol=1e-5)
def test_gradient_flows(self, model):
"""Backward works, grad on x_t exists."""
model.train()
x_t = torch.randn(2, 64, 3, requires_grad=True)
t = torch.rand(2)
cond = torch.randn(2, 3)
out = model(x_t, t, cond)
loss = out.sum()
loss.backward()
assert x_t.grad is not None
assert x_t.grad.shape == (2, 64, 3)
assert x_t.grad.abs().sum() > 0