natmin322 commited on
Commit
aeb2d78
·
1 Parent(s): 2dea138

v7: C5 Data-Informed Subspace Init + restructure contributions to 2 core claims

Browse files
improve_gainlora/IDEA_Overall.md ADDED
@@ -0,0 +1,432 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SpecRoute: Định tuyến Phổ thông qua Duality Định tuyến–Bảo vệ trong Học liên tục với LoRA
2
+
3
+ > **Tài liệu thiết kế chính thức — V7**
4
+ > Ràng buộc: Zero-replay nghiêm ngặt. Theory-first.
5
+
6
+ ---
7
+
8
+ ## 1. Đặt bài toán
9
+
10
+ **Setting.** Học liên tục với LoRA mở rộng trên một LLM đóng băng.
11
+ Các tasks $\mathcal{T}_1, \ldots, \mathcal{T}_T$ đến tuần tự. Với mỗi task $t$:
12
+
13
+ - Một adapter low-rank $\Delta W_t = B_t A_t$ ($A_t \in \mathbb{R}^{r \times d}$, $B_t \in \mathbb{R}^{d \times r}$) được thêm vào mọi phép chiếu attention.
14
+ - Chỉ $B_t$ được huấn luyện; $A_t$ bị đóng băng sau khi khởi tạo null-space (InfLoRA).
15
+ - Sau khi huấn luyện, cả $A_t, B_t$ đều bị đóng băng và một nhánh mới được tạo cho task tiếp theo.
16
+
17
+ **Inference.** Cho input $x$ *không có* task identifier, mô hình phải tạo ra output đúng:
18
+
19
+ $$y = f\!\Bigl(W_0\, x \;+\; \sum_{t=1}^{T} w_t(x)\; B_t A_t\, x\Bigr)$$
20
+
21
+ **Ba bài toán con kết hợp:**
22
+
23
+ | Bài toán con | Mục tiêu | Yêu cầu hình thức |
24
+ |:------------:|---------|-------------------|
25
+ | **Routing (R)** | Gán input đúng expert | $w_{t^*}(x) \gg w_t(x)$ với $t \neq t^*$ |
26
+ | **Protection (P)** | Ngăn suy giảm expert cũ | $\Delta W_t$ không đổi sau task $t$ |
27
+ | **Allocation (A)** | Quản lý capacity không gian con hữu hạn | $\sum_t \dim\bigl(\mathrm{span}(A_t)\bigr) \leq d$ |
28
+
29
+ **Ràng buộc setting:** *Zero-replay* — không tái sử dụng dữ liệu task cũ dưới bất kỳ hình thức nào (thô, synthetic, hay phân phối thống kê).
30
+
31
+ ---
32
+
33
+ ## 2. Quan sát: Duality Ẩn
34
+
35
+ ### 2.1 Tiếp cận của GainLoRA và Điểm yếu
36
+
37
+ GainLoRA (NeurIPS 2025) xử lý R, P, A như các bài toán **độc lập**:
38
+
39
+ | Khía cạnh | Cơ chế | Chi phí |
40
+ |-----------|--------|---------|
41
+ | R | MLP `trans_input` học được + `prompt_key` học được → cosine gating | Tham số thêm + subspace GPM |
42
+ | P | GPM chiếu gradient vào null-space của task cũ | Tiêu thụ subspace mỗi task |
43
+ | A | Threshold tăng dần $\varepsilon_t \nearrow 1$ | Task sau bị ràng buộc hơn |
44
+
45
+ **Điểm yếu cơ bản:** Vì routing được *học*, nó tạo ra vòng lặp xấu:
46
+
47
+ 1. `trans_input` thay đổi mỗi task → routing space trôi dạt → prompt keys cũ mất alignment → routing suy giảm.
48
+ 2. GPM phải bảo vệ routing params → *tiêu thụ subspace có thể dùng cho task learning*.
49
+ 3. KL distillation trên routing cần thiết → yêu cầu replay hoặc frozen copies → overhead bộ nhớ.
50
+
51
+ ### 2.2 Nhận thức then chốt
52
+
53
+ Chúng tôi quan sát rằng GPM đảm bảo xấp xỉ các subspace input của expert trực giao nhau:
54
+
55
+ $$\mathrm{span}(V_i) \;\approx\perp\; \mathrm{span}(V_j), \qquad i \neq j$$
56
+
57
+ trong đó $V_t$ là các right singular vectors của $\Delta W_t$. Tính trực giao này, được đảm bảo cho mục đích **bảo vệ**, đồng thời cung cấp tiêu chí **routing** tự nhiên: vì các subspace không chồng chéo, đo lường mức độ một input căn chỉnh với từng subspace sẽ xác định duy nhất task gốc.
58
+
59
+ > **Duality Định tuyến–Bảo vệ.**
60
+ > Chống quên (bảo vệ subspace trực giao) và nhận diện task (routing phân biệt)
61
+ > là *hai biểu hiện kép của cùng một cấu trúc phổ*.
62
+ > Giải quyết một bài toán tự động giải quyết bài toán kia.
63
+
64
+ **Hệ quả:**
65
+ - Không cần tham số routing học được → không trôi dạt routing, không tốn GPM cho routing.
66
+ - Không cần replay để duy trì routing → tự nhiên tuân thủ zero-replay.
67
+ - Độ chính xác routing được *đảm bảo* bởi chất lượng bảo vệ (được hình thức hoá bên dưới).
68
+
69
+ ---
70
+
71
+ ## 3. Khung Lý thuyết
72
+
73
+ ### 3.1 Spectral Expert Signatures
74
+
75
+ **Định nghĩa 1** *(Spectral Signature).* Với expert đóng băng $\Delta W_t = B_t A_t$ và thin SVD
76
+
77
+ $$\Delta W_t = U_t\, \Sigma_t\, V_t^\top, \qquad V_t \in \mathbb{R}^{d \times r},\; \Sigma_t = \mathrm{diag}(\sigma_{t,1}, \ldots, \sigma_{t,r}),$$
78
+
79
+ spectral signature là $\mathcal{S}_t = (V_t,\, \boldsymbol{\sigma}_t)$ trong đó:
80
+
81
+ - $V_t$: **input receptive field** — $r$ hướng input mà expert xử lý,
82
+ - $\boldsymbol{\sigma}_t$: **sensitivity spectrum** — hệ số khuếch đại biến đổi dọc mỗi hướng.
83
+
84
+ **Góc nhìn lý thuyết thông tin.** Xem $\Delta W_t$ như một kênh tuyến tính, cột của $V_t$ là *input modes* của kênh và $\sigma_{t,i}^2$ là *gain* của mode $i$. Tổng channel capacity (Frobenius energy) là $\|\Delta W_t\|_F^2 = \sum_i \sigma_{t,i}^2$.
85
+
86
+ ### 3.2 Spectral Affinity
87
+
88
+ **Định nghĩa 2** *(Spectral Affinity).* Độ tương hợp của input $h \in \mathbb{R}^d$ với expert $t$:
89
+
90
+ $$\alpha_t(h) \;=\; \frac{h^\top M_t\, h}{\mathrm{tr}(M_t)\;\|h\|^2}, \qquad M_t = V_t\, \mathrm{diag}(\boldsymbol{\sigma}_t^2)\, V_t^\top$$
91
+
92
+ Khai triển:
93
+
94
+ $$\alpha_t(h) = \frac{\displaystyle\sum_{i=1}^{r} \sigma_{t,i}^2\;(v_{t,i}^\top h)^2}{\displaystyle\Bigl(\sum_{i=1}^{r} \sigma_{t,i}^2\Bigr)\,\|h\|^2}$$
95
+
96
+ **Tính chất:**
97
+
98
+ | Tính chất | Phát biểu |
99
+ |-----------|-----------|
100
+ | Dải giá trị | $\alpha_t(h) \in [0,\, 1]$ — weighted Rayleigh quotient chuẩn hoá |
101
+ | Energy ratio | $\alpha_t(h) = \|\Delta W_t\, h\|^2 \;/\; \bigl(\|\Delta W_t\|_F^2\, \|h\|^2\bigr)$ |
102
+ | Ý nghĩa | Phần channel capacity của expert $t$ được kích hoạt bởi $h$ |
103
+ | In-distribution | $h \in \mathrm{span}(V_t) \;\Rightarrow\; \alpha_t(h) \geq \kappa_{\min}(t) > 0$ |
104
+ | Out-of-distribution | $h \perp \mathrm{span}(V_t) \;\Rightarrow\; \alpha_t(h) = 0$ chính xác |
105
+
106
+ ### 3.3 Định lý Duality Định tuyến–Bảo vệ
107
+
108
+ **Định nghĩa 3** *(Subspace Overlap).* Độ chồng chéo giữa các expert $i$ và $j$:
109
+
110
+ $$\delta_{ij} = \|V_i^\top V_j\|_F^2 = \sum_{k=1}^{r} \cos^2 \theta_{ij}^{(k)}$$
111
+
112
+ trong đó $\theta_{ij}^{(k)}$ là các *principal angles* giữa $\mathrm{span}(V_i)$ và $\mathrm{span}(V_j)$.
113
+
114
+ ---
115
+
116
+ **Định lý 1** *(Duality Định tuyến–Bảo vệ).* Nếu GPM đảm bảo $\delta_{ij} \leq \varepsilon$ với mọi $i \neq j$, thì với mọi unit input $h \in \mathrm{span}(V_{t^*})$, **routing margin** thoả mãn:
117
+
118
+ $$\boxed{\;\alpha_{t^*}(h) \;-\; \max_{t \neq t^*}\, \alpha_t(h) \;\;\geq\;\; \kappa_{\min}(t^*)\; -\; \varepsilon\, \kappa_{\max}\;}$$
119
+
120
+ trong đó:
121
+
122
+ $$\kappa_{\min}(t) = \frac{\sigma_{t,\min}^2}{\sum_i \sigma_{t,i}^2}, \qquad \kappa_{\max} = \max_t\, \frac{\sigma_{t,\max}^2}{\sum_i \sigma_{t,i}^2}$$
123
+
124
+ **Chứng minh.**
125
+
126
+ *Cận dưới cho expert đúng.* Viết $h = V_{t^*}\, c$ với $\|c\| = 1$. Khi đó $(v_{t^*,i}^\top h)^2 = c_i^2$ và $\sum c_i^2 = 1$:
127
+
128
+ $$\alpha_{t^*}(h) = \frac{\sum_i \sigma_{t^*,i}^2\, c_i^2}{\sum_i \sigma_{t^*,i}^2} \;\geq\; \kappa_{\min}(t^*)$$
129
+
130
+ *Cận trên cho expert sai.* Với $t \neq t^*$:
131
+
132
+ $$\|V_t^\top h\|^2 \leq \delta_{t,t^*} \leq \varepsilon \;\;\Rightarrow\;\; \alpha_t(h) \leq \kappa_{\max}\, \varepsilon \qquad\square$$
133
+
134
+ ---
135
+
136
+ **Hệ quả 1** *(Routing Confidence).* Với softmax routing nhiệt độ $\tau$:
137
+
138
+ $$w_{t^*}(h) \;\geq\; \frac{1}{1 + (T{-}1)\,\exp\!\bigl(-m/\tau\bigr)}, \qquad m = \kappa_{\min}(t^*) - \varepsilon\, \kappa_{\max}$$
139
+
140
+ Để đạt confidence mục tiêu $w_{t^*} \geq 1 - \delta$, đặt $\tau \leq m \,/\, \ln\!\bigl(\tfrac{T-1}{\delta}\bigr)$.
141
+
142
+ ---
143
+
144
+ **Hệ quả 2** *(Capacity Bound — Kết nối Grassmannian).* Số lượng tối đa subspace $r$-chiều trong $\mathbb{R}^d$ với pairwise overlap $\delta \leq \varepsilon$:
145
+
146
+ $$T_{\max} \;\leq\; \frac{d}{r\,(1 - \varepsilon)}$$
147
+
148
+ Với T5-Small ($d = 512$, $r = 8$, $\varepsilon = 0.02$): $T_{\max} \leq 65 \gg 15$ tasks. Điều này kết nối capacity học liên tục với lý thuyết Grassmannian packing.
149
+
150
+ ### 3.4 Drift Invariance
151
+
152
+ **Mệnh đề 1** *(Drift-Free Routing).* Hàm routing $h \mapsto \alpha_t(h)$ hoàn toàn ổn định qua tất cả các task.
153
+
154
+ **Chứng minh.** Routing input được tính từ frozen embedding table, *trước* bất kỳ transformer block nào. LoRA chỉ tồn tại trong các attention layer sâu hơn → $h$ độc lập với mọi tham số LoRA. Kết hợp với $\mathcal{S}_t$ đóng băng, $\alpha_t(h)$ bất biến với mọi thay đổi tích luỹ. $\square$
155
+
156
+ ### 3.5 Vấn đề then chốt: Null-Space Collapse
157
+
158
+ Định lý 1 giả định $h \in \mathrm{span}(V_{t^*})$. Trong thực tế điều này đòi hỏi hai điều kiện:
159
+
160
+ **(A) Expert phải học được:** $A_t$ phải nằm trong subspace có liên quan đến task $t$ để $B_t$ có thể học các biến đổi có ý nghĩa, tạo ra $\sigma_{t,i} > 0$ đáng kể.
161
+
162
+ **(B) Input phải có projection:** Inputs thực tế của task $t$ phải chiếu có năng lượng lên $\text{span}(V_t)$.
163
+
164
+ **InfLoRA gốc vi phạm (A):** $A_t$ được khởi tạo ngẫu nhiên (Kaiming) rồi chiếu vào null-space của GPM:
165
+
166
+ $$A_t \leftarrow A_t - A_t P_{\text{old}}, \quad \text{normalize}$$
167
+
168
+ Null-space (sau $t-1$ tasks) là một không gian $d - N_{\text{protected}}$ chiều. Kaiming random trong không gian này KHÔNG ĐẢM BẢO alignment với các hướng có liên quan đến task $t$. Khi null-space thu hẹp dần (Layer 7: 8/512 → 161/512 → 344/512 qua 13 tasks), xác suất random init bắt được đúng hướng task-relevant giảm theo.
169
+
170
+ **Hệ quả thực nghiệm (V6):** IMDB (task 8) — eval_loss dừng ở 6.37 sau 10 epoch, EM=0.0 suốt quá trình, expert thực sự không thể học bất cứ điều gì hữu ích.
171
+
172
+ ---
173
+
174
+ ## 4. Các Thành phần Framework
175
+
176
+ ### C1 — Spectral Expert Signatures
177
+
178
+ Sau khi train task $t$, tính $\mathcal{S}_t = (V_t, \boldsymbol{\sigma}_t)$ qua **thin SVD**:
179
+
180
+ $$B_t,\, A_t \;\xrightarrow[\text{QR + SVD}]{O(dr^2)}\; (V_t,\, \boldsymbol{\sigma}_t)$$
181
+
182
+ - QR decomposition của $B$ và $A^\top$, sau đó SVD của $r \times r$ core ��� chính xác, $O(dr^2)$ so với $O(d^2 r)$.
183
+ - Lưu trên mỗi LoRA layer (encoder Q, V; decoder self/cross Q, V).
184
+ - **Bất biến** theo cấu trúc: weights đóng băng → signatures đóng băng → không trôi dạt.
185
+
186
+ ### C2 — Spectral Affinity Routing
187
+
188
+ **Inference** (tất cả task, routing SVD đối xứng):
189
+
190
+ $$w(h) = \mathrm{softmax}\!\left(\frac{[\alpha_1(h),\; \ldots,\; \alpha_T(h)]}{\tau}\right)$$
191
+
192
+ Mọi task đều dùng cùng công thức $\sigma^2$-weighted spectral affinity (Định nghĩa 2). Sau khi train task $t$, tính $\mathcal{S}_t$ một lần qua `prepare_inference_routing()` và sử dụng cùng signatures của task cũ.
193
+
194
+ **Training** (task $t$, SVD cuối chưa biết vì $B_t$ đang train):
195
+
196
+ $$\alpha_t^{\mathrm{train}}(h) = \frac{\|A_t\, h\|^2}{r\,\|h\|^2} + \beta(n), \qquad \beta(n) = \tau \cdot \ln\!\left(\frac{\alpha_{\mathrm{target}} \cdot n}{1 - \alpha_{\mathrm{target}}}\right)$$
197
+
198
+ trong đó $n = |\{\text{task cũ}\}|$ và $\alpha_{\mathrm{target}} \in (0,1)$ là routing weight mục tiêu cho task hiện tại (mặc định 0.8).
199
+
200
+ **Lý giải proxy A-row:** Với $B_t$ full-rank bất kỳ, column span của $V_t$ (từ SVD của $B_t A_t$) bằng $\mathrm{range}(A_t^\top)$. Vì vậy các hàng $A$ span *cùng* subspace input mà $V_t$ hội tụ sẽ capture. Proxy đo alignment input với subspace này dùng weighting đồng đều (chưa có $\sigma$).
201
+
202
+ **Lý giải adaptive $\beta(n)$:** Bias hằng số gây routing weight của task hiện tại giảm $O(1/n)$ theo số task (softmax dilution). Công thức adaptive chuẩn hoá điều này: giải $w_t = \alpha_{\mathrm{target}}$ trong phương trình softmax cho ra closed-form trên. Đảm bảo task hiện tại nhận được routing weight $\approx \alpha_{\mathrm{target}}$ bất kể $n$.
203
+
204
+ **Lý giải symmetric inference:** Tại inference, $B_t$ đóng băng và $\Delta W_t = B_t A_t$ có SVD xác định. Dùng cùng $\sigma^2$-weighted Rayleigh quotient cho tất cả task đảm bảo *đối xứng đo lường* — mọi affinity đều sống trên cùng metric space, và Định lý 1 áp dụng thống nhất.
205
+
206
+ | Phase | Cơ chế routing | Nhiệt độ | Lý do |
207
+ |-------|----------------|----------|-------|
208
+ | Training (task $t$) | A-row fit + adaptive $\beta(n)$ | $\tau = 1.0$ | $B=0$ cold-start; β bù softmax dilution |
209
+ | Inference (mọi task) | SVD spectral affinity (đối xứng) | $\tau = 1.0$ | Mọi task dùng σ²-weighted Rayleigh quotient |
210
+
211
+ ### C3 — Capacity-Aware Subspace Allocation
212
+
213
+ GPM threshold kiểm soát đánh đổi bảo vệ–capacity. Từ Định lý 1:
214
+ - $\varepsilon$ thấp hơn → bảo vệ & routing tốt hơn, nhưng null-space cạn nhanh hơn.
215
+ - $\varepsilon$ cao hơn → nhiều capacity hơn, nhưng đảm bảo routing yếu hơn.
216
+
217
+ **Dynamic threshold** (theo InfLoRA):
218
+
219
+ $$\varepsilon_t = (1 - \varepsilon_0) \cdot \frac{t}{T} + \varepsilon_0$$
220
+
221
+ trong đó $\varepsilon_0$ là base threshold. Phân bổ bảo vệ nghiêm ngặt dần khi task tích luỹ. Đánh đổi là *có nguyên tắc* qua Hệ quả 2: miễn là $\varepsilon_t$ vượt $(1 - d/(rT))$, capacity cho tất cả $T$ task được đảm bảo.
222
+
223
+ ---
224
+
225
+ ### C4 — Spectrally-Conditioned Gradient (Implementation Detail)
226
+
227
+ > **Lưu ý phân loại:** C4 là chi tiết triển khai, không phải đóng góp lý thuyết độc lập. Nó giải quyết một vấn đề kỹ thuật thuần túy: sau khi `get_reg_matrix()` chiếu $A_t$ vào null-space, column space của $A_t$ không còn trực giao, khiến gradient $\nabla_B \mathcal{L} = \nabla_{\Delta W} \mathcal{L} \cdot A^T$ bị biến dạng. Việc áp dụng preconditioner là một hiệu chỉnh kỹ thuật cần thiết, không phải một luận điểm học thuật mới.
228
+
229
+ Gradient $\nabla_B \mathcal{L}$ bị biến dạng bởi condition number của $A^T$. Chúng tôi áp dụng preconditioner một lần sau khi $A$ đóng băng:
230
+
231
+ $$\tilde{\nabla}_B = \nabla_B \mathcal{L} \cdot (AA^T + \epsilon I)^{-1/2}$$
232
+
233
+ Preconditioner được tính **một lần** sau `get_reg_matrix()` — không có overhead per-step.
234
+
235
+ > **Lưu ý:** Spectral entropy regularization (C4.2) được loại bỏ khỏi V7. Lý do: C5 (Data-Informed Init) khởi tạo $A_t$ sao cho $B_t$ học trong subspace task-relevant → singular values tự nhiên sẽ phân tán theo dữ liệu. Cưỡng bức entropy uniform qua regularization mâu thuẫn với triết lý của C5 (để dữ liệu dẫn dắt phân phối phổ, không phải regularizer). Preconditioner gradient (C4.1) vẫn giữ vì nó sửa điều kiện ma trận, không ảnh hưởng đến triết lý data-driven.
236
+
237
+ ---
238
+
239
+ ### C5 — Data-Informed Subspace Initialization (Đóng góp chính)
240
+
241
+ #### Động lực
242
+
243
+ Khi $A_t$ được khởi tạo ngẫu nhiên và chiếu vào null-space, nó chiếm một điểm *tùy ý* trên restricted Grassmannian $\mathrm{Gr}(r,\, d - N_{\text{protected}})$. Với $\dim\bigl(\mathrm{Gr}(8, 351)\bigr) = 8 \times 343 = 2744$, không gian lựa chọn rất lớn — random init gần như chắc chắn sub-optimal. Đặc biệt khi null-space thu hẹp, các hướng task-relevant ngày càng chiếm tỷ lệ nhỏ trong không gian còn lại, làm cho random init càng kém hiệu quả.
244
+
245
+ #### Bài toán tối ưu
246
+
247
+ Chúng tôi đặt vấn đề khởi tạo $A_t$ như bài toán tối ưu có ràng buộc:
248
+
249
+ $$\max_{A_t} \quad \text{tr}\!\bigl(A_t\, Q\, C_t\, Q\, A_t^T\bigr) \quad \text{s.t.} \quad A_t A_t^T = I_r$$
250
+
251
+ trong đó $Q = I - P_{\text{old}}$ là null-space projector (với $P_{\text{old}} = \mathcal{B}\mathcal{B}^T$ là GPM projection matrix), và:
252
+
253
+ $$C_t = \frac{1}{|\mathcal{X}_t|} \sum_{x \in \mathcal{X}_t} h(x)\, h(x)^T$$
254
+
255
+ là activation covariance của task $t$ được ước tính từ vài batch đầu của dữ liệu training.
256
+
257
+ **Ý nghĩa:** Maximize variance captured trong null-space theo phân phối dữ liệu task $t$ — tức là tìm subspace $r$-chiều trong null-space *phù hợp nhất* với dữ liệu task hiện tại.
258
+
259
+ #### Lời giải dạng đóng
260
+
261
+ Định nghĩa **projected covariance**: $\tilde{C}_t = Q\, C_t\, Q$.
262
+
263
+ Bài toán trở thành constrained PCA tiêu chuẩn trên $\tilde{C}_t$. Lời giải chính xác là:
264
+
265
+ $$A_t = \text{top-}r\text{ eigenvectors của } \tilde{C}_t$$
266
+
267
+ hay tương đương, các hàng của $A_t$ là $r$ eigenvectors ứng với eigenvalues lớn nhất của $\tilde{C}_t = Q C_t Q$.
268
+
269
+ **Thuật toán** (Constrained PCA trong null-space):
270
+
271
+ ```
272
+ # Bước 1: Thu thập activation covariance (forward pass nhỏ, trước training)
273
+ C_t = ∑ h(x)h(x)^T / N_batch # covariance input task t (N_batch ~200 batches)
274
+
275
+ # Bước 2: Project covariance vào null-space
276
+ Q = I - P_old # null-space projector (từ GPM bases đã lưu)
277
+ C_tilde = Q @ C_t @ Q # projected covariance
278
+
279
+ # Bước 3: Eigenvector decomposition
280
+ eigvals, eigvecs = eigh(C_tilde) # đối xứng → eigh nhanh hơn SVD
281
+ top_r_idx = argsort(eigvals, descending=True)[:r]
282
+
283
+ # Bước 4: Set A_t
284
+ A_t = eigvecs[:, top_r_idx].T # shape (r, d) — direction task-relevant nhất trong null-space
285
+ A_t = A_t / norm(A_t, dim=1, keepdim=True) * sqrt(3) # normalize như InfLoRA gốc
286
+ ```
287
+
288
+ #### Ý nghĩa Lý thuyết Thông tin
289
+
290
+ Theo Data Processing Inequality, với bất kỳ ma trận $A_t$ nào:
291
+ $$I(A_t h;\, y) \leq I(h;\, y)$$
292
+
293
+ Nhưng trong ràng buộc null-space, không phải mọi $A_t$ đều bằng nhau. Data-informed $A_t$ **maximize** $I(A_t h; y)$ trong lớp các $A_t$ thỏa mãn null-space constraint — trong khi random $A_t$ chỉ capture một phần ngẫu nhiên, không được tối ưu hoá.
294
+
295
+ Ngoài ra, khi $A_t$ được khởi tạo tốt hơn, $B_t$ huấn luyện trong subspace có liên quan đến task → $\sigma_{t,i}$ lớn hơn → spectral signature $\mathcal{S}_t$ mạnh hơn → routing margin $\kappa_{\min}(t)$ trong Định lý 1 **tăng**. Đây là kết nối trực tiếp từ C5 trở lại lý thuyết routing.
296
+
297
+ #### Tương thích Zero-Replay
298
+
299
+ $C_t$ được tính từ **dữ liệu training của task hiện tại** (task $t$ đang được huấn luyện). Đây không phải replay (replay = tái sử dụng dữ liệu *cũ*). Dữ liệu training của task hiện tại luôn sẵn có trong CL setting. $A_t$ (model parameter) chỉ encode *hướng* (không phải giá trị hay vị trí dữ liệu cụ thể), tương tự GPM bases cũng tính từ activation covariance và đã được chấp nhận trong InfLoRA, GainLoRA. ✅ zero-replay compliant.
300
+
301
+ #### Kết nối với Bài toán Gốc
302
+
303
+ | V6 failure mode | Root cause | C5 giải quyết |
304
+ |-----------------|-----------|---------------|
305
+ | IMDB/SST2 EM=0 (never-learning) | $A_t$ random bỏ lỡ task-relevant directions trong null-space | $A_t$ data-informed capture variance cao nhất trong null-space → $B_t$ CÓ THỂ học |
306
+ | Routing degradation (yelp 55→36) | Expert quality thấp → $\sigma \approx 0$ → signature = noise → routing ngẫu nhiên | Expert quality tăng → $\sigma > 0$ đáng kể → routing có phân biệt |
307
+
308
+ ---
309
+
310
+ ## 5. Những gì Loại bỏ từ GainLoRA
311
+
312
+ | Thành phần | GainLoRA | SpecRoute | Lý do |
313
+ |------------|----------|-----------|-------|
314
+ | MLP `trans_input` | Learned routing projection | ❌ Loại bỏ | Duality: spectral affinity là đủ |
315
+ | `prompt_key` | Learned per-task key | ❌ Loại bỏ | Thay bằng spectral signatures |
316
+ | `previous_trans_input` | Frozen MLP copies | ❌ Loại bỏ | Signatures bất biến theo cấu trúc |
317
+ | KL distillation | Replay-based routing loss | ❌ Loại bỏ | Không learned routing → không cần distill |
318
+ | GPM trên routing params | Subspace cho routing | ❌ Loại bỏ | Không có routing parameters để bảo vệ |
319
+
320
+ **Hiệu ứng tổng thể:** Toàn bộ subspace và compute budget mà GainLoRA dành cho routing infrastructure được *thu hồi* cho task learning.
321
+
322
+ ---
323
+
324
+ ## 6. Hai Đóng góp Cốt lõi
325
+
326
+ > **Nguyên tắc cấu trúc:** Hai đóng góp này tạo thành một vòng lặp logic khép kín — phần 1 xây dựng lý thuyết, phần 2 giải quyết rào cản thực tế để lý thuyết đó có thể hoạt động. Không có phần nào có thể đứng độc lập mà không cần phần kia.
327
+
328
+ ---
329
+
330
+ ### Đóng góp 1: Khung Định tuyến Phổ Phi tham số
331
+
332
+ > *Tổng hợp từ C1, C2, C3 — một lập luận thống nhất, không phải ba thủ thuật riêng biệt.*
333
+
334
+ **Vấn đề trung tâm:** Các phương pháp CL trước đây (GainLoRA, O-LoRA) coi routing và bảo vệ là hai bài toán độc lập, dẫn đến vòng lặp xấu: routing parameter trôi dạt → GPM phải bảo vệ routing → subspace của task learning bị thu hẹp → routing lại yếu hơn.
335
+
336
+ **Đóng góp:** Chúng tôi hình thức hóa và chứng minh rằng **bảo vệ không gian con trực giao và routing phân biệt là hai biểu hiện kép của cùng một cấu trúc phổ** (Định lý 1). Từ tính đối ngẫu này, chúng tôi dẫn xuất cơ chế routing hoàn toàn phi tham số: mỗi input được định tuyến đến expert có spectral affinity cao nhất với subspace đặc trưng của expert đó — không cần tham số học, không cần replay, không tốn GPM overhead cho routing infrastructure.
337
+
338
+ **Đảm bảo lý thuyết:**
339
+ - Routing margin $\geq \kappa_{\min}(t^*) - \varepsilon\, \kappa_{\max}$ — tỷ lệ thuận với chất lượng bảo vệ (Định lý 1).
340
+ - Routing weight $w_{t^*} \geq 1-\delta$ với nhiệt độ $\tau \leq m/\ln\!\bigl((T-1)/\delta\bigr)$ (Hệ quả 1).
341
+ - Capacity bound $T_{\max} \leq d/r(1-\varepsilon)$ qua lý thuyết Grassmannian packing (Hệ quả 2).
342
+ - Routing hoàn toàn bất biến qua thời gian: $h$ từ frozen embedding table, $\mathcal{S}_t$ đóng băng sau training (Mệnh đề 1).
343
+
344
+ **Tại sao không phải đơn giản hoá mà là tiến bộ lý thuyết:** Kết quả này cho thấy các kiến trúc như GainLoRA đang giải quyết một bài toán không tồn tại (routing parameter learning). Chúng tôi chứng minh rằng bảo vệ tốt ↔ routing tốt — hai bài toán hóa ra là *một*.
345
+
346
+ ---
347
+
348
+ ### Đóng góp 2: Tối ưu hóa Không gian con Dựa trên Dữ liệu
349
+
350
+ > *Tổng hợp từ C5 — giải quyết rào cản thực tế làm Đóng góp 1 sụp đổ lúc runtime.*
351
+
352
+ **Vấn đề trung tâm:** Đóng góp 1 yêu cầu $h \in \mathrm{span}(V_{t^*})$ — tức là expert $t^*$ phải học được các biến đổi có ý nghĩa từ dữ liệu task. Điều này phụ thuộc vào chất lượng của $A_t$. InfLoRA (và GainLoRA) khởi tạo $A_t$ ngẫu nhiên rồi chiếu vào null-space — một điểm *tùy ý* trên Grassmannian $\mathrm{Gr}(r, d - N_{\text{protected}})$ với dimension $r(d - N_{\text{protected}} - r)$ rất lớn. Khi null-space co lại theo tasks, xác suất ngẫu nhiên bắt đúng hướng task-relevant tiệm cận về 0.
353
+
354
+ **Đóng góp:** Chúng tôi phát biểu khởi tạo $A_t$ như **bài toán Constrained PCA trên Grassmannian bị giới hạn** và cung cấp lời giải dạng đóng:
355
+
356
+ $$\max_{A_t} \;\text{tr}(A_t\, Q C_t Q\, A_t^T) \quad \text{s.t.} \quad A_t A_t^T = I_r \;\Rightarrow\; A_t = \text{top-}r\text{ eigenvectors của } QC_tQ$$
357
+
358
+ $A_t$ này đảm bảo capture **variance task-relevant tối đa** trong null-space có sẵn — biến vấn đề ngẫu nhiên thành vấn đề tất định. Tuân thủ zero-replay vì $C_t$ tính từ dữ liệu task *hiện tại* (không phải cũ), cùng logic với GPM bases đã được chấp nhận trong InfLoRA.
359
+
360
+ **Vòng lặp khép kín với Đóng góp 1:** $A_t$ tốt hơn → $B_t$ học trong subspace task-relevant → $\sigma_{t,i}$ lớn hơn sau training → $\kappa_{\min}(t^*)$ trong Định lý 1 tăng → routing margin tăng → Đóng góp 1 hoạt động như lý thuyết dự đoán.
361
+
362
+ ---
363
+
364
+ > **C4 (gradient preconditioning)** là chi tiết triển khai kỹ thuật cần thiết để sửa điều kiện ma trận sau projection, không phải đóng góp lý thuyết. Xem §4 để biết chi tiết.
365
+
366
+ ---
367
+
368
+ ## 7. Pipeline Huấn luyện
369
+
370
+ ### Task 1 (`--run_single True`)
371
+ 1. Load pretrained model + fresh LoRA ($A$: Kaiming, $B$: zeros).
372
+ 2. Huấn luyện chuẩn (chỉ `lora_B`) — single expert, không routing.
373
+ 3. Sau training: tính $\mathcal{S}_1$ (thin SVD) + GPM bases (ESA threshold).
374
+ 4. Lưu: LoRA weights, spectral signatures, GPM reg files.
375
+
376
+ ### Task $t \geq 2$
377
+ 1. Load model + fresh LoRA; load LoRA weights và spectral signatures cũ.
378
+ 2. **[C5 — MỚI]** Pre-task forward pass (200 batch, no grad):
379
+ - Thu thập activation covariance $C_t$ của inputs task $t$
380
+ - Tính projected covariance: $\tilde{C}_t = Q C_t Q$ ($Q = I - P_{\text{old}}$)
381
+ - Eigenvectors của $\tilde{C}_t$ → khởi tạo $A_t$ (thay thế random Kaiming)
382
+ 3. InfLoRA: chuẩn hoá $A_t$ (đã nằm trong null-space từ eigenvector decomposition).
383
+ 4. Huấn luyện `lora_B` với spectral affinity routing + adaptive bias $\beta(n)$ + C4.
384
+ 5. Sau training: tính $\mathcal{S}_t$ (cả inference routing và storage) + cập nhật GPM bases.
385
+ 6. Lưu tất cả artifacts cho task tiếp theo.
386
+
387
+ ---
388
+
389
+ ## 8. Mapping Lý thuyết – Implementation
390
+
391
+ | Lý thuyết | Implementation | File |
392
+ |-----------|---------------|------|
393
+ | Spectral signature $\mathcal{S}_t$ | `compute_spectral_signatures()` (thin QR+SVD) | `t5_specroute.py` |
394
+ | Spectral affinity $\alpha_t(h)$ (inference) | σ²-weighted Rayleigh quotient | `compute_spectral_routing()` |
395
+ | A-row proxy $\alpha_t^{\mathrm{train}}$ (training) | A-row fit + adaptive bias $\beta(n)$ | `compute_spectral_routing()` |
396
+ | Symmetric inference SVD | `prepare_inference_routing()` → SVD của $B_t A_t$ | `t5_specroute.py` |
397
+ | Routing $w = \mathrm{softmax}(\alpha / \tau)$ | `torch.softmax(fit_scores / temp)` | `compute_spectral_routing()` |
398
+ | Drift-free input $h$ | `inputs_embeds = embed_tokens(input_ids)` → mean-pool | `T5Stack.forward()` |
399
+ | GPM + InfLoRA null-space | `get_reg_matrix()` | `cl_trainer_specroute.py` |
400
+ | Dynamic ESA threshold | `(1−ε₀)·t/T + ε₀` | `cl_trainer_specroute.py` |
401
+ | C4: Preconditioner | `precompute_preconditioners()` → eigendecomposition | `cl_trainer_specroute.py` |
402
+ | C4: Spectral entropy reg | `_compute_spectral_entropy_loss()` → QR trick | `cl_trainer_specroute.py` |
403
+ | **C5: Data-informed init** | **`pre_task_data_collection()` → `eigh(Q@C@Q)` → set `lora_A.data`** | **`cl_trainer_specroute.py`** |
404
+
405
+ ---
406
+
407
+ ## 9. Thiết lập Thí nghiệm
408
+
409
+ | Hạng mục | Giá trị |
410
+ |----------|---------|
411
+ | Mô hình | `google/flan-t5-small` (60M) / `flan-t5-large` (783M) |
412
+ | Benchmarks | SuperNI (15 tasks, 2 orderings), Long (15 tasks, 2 orderings) |
413
+ | Metrics | AP (Average Performance, ↑), FT (Forgetting, ↓) |
414
+ | LoRA | $r = 8$, target=Q+V, InfLoRA (chỉ B trained, A đóng băng) |
415
+ | Routing | $\tau = 1.0$, $\alpha_{\mathrm{target}} = 0.8$, adaptive $\beta(n)$ (train); SVD đối xứng (inference) |
416
+ | ESA | $\varepsilon_0 = 0.995$ (dynamic) |
417
+ | C4 | $\lambda_{\text{entropy}} = 0.01$, preconditioning on, $\epsilon = 10^{-6}$, warmup = 10% |
418
+ | **C5** | **N_batch_warmup = 200, dùng `torch.linalg.eigh` trên projected covariance** |
419
+ | Precision | fp32 + gradient checkpointing |
420
+ | So sánh | Batch size, LR, scheduler khớp chính xác ROOT (GainLoRA) |
421
+
422
+ ---
423
+
424
+ ## 10. File Map
425
+
426
+ | File | Vai trò |
427
+ |------|---------|
428
+ | `src/t5_specroute.py` | T5Stack + spectral routing + thin SVD |
429
+ | `src/t5_gainlora_inflora.py` | LoRALayer, T5Attention, T5Block (shared base) |
430
+ | `src/cl_trainer_specroute.py` | Trainer: GPM, InfLoRA, ESA, C4, C5, training_step |
431
+ | `src/run_t5.py` | Entry: model loading, parameter freezing |
432
+ | `gen_script_*_specroute*.sh` | Experiment scripts |
improve_gainlora/src/cl_trainer_specroute.py CHANGED
@@ -89,7 +89,8 @@ class SpecRoute_Trainer(Seq2SeqTrainer):
89
  eval_dataset=None, tokenizer=None, data_collator=None,
