Module neuralops.tests.test_tpa_comprehensive
Functions
def make_config(hidden_size=64, num_heads=4, num_kv_heads=2, is_decoder=False, model_type='bert')-
Expand source code
def make_config(hidden_size=64, num_heads=4, num_kv_heads=2, is_decoder=False, model_type="bert"): return types.SimpleNamespace( hidden_size=hidden_size, num_attention_heads=num_heads, num_key_value_heads=num_kv_heads, head_dim=hidden_size // num_heads, is_decoder=is_decoder, model_type=model_type, dropout=0.0, lora_rank=16, ) def test_tpa_causal_mode()-
Expand source code
def test_tpa_causal_mode(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2, is_decoder=True, model_type="gpt2") attn = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), is_decoder=True, rank=4) 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_tpa_forward_and_shapes()-
Expand source code
def test_tpa_forward_and_shapes(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4) attn.eval() for seq_len in [2, 8, 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_tpa_gpt2_is_decoder_detection()-
Expand source code
def test_tpa_gpt2_is_decoder_detection(): class DummyGPT2Attention(nn.Module): def __init__(self, dim=64): super().__init__() self.c_attn = nn.Linear(dim, 3 * dim) self.c_proj = nn.Linear(dim, dim) self.is_decoder = True gpt_layer = DummyGPT2Attention(64) cfg = make_config(hidden_size=64, num_heads=4, is_decoder=False) attn = TPAttention(cfg, pretrained_attn=gpt_layer, rank=4) assert attn.is_decoder is True def test_tpa_gradient_checkpointing_toggle()-
Expand source code
def test_tpa_gradient_checkpointing_toggle(): cfg = make_config(hidden_size=64, num_heads=4) # 1. With gradient checkpointing enabled in training attn_ckpt = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4, gradient_checkpointing=True) attn_ckpt.train() x1 = torch.randn(2, 8, 64, requires_grad=True) out1, _ = attn_ckpt(x1) loss1 = out1.sum() loss1.backward() assert x1.grad is not None assert not torch.isnan(x1.grad).any() # 2. With gradient checkpointing disabled attn_no_ckpt = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4, gradient_checkpointing=False) attn_no_ckpt.train() x2 = torch.randn(2, 8, 64, requires_grad=True) out2, _ = attn_no_ckpt(x2) loss2 = out2.sum() loss2.backward() assert x2.grad is not None assert not torch.isnan(x2.grad).any() def test_tpa_inject()-
Expand source code
def test_tpa_inject(): class DummyLayer(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.attention = DummyAttn(d, h) layer = DummyLayer(64, 4) cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) injected = inject_tpa(layer, model_config=cfg, old_attn=layer.attention) assert isinstance(injected, TPAttention) assert layer.attention is injected empty_layer = nn.Module() # assert inject_tpa(empty_layer, model_config=cfg, old_attn=None) is None def test_tpa_lora_and_gradients()-
Expand source code
def test_tpa_lora_and_gradients(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4, lora_rank=8) attn.train() # Base frozen, lora trainable assert not attn.v_proj.weight.requires_grad assert attn.v_proj.lora_A.requires_grad assert attn.v_proj.lora_B.requires_grad x = torch.randn(2, 8, 64, requires_grad=True) out, _ = attn(x) loss = out.sum() loss.backward() assert attn.v_proj.lora_A.grad is not None assert attn.v_proj.lora_B.grad is not None assert attn.v_proj.weight.grad is None def test_tpa_masks()-
Expand source code
def test_tpa_masks(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4) attn.eval() B, L, D = 2, 12, 64 x = torch.randn(B, L, D) # 2D 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 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() def test_tpa_nested_encoder_injection()-
Expand source code
def test_tpa_nested_encoder_injection(): class DummyBertSelf(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) class DummyBertAttention(nn.Module): def __init__(self): super().__init__() self.self = DummyBertSelf() self.output = nn.Module() self.output.dense = nn.Linear(64, 64) class DummyBertLayer(nn.Module): def __init__(self): super().__init__() self.attention = DummyBertAttention() class DummyLlamaLayer(nn.Module): def __init__(self): super().__init__() self.self_attn = DummyAttn(64, 4) bert_layer = DummyBertLayer() injected_bert = inject_tpa(bert_layer, model_config=make_config(64, 4), old_attn=bert_layer.attention.self) assert injected_bert.is_nested_encoder is True assert bert_layer.attention.self is injected_bert llama_layer = DummyLlamaLayer() injected_llama = inject_tpa(llama_layer, model_config=make_config(64, 4), old_attn=llama_layer.self_attn) assert injected_llama.is_nested_encoder is False assert llama_layer.self_attn is injected_llama def test_tpa_no_output_scale()-
Expand source code
def test_tpa_no_output_scale(): cfg = make_config(hidden_size=64, num_heads=4) attn = TPAttention(cfg, pretrained_attn=DummyAttn(64, 4), rank=4) assert not hasattr(attn.q_proj1, "output_scale") assert not hasattr(attn.q_proj2, "output_scale") assert not hasattr(attn.v_proj, "output_scale") assert not hasattr(attn.out_proj, "output_scale") def test_tpa_non_square_head_dim()-
Expand source code
def test_tpa_non_square_head_dim(): cfg = types.SimpleNamespace( hidden_size=512, num_attention_heads=4, num_key_value_heads=4, head_dim=128, is_decoder=False, model_type="bert", dropout=0.0, ) attn = TPAttention(cfg, rank=8) assert attn.head_dim == 128 assert attn.rank == 8 assert attn.qk_proj is not None x = torch.randn(2, 6, 512) out, _ = attn(x) assert out.shape == (2, 6, 512) def test_tpa_orthogonal_init()-
Expand source code
def test_tpa_orthogonal_init(): cfg = make_config(hidden_size=64, num_heads=4) dummy = DummyAttn(64, 4) attn = TPAttention(cfg, pretrained_attn=dummy, rank=4) w1 = attn.q_proj1.weight w2 = attn.q_proj2.weight assert float(torch.linalg.norm(w1)) > 0.5 assert float(torch.linalg.norm(w2)) > 0.5 assert not torch.isnan(w1).any() assert not torch.isnan(w2).any() def test_tpa_qwen_head_dim_and_rank()-
Expand source code
def test_tpa_qwen_head_dim_and_rank(): class Qwen35Config: hidden_size = 1024 num_attention_heads = 8 num_key_value_heads = 8 head_dim = 256 model_type = "qwen3_5" is_decoder = True dropout = 0.0 attn = TPAttention(Qwen35Config()) assert attn.head_dim == 256 assert attn.q_head_size == 2048 assert attn.rank == 8 # 16*16 = 256 assert attn.is_decoder is True assert attn.qk_proj is not None x = torch.randn(2, 4, 1024) out, _ = attn(x) assert out.shape == (2, 4, 1024) def test_tpa_rotate_half_and_odd_dim()-
Expand source code
def test_tpa_rotate_half_and_odd_dim(): for d in [16, 17, 31, 32]: t = torch.randn(2, 4, 8, d) rotated = _rotate_half(t) assert rotated.shape == t.shape, f"Odd dim {d} failed in _rotate_half" head_dim_odd = 15 q = torch.randn(2, 4, 8, head_dim_odd) k = torch.randn(2, 2, 8, head_dim_odd) cos = torch.randn(8, head_dim_odd) sin = torch.randn(8, head_dim_odd) q_rot, k_rot = apply_rotary_pos_emb(q, k, cos, sin) assert q_rot.shape == q.shape assert k_rot.shape == k.shape assert not torch.isnan(q_rot).any()
Classes
class DummyAttn (d=64, h=4)-
Expand source code
class DummyAttn(nn.Module): def __init__(self, d=64, h=4): 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 = d self.num_heads = hBase 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