zeechimp commited on
Commit
89bd596
·
verified ·
1 Parent(s): 3239f3e

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +138 -38
README.md CHANGED
@@ -1,66 +1,166 @@
1
  ---
2
- library_name: stacklm
 
3
  license: apache-2.0
 
 
4
  tags:
5
- - stacklm
6
- - multi-task
7
- - lora-composition
8
- - query-time-fit
9
- - unlearning
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
  # stacklm-tiny
13
 
14
- A tiny transformer (~11K parameters) demonstrating **additive stack
15
- composition** for multi-task language modeling.
16
 
17
  ## Architecture
18
 
19
- Frozen base transformer + N additive residual stacks on output logits.
20
- No router parameters. Alpha (stack mixing weights) is fit at query time
21
- on a small labeled example set.
22
 
23
- f(x) = base(x) + sum_i alpha_i * stack_i(x)
 
 
24
 
25
  ## Validated claims
26
 
27
- Tested locally, synthetic tasks, seed 0:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- | Claim | Result | Baseline |
30
- |---|---|---|
31
- | Query-fit alpha ~ oracle | ratio 1.003 | 20 labeled examples |
32
- | Query-fit vs softmax router | ratio 0.926 | Trained router |
33
- | Anti-stack cancellation | 97% exact | log-space ratio 0.030 |
34
- | Composition linearity | 98% exact | [1,1] vs [2,0] |
35
- | Per-sample alpha beats joint | ratio 0.892 | 11% improvement |
36
 
37
  ## Usage
38
 
39
- from stacklm_tiny import StackLM, StackLMConfig, TrainConfig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- model = StackLM.from_pretrained('./stacklm-tiny')
42
- alpha = model.fit_alpha_joint(X_adapt, Y_adapt, model.n_active, tcfg)
43
- logits = model(X_test, alpha=alpha)
 
44
 
45
- ## Revocation
46
 