90
  compute_metrics=None, callbacks=None,
91
  lambda_entropy=0.0, use_preconditioning=False,
92
- precond_eps=1e-6, entropy_warmup_ratio=0.1):
 
93
  super().__init__(
94
  model=model, args=args, train_dataset=train_dataset,
95
  eval_dataset=eval_dataset, tokenizer=tokenizer,
@@ -99,12 +100,15 @@ class SpecRoute_Trainer(Seq2SeqTrainer):
99
  self.task_order = task_order
100
  self.cur_task_id = cur_task_id
101
  self._grad_check_done = False
102
- # C4: Spectrally-Conditioned LoRA Training
103
- self.lambda_entropy = lambda_entropy
104
  self.use_preconditioning = use_preconditioning
105
  self.precond_eps = precond_eps
106
  self.entropy_warmup_ratio = entropy_warmup_ratio
107
  self._precond_matrices = {}
 
 
 
108
 
109
  def _save(self, output_dir=None, state_dict=None):
110
  # T5 shared embeddings are incompatible with safetensors; force pytorch format
@@ -177,20 +181,14 @@ class SpecRoute_Trainer(Seq2SeqTrainer):
177
  lora.lora_B.grad.data.nan_to_num_(nan=0.0)
178
 
179
  def training_step(self, model, inputs, **kwargs):
180
- """CE training step + C4 spectral entropy regularization + preconditioning."""
 
181
  model.train()
182
  inputs = self._prepare_inputs(inputs)
183
 
184
  with self.compute_loss_context_manager():
185
  loss = self.compute_loss(model, inputs)
186
 
187
- # C4: Spectral entropy regularization (after warmup)
188
- if self.lambda_entropy > 0:
189
- warmup_steps = int(self.entropy_warmup_ratio * self.state.max_steps)
190
- if self.state.global_step >= warmup_steps:
191
- ent_loss = self._compute_spectral_entropy_loss()
192
- loss = loss + self.lambda_entropy * ent_loss
193
-
194
  if self.args.n_gpu > 1:
195
  loss = loss.mean()
196
 
@@ -233,6 +231,56 @@ class SpecRoute_Trainer(Seq2SeqTrainer):
233
 
234
  return loss.detach()
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  def load_previous_reg_matrix(self):
237
  """Load LoRA GPM bases from previous task. No trans_input GPM needed."""
238
  log_path = os.path.dirname(self.args.output_dir)
@@ -280,7 +328,31 @@ class SpecRoute_Trainer(Seq2SeqTrainer):
280
  ).to("cuda:0")
