wannaq commited on
Commit
07f5733
·
verified ·
1 Parent(s): 773f60d

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +47 -3
  2. configuration_waveformer.py +16 -0
  3. modeling_waveformer.py +99 -0
README.md CHANGED
@@ -1,3 +1,47 @@
1
- ---
2
- license: cc-by-nc-nd-4.0
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Waveformer
2
+
3
+ Continuous-time language model using Kuramoto phase synchronization instead of attention. O(1) memory scaling across sequence lengths. Trains on 8GB consumer GPU.
4
+
5
+ ## Paper
6
+
7
+ "Emergence Over Attention: Continuous-Time Phase Synchronization as a Computational Primitive"
8
+ DOI: [10.5281/zenodo.20741536](https://doi.org/10.5281/zenodo.20741536)
9
+
10
+ Prior work: "Deterministic Layer Freezing in Autoregressive Language Models via Continuous Phase Coherence Analysis"
11
+ DOI: [10.5281/zenodo.20720827](https://doi.org/10.5281/zenodo.20720827)
12
+
13
+ ## Usage
14
+
15
+ ```python
16
+ from transformers import AutoModelForCausalLM, AutoTokenizer
17
+
18
+ model = AutoModelForCausalLM.from_pretrained(
19
+ "Wannavf/Waveformer-207M-Chat",
20
+ trust_remote_code=True
21
+ )
22
+ tokenizer = AutoTokenizer.from_pretrained("gpt2")
23
+ tokenizer.add_special_tokens({
24
+ 'additional_special_tokens': ['<|im_start|>', '<|im_end|>']
25
+ })
26
+
27
+ prompt = "<|im_start|>user\nHello! What can you do?<|im_end|>\n<|im_start|>assistant\n"
28
+ inputs = tokenizer(prompt, return_tensors="pt")
29
+ outputs = model.generate(**inputs, max_new_tokens=50, temperature=0.7, top_p=0.8, top_k=40)
30
+ ```
31
+
32
+ ## Architecture
33
+
34
+ | Component | Description |
35
+ |-----------|-------------|
36
+ | Attention | Kuramoto phase synchronization (no Q/K/V, no softmax) |
37
+ | Position | KAM irrational frequency (zero learned parameters) |
38
+ | Memory | O(1) in sequence length, flat VRAM at any context length |
39
+ | Backward | Reversible integration (no intermediate activation storage) |
40
+
41
+ ## VRAM
42
+
43
+ Flat at all sequence lengths. Attention mechanism contributes zero additional memory per token.
44
+
45
+ ## License
46
+
47
+ This model is provided for research purposes. Commercial use requires explicit permission.
configuration_waveformer.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+ class WaveformerConfig(PretrainedConfig):
4
+ model_type = "waveformer"
5
+
6
+ def __init__(self,
7
+ vocab_size=50257,
8
+ d_model=1024,
9
+ n_layers=12,
10
+ max_seq_len=32768,
11
+ **kwargs):
12
+ super().__init__(**kwargs)
13
+ self.vocab_size = vocab_size
14
+ self.d_model = d_model
15
+ self.n_layers = n_layers
16
+ self.max_seq_len = max_seq_len
modeling_waveformer.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Waveformer model for HuggingFace transformers."""
2
+ import torch, torch.nn as nn, math
3
+ from transformers import PreTrainedModel
4
+ from transformers.modeling_outputs import CausalLMOutputWithPast
5
+ from transformers.generation import GenerationMixin
6
+ try:
7
+ from .configuration_waveformer import WaveformerConfig
8
+ except ImportError:
9
+ from configuration_waveformer import WaveformerConfig
10
+
11
+
12
+ class _OscillatorAttention(nn.Module):
13
+ def __init__(self, d_model, d_out, n_osc):
14
+ super().__init__()
15
+ self.n_osc = n_osc
16
+ self.perturb = nn.Linear(d_model, n_osc, bias=False)
17
+ self.readout = nn.Linear(n_osc, d_out, bias=False)
18
+ omega = (torch.arange(n_osc).float() * 1.618033988749895).fmod(1.0) * 2 * math.pi
19
+ self.register_buffer('omega', omega)
20
+ idx = torch.arange(n_osc)
21
+ dist = (idx.unsqueeze(1) - idx.unsqueeze(0)).abs().float()
22
+ K = torch.zeros(n_osc, n_osc)
23
+ K[dist > 0] = torch.exp(-dist[dist > 0] / 100.0)
24
+ self.register_buffer('coupling', K)
25
+
26
+ def forward(self, x):
27
+ B, S, D = x.shape
28
+ theta = self.perturb(x.mean(1))
29
+ for _ in range(3):
30
+ sd = torch.sin(theta.unsqueeze(-1) - theta.unsqueeze(-2))
31
+ theta = theta + 0.1 * (self.omega + (self.coupling * sd).sum(-1))
32
+ return self.readout(torch.cos(theta))
33
+
34
+
35
+ class WaveformerPreTrainedModel(PreTrainedModel):
36
+ config_class = WaveformerConfig
37
+ base_model_prefix = "waveformer"
38
+
39
+ def _init_weights(self, module):
40
+ if isinstance(module, nn.Linear):
41
+ module.weight.data.normal_(mean=0.0, std=0.02)
42
+ if module.bias is not None:
43
+ module.bias.data.zero_()
44
+
45
+
46
+ class WaveformerLayer(nn.Module):
47
+ def __init__(self, config):
48
+ super().__init__()
49
+ D = config.d_model
50
+ self.osc = _OscillatorAttention(D, D, D * 2)
51
+ self.norm1 = nn.RMSNorm(D, eps=1e-5)
52
+ self.norm2 = nn.RMSNorm(D, eps=1e-5)
53
+ self.ffn = nn.Sequential(
54
+ nn.Linear(D, D * 8 // 3, bias=False),
55
+ nn.SiLU(),
56
+ nn.Linear(D * 8 // 3, D, bias=False),
57
+ )
58
+
59
+ def forward(self, x):
60
+ return x + self.osc(self.norm1(x)).unsqueeze(1).expand(-1, x.shape[1], -1) + self.ffn(self.norm2(x))
61
+
62
+
63
+ class WaveformerModel(WaveformerPreTrainedModel, GenerationMixin):
64
+ def __init__(self, config):
65
+ super().__init__(config)
66
+ self.embed = nn.Embedding(config.vocab_size, config.d_model)
67
+
68
+ pos = torch.arange(config.max_seq_len).float()
69
+ omega = (pos * 1.618033988749895).fmod(1.0) * 2 * math.pi
70
+ sub = torch.arange(config.d_model).float() * 0.01
71
+ theta = omega.unsqueeze(1) + sub.unsqueeze(0)
72
+ self.register_buffer('kam_sin', torch.sin(theta))
73
+ self.register_buffer('kam_cos', torch.cos(theta))
74
+
75
+ self.layers = nn.ModuleList([
76
+ WaveformerLayer(config) for _ in range(config.n_layers)
77
+ ])
78
+ self.norm_f = nn.RMSNorm(config.d_model, eps=1e-5)
79
+ self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False)
80
+ self.lm_head.weight = self.embed.weight
81
+ self.post_init()
82
+
83
+ def forward(self, input_ids, attention_mask=None, **kwargs):
84
+ B, S = input_ids.shape
85
+ sp = min(S, self.kam_sin.shape[0])
86
+ x = self.embed(input_ids)
87
+ x = x * self.kam_cos[:sp].unsqueeze(0) + x.roll(1, -1) * self.kam_sin[:sp].unsqueeze(0)
88
+ for layer in self.layers:
89
+ x = layer(x)
90
+ return CausalLMOutputWithPast(logits=self.lm_head(self.norm_f(x)))
91
+
92
+ def prepare_inputs_for_generation(self, input_ids, **kwargs):
93
+ return {"input_ids": input_ids}
94
+
95
+ def get_input_embeddings(self):
96
+ return self.embed
97
+
98
+ def set_input_embeddings(self, value):
99
+ self.embed = value