Bài 3 — Adaptation: chọn update space và giữ đúng gradient path#
Điểm vào · Trước: front-end · Tiếp: layer fusion/pooling.
Mục tiêu và tiền đề#
Phân biệt frozen, linear probe, partial/full tuning, adapters, LoRA và các chế độ cập nhật khác; tự tính một LoRA update. Cần matrix/geometry, chain rule/tối ưu, teacher–student. Nội dung code dưới là pseudocode minh họa, không recipe chạy model.
1. “Linear” cần chỉ rõ tuyến tính theo đầu vào nào#
Cho representation fixed u(x) ∈ R^D. Linear probe học z = Wu + c, giữ encoder và mọi bước tạo u cố định. Mean pooling fixed có thể nằm trong u. Nếu học attention weights từ tokens rồi pool, hoặc học MLP trên u, hệ trainable đã có phi tuyến. Statistics pooling cũng phi tuyến theo tokens vì std; có thể gọi classifier tuyến tính trên fixed statistics vector, nhưng phải công bố readout ấy.
Ví dụ: h₁ = a, h₂ = b; mean fixed u = (a+b)/2, z = wu+c là affine theo (a,b). Attention học softmax(vhᵢ) rồi z = wΣαᵢhᵢ+c không affine theo tokens vì α phụ thuộc đầu vào. Tăng backend capacity có thể đọc thông tin vốn không tuyến tính, nhưng không lấy lại cue encoder đã làm mất; nối XOR/collision lớp 3.
2. Bốn công tắc độc lập và state ngoài optimizer#
| Công tắc | Tác dụng trực tiếp | Không tự bảo đảm |
|---|---|---|
| parameter.requires_grad = False | Không tích lũy gradient cho parameter ấy | Dropout tắt, buffers đứng yên, toàn graph không có gradient |
| torch.no_grad() | Không ghi backward graph trong block | Eval mode hoặc không update buffers |
| torch.inference_mode() | No backward tracking, bỏ thêm tracking overhead | Tensor sinh trong block dùng được ngay trong head training |
| module.eval() | Đặt training=False cho module/submodules | Tắt autograd hoặc freeze weights |
Đây là semantics được đối chiếu ở PyTorch 2.14 autograd notes; không tuyên bố môi trường notebook đã dùng version này. Khi head cần save features để backward, dùng no_grad cho frozen encoder thường đơn giản hơn inference tensors; nếu dùng inference_mode phải xử lý tensor theo contract, ví dụ clone thành tensor thường ngoài context.
Dropout train thay activation ngẫu nhiên; eval dùng identity. BatchNorm mặc định cập nhật running_mean/running_var trong forward train, dù affine parameters frozen và no_grad. Eval dùng running stats khi track_running_stats=True; False thì vẫn dùng batch stats. Những buffers này không phải optimizer parameters. model.train() gọi xuống children có thể bật encoder trở lại; phải quản lý encoder.eval() theo recipe. Dropout API, BatchNorm1d API.
Counterexample tự biên soạn: frozen BN có running mean 0, momentum 0,1, batch mean 10. Forward train cập nhật running mean = 0,9×0 + 0,1×10 = 1. Đã đổi state dù không có gradient. Đây là toy state update, không mô tả ViT paper có BN.
# Minh họa frozen feature extractor + trainable nonlinear backend
encoder.requires_grad_(False)
encoder.eval()
backend.train()
with torch.no_grad():
features = encoder(augmented_input)
logits = backend(features) # ngoài no_grad: backend cần graph
loss = criterion(logits, labels)
loss.backward()
# optimizer chỉ quản lý parameters của backend; zero grad theo vòng lặpSai thường gặp: bao cả backend bằng no_grad khiến loss không có graph; hoặc bao frozen block giữa các trainable adapters bằng no_grad làm đứt đường về adapter trước đó. Freeze weight W của h=Wx không có nghĩa derivative theo x bằng 0: ∂h/∂x=W vẫn cần cho tham số tạo x. Khi đổi chế độ giữa một run, còn cần clear stale grads và kiểm optimizer groups/state; requires_grad không tự sửa mọi state cũ.
3. Partial/full tuning và adapters#
Partial tuning chọn vài blocks/norms/projection học; layers frozen sau block học vẫn có thể cần backward đối với input. Full tuning mở update space lớn hơn, nhưng finite data, LR và regularization có thể làm model khai thác shortcut hoặc quên thông tin transfer. Không có thứ tự chất lượng mặc định frozen < partial < full.
Adapter kiểu bottleneck dưới đây là ví dụ để học cơ chế residual module, không đại diện mọi adapter:
V nén xuống r, ρ là activation, U mở lại D, rồi cộng residual. Học U,V với backbone fixed vẫn cần gradient đi qua backbone giữa adapters. Khối nonlinear thường không gộp thành một weight linear duy nhất. Paper adapter gốc thuộc NLP, không bằng chứng giúp detector này. Houlsby et al., §2/2.1.
4. LoRA bằng số: low-rank update, không embedding rank#
Theo Hu et al., LoRA v2 §4.1, weight W₀ shape d_out × d_in giữ fixed, học A shape r × d_in và B_L shape d_out × r:
B_L là LoRA matrix, khác nhãn B. α/r là scalar không đơn vị; rank(B_LA) ≤ r. Số params thêm r(d_in+d_out), so với d_in d_out của dense weight, chưa tính bias/modules khác. α, init, target matrices và variant phải ghi rõ.
Toy: W₀ = I₂, r = 1, α = 2, A = [1, −1], B_L = [0,5; 1], x = [3; 1]. Ax = 2; B_LAx = [1; 2]; scale 2 cho update [2; 4]. Output h = [3; 1]+[2; 4]=[5; 5]. ΔW = [[1, −1],[2, −2]], rank 1; W_eff = [[2, −1],[2, −1]] trong toy cụ thể này cũng rank 1, nhưng đó không là quy luật: chọn ΔW=[[1,0],[0,0]] và W₀=I₂ thì W_eff=diag(2,1), rank 2. Output dataset embedding rank còn phụ thuộc inputs, nhiều layers và nonlinearities.
LoRA gốc init A ngẫu nhiên, B_L = 0 nên initial ΔW=0. Với upstream gradient g=∂L/∂h, ∂L/∂B_L=(α/r)g(Ax)ᵀ; ∂L/∂A=(α/r)B_Lᵀg xᵀ. B_L=0 làm data-loss gradient của A bằng 0 ở bước đầu, B_L có thể học; nếu cả hai zero, cả hai gradients bằng 0. Weight decay có thể làm optimizer update khác data gradient.
Merge ở inference tạo W_eff khi nhánh update là linear cố định, dropout không hoạt động và variant cho phép merge. Không merge khi đang train rồi đếm update hai lần. Low trainable count giảm optimizer state nhưng không bỏ base forward/activation cần backward qua adapters; tốc độ và generalization cần đo ở cùng input/batch/budget. Không suy lợi ích NLP của LoRA thành forensic evidence.
5. Distillation, continued SSL và test-time adaptation đặt ở đâu?#
| Chế độ | Tín hiệu và update | Assumption/failure |
|---|---|---|
| Distillation | Student match teacher logits/features, có thể thêm labels | Teacher errors/shortcuts truyền sang student; compression cần architecture nhỏ thật |
| Continued SSL | Encoder/predictor/teacher update theo SSL trên domain mới | Target/augmentation có thể xóa forensic cue; exact recipe phải nối lớp 3 |
| TTA | Update bằng target stream, thường unlabeled objective | Test access khác frozen deployment; contamination, drift và order dependence |
Distillation soft targets có temperature; match teacher distributions là mục tiêu phụ, không nhãn thật thay thế hoàn hảo. TTA entropy minimization có thể làm sai tự tin hơn và cần nói tham số nào học, có reset per sample/domain không. Hinton et al., §2, Tent, method §3. Đây là nhánh đọc tự chọn; không áp dụng lên test trong lượt này.
6. Liên hệ paper và caching#
PDF §3.3 ghi encoder frozen chạy eval không gradient; backend trainable. Notebook mẫu v38 cell 3 cũng thể hiện enc.eval() trong forward và no_grad riêng encoder; outputs trống nên chỉ chứng thực source behavior, không run. Crosswalk lớp 4.
Online augmentation a đổi input thành f(a(x)); cache một view chỉ có f(x). Thường không tồn tại feature transform a' cho f(a(x))=a'(f(x)); nonlinear encoder/log-mel không commute với waveform codec/noise. Cache nhiều views cố định vẫn khác fresh sampling mỗi epoch; có thể là recipe hợp lệ khác nếu công bố. Chi phí storage: 13×128×768×4 = 5.111.808 bytes/mẫu float32 cho mọi readouts, khoảng 4,88 MiB chưa metadata; cache chỉ layer sum làm không còn khả năng học 13 weights từ readouts nếu sum bị fixed.
7. Bài tập và đáp án#
- Encoder frozen, encoder.train(), no_grad: BN buffers và Dropout có đứng yên không?
- Có trainable input adapter trước frozen linear W. Được dùng no_grad cho W forward không nếu muốn học adapter?
- W₀ có shape 768×768, LoRA r=8: hai matrix shapes và số params update là gì?
- Softmax layer sum + attentive stats + MLP của paper có phải linear probe không?
- Vì sao cache một view không xác minh lợi ích online RawBoost?
Đáp án giải thích
- Không với BN mặc định trong train; dropout còn stochastic. Freeze/no_grad khác eval.
- Không theo cách đó: chặn graph sẽ mất derivative tới input adapter. Freeze W parameters nhưng giữ graph theo input.
- A:8×768, B_L:768×8; tổng 12.288, so dense 589.824, chưa counting các weights/modules khác.
- Không: input-dependent pooling và nonlinear classifier học được. Linear classifier trên vector fixed là một thiết kế khác.
- Cached f(x) không thấy waveform views mới, có thể thiếu nuisance diversity lẫn cue erasure của augmentation. Hai recipe khác nhau, không chỉ implementation optimization.