Lab 21 — Evaluation Report
Họ tên: VŨ ĐĂNG HUY MSSV: 2A202601761 Ngày: 21/08/2026
Tier: T4 Base model: unsloth/Qwen3.5-4B GPU thực tế: Tesla T4, 14.6 GB, fp16
Mọi con số dưới đây được lấy từ các artefact trong results/ của lần chạy full eval gồm 50 mẫu target và 15 mẫu regression.
1. Setup
| |
|---|
| Dataset | 250 ticket CSKH tiếng Việt → JSON triage 4 trường |
| Train / val | 225 / 25 (seed 42) |
max_length | 1024 — p95 đo được là 98 token, mức gợi ý là 256 |
MASK_MODE | assistant-only |
| Epochs / max_steps | 2 epoch / 30 optimizer step |
max_length=1024 lớn hơn mức 256 được gợi ý từ p95. Tôi giữ cấu hình cố định của tier T4 để phép đối chứng giữa bốn run dùng cùng điều kiện và chắc chắn không cắt mất phần trả lời; đổi lại, cấu hình này dùng padding/VRAM nhiều hơn mức corpus thực sự cần.
Template có giữ khối <think> không? Có. template_check.json ghi nhận cả thẻ mở và nội dung reasoning đều xuất hiện, với verdict reasoning preserved — safe to train on traces. Corpus mặc định chỉ chứa câu trả lời JSON nên valid_trace_rate=0.0 ở lần chạy này không phải bằng chứng về reasoning-trace collapse.
2. Mask proof (NB1)
| |
|---|
supervised_fraction | 0.4149 (39/94 token) |
| Câu trả lời nằm trong loss | true |
| Câu hỏi KHÔNG nằm trong loss | true |
Đoạn đầu được tính loss:
1</think>
2
3{"intent": "doi_tra", "urgency": "trung_binh", "product": "balo laptop", "sentiment": "trung_tinh"}<|im_end|>
Đoạn supervise chứa JSON của assistant và token kết thúc, trong khi phần system/user nằm trong masked_preview. Hai assert vì vậy chứng minh loss mask đúng bằng nội dung token đã giải mã, không chỉ dựa vào cờ cấu hình của thư viện.
3. Ba baseline (NB2 — đo TRƯỚC khi train)
| Run | target | regression | format | latency (ms) |
|---|
| (a) base + naive prompt | 0.0000 | 0.7578 | 0.0000 | 3144.9 |
| (b) base + optimized prompt | 0.7650 | 0.7578 | 1.0000 | 1001.4 |
| (c) LoRA fine-tune | 0.9700 | 0.5222 | 1.0000 | 1368.6 |
(b) có thật sự mạnh hơn (a) không? Có. Target tăng từ 0.000 lên 0.765, format tăng từ 0.000 lên 1.000 và latency còn giảm khoảng 2.14 giây/mẫu. Tôi không sửa OPTIMIZED_PROMPT; SHA được gatekeeper xác nhận là 719e74d3b6232053. Vì vậy mốc mà LoRA phải vượt là baseline (b) mạnh và đã được đóng băng trước khi train, không phải baseline (a) yếu.
4. Giải phẫu cấu hình sai (NB4)
| Run | vị trí | r | trainable | LR | train loss | target | s | VRAM GB |
|---|
correct | text-linear (12 module) | 16 | 32,464,896 | 1e-4 | 0.6270 | 0.9700 | 944.2 | 12.01 |
attn_only | q,v (2 module) | 283 matched | 32,456,704 | 1e-4 | 0.5380 | 0.9650 | 770.9 | 12.02 |
wrong_lr | text-linear | 16 | 32,464,896 | 1e-5 | 1.5704 | 0.0000 | 910.9 | 12.01 |
qlora | text-linear, 4-bit | 16 | 32,464,896 | 1e-4 | 0.7058 | 0.9400 | 962.3 | 7.09 |
4.1 — Vị trí adapter so với rank
attn_only có ngân sách 32,456,704 tham số, chỉ thấp hơn correct 8,192 tham số (khoảng 0.025%), nên đây là phép so sánh vị trí công bằng. Trên target, attn_only đạt 0.965 và thua nhẹ correct 0.970, có thể xem là gần hòa trên tác vụ hẹp này. Tuy nhiên thứ tự theo train loss lại ngược: attn_only có loss 0.538 thấp hơn 0.627 của correct, nhưng target vẫn thấp hơn 0.005. Kết quả cho thấy train loss không đủ để xếp hạng adapter, và tăng rank q,v lên 283 không làm attention-only vượt cách phủ toàn bộ linear text decoder; vị trí gắn adapter vẫn là biến có ý nghĩa, dù chênh lệch target trong thí nghiệm này nhỏ.
4.2 — Learning rate sai
wrong_lr chỉ giảm learning rate từ 1e-4 xuống 1e-5 nhưng final loss tăng từ 0.6270 lên 1.5704. Trên phép đo tác vụ, cấu hình này đạt target 0.000 và format 0.000, trong khi correct đạt lần lượt 0.970 và 1.000. Điều đó cho thấy LR theo thang full fine-tune quá nhỏ đối với LoRA trong ngân sách 30 step, khiến adapter gần như không học được hành vi JSON cần thiết. Nếu chỉ nhìn loss mà không biết LR, tôi có thể kết luận sai rằng LoRA hoặc bộ target module không phù hợp; phép đối chứng một biến cho thấy nguyên nhân trực tiếp là thang learning rate.
4.3 — Đánh đổi của QLoRA
QLoRA giảm peak VRAM từ 12.01 GB xuống 7.09 GB, tiết kiệm 4.92 GB, tương đương khoảng 41%. Đổi lại, target giảm từ 0.970 xuống 0.940, train loss tăng từ 0.6270 lên 0.7058 và latency tăng từ 1368.6 lên 1748.0 ms/mẫu. QLoRA vẫn giữ format 1.000 và chất lượng target khá cao, nên nó có thể hữu ích nếu VRAM là ràng buộc bắt buộc. Tuy nhiên trên T4, LoRA 16-bit đã vừa bộ nhớ và cho kết quả tốt hơn; số đo này vì vậy ủng hộ khuyến nghị không dùng QLoRA mặc định cho Qwen3.5, trừ khi khoản tiết kiệm 4.92 GB quan trọng hơn phần chất lượng và độ trễ bị mất.
5. Phán quyết (NB5)
Kết quả cổng hồi quy: FAILED
target Δ = +0.205 · regression Δ = -0.236 · valid_trace_rate = 0.00
LoRA đã học tác vụ chuyên biệt rất tốt: target tăng từ 0.765 của baseline prompt tối ưu lên 0.970, format vẫn đạt 1.000. Tuy nhiên regression giảm từ 0.7578 xuống 0.5222, tức giảm 0.2356, vượt xa ngưỡng cho phép 0.020. Vì cổng yêu cầu vừa thắng target vừa không làm mất năng lực chung, kết quả đúng phải là FAILED, dù accuracy của tác vụ CSKH tăng rõ rệt. Đây là dấu hiệu catastrophic forgetting: corpus gồm 225 mẫu train đều tập trung vào việc sinh JSON triage, không có dữ liệu replay để duy trì hành vi kiến thức phổ thông. Tôi không nới ngưỡng, sửa eval hay làm yếu prompt (b), vì các thao tác đó chỉ che giấu rủi ro triển khai. Hướng thử tiếp theo hợp lý là bổ sung 1–5% replay data đa dạng, giữ nguyên eval đã đóng băng rồi train lại để đo xem có giữ được target trong khi phục hồi regression hay không.
6. Định tính — có cả ca đúng và ca sai
qualitative.json chỉ lưu prediction rút gọn của fine-tune, không lưu raw prediction từng mẫu của baseline (b). Vì vậy cột (b) được ghi trung thực là không có artifact thay vì suy đoán output; so sánh định lượng với (b) đã được thực hiện trên đủ 50 mẫu ở mục 3.
| # | Ticket (rút gọn) | Nhãn đúng | (b) prompt | (c) fine-tune | Nhận xét |
|---|
| 1 | Máy xay sinh tố bị lỗi, gấp | san_pham_loi / cao / máy xay sinh tố / trung_tinh | Raw output không được lưu | Đúng 4/4 trường (ft_score=1.00) | ✅ FT đạt hoàn toàn |
| 2 | Balo laptop còn hàng không, hỏi cho biết thôi | hoi_thong_tin / thap / balo laptop / tich_cuc | Raw output không được lưu | Đúng 4/4 trường (ft_score=1.00) | ✅ FT đạt hoàn toàn |
| 3 | Nồi chiên không dầu, hoàn tiền, khi nào tiện | hoan_tien / thap / nồi chiên không dầu / tieu_cuc | Raw output không được lưu | Dự đoán urgency=trung_binh (ft_score=0.75) | ❌ FT sai urgency |
| 4 | Đèn bàn LED giao chậm, khi nào tiện, cảm ơn | van_chuyen / thap / đèn bàn LED / tich_cuc | Raw output không được lưu | Dự đoán urgency=trung_binh (ft_score=0.75) | ❌ FT sai urgency |
| 5 | Đèn bàn LED sai màu, khi nào tiện, hỗ trợ tốt | san_pham_loi / thap / đèn bàn LED / tich_cuc | Raw output không được lưu | Dự đoán urgency=trung_binh (ft_score=0.75) | ❌ FT sai urgency |
Mẫu chung rõ nhất ở các ca fine-tune sai là trường urgency: cả ba ticket đều chứa tín hiệu nhẹ “khi nào tiện” và nhãn đúng là thap, nhưng model thiên về trung_binh. Intent và product vẫn đúng, cho thấy lỗi không nằm ở khả năng sinh JSON mà ở ranh giới phân loại giữa urgency thấp và trung bình. Điều này gợi ý cần kiểm tra cân bằng nhãn và bổ sung thêm các ví dụ khó có cụm từ lịch sự/không gấp, thay vì tăng rank một cách chung chung.
7. Kết luận & điều tôi học được
Kết luận. Tôi chưa nên deploy trực tiếp adapter này vào môi trường tổng quát. Về tác vụ CSKH, LoRA tạo ra cải thiện lớn và có ý nghĩa: target tăng 0.205 so với base model đã được prompt tối ưu, format đạt 1.000 và các lỗi còn lại tập trung chủ yếu ở ranh giới urgency thấp/trung bình. Tuy nhiên regression giảm 0.2356, lớn hơn gần mười hai lần ngưỡng 0.020, nên adapter có nguy cơ trả lời kém ở các yêu cầu ngoài miền triage. Kết quả FAILED vì vậy là cảnh báo triển khai đúng, không phải thất bại của quy trình đo. Trong các đòn bẩy, loss mask là điều kiện nền tảng: nếu mask sai thì mọi kết quả sau đều vô nghĩa. Learning rate là đòn bẩy mạnh nhất quan sát được, vì giảm LR 10 lần làm target và format về 0. Vị trí adapter cũng quan trọng hơn việc chỉ tăng rank: attention-only r=283 có train loss thấp hơn nhưng target vẫn không vượt text-linear r=16. Cuối cùng, chất lượng/phạm vi dữ liệu là vấn đề cần giải quyết trước deployment, vì corpus chuyên biệt giúp target rất cao nhưng không bảo toàn năng lực chung. Tôi sẽ thêm replay data và ví dụ urgency khó, rồi đánh giá lại trên đúng tập đã đóng băng.
Ba điều tôi học được:
- Tôi phải giải mã phần token được supervise để chứng minh mask đúng; một cờ
assistant-only tự nó chưa phải bằng chứng.
- Train loss có thể xếp hạng sai mô hình:
attn_only có loss 0.538 tốt hơn correct 0.627 nhưng target lại thấp hơn.
- Thắng target chưa đủ để deploy; adapter tăng target lên 0.970 nhưng regression tụt xuống 0.5222 nên cổng vẫn phải FAILED.
Nếu có thêm 2 giờ nữa, tôi sẽ thử: thêm 1–5% replay data kiến thức phổ thông và tăng số ví dụ có urgency=thap, giữ nguyên seed, số step và tập eval để đo riêng ảnh hưởng của chất lượng dữ liệu.
Phụ lục — thưởng đã làm