281
  self.feature_mat.append(feature_mat)
282
 
283
- # Project lora_A into null-space (InfLoRA constraint)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  for index in self.feature_list[i].keys():
285
  module.lora_q.lora_A.data[:, index*module.step:(index+1)*module.step].copy_(
286
  module.lora_q.lora_A.data[:, index*module.step:(index+1)*module.step]
 
89
  eval_dataset=None, tokenizer=None, data_collator=None,
90
  compute_metrics=None, callbacks=None,
91
  lambda_entropy=0.0, use_preconditioning=False,
92
+ precond_eps=1e-6, entropy_warmup_ratio=0.1,
93
+ n_batches_c5=200):
94
  super().__init__(
95
  model=model, args=args, train_dataset=train_dataset,
96
  eval_dataset=eval_dataset, tokenizer=tokenizer,
 
100
  self.task_order = task_order
101
  self.cur_task_id = cur_task_id
102
  self._grad_check_done = False
103
+ # C4.1: Gradient preconditioning (C4.2 entropy reg removed in V7)
104
+ self.lambda_entropy = 0.0 # disabled in V7 — conflicts with C5 philosophy
105
  self.use_preconditioning = use_preconditioning
106
  self.precond_eps = precond_eps
107
  self.entropy_warmup_ratio = entropy_warmup_ratio
108
  self._precond_matrices = {}
109
+ # C5: Data-Informed Subspace Initialization
110
+ self.n_batches_c5 = n_batches_c5
111
+ self._task_covariance = [] # list of {chunk_index: cov_tensor} per layer
112
 
113
  def _save(self, output_dir=None, state_dict=None):
114
  # T5 shared embeddings are incompatible with safetensors; force pytorch format
 
181
  lora.lora_B.grad.data.nan_to_num_(nan=0.0)
182
 
183
  def training_step(self, model, inputs, **kwargs):
184
+ """CE training step + C4.1 gradient preconditioning.
185
+ C4.2 spectral entropy regularization removed in V7 (conflicts with C5)."""
186
  model.train()
187
  inputs = self._prepare_inputs(inputs)
188
 
189
  with self.compute_loss_context_manager():
190
  loss = self.compute_loss(model, inputs)
191
 
 
 
 
 
 
 
 
192
  if self.args.n_gpu > 1:
193
  loss = loss.mean()
194
 
 
231
 
232
  return loss.detach()
233
 
234
+ # ================================================================
235
+ # C5: Data-Informed Subspace Initialization
236
+ # ================================================================
237
+
238
+ def pre_task_data_collection(self):
239
+ """C5: Collect activation covariance for the current task.
240
+ Must be called BEFORE get_reg_matrix().
241
+ Stores per-layer, per-chunk covariance matrices in self._task_covariance.
242
+ These are used in get_reg_matrix() to initialize A_t optimally.
243
+ """
244
+ # Reset module covariance accumulators and enable collection
245
+ for module in self.model.modules():
246
+ if hasattr(module, 'get_feature'):
247
+ module.get_feature = True
248
+ module.stage = 0
249
+ for index in range(module.index):
250
+ module.matrix[index] = torch.zeros(
251
+ module.step, module.step, device='cuda'
252
+ )
253
+ module.n_matrix[index] = 0
254
+
255
+ print(f'[C5] Collecting activation covariance ({self.n_batches_c5} batches)...')
256
+ train_dataloader = self.get_train_dataloader()
257
+ if isinstance(train_dataloader, DataLoader) and isinstance(
258
+ train_dataloader.sampler, DistributedSampler
259
+ ):
260
+ train_dataloader.sampler.set_epoch(42)
261
+
262
+ with torch.no_grad():
263
+ for step, inputs in enumerate(train_dataloader):
264
+ if step >= self.n_batches_c5:
265
+ break
266
+ inputs = self._prepare_inputs(inputs)
267
+ # Drop labels — we only want activations, not loss
268
+ inputs.pop('labels', None)
269
+ self.model(**inputs)
270
+
271
+ # Harvest and store covariance
272
+ self._task_covariance = []
273
+ for module in self.model.modules():
274
+ if hasattr(module, 'get_feature'):
275
+ cov = {}
276
+ for index in range(module.index):
277
+ cov[index] = module.matrix[index].detach().float().cuda()
278
+ self._task_covariance.append(cov)
279
+ module.get_feature = False
280
+ module.stage = 0
281
+
282
+ print(f'[C5] Covariance collected for {len(self._task_covariance)} layers.')
283
+
284
  def load_previous_reg_matrix(self):
285
  """Load LoRA GPM bases from previous task. No trans_input GPM needed."""
286
  log_path = os.path.dirname(self.args.output_dir)
 
328
  ).to("cuda:0")
