Module neuralops.tests.test_upi_mamba_comprehensive
Functions
def make_config(hidden_size=64, is_decoder=False, model_type='bert')-
Expand source code
def make_config(hidden_size=64, is_decoder=False, model_type="bert"): return types.SimpleNamespace( hidden_size=hidden_size, is_decoder=is_decoder, model_type=model_type, dropout=0.0, lora_rank=16, ) def test_upi_mamba_causal_mode()-
Expand source code
def test_upi_mamba_causal_mode(): cfg = make_config(hidden_size=64, is_decoder=True, model_type="gpt2") attn = UPIMambaBlock(cfg, pretrained_attn=DummyAttn(64), is_decoder=True) attn.eval() B, L, D = 2, 16, 64 x = torch.randn(B, L, D) out, _ = attn(x) assert out.shape == (B, L, D) assert not torch.isnan(out).any() def test_upi_mamba_copy_weights_all_4_architectures()-
Expand source code
def test_upi_mamba_copy_weights_all_4_architectures(): d = 64 cfg = make_config(hidden_size=d) # 1. DistilBERT class DummyDistilBert(nn.Module): def __init__(self): super().__init__() self.q_lin = nn.Linear(d, d) self.k_lin = nn.Linear(d, d) self.v_lin = nn.Linear(d, d) self.out_lin = nn.Linear(d, d) m_distil = UPIMambaBlock(cfg, pretrained_attn=DummyDistilBert()) x = torch.randn(2, 8, d) out1, _ = m_distil(x) assert out1.shape == (2, 8, d) # 2. RoBERTa nested class DummyRoberta(nn.Module): def __init__(self): super().__init__() self.self = nn.Module() self.self.query = nn.Linear(d, d) self.self.key = nn.Linear(d, d) self.self.value = nn.Linear(d, d) self.output = nn.Module() self.output.dense = nn.Linear(d, d) m_roberta = UPIMambaBlock(cfg, pretrained_attn=DummyRoberta()) out2, _ = m_roberta(x) assert out2.shape == (2, 8, d) # 3. GPT-2 Conv1D class Conv1D(nn.Module): def __init__(self, nf, nx): super().__init__() self.weight = nn.Parameter(torch.randn(nx, nf)) self.bias = nn.Parameter(torch.zeros(nf)) class DummyGPT2(nn.Module): def __init__(self): super().__init__() self.c_attn = Conv1D(3 * d, d) self.c_proj = Conv1D(d, d) m_gpt2 = UPIMambaBlock(cfg, pretrained_attn=DummyGPT2(), is_decoder=True) out3, _ = m_gpt2(x) assert out3.shape == (2, 8, d) # 4. Qwen GQA class DummyQwen(nn.Module): def __init__(self): super().__init__() self.q_proj = nn.Linear(d, d) self.k_proj = nn.Linear(d, d // 2) self.v_proj = nn.Linear(d, d // 2) self.o_proj = nn.Linear(d, d) m_qwen = UPIMambaBlock(cfg, pretrained_attn=DummyQwen()) out4, _ = m_qwen(x) assert out4.shape == (2, 8, d) def test_upi_mamba_forward_and_shapes()-
Expand source code
def test_upi_mamba_forward_and_shapes(): cfg = make_config(hidden_size=64) attn = UPIMambaBlock(cfg, pretrained_attn=DummyAttn(64), d_state=16, d_conv=4) attn.eval() for seq_len in [4, 16, 25]: B, L, D = 2, seq_len, 64 x = torch.randn(B, L, D) out, _ = attn(x) assert out.shape == (B, L, D), f"Expected shape {(B, L, D)}, got {out.shape}" assert not torch.isnan(out).any() def test_upi_mamba_inject()-
Expand source code
def test_upi_mamba_inject(): class DummyLayer(nn.Module): def __init__(self, d=64): super().__init__() self.attention = DummyAttn(d) layer = DummyLayer(64) cfg = make_config(hidden_size=64) injected = inject_upi_mamba(layer, model_config=cfg, old_attn=layer.attention) assert isinstance(injected, UPIMambaBlock) assert layer.attention is injected # Test None graceful handling res = inject_upi_mamba(layer, model_config=cfg, old_attn=None) assert res is None def test_upi_mamba_is_selective()-
Expand source code
def test_upi_mamba_is_selective(): """Verify the SSM is truly selective: B_t, C_t depend on input, and a spike evolves state.""" d = 64 cfg = make_config(hidden_size=d, is_decoder=True, model_type="gpt2") m = UPIMambaBlock(cfg, pretrained_attn=DummyAttn(d), is_decoder=True) m.eval() L = 16 x1 = torch.randn(1, L, d) x2 = x1.clone() # Inject large perturbation only at position 5 x2[0, 5, :] += 10.0 with torch.no_grad(): out1, _ = m(x1) out2, _ = m(x2) # State evolution: outputs prior to position 5 should be identical (causal) diff_before = torch.norm(out1[0, :5] - out2[0, :5]).item() assert diff_before < 1e-4, f"Causality violated before spike: diff={diff_before}" # Output at and after position 5 must differ due to state evolution diff_at_and_after = torch.norm(out1[0, 5:] - out2[0, 5:]).item() assert diff_at_and_after > 1.0, f"Expected state to evolve after spike, got diff={diff_at_and_after}" # Verify B_t and C_t projections are input-dependent x_proj_out1 = m.x_proj(x1) _, B_t1, C_t1 = torch.split(x_proj_out1, [m.inner_dim, m.d_state, m.d_state], dim=-1) x_proj_out2 = m.x_proj(x2) _, B_t2, C_t2 = torch.split(x_proj_out2, [m.inner_dim, m.d_state, m.d_state], dim=-1) assert not torch.allclose(B_t1[0, 5], B_t2[0, 5]), "B_t must be input-dependent" assert not torch.allclose(C_t1[0, 5], C_t2[0, 5]), "C_t must be input-dependent"Verify the SSM is truly selective: B_t, C_t depend on input, and a spike evolves state.
def test_upi_mamba_lora_and_gradients()-
Expand source code
def test_upi_mamba_lora_and_gradients(): cfg = make_config(hidden_size=64) attn = UPIMambaBlock(cfg, pretrained_attn=DummyAttn(64), lora_rank=8) attn.train() # Check base weights frozen and lora weights trainable assert not attn.in_proj.weight.requires_grad assert attn.in_proj.lora_A.requires_grad assert attn.in_proj.lora_B.requires_grad assert not attn.out_proj.weight.requires_grad assert attn.out_proj.lora_A.requires_grad assert attn.out_proj.lora_B.requires_grad x = torch.randn(2, 8, 64, requires_grad=True) out, _ = attn(x) loss = out.sum() loss.backward() assert attn.in_proj.lora_A.grad is not None assert attn.in_proj.lora_B.grad is not None assert attn.out_proj.lora_A.grad is not None assert attn.out_proj.lora_B.grad is not None assert attn.in_proj.weight.grad is None assert attn.out_proj.weight.grad is None def test_upi_mamba_masks()-
Expand source code
def test_upi_mamba_masks(): cfg = make_config(hidden_size=64) attn = UPIMambaBlock(cfg, pretrained_attn=DummyAttn(64)) attn.eval() B, L, D = 2, 12, 64 x = torch.randn(B, L, D) # 2D boolean/binary mask mask_2d = torch.ones(B, L) mask_2d[:, -3:] = 0 out_2d, _ = attn(x, attention_mask=mask_2d) assert out_2d.shape == (B, L, D) assert not torch.isnan(out_2d).any() # 4D attention mask mask_4d = torch.zeros(B, 1, L, L) mask_4d[:, :, :, -3:] = -10000.0 out_4d, _ = attn(x, attention_mask=mask_4d) assert out_4d.shape == (B, L, D) assert not torch.isnan(out_4d).any()
Classes
class DummyAttn (d=64)-
Expand source code
class DummyAttn(nn.Module): def __init__(self, d=64): super().__init__() self.q_proj = nn.Linear(d, d) self.k_proj = nn.Linear(d, d) self.v_proj = nn.Linear(d, d) self.o_proj = nn.Linear(d, d) self.hidden_size = dBase class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module