Module neuralops.tests.test_svd_linear_attention_comprehensive
Functions
def test_dual_whole_model_injection()-
Expand source code
def test_dual_whole_model_injection(): class DummyTransformerLayer(nn.Module): def __init__(self): super().__init__() self.attention = nn.MultiheadAttention(embed_dim=64, num_heads=4, batch_first=True) class DummyDistilBert(nn.Module): def __init__(self): super().__init__() self.config = DummyConfig(hidden_size=64, num_heads=4, head_dim=16) self.distilbert = nn.Module() self.distilbert.transformer = nn.Module() self.distilbert.transformer.layer = nn.ModuleList([DummyTransformerLayer() for _ in range(3)]) model = DummyDistilBert() injected_model = inject_svd_linear_attention(model=model, rank=16) assert injected_model is not None for lyr in model.distilbert.transformer.layer: assert isinstance(lyr.attention, SVDLinearAttention) x = torch.randn(2, 8, 64) out, _ = lyr.attention(x) assert out.shape == (2, 8, 64) def test_odd_dim_rope_safety()-
Expand source code
def test_odd_dim_rope_safety(): # Odd dimension head_dim = 17 B, H, N, D = 2, 4, 8, 17 q = torch.randn(B, H, N, D) k = torch.randn(B, H, N, D) cos = torch.randn(N, D) sin = torch.randn(N, D) q_rot, k_rot = apply_rotary_pos_emb(q, k, cos, sin) assert q_rot.shape == (B, H, N, D) assert k_rot.shape == (B, H, N, D) assert not torch.isnan(q_rot).any() assert not torch.isnan(k_rot).any() def test_svd_linear_attention_copy_weights_and_lora()-
Expand source code
def test_svd_linear_attention_copy_weights_and_lora(): cfg = DummyConfig(hidden_size=64, num_heads=4, head_dim=16) # Mock source layer like RoBERTa SelfAttention class MockInnerAttn(nn.Module): def __init__(self): super().__init__() self.query = nn.Linear(64, 64) self.key = nn.Linear(64, 64) self.value = nn.Linear(64, 64) self.dense = nn.Linear(64, 64) mock_src = MockInnerAttn() attn = SVDLinearAttention(config=cfg, old_attn=mock_src, rank=16, freeze_svd=True, lora_rank=8) # Check SVD weights are frozen and LoRA is trainable assert attn.q_proj.U.requires_grad is False assert attn.q_proj.V.requires_grad is False assert attn.q_proj.lora_A.requires_grad is True assert attn.q_proj.lora_B.requires_grad is True x = torch.randn(2, 8, 64, requires_grad=True) out, _ = attn(x) loss = out.sum() loss.backward() assert attn.q_proj.lora_A.grad is not None assert attn.q_proj.lora_B.grad is not None def test_svd_linear_attention_forward()-
Expand source code
def test_svd_linear_attention_forward(): cfg = DummyConfig(hidden_size=64, num_heads=4, head_dim=16) attn = SVDLinearAttention(config=cfg, rank=16, lora_rank=8) x = torch.randn(2, 8, 64) out, attn_weights = attn(x) assert out.shape == (2, 8, 64), f"Expected (2, 8, 64), got {out.shape}" assert attn_weights is None def test_svd_linear_attention_gpt2_conv1d()-
Expand source code
def test_svd_linear_attention_gpt2_conv1d(): # Mock Conv1D from GPT-2 class MockConv1D(nn.Module): def __init__(self, nf, nx): super().__init__() self.nf = nf self.weight = nn.Parameter(torch.randn(nx, nf)) self.bias = nn.Parameter(torch.zeros(nf)) def forward(self, x): return torch.matmul(x, self.weight) + self.bias class MockGPT2Attn(nn.Module): def __init__(self): super().__init__() self.c_attn = MockConv1D(192, 64) # 3 * 64 self.c_proj = MockConv1D(64, 64) mock_gpt2 = MockGPT2Attn() cfg = DummyConfig(hidden_size=64, num_heads=4, head_dim=16, is_decoder=True) attn = SVDLinearAttention(config=cfg, old_attn=mock_gpt2, rank=16) x = torch.randn(2, 8, 64) out, _ = attn(x) assert out.shape == (2, 8, 64)
Classes
class DummyConfig (hidden_size=64, num_heads=4, head_dim=16, is_decoder=False)-
Expand source code
class DummyConfig: def __init__(self, hidden_size=64, num_heads=4, head_dim=16, is_decoder=False): self.hidden_size = hidden_size self.num_attention_heads = num_heads self.num_heads = num_heads self.head_dim = head_dim self.num_key_value_heads = num_heads self.is_decoder = is_decoder self.dropout = 0.0 self.attention_probs_dropout_prob = 0.0