Simo76 commited on
Commit
79ad95d
·
1 Parent(s): 8162dad

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +127 -9
README.md CHANGED
@@ -1,24 +1,142 @@
1
- # Unified-LoRA
2
 
3
  **Adaptive LoRA fine-tuning with nested orbital rank control.**
4
 
5
  A closed-loop controller that dynamically adjusts LoRA rank during training based on observed stress, using a single adapter with sliced dimensions — no cold start, no capacity loss on transitions.
6
 
7
- ---
8
-
9
  ## Key results
10
 
11
  ### Stress test: task switch (MRPC → SST-2, DistilBERT, 3 seeds)
12
 
13
- | | Baseline (r=16 fixed) | Unified (orbital) | Delta |
14
- |------------------------|-----------------------|-------------------|-----------|
15
  | SST-2 Acc (new task) | 0.736 | 0.740 | **+0.004** |
16
- | MRPC F1 (retention) | 0.526 | 0.515 | -0.011 |
17
- | Effective rank | 16.0 | 13.6 | |
18
- | Rank saving | 0% | **15%** | |
19
 
20
  Under distribution shift, the controller adapts capacity dynamically with 15% rank saving and no performance loss.
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  ---
23
 
24
- ### Rank trace under shock (Seed 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Unified-LoRA
2
 
3
  **Adaptive LoRA fine-tuning with nested orbital rank control.**
4
 
5
  A closed-loop controller that dynamically adjusts LoRA rank during training based on observed stress, using a single adapter with sliced dimensions — no cold start, no capacity loss on transitions.
6
 
 
 
7
  ## Key results
8
 
9
  ### Stress test: task switch (MRPC → SST-2, DistilBERT, 3 seeds)
10
 
11
+ | | Baseline (r=16 fixed) | Unified (orbital) | Delta |
12
+ |------------------------|-----------------------|-------------------|------------|
13
  | SST-2 Acc (new task) | 0.736 | 0.740 | **+0.004** |
14
+ | MRPC F1 (retention) | 0.526 | 0.515 | -0.011 |
15
+ | Effective rank | 16.0 | 13.6 | |
16
+ | Rank saving | 0% | **15%** | |
17
 
18
  Under distribution shift, the controller adapts capacity dynamically with 15% rank saving and no performance loss.
19
 
20
+ ### Rank trace under shock (Seed 1)
21
+
22
+ ```
23
+ [ 0] r4 r4 r4 r8 r8 r8 r8 r16 r16 r16
24
+ [ 10] r16 r16 r16 r16 r16 r16 r16 r16 r16 r16
25
+ ...
26
+ [ 60] <<<SHOCK r16 r16 r16 r16 r16 r16 r16 r16
27
+ [ 68] r8 r8 r8 r8 r8 r8 r4 r4 r4 r4
28
+ [ 80] r4 r4 r4 r4 r4 r4 r4 r4 r4 r4
29
+ [ 92] r8 r16 r16 r16 r16 r16 r16 r16 r16 r16
30
+ ```
31
+
32
+ The controller exhibits **disturbance rejection**: detects the shock, stabilizes, then reallocates capacity only when needed.
33
+
34
+ ### Stable task (MRPC only, 120 steps, 3 seeds)
35
+
36
+ | | Baseline (r=16) | Unified | Delta |
37
+ |--------------|-----------------|---------|--------|
38
+ | F1 mean | 0.818 | 0.820 | +0.002 |
39
+ | σ | 0.008 | 0.008 | = |
40
+
41
+ On stable training, the controller stays at max rank. Zero degradation.
42
+
43
  ---
44
 
45
+ ## How it works
46
+
47
+ ### Architecture: nested orbitals (r4 ⊂ r8 ⊂ r16)
48
+
49
+ Unified-LoRA uses a single pair of matrices with rank slicing:
50
+
51
+ ```python
52
+ self.lora_A = Parameter(shape=[max_rank, in_features])
53
+ self.lora_B = Parameter(shape=[out_features, max_rank])
54
+
55
+ h = x @ A[:r, :].T
56
+ delta = h @ B[:, :r].T
57
+ ```
58
+
59
+ Lower ranks reuse learned weights. No reset, no cold start.
60
+
61
+ ---
62
+
63
+ ### Controller
64
+
65
+ ```
66
+ Stress → increase rank
67
+ Stable → decrease rank
68
+ Neutral → hold
69
+ ```
70
+
71
+ Stress signal:
72
+
73
+ ```
74
+ φ(t) = |loss - EMA(loss)| + 2.0 × max(0, loss - prev_loss)
75
+ ```
76
+
77
+ Adaptive thresholds (μ ± kσ) → no manual tuning.
78
+
79
+ ---
80
+
81
+ ## Quick start
82
+
83
+ ```python
84
+ from controller import setup_unified_lora, set_rank
85
+
86
+ model, ctrl = setup_unified_lora(model, max_rank=16)
87
+ optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5)
88
+
89
+ for batch in train_loader:
90
+ loss = model(**batch).loss
91
+ r = ctrl.step(loss.item())
92
+ set_rank(model, r)
93
+
94
+ loss.backward()
95
+ optimizer.step()
96
+ optimizer.zero_grad()
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Where it helps
102
+
103
+ - Distribution shift
104
+ - Noisy training
105
+ - Black-box fine-tuning APIs
106
+
107
+ ## Where it doesn't
108
+
109
+ - Clean stable training (no benefit, no harm)
110
+
111
+ ---
112
+
113
+ ## Overhead
114
+
115
+ O(1) per step. Negligible.
116
+
117
+ ---
118
+
119
+ ## Control view
120
+
121
+ | Method | Control | Rank |
122
+ |---------------|------------|---------------|
123
+ | LoRA | None | constant |
124
+ | AdaLoRA | Open-loop | f(step) |
125
+ | Unified-LoRA | Closed-loop| f(stress) |
126
+
127
+ ---
128
+
129
+ ## Structure
130
+
131
+ ```
132
+ controller.py
133
+ experiments/
134
+ docs/
135
+ notebooks/
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Author
141
+
142
+ Simona Vargiu