Text Classification
Transformers
lora
fine-tuning
adaptive
research
nested-lora
synaptic-plasticity
rank-adaptation
Instructions to use Simo76/Unified-LoRA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Simo76/Unified-LoRA with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Simo76/Unified-LoRA")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Simo76/Unified-LoRA", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Revise results and limitations in README
Browse filesUpdated results section to reflect evaluations on 3 GLUE tasks and added detailed performance metrics. Revised summary and limitations for clarity.
README.md
CHANGED
|
@@ -8,18 +8,20 @@ A lightweight per-layer controller that dynamically adjusts LoRA rank during tra
|
|
| 8 |
|
| 9 |
Instead of fixing `rank=8` or `rank=16` and hoping it works, Unified-LoRA adapts the rank of each layer independently during training. Layers under stress get more capacity; stable layers get less. No grid search, no guessing.
|
| 10 |
|
| 11 |
-
##
|
| 12 |
|
| 13 |
-
Evaluated on
|
|
|
|
| 14 |
|
| 15 |
-
| Task | Metric |
|
| 16 |
-
|------|--------|-----------------
|
| 17 |
-
| MRPC | F1 | 0.
|
| 18 |
-
|
|
| 19 |
-
|
|
| 20 |
-
| RTE | Accuracy | 0.556 | **0.592** | 10.8 | 33% |
|
| 21 |
|
| 22 |
-
**Summary:**
|
|
|
|
|
|
|
| 23 |
|
| 24 |
## How it works
|
| 25 |
|
|
@@ -42,18 +44,32 @@ The controller discovers meaningful patterns automatically:
|
|
| 42 |
|
| 43 |
- **v_proj consistently needs more rank than q_proj** across all tasks
|
| 44 |
- **Deep layers (4-5) need more rank** than early layers on complex tasks
|
| 45 |
-
- **Easier tasks
|
| 46 |
|
| 47 |
Example per-layer rank on MRPC:
|
| 48 |
```
|
| 49 |
-
layer0.q:
|
| 50 |
-
layer1.q: 7.8 layer1.v: 7.
|
| 51 |
-
layer2.q:
|
| 52 |
-
layer3.q: 8.
|
| 53 |
-
layer4.q: 10.
|
| 54 |
-
layer5.q:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
```
|
| 56 |
|
|
|
|
|
|
|
| 57 |
## What was tested and didn't improve results
|
| 58 |
|
| 59 |
In the interest of scientific honesty, the following extensions were tested and did **not** outperform the simple Adaptive controller:
|
|
@@ -67,11 +83,11 @@ The simple version works best. Complexity did not pay.
|
|
| 67 |
|
| 68 |
## Comparison with existing methods
|
| 69 |
|
| 70 |
-
| Method | Approach | Overhead |
|
| 71 |
-
|--------|----------|----------|------------
|
| 72 |
-
| AdaLoRA | SVD importance scoring per layer | High (SVD each step) | ~30 lines, zero SVD |
|
| 73 |
| DyLoRA | Train on multiple ranks simultaneously | Medium | Runtime adaptation, not post-hoc |
|
| 74 |
-
| Fixed LoRA | Manual rank selection | None |
|
| 75 |
|
| 76 |
Note: Direct numerical comparison with AdaLoRA was attempted but AdaLoRA did not function correctly in our setup (no rank pruning occurred). A fair comparison requires architecture-specific tuning of AdaLoRA scheduling parameters.
|
| 77 |
|
|
@@ -84,23 +100,20 @@ pip install transformers datasets evaluate accelerate scikit-learn
|
|
| 84 |
python benchmark.py
|
| 85 |
```
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
- Validated on DistilBERT (67M) and TinyLlama (1.1B) only
|
| 90 |
-
- Single-seed runs (variance not quantified)
|
| 91 |
-
- GLUE tasks only — no generation or instruction-following evaluation
|
| 92 |
-
- Rank changes don't reduce peak memory (matrices allocated at max_rank)
|
| 93 |
-
- Throughput overhead from dynamic slicing on small models
|
| 94 |
|
| 95 |
-
|
|
|
|
|
|
|
| 96 |
|
| 97 |
-
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
| 104 |
|
| 105 |
## Two validated systems
|
| 106 |
|
|
@@ -128,7 +141,7 @@ Key finding: φ returns to pre-shock regime after recovery (0.33 → 0.83 → 0.
|
|
| 128 |
|
| 129 |
### 2. Per-layer Adaptive Rank Controller
|
| 130 |
|
| 131 |
-
Validated on DistilBERT across
|
| 132 |
|
| 133 |
### Evolution
|
| 134 |
|
|
|
|
| 8 |
|
| 9 |
Instead of fixing `rank=8` or `rank=16` and hoping it works, Unified-LoRA adapts the rank of each layer independently during training. Layers under stress get more capacity; stable layers get less. No grid search, no guessing.
|
| 10 |
|
| 11 |
+
## Results (multi-seed, 3 seeds)
|
| 12 |
|
| 13 |
+
Evaluated on 3 GLUE tasks with DistilBERT-base-uncased, 3 epochs, LR=5e-4, α=16.
|
| 14 |
+
Each result is mean ± std over 3 seeds.
|
| 15 |
|
| 16 |
+
| Task | Metric | r=8 (fixed) | r=16 (fixed) | Unified (adaptive) | Avg Rank |
|
| 17 |
+
|------|--------|-------------|--------------|-------------------|----------|
|
| 18 |
+
| MRPC | F1 | **0.885 ± 0.007** | 0.882 ± 0.006 | 0.862 ± 0.025 | 9.1 |
|
| 19 |
+
| CoLA | MCC | 0.474 ± 0.001 | **0.478 ± 0.011** | 0.477 ± 0.021 | 7.0 |
|
| 20 |
+
| RTE | Accuracy | **0.560 ± 0.014** | 0.560 ± 0.018 | 0.543 ± 0.010 | 11.7 |
|
|
|
|
| 21 |
|
| 22 |
+
**Summary:** The adaptive controller reduces average rank by 33-56% and produces interpretable per-layer rank patterns. Performance is within the noise margin of fixed-rank baselines on CoLA, but shows a gap on MRPC and RTE. The controller has higher variance than fixed-rank approaches.
|
| 23 |
+
|
| 24 |
+
**Honest assessment:** At this scale (DistilBERT, GLUE), the choice between r=8 and r=16 makes little difference — the problem the controller tries to solve may not exist at small scale. Validation on larger models where rank selection matters more is needed.
|
| 25 |
|
| 26 |
## How it works
|
| 27 |
|
|
|
|
| 44 |
|
| 45 |
- **v_proj consistently needs more rank than q_proj** across all tasks
|
| 46 |
- **Deep layers (4-5) need more rank** than early layers on complex tasks
|
| 47 |
+
- **Easier tasks converge to lower rank** than harder tasks
|
| 48 |
|
| 49 |
Example per-layer rank on MRPC:
|
| 50 |
```
|
| 51 |
+
layer0.q: 7.9 layer0.v: 8.8
|
| 52 |
+
layer1.q: 7.8 layer1.v: 7.9
|
| 53 |
+
layer2.q: 7.9 layer2.v: 8.5
|
| 54 |
+
layer3.q: 8.8 layer3.v: 11.3
|
| 55 |
+
layer4.q: 10.3 layer4.v: 12.9
|
| 56 |
+
layer5.q: 7.6 layer5.v: 11.3
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
Rank trajectory over training (MRPC, seed=0):
|
| 60 |
+
```
|
| 61 |
+
Step Avg Rank Loss
|
| 62 |
+
0 4.0 0.696
|
| 63 |
+
76 13.8 0.495
|
| 64 |
+
153 11.5 0.588
|
| 65 |
+
306 8.8 0.460
|
| 66 |
+
459 6.8 0.069
|
| 67 |
+
612 6.5 0.341
|
| 68 |
+
689 5.8 0.028
|
| 69 |
```
|
| 70 |
|
| 71 |
+
The controller starts low, expands during early instability, then converges to lower rank as training stabilizes.
|
| 72 |
+
|
| 73 |
## What was tested and didn't improve results
|
| 74 |
|
| 75 |
In the interest of scientific honesty, the following extensions were tested and did **not** outperform the simple Adaptive controller:
|
|
|
|
| 83 |
|
| 84 |
## Comparison with existing methods
|
| 85 |
|
| 86 |
+
| Method | Approach | Overhead | Difference |
|
| 87 |
+
|--------|----------|----------|------------|
|
| 88 |
+
| AdaLoRA | SVD importance scoring per layer | High (SVD each step) | Unified-LoRA is ~30 lines, zero SVD |
|
| 89 |
| DyLoRA | Train on multiple ranks simultaneously | Medium | Runtime adaptation, not post-hoc |
|
| 90 |
+
| Fixed LoRA | Manual rank selection | None | Unified-LoRA removes rank as a hyperparameter |
|
| 91 |
|
| 92 |
Note: Direct numerical comparison with AdaLoRA was attempted but AdaLoRA did not function correctly in our setup (no rank pruning occurred). A fair comparison requires architecture-specific tuning of AdaLoRA scheduling parameters.
|
| 93 |
|
|
|
|
| 100 |
python benchmark.py
|
| 101 |
```
|
| 102 |
|
| 103 |
+
For multi-seed validation, run `validation_complete.py` (~15-20 min):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
+
```bash
|
| 106 |
+
python validation_complete.py
|
| 107 |
+
```
|
| 108 |
|
| 109 |
+
## Limitations
|
| 110 |
|
| 111 |
+
- Validated on DistilBERT (67M) only at multi-seed level
|
| 112 |
+
- At this scale, fixed r=8 performs comparably to r=16, limiting the potential benefit of adaptive rank
|
| 113 |
+
- Higher variance than fixed-rank baselines
|
| 114 |
+
- GLUE classification tasks only — no generation or instruction-following
|
| 115 |
+
- Rank changes don't reduce peak memory (matrices allocated at max_rank)
|
| 116 |
+
- Needs validation on larger models (3B-7B) where rank selection has more impact
|
| 117 |
|
| 118 |
## Two validated systems
|
| 119 |
|
|
|
|
| 141 |
|
| 142 |
### 2. Per-layer Adaptive Rank Controller
|
| 143 |
|
| 144 |
+
Validated on DistilBERT across 3 GLUE tasks with 3 seeds (results table above). Each layer independently adjusts its LoRA rank based on gradient stress EMA. Performance is within noise of fixed-rank baselines with 33-56% rank reduction.
|
| 145 |
|
| 146 |
### Evolution
|
| 147 |
|