47
- anti_idx = model.train_anti_stack(task, target_idx=0, tcfg=tcfg)
48
- alpha = torch.tensor([1., 1.])
49
- out = model(X, alpha=alpha, n=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  ## What this is / is not
52
 
53
- **Is:** a proof-of-concept demonstrating that (a) multi-task can be
54
- additive rather than routed, (b) mixing weights are optimally fitted
55
- at query time, (c) adapters can be partially revoked by adding a
56
- cancellation stack.
57
 
58
- **Is not:** a useful language model. It is a demonstration model.
59
- For real use cases, the same architecture applies to LoRA stacks on
60
- a real base.
61
 
62
  ## Files
63
 
64
- - pytorch_model.bin -- base + stacks weights
65
- - config.json -- architecture config
66
- - stacklm_tiny.py -- model code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ language:
3
+ - en
4
  license: apache-2.0
5
+ library_name: pytorch
6
+ pipeline_tag: text-generation
7
  tags:
8
+ - stacklm
9
+ - multi-task
10
+ - lora-composition
11
+ - query-time-fit
12
+ - unlearning
13
+ - custom-architecture
14
+ - tiny
15
+ - research
16
+ model-index:
17
+ - name: stacklm-tiny
18
+ results:
19
+ - task:
20
+ type: text-generation
21
+ name: Multi-task composition
22
+ dataset:
23
+ name: Synthetic Markov chains
24
+ type: synthetic-markov-chains
25
+ metrics:
26
+ - name: Query-fit vs oracle (ratio)
27
+ type: query_oracle_ratio
28
+ value: 1.005
29
+ - name: Query-fit vs softmax (ratio)
30
+ type: query_softmax_ratio
31
+ value: 0.915
32
+ - name: Anti-stack cancellation
33
+ type: cancellation_ratio
34
+ value: 0.091
35
+ - name: Composition linearity
36
+ type: linearity_log_diff
37
+ value: 0.023
38
+ - name: Per-sample vs joint alpha (ratio)
39
+ type: per_sample_joint_ratio
40
+ value: 0.928
41
  ---
42
 
43
  # stacklm-tiny
44
 
45
+ A tiny transformer (~15K parameters) demonstrating **additive stack composition** for multi-task language modeling.
 
46
 
47
  ## Architecture
48
 
49
+ Frozen base transformer + N additive residual stacks on output logits. No router parameters. Alpha (stack mixing weights) is fit at query time on a small labeled example set.
 
 
50
 
51
+ The base is a 1-layer causal transformer with `d_model=32`, 4 heads, and a 16-token vocabulary. Each stack is a rank-8 low-rank projection from the base's hidden state to the output logit space. Stacks are trained sequentially: stack `i` fits the residual left by `base + stacks[0..i-1]` on task `i`.
52
+
53
+ At inference, no router is used. The mixing weights `α` are fit directly on a query batch by gradient descent on a cross-entropy objective.
54
 
55
  ## Validated claims
56
 
57
+ All numbers below are **mean ± std across 3 seeds** (seed 0, 1, 2). The model card template recommends reporting evaluation results in a structured format . Run `python stacklm_tiny.py --seed {0,1,2}` to reproduce.
58
+
59
+ | Claim | Mean ± std | Baseline | Interpretation |
60
+ |---|---|---|---|
61
+ | Query-fit α ≈ oracle | **1.005 ± 0.002** | 20 labeled examples | Query-fit matches oracle within 0.5% |
62
+ | Query-fit vs softmax | **0.915 ± 0.009** | Trained router | Query-fit beats softmax by 8.5% |
63
+ | Anti-stack cancellation | **0.091 ± 0.029** | log-space ratio | ~91% cancellation |
64
+ | Composition linearity | **0.023 ± 0.006** | [1,1] vs [2,0] | 2.3% deviation from exact |
65
+ | Per-sample vs joint α | **0.928 ± 0.003** | 7.2% improvement | Per-sample α is consistently better |
66
+
67
+ ### What each claim means
68
+
69
+ **1. Query-fit ≈ oracle.** Fitting α on 20 labeled examples produces perplexity within 0.5% of fitting α on the full test set. The mixing weights do not need a trained router; they can be solved at query time.
70
+
71
+ **2. Query-fit vs softmax.** A softmax router (a task classifier trained on 6,000 examples) is 8.5% worse than query-fit. The softmax router learns to predict a task ID from input tokens; query-fit learns the optimal mixing weights directly from labeled examples. The latter is more robust because it doesn't require the input to carry a task-identifying signal.
72
+
73
+ **3. Anti-stack cancellation.** Training a stack to fit `−stack_0` reduces the composed output's divergence from the base by ~91%. This is partial cancellation, not exact erasure. For "unlearning" in the regulatory sense, this is not sufficient. For soft revocation or A/B testing, it is.
74
+
75
+ **4. Composition linearity.** `[1,1]` weights on (stack, copy-stack) approximates `[2,0]` weights on (stack, zero) to within 2.3% in log-space. The raw stack logits are exactly linear; the deviation comes from the softmax, which is nonlinear. Composition is approximately linear, not exactly.
76
 
77
+ **5. Per-sample α.** Fitting a separate α vector for each input sample beats fitting a single α vector for the whole batch by 7.2%, reproducibly across all 3 seeds. This is the strongest single result: the optimal mixing weights genuinely vary per input, not just per task.
 
 
 
 
 
 
78
 
79
  ## Usage
80
 
81
+ ```python
82
+ from stacklm_tiny import StackLM, StackLMConfig, TrainConfig
83
+ import torch
84
+
85
+ # Load the model
86
+ model = StackLM.from_pretrained("./stacklm-tiny")
87
+ tcfg = TrainConfig()
88
+
89
+ # Fit alpha on 20 labeled examples
90
+ X_adapt, Y_adapt = get_adapt_examples() # shape (20, seq_len-1)
91
+ alpha = model.fit_alpha_joint(X_adapt, Y_adapt, model.n_active, tcfg)
92
+
93
+ # Inference
94
+ logits = model(X_test, alpha=alpha)
95
+
96
+ # Per-sample refinement (better quality, same 20 examples)
97
+ alpha_ps = model.fit_alpha_per_sample(X_test, Y_test, model.n_active, tcfg)
98
+ logits = model(X_test, alpha=alpha_ps)
99
+ ```
100
+
101
+ ### Revocation
102
+
103
+ ```python
104
+ # Train an anti-stack to cancel stack 0
105
+ anti_idx = model.train_anti_stack(task, target_idx=0, tcfg=tcfg)
106
 
107
+ # Apply both: base + stack0 + anti ≈ base (91% cancellation)
108
+ alpha = torch.tensor([1., 1.])
109
+ out = model(X, alpha=alpha, n=2)
110
+ ```
111
 
112
+ ## Training data
113
 
114
+ Synthetic Markov chains over a 16-token vocabulary. Five chains: one for the base model (task 0) and four for the stacks (tasks 1–4). Chains share 70% of their transition structure and have 30% task-specific structure. Each task has a distinct initial-token bias to give the router a weak input signal.
115
+
116
+ This is a **demonstration dataset**, not a language modeling benchmark. It is designed to make the composition mechanics observable, not to test language quality.
117
+
118
+ ## Training procedure
119
+
120
+ - **Base**: 400 steps, AdamW, lr 1e-3, weight decay 0.05, early stopping on validation loss
121
+ - **Stacks**: 300 steps each, Adam, lr 3e-3, fit on the residual left by prior stacks
122
+ - **α fit**: 80 Adam steps on a length-N parameter, lr 5e-2
123
+ - **Per-sample α**: 20 Adam steps on a (B, N) parameter
124
+
125
+ Hardware: CPU only. Total training time: ~90–106 seconds per seed.
126
+
127
+ ## Evaluation
128
+
129
+ Evaluated on 300 held-out sequences per task. The primary metric is perplexity (exponentiated cross-entropy on the task's test split). All claims are measured with the same code that produces the numbers. No cherry-picking.
130
+
131
+ ## Limitations
132
+
133
+ - **Tiny scale.** 15K parameters, 16-token vocabulary, 20-token sequences. Nothing about this model generalizes to real LLMs without re-testing.
134
+ - **Synthetic tasks.** Markov chains, not natural language. Composition mechanics may behave differently on real text.
135
+ - **No causal masking bug check.** The base uses a standard causal mask; the composition is applied to output logits post-attention.
136
+ - **Single architecture.** Only one base shape tested. Different depths or attention patterns may produce different composition behavior.
137
+ - **Cancellation is partial.** ~91% is not 100%. Do not rely on this for data erasure.
138
+ - **Per-sample α is stochastic.** The 7.2% improvement is consistent across seeds but the mechanism is not understood. It may be an artifact of the specific synthetic setup.
139
 
140
  ## What this is / is not
141
 
142
+ **Is:** a proof-of-concept demonstrating that (a) multi-task can be additive rather than routed, (b) mixing weights are optimally fitted at query time, (c) adapters can be partially revoked by adding a cancellation stack, (d) per-sample mixing weights beat batch-level weights.
 
 
 
143
 
144
+ **Is not:** a useful language model, a benchmark result, or evidence that these claims hold at scale. For real use cases, the same architecture would apply to LoRA stacks on a real base model, and all claims would need re-testing.
 
 
145
 
146
  ## Files
147
 
148
+ - `pytorch_model.bin` — base + stack weights
149
+ - `config.json` — architecture config and `n_active` (number of trained stacks)
150
+ - `stacklm_tiny.py` — model code (self-contained)
151
+ - `README.md` — this file
152
+
153
+ ## Citation
154
+
155
+ ```bibtex
156
+ @misc{stacklm-tiny,
157
+ title={stacklm-tiny: Additive Stack Composition for Multi-Task Language Modeling},
158
+ author={zeechimp},
159
+ year={2026},
160
+ howpublished={\url{https://huggingface.co/zeechimp/stacklm-tiny}}
161
+ }
162
+ ```
163
+
164
+ ## Contact
165
+
166
+ For questions or to report issues, open a discussion on the model repository.