Update README.md
Browse files
README.md
CHANGED
|
@@ -17,23 +17,184 @@ tags:
|
|
| 17 |
|
| 18 |
## Model Description
|
| 19 |
|
| 20 |
-
This model is a surgically optimized version of **meta-llama/Llama-3.2-3B**, created as part of **Chapter 8** in the book **"Rearchitecting LLMs"**.
|
| 21 |
|
| 22 |
* **Book:** [Rearchitecting LLMs](https://hubs.la/Q040tvtp0)
|
| 23 |
* **Framework:** [OptiPFair](https://github.com/peremartra/optipfair)
|
| 24 |
* **Technique:** Attention Optimization (Physical Attention Layer Removal)
|
| 25 |
* **Chapter:** Chapter 8 - Attention Optimization
|
|
|
|
|
|
|
| 26 |
|
| 27 |
[](https://hubs.la/Q040tvsK0)
|
| 28 |
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
|
|
|
|
|
|
|
| 32 |
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
| :--- | :--- | :--- | :--- |
|
| 35 |
-
|
|
| 36 |
-
|
|
| 37 |
-
|
|
| 38 |
-
|
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
## Model Description
|
| 19 |
|
| 20 |
+
This model is a surgically optimized version of **meta-llama/Llama-3.2-3B**, created as part of **Chapter 8** in the book **"Rearchitecting LLMs"**.
|
| 21 |
|
| 22 |
* **Book:** [Rearchitecting LLMs](https://hubs.la/Q040tvtp0)
|
| 23 |
* **Framework:** [OptiPFair](https://github.com/peremartra/optipfair)
|
| 24 |
* **Technique:** Attention Optimization (Physical Attention Layer Removal)
|
| 25 |
* **Chapter:** Chapter 8 - Attention Optimization
|
| 26 |
+
* **Notebook:** [CH08_NB03_Remove_Attention_](https://github.com/peremartra/Rearchitecting-LLMs/blob/main/CH08/CH08_NB03_Remove_Attention_.ipynb)
|
| 27 |
+
* **Paper:** [What Matters in Transformers? Not All Attention is Needed](https://arxiv.org/abs/2406.15786) β He et al., 2024
|
| 28 |
|
| 29 |
[](https://hubs.la/Q040tvsK0)
|
| 30 |
|
| 31 |
+
---
|
| 32 |
+
|
| 33 |
+
## Implementation
|
| 34 |
+
|
| 35 |
+
### How It Works
|
| 36 |
+
|
| 37 |
+
Unlike KV cache quantization, this technique **permanently removes** the least important attention modules from the model architecture. The result is a smaller model β fewer parameters, less VRAM, faster inference β that can be saved and reloaded without any custom inference engine.
|
| 38 |
+
|
| 39 |
+
The importance of each attention sublayer is measured via **cosine similarity between its input and output**, including the residual connection. A layer whose output is nearly identical to its input is doing very little work and is a strong candidate for removal.
|
| 40 |
+
|
| 41 |
+
The metric, as defined in the paper, is:
|
| 42 |
|
| 43 |
+
```
|
| 44 |
+
S = 1 - CosineSim(X_A, Y_A)
|
| 45 |
+
```
|
| 46 |
|
| 47 |
+
Where `X_A` is the hidden state arriving at the attention sublayer (captured before `input_layernorm`) and `Y_A` is the hidden state after the attention computation and its residual (`X_A + Attention(LayerNorm(X_A))`). Including the residual in the measurement prevents underestimating layers that rely on it to preserve information flow.
|
| 48 |
+
|
| 49 |
+
### Calibration Data
|
| 50 |
+
|
| 51 |
+
Importance scores are computed over **400 samples** from [Cosmopedia](https://huggingface.co/datasets/HuggingFaceTB/cosmopedia), weighted to cover the same range of tasks as the evaluation benchmarks:
|
| 52 |
+
|
| 53 |
+
| Subset | Weight | Samples | Activates |
|
| 54 |
| :--- | :--- | :--- | :--- |
|
| 55 |
+
| stories | 0.300 | 120 | Contextual reasoning (hellaswag, winogrande) |
|
| 56 |
+
| web_samples_v2 | 0.200 | 80 | Contextual reasoning |
|
| 57 |
+
| web_samples_v1 | 0.150 | 60 | Contextual reasoning |
|
| 58 |
+
| wikihow | 0.150 | 60 | Procedural understanding (piqa) |
|
| 59 |
+
| openstax | 0.125 | 50 | Academic reasoning (arc_easy) |
|
| 60 |
+
| stanford | 0.075 | 30 | Academic reasoning |
|
| 61 |
+
|
| 62 |
+
### Measuring Layer Importance
|
| 63 |
+
|
| 64 |
+
Hooks are anchored at two points inside each `LlamaDecoderLayer`:
|
| 65 |
+
|
| 66 |
+
```python
|
| 67 |
+
def setup_attention_hooks(model):
|
| 68 |
+
hooks = []
|
| 69 |
+
for i, layer in enumerate(model.model.layers):
|
| 70 |
+
# X_A: hidden state before attention transformation
|
| 71 |
+
hooks.append(layer.input_layernorm.register_forward_pre_hook(make_input_hook(i)))
|
| 72 |
+
# Y_A: hidden state after attention + residual
|
| 73 |
+
hooks.append(layer.post_attention_layernorm.register_forward_pre_hook(make_output_hook(i)))
|
| 74 |
+
return hooks, ...
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
The resulting importance scores for Llama-3.2-3B (ascending β lowest = most redundant):
|
| 78 |
+
|
| 79 |
+
```
|
| 80 |
+
Layer Score
|
| 81 |
+
------ ----------
|
| 82 |
+
21 0.006152 β dropped
|
| 83 |
+
18 0.006841 β dropped
|
| 84 |
+
22 0.007109 β dropped
|
| 85 |
+
2 0.007285
|
| 86 |
+
...
|
| 87 |
+
1 0.110186
|
| 88 |
+
0 0.278848 β most important, never touched
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
Layers 0 and 1 are clearly the most active and are never candidates for removal. The intermediate region (roughly layers 2β25) clusters near zero. Layers 26 and 27 recover, consistent with their role in consolidating representations before the language model head.
|
| 92 |
+
|
| 93 |
+
### Physical Deletion
|
| 94 |
+
|
| 95 |
+
The 3 selected layers (18, 21, 22) are physically removed. For each layer, both `self_attn` and `input_layernorm` are deleted and the layer's `forward()` is patched to route hidden states directly to the MLP block:
|
| 96 |
+
|
| 97 |
+
```python
|
| 98 |
+
def drop_attention_layer(model, layer_idx):
|
| 99 |
+
layer = model.model.layers[layer_idx]
|
| 100 |
+
|
| 101 |
+
# Release attention parameters from memory
|
| 102 |
+
delattr(layer, "self_attn")
|
| 103 |
+
delattr(layer, "input_layernorm")
|
| 104 |
+
|
| 105 |
+
def forward_no_attn(self, hidden_states, ...) -> Tuple[torch.Tensor]:
|
| 106 |
+
# Attention block is skipped β hidden states flow through unchanged
|
| 107 |
+
# MLP block: normalize, transform, add residual
|
| 108 |
+
residual = hidden_states
|
| 109 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 110 |
+
hidden_states = self.mlp(hidden_states)
|
| 111 |
+
hidden_states = residual + hidden_states
|
| 112 |
+
return hidden_states
|
| 113 |
+
|
| 114 |
+
PrunedLayer = type("PrunedDecoderLayer", (type(layer),), {"forward": forward_no_attn})
|
| 115 |
+
layer.__class__ = PrunedLayer
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
The dropped layer indices are stored in `config.json` so the model can be reloaded correctly:
|
| 119 |
+
|
| 120 |
+
```json
|
| 121 |
+
"dropped_attn_layers": [18, 21, 22]
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
---
|
| 125 |
+
|
| 126 |
+
## Loading the Model
|
| 127 |
+
|
| 128 |
+
The model uses a custom class (`PrunedLlamaForCausalLM`) that re-applies the attention bypass automatically at load time. A single `trust_remote_code=True` flag is all that's needed:
|
| 129 |
+
|
| 130 |
+
```python
|
| 131 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 132 |
+
|
| 133 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 134 |
+
"oopere/llama-3.2-3b-attn-drop-3",
|
| 135 |
+
torch_dtype=torch.float16,
|
| 136 |
+
device_map="auto",
|
| 137 |
+
trust_remote_code=True,
|
| 138 |
+
)
|
| 139 |
+
tokenizer = AutoTokenizer.from_pretrained("oopere/llama-3.2-3b-attn-drop-3")
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
> **Note:** This model was developed and tested on a **Google Colab T4 GPU (free tier)**. Use `torch.float16` on T4; switch to `torch.bfloat16` on Ampere-class GPUs or newer (L4, A100, etc.).
|
| 143 |
+
|
| 144 |
+
---
|
| 145 |
+
|
| 146 |
+
## Benchmarks
|
| 147 |
+
|
| 148 |
+
The following table compares the pruned model against the baseline (`meta-llama/Llama-3.2-3B`) on general knowledge benchmarks (0-shot):
|
| 149 |
+
|
| 150 |
+
| Benchmark | Metric | Baseline | Pruned | Ξ |
|
| 151 |
+
| :--- | :--- | :---: | :---: | :---: |
|
| 152 |
+
| **ARC Easy** | acc_norm | 0.7180 | 0.7104 | -1.06% |
|
| 153 |
+
| **HellaSwag** | acc_norm | 0.7405 | 0.7274 | -1.77% |
|
| 154 |
+
| **LAMBADA OpenAI** | accuracy | 0.6969 | 0.6189 | -11.19% |
|
| 155 |
+
| **PIQA** | acc_norm | 0.7813 | 0.7693 | -1.54% |
|
| 156 |
+
| **WinoGrande** | accuracy | 0.6961 | 0.6843 | -1.70% |
|
| 157 |
+
|
| 158 |
+
### What the numbers mean
|
| 159 |
+
|
| 160 |
+
Removing 3 attention modules eliminates approximately **75M parameters (~150MB in FP16)**, representing a ~10.7% reduction in dynamic memory growth per generated token.
|
| 161 |
+
|
| 162 |
+
Four of the five benchmarks show contained degradation of **1β2%**. ARC-Easy, HellaSwag, PIQA, and WinoGrande are all multiple-choice or binary-selection tasks: the model receives a context and must pick the correct continuation from a closed set of alternatives. This type of task primarily activates factual reasoning and local semantic coherence. A 1β2% drop is consistent with having removed layers that the importance scores already identified as redundant β **the model is still reasoning**.
|
| 163 |
+
|
| 164 |
+
**LAMBADA is a different story.** This benchmark requires predicting the last word of a paragraph from the full preceding context β a task that demands generative coherence across several sentences. The 11.2 percentage point drop contrasts sharply with the behavior on all other evaluations.
|
| 165 |
+
|
| 166 |
+
### The repetition problem
|
| 167 |
+
|
| 168 |
+
The difference becomes immediately visible in free-text generation:
|
| 169 |
+
|
| 170 |
+
**Baseline:**
|
| 171 |
+
```
|
| 172 |
+
France and the largest city in the country. It is located in the north-central part of the
|
| 173 |
+
country, on the banks of the Seine River. The city is known for its rich history, culture,
|
| 174 |
+
and architecture.
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
**Pruned model:**
|
| 178 |
+
```
|
| 179 |
+
France. It is the largest city in France and the second largest city in Europe. The city is
|
| 180 |
+
located on the River Seine in the north of France. Paris is the most visited city in the
|
| 181 |
+
world. It is the most visited city in the world. It is the most visited city in the world.
|
| 182 |
+
```
|
| 183 |
+
|
| 184 |
+
The pruned model falls into a repetition loop it cannot exit. The same pattern was reproduced with Llama-3.1-8B.
|
| 185 |
+
|
| 186 |
+
The reason is structural: **attention modules do not only transform token information β they also participate in suppressing the probability of recently generated tokens**. When several are removed, that suppression weakens and the model tends to reinforce the most probable next token instead of advancing. LAMBADA captures exactly this limitation, which explains why its drop is ten times larger than the rest of the benchmarks.
|
| 187 |
+
|
| 188 |
+
### When to use this model
|
| 189 |
+
|
| 190 |
+
This technique is **viable when outputs are short and structured** β question answering, classification, information extraction, or any task where responses are a few tokens long. It is **problematic for open-ended generation**, where repetition loops degrade output quality significantly.
|
| 191 |
+
|
| 192 |
+
> β οΈ This is not a neutral optimization. It carries a meaningful trade-off that is worth understanding before applying it in practice.
|
| 193 |
+
|
| 194 |
+
---
|
| 195 |
+
|
| 196 |
+
## Intended Use
|
| 197 |
+
|
| 198 |
+
This model is intended as a **learning artifact** for readers of *Rearchitecting LLMs* (Chapter 8 Hands-On Lab). It demonstrates that a non-trivial fraction of attention layers in a modern LLM can be physically removed with surprisingly small benchmark loss β and that the real cost only becomes visible in free-text generation. No custom inference stack is required to load or run it.
|
| 199 |
+
|
| 200 |
+
It is not intended for production use.
|