329
  self.feature_mat.append(feature_mat)
330
 
331
+ # C5: Data-Informed Subspace Initialization
332
+ # Replace random A_t with optimal subspace from Constrained PCA.
333
+ # Eigenvectors of Q@C_t@Q are in null(P_old) by construction,
334
+ # so the InfLoRA projection below becomes a numerical near-no-op.
335
+ if self._task_covariance and i < len(self._task_covariance):
336
+ r = module.lora_q.lora_A.data.shape[0] # LoRA rank
337
+ for index in self.feature_list[i].keys():
338
+ C_t = self._task_covariance[i][index] # [step, step]
339
+ P_old = feature_mat[index] # [step, step]
340
+ Q = torch.eye(module.step, device=P_old.device) - P_old
341
+ C_tilde = Q @ C_t.to(P_old.device) @ Q
342
+ # Enforce symmetry for numerical stability
343
+ C_tilde = (C_tilde + C_tilde.T) * 0.5
344
+ # eigh returns ascending eigenvalues; take last r (largest)
345
+ eigvals, eigvecs = torch.linalg.eigh(C_tilde.float())
346
+ top_eigvecs = eigvecs[:, -r:].flip(dims=[1]) # [step, r]
347
+ A_init = top_eigvecs.T # [r, step]
348
+ dtype = module.lora_q.lora_A.data.dtype
349
+ sl = slice(index * module.step, (index + 1) * module.step)
350
+ module.lora_q.lora_A.data[:, sl].copy_(A_init.to(dtype))
351
+ module.lora_v.lora_A.data[:, sl].copy_(A_init.to(dtype))
352
+ print(f'[C5] Layer {i+1}: A_t initialized via Constrained PCA.')
353
+
354
+ # InfLoRA null-space projection (near no-op after C5, still applied
355
+ # for numerical correctness and to enforce InfLoRA invariant exactly)
356
  for index in self.feature_list[i].keys():
357
  module.lora_q.lora_A.data[:, index*module.step:(index+1)*module.step].copy_(
358
  module.lora_q.lora_A.data[:, index*module.step:(index+1)*module.step]
improve_gainlora/src/run_t5.py CHANGED
@@ -188,7 +188,11 @@ class ModelArguments:
188
  )
189
  entropy_warmup_ratio: Optional[float] = field(
190
  default=0.1,
191
- metadata={"help": "Fraction of training steps before enabling entropy loss (C4)."},
 
 
 
 
192
  )
193
 
194
  run_single: bool = field(
@@ -948,8 +952,10 @@ def main():
948
  use_preconditioning=model_args.use_preconditioning,
949
  precond_eps=model_args.precond_eps,
950
  entropy_warmup_ratio=model_args.entropy_warmup_ratio,
 
951
  )
952
  if training_args.do_train:
 
953
  trainer.get_reg_matrix()
954
  trainer.precompute_preconditioners()
955
  else:
 
188
  )
189
  entropy_warmup_ratio: Optional[float] = field(
190
  default=0.1,
191
+ metadata={"help": "Fraction of training steps before enabling entropy loss (C4, disabled in V7)."},
192
+ )
193
+ n_batches_c5: Optional[int] = field(
194
+ default=200,
195
+ metadata={"help": "Number of training batches for C5 activation covariance collection."},
196
  )
197
 
198
  run_single: bool = field(
 
952
  use_preconditioning=model_args.use_preconditioning,
953
  precond_eps=model_args.precond_eps,
954
  entropy_warmup_ratio=model_args.entropy_warmup_ratio,
955
+ n_batches_c5=model_args.n_batches_c5,
956
  )
957
  if training_args.do_train:
958
+ trainer.pre_task_data_collection()
959
  trainer.get_reg_matrix()
960
  trainer.precompute_preconditioners()
961
  else: