Hãy hình dung trang quản trị của một cửa hàng: người dùng tải lên một ảnh và bạn muốn gợi ý một danh mục trước khi họ lưu trang sản phẩm. Với ứng dụng của bạn, câu hỏi có vẻ đơn giản: « Đây là áo chui đầu, giày hay túi xách? » Với mô hình, nó phải học cách nhận ra các mẫu trong điểm ảnh.
Một mạng đầu tiên có thể cho kết quả đáng quan tâm nhưng lại quá tốn kém cho môi trường bạn muốn chạy nó. Vì vậy, bạn xây dựng một mạng nhỏ hơn. Nhưng nên huấn luyện nó thế nào: chỉ bằng đáp án đúng của bộ dữ liệu, hay cả dự đoán của mạng lớn?
Đó là câu hỏi của hướng dẫn này. Ở đây, chưng cất là việc huấn luyện một mô hình nhỏ, gọi là học sinh, bằng các xác suất của mô hình giáo viên, bên cạnh các nhãn đã biết. Chúng ta sẽ theo dõi sự chuyển giao này, hiểu phép tính của nó và kiểm tra liệu nó có thật sự cải thiện học sinh hay không.
Kết quả không được định sẵn: một học sinh nhỏ hơn không nhất thiết tốt hơn sau chưng cất. Trong thí nghiệm trình bày, nó thậm chí kém hơn cùng loại học sinh được huấn luyện chỉ bằng nhãn. Kết quả âm này chính là cơ hội để học cách so sánh đúng hai phương pháp.
Tải toàn bộ dự án của hướng dẫn
Những gì chúng ta xây dựng
Chúng ta xây dựng một thí nghiệm cục bộ bằng Python và Docker xoay quanh Fashion-MNIST, bộ ảnh quần áo, giày dép và phụ kiện. Trang quản trị nêu trên là một động lực cụ thể; dự án không cung cấp giao diện đó và không xác thực việc phân loại ảnh chụp thực tế từ danh mục của bạn.
Chúng ta huấn luyện và so sánh ba mô hình:
| Mô hình | Điều nó học từ dữ liệu | Vì sao giữ nó trong so sánh |
|---|---|---|
| CNN giáo viên | Gắn mỗi ảnh với nhãn của nó | Đo chất lượng của mô hình cung cấp xác suất |
| Học sinh dùng nhãn | Tìm lại nhãn với kiến trúc nhỏ hơn | Xác lập khả năng của mạng nhỏ khi không có chưng cất |
| Học sinh chưng cất | Tìm lại nhãn và đưa xác suất của mình gần xác suất giáo viên | Kiểm tra ích lợi của tín hiệu bổ sung từ giáo viên |
Hai học sinh có cùng kiến trúc và cùng số tham số, nhưng mục tiêu học của chúng khác nhau. Điều đó không có nghĩa các trọng số đã học sẽ giống hệt nhau.
Chương trình so sánh accuracy, macro-F1, số tham số, kích thước trọng số và thời gian nóng. 10 000 ảnh của bộ kiểm thử chính thức được giữ nguyên. Các bản sao trùng khớp bị loại khỏi nhóm train/validation trước khi chọn phân tầng; chúng ta sẽ quay lại vai trò của bước chuẩn bị này.
Vì vậy, chưng cất không phải là nén ZIP các trọng số, cũng không phải sao chép mạng lớn vào mạng nhỏ. Kiến trúc nhỏ đã tồn tại; chúng ta tìm cách huấn luyện nó tốt hơn. Sau khi được huấn luyện, học sinh có thể tự đưa ra dự đoán mà không cần hỏi giáo viên.
Các ví dụ số nhỏ sau đây dùng để hiểu công thức. Chúng không phải là đầu ra được ghi lại từ mô hình. Các kết quả thí nghiệm r1 được tập hợp trong phần « Kết quả thực tế và bài học ».
Các khái niệm được giải thích
Từ một ảnh đến mười điểm số
Một ảnh Fashion-MNIST có kích thước 28 × 28 pixel, thang xám. Ta có thể biểu diễn nó bằng một mảng gồm 784 cường độ. 784 giá trị này là dữ liệu đầu vào, không phải tham số của mô hình.
Một CNN, viết tắt của convolutional neural network, là mạng nơ-ron tích chập. Nó áp dụng các bộ lọc nhỏ lên nhiều vùng của ảnh. Mỗi bộ lọc kết hợp các pixel lân cận, rồi tạo ra một bản đồ kích hoạt: một mảng mới cho biết nơi nó phản ứng. Các lớp tiếp theo kết hợp các bản đồ này để xây dựng những biểu diễn khác.
Có thể liên hệ nguyên lý của một bộ lọc với xử lý ảnh, nhưng có một khác biệt thiết yếu: giá trị của các bộ lọc được học, thay vì được chọn thủ công. Tham số là các số có thể điều chỉnh này, cùng các trọng số và bias khác của mạng. Một phép tích chập dùng lại bộ lọc ở nhiều vị trí; nó không nhất thiết gán một tham số riêng cho từng pixel.
Ở cuối mạng, nó tạo ra mười logit, một cho mỗi lớp. Logit là điểm số thô: nó có thể âm và mười điểm không bắt buộc cộng lại thành 1.
Softmax biến danh sách này thành một phân phối xác suất: mỗi giá trị dương và tổng của chúng bằng 1. Lớp có điểm cao nhất là dự đoán phân loại. Phân phối như vậy mô tả sự ưu tiên của mô hình; nó không chứng minh độ tin cậy của mô hình tương ứng với tần suất thành công thực tế.
Kho chính thức Fashion-MNIST mô tả các ảnh và mười lớp, trong đó có áo chui đầu, áo sơ mi và túi xách.
Vì sao truyền đi thứ gì đó ngoài đáp án đúng?
Một nhãn là lớp được mong đợi của một ảnh. Chẳng hạn, nó cho biết « áo chui đầu ». Đây là thông tin không thể thiếu, nhưng nó không mô tả những nét tương đồng có thể có với các lớp khác.
Giáo viên cung cấp một phân phối chi tiết hơn. Nó có thể gán xác suất cao cho áo chui đầu, xác suất thứ cấp cho áo sơ mi và xác suất thấp cho túi xách. Giả thuyết của chưng cất là sự phân bố này đem đến tín hiệu hữu ích cho mạng nhỏ: một số nhầm lẫn có khả năng xảy ra hơn những nhầm lẫn khác.
Nhưng giáo viên cũng có thể sai. Xác suất của nó không trở thành sự thật chỉ vì mạng của nó lớn hơn. Vì thế chúng ta giữ các nhãn, rồi đo kết quả trên các ảnh kiểm thử.
Nhiệt độ: làm các lớp thứ cấp dễ thấy hơn
Nhiệt độ T xuất hiện trước softmax: chúng ta chia các logit cho T. Với lớp i, công thức là:
p_i(T) = exp(z_i / T) / somme_j exp(z_j / T).
z_i chỉ logit của lớp; exp là hàm mũ. Mẫu số đưa tổng xác suất về 1.
Hãy lấy một ví dụ hư cấu với ba lớp, không phải mười đầu ra thực tế của dự án. Các logit là [3, 1, 0], lần lượt gắn với áo chui đầu, áo sơ mi và túi xách.
| Lớp hư cấu | Logit ban đầu | Xác suất với T=1 | Xác suất với T=3 |
|---|---|---|---|
| Áo chui đầu | 3 | 84,38 % | 53,15 % |
| Áo sơ mi | 1 | 11,42 % | 27,29 % |
| Túi xách | 0 | 4,20 % | 19,55 % |
Các phần trăm được làm tròn. Ở T=3, xác suất ít tập trung hơn vào lựa chọn đầu tiên: phân phối được làm mềm. Lớp áo chui đầu vẫn đứng đầu. Khi logit cố định, chia cho nhiệt độ dương không thay đổi thứ tự của chúng; điều đó thay đổi sự phân bố được dùng để học.
Do đó, tăng nhiệt độ không tự động làm dự đoán chính xác hơn. Nó thay đổi tín hiệu truyền cho học sinh.
Hai chỉ dẫn học, hai hạng tử mất mát
Mất mát, hay loss, là một số mà quá trình huấn luyện tìm cách giảm. Trong dự án này, nó kết hợp hai câu hỏi.
Entropy chéo, hay CE, hỏi: « Học sinh gán xác suất nào cho lớp đúng? » Với một nhãn duy nhất, với một ảnh, nó bằng âm logarit của xác suất đó. Xác suất 0,8 cho khoảng 0,2231 mất mát; xác suất 0,2 cho khoảng 1,6094. Vì vậy, gán ít xác suất hơn cho đáp án đúng sẽ tốn nhiều hơn.
Phân kỳ KL hỏi: « Phân phối của học sinh lệch khỏi phân phối của giáo viên đến mức nào? » Nó xét tất cả lớp, không chỉ lựa chọn đầu tiên. Ở đây, chiều là KL(enseignant || étudiant): giáo viên cung cấp phân phối mục tiêu. Phân kỳ này nói chung không đối xứng.
Huấn luyện kết hợp hai hạng tử này. Sau đó, lan truyền ngược, gọi là backward, tính gradient của chúng: một thay đổi nhỏ ở tham số sẽ làm mất mát thay đổi thế nào. Bộ tối ưu hóa dùng các gradient này để cập nhật trọng số. Trái lại, suy luận dùng một mạng đã huấn luyện để dự đoán mà không học từ ảnh được gửi vào.
Điều kiện Docker và GPU
Để theo dõi mã, bạn cần biết đọc hàm Python, thao tác với mảng và dùng terminal. Các lệnh giả định bạn có kiến thức cơ bản về Docker: image mô tả môi trường phần mềm, container chạy môi trường đó và Compose tổ chức các dịch vụ.
Lộ trình r1 cần Linux x86_64, Docker Compose, NVIDIA Container Toolkit và RTX 3090 24 Gio. README khuyên có 16 Gio RAM và 16 Gio đĩa, chưa tính các lớp Docker. Đây là tài nguyên được nêu cho lộ trình này; không có cấu hình CPU nào được xác thực.
RAM thuộc máy chủ; bộ nhớ video thuộc GPU. NVIDIA Container Toolkit cho phép đưa tài nguyên GPU vào Docker. Một card được Linux nhận diện là chưa đủ: check_environment.py cũng phải kiểm tra CUDA trong container.
Dịch vụ acquire tải các kho lưu trữ công khai. Dịch vụ gpu chạy các phép tính cục bộ. locks/models.lock.json khóa các kho lưu trữ và locks/environment.lock.json khóa môi trường. Các tệp này có vai trò gần giống tệp khóa phụ thuộc: chúng cố định các thành phần dự kiến để thí nghiệm không âm thầm thay đổi.
Các tài liệu tham khảo ở cuối bài giải thích cơ chế. Các phiên bản cần dùng để tái lập r1 vẫn là các phiên bản của dự án, không phải phiên bản từ một hướng dẫn khác hoặc một bản cài đặt được cập nhật tùy tiện.
Dữ liệu và hàm trung tâm
Tách ảnh học và ảnh đánh giá
Bộ Fashion-MNIST chính thức cung cấp 60 000 ảnh huấn luyện và 10 000 ảnh kiểm thử. Tập đầu tạo thành nhóm ban đầu để chuẩn bị train và validation; không được nhầm nó với kích thước cuối cùng được cấu hình cho hướng dẫn này.
Train dùng để cập nhật trọng số. Validation dùng để quan sát các lựa chọn huấn luyện. Test dùng để so sánh mô hình khi các lựa chọn đó đã được cố định. Ở đây, 10 000 ảnh của bộ kiểm thử chính thức vẫn được giữ lại.
Trước khi chọn train/validation, dự án loại các bản sao giống hệt khỏi nhóm liên quan. Sau đó việc chọn là phân tầng: nó tính đến các lớp để kiểm soát mức độ đại diện của chúng. Hai thao tác này giải quyết các vấn đề khác nhau. Cân bằng lớp không đủ để ngăn một ảnh xuất hiện nhiều lần.
Số lượng cuối cùng của train/validation và số bản sao bị loại không được nêu trong kết quả tái lập của bài này. Hãy ghi nhận chúng trong nhật ký prepare: đừng suy ra chúng chỉ từ quy mô chính thức của Fashion-MNIST.
Một mạng lớn và một mạng nhỏ, nhưng cùng đầu ra
Giáo viên có 93 962 tham số. Nó gồm ba khối tích chập với độ rộng 32, 64, 128. Học sinh có 5 130 tham số, với hai khối độ rộng 16, 32. Các độ rộng này là số kênh biểu diễn của khối, không phải kích thước ảnh đầu vào.
Dù khác biệt bên trong, mỗi mô hình phải tạo ra mười điểm ứng với cùng mười lớp, theo cùng thứ tự. Nếu không, so sánh phân phối sẽ giống như so sánh cột « áo chui đầu » của mô hình này với cột « túi xách » của mô hình kia.
Với một lô B ảnh, biểu diễn thường dùng là B × 1 × 28 × 28: ảnh, kênh đơn sắc, chiều cao, chiều rộng. Logit có dạng B × 10 và nhãn có dạng B, với một mã lớp cho mỗi ảnh. Tensor đơn giản là mảng số đa chiều mang các giá trị này trong PyTorch.
Mã của hàm mất mát
Đây là trích đoạn liên tục từ src/vision_distill/losses.py. Dù tên như vậy, đối số student và teacher ở đây là các tensor logit đã được tính, không phải đối tượng mạng. F chỉ các hàm của torch.nn.functional.
def distillation_loss(student, teacher, labels, alpha=0.5, temperature=3.0):
if temperature <= 0 or not 0 <= alpha <= 1:
raise ValueError("T>0 and 0<=alpha<=1 required")
ce = F.cross_entropy(student, labels)
target = F.softmax(teacher.detach() / temperature, dim=-1)
logp = F.log_softmax(student / temperature, dim=-1)
kl = (target * (torch.log(target.clamp_min(1e-30)) - logp)).sum(-1).mean()
return (1 - alpha) * ce + alpha * temperature**2 * kl
Điều gì vừa xảy ra? Hàm đã tính một chi phí vô hướng từ các dự đoán và nhãn. Nó không nạp mô hình, không tính dự đoán của chúng và không cập nhật trọng số. Các lệnh gọi backward() và bộ tối ưu hóa thuộc về vòng lặp huấn luyện, nằm ngoài trích đoạn này.
Đọc phép tính từng dòng
Kiểm tra đầu tiên liên quan đến các thiết lập. Nhiệt độ phải dương nghiêm ngặt và alpha nằm trong khoảng từ 0 đến 1. Việc kiểm tra tường minh này tự nó không phải là xác thực đầy đủ về hình dạng, thiết bị và giá trị số của các tensor.
ce tính lỗi so với nhãn. Nó nhận trực tiếp logit của học sinh, không chia cho nhiệt độ. Đừng áp dụng thêm softmax trước lời gọi này: tài liệu CrossEntropyLoss nêu rõ đầu vào phải chứa các điểm chưa chuẩn hóa.
target xây dựng đáp án được làm mềm của giáo viên. dim=-1 chỉ chiều cuối cùng, tức là các lớp. Softmax được áp dụng riêng cho từng ảnh trong lô.
teacher.detach() cắt đường gradient đến các logit của giáo viên. Mất mát vẫn có thể dùng giá trị của chúng, nhưng không lan ngược theo nhánh này để huấn luyện giáo viên. Đó là vai trò được mô tả của detach().
Cần phân biệt việc cắt gradient này với chế độ chạy của mạng: detach() không đặt giáo viên vào chế độ đánh giá. Hướng dẫn PyTorch chính thức về chưng cất trình bày riêng teacher.eval(), phép tính giáo viên không gradient và tối ưu hóa tham số học sinh. Trích đoạn mất mát ở đây không cho thấy vòng lặp đầy đủ đó.
logp tính logarit của các xác suất được làm mềm của học sinh. Cùng nhiệt độ được dùng cho cả hai phía. Phép tính dùng trực tiếp log_softmax, thay vì nối thủ công softmax rồi logarit.
kl so sánh hai phân phối. Gọi q là xác suất giáo viên và p là xác suất học sinh, một ảnh đóng góp:
KL(q || p) = somme_classes q × (log(q) − log(p)).
Bảo vệ clamp_min(1e-30) chặn dưới các giá trị đưa vào logarit của mục tiêu. Nó không thay toàn bộ xác suất bằng mức tối thiểu này và cũng không chuẩn hóa lại phân phối: hệ số nhân vẫn là target.
.sum(-1).mean() xác định mẫu số. Trước hết chúng ta cộng đóng góp của mười lớp cho từng ảnh, rồi lấy trung bình trên các ảnh của lô. Đây không phải trung bình trên mọi ô của mảng. Tài liệu KLDivLoss phân biệt hành vi này, tương ứng ở đây với batchmean, với phép rút gọn mean. Với mười lớp, lấy trung bình mọi ô sẽ lại chia hạng tử cho mười.
Một phép tính KL nhỏ
Để kiểm tra chiều của công thức, hãy lấy các phân phối hư cấu đã được làm mềm: q = [0,50 ; 0,25 ; 0,25] cho giáo viên và p = [0,25 ; 0,25 ; 0,50] cho học sinh.
Lớp đầu đóng góp 0,50 × log(2). Lớp thứ hai đóng góp bằng không. Lớp thứ ba đóng góp 0,25 × log(0,5), một lượng âm. Tổng của chúng xấp xỉ 0,1733.
Vì vậy, một đóng góp riêng lẻ có thể âm, dù phân kỳ tổng không âm trong số học chính xác. Khi hai phân phối giống nhau, KL bằng không. Điều đó không có nghĩa CE bằng không: giáo viên và học sinh có thể đồng ý mà không gán toàn bộ xác suất cho nhãn mong đợi.
Alpha và T² không có cùng vai trò
Dòng cuối xây dựng:
perte = (1 − alpha) × CE + alpha × T² × KL.
alpha=0 cho mục tiêu dựa trên nhãn; alpha=1 cho mục tiêu dựa trên phân phối của giáo viên. Tuy vậy, trong trích đoạn này, cả hai hạng tử vẫn được tính trước khi cộng: đặt alpha=0 không tự động loại bỏ phép tính nhánh giáo viên.
Với giá trị mặc định alpha=0.5 và temperature=3.0, công thức trở thành 0,5 × CE + 4,5 × KL. Hệ số bằng nhau giữa CE và T² × KL, không phải giữa CE và KL thô. Điều đó cũng không đảm bảo gradient có cùng độ lớn.
Vì sao có T²? Chia logit cho nhiệt độ cũng làm thay đổi gradient của hạng tử chưng cất. Hệ số này là cách bù thang đo thông dụng để giữ tín hiệu có thể so sánh; nó không bảo đảm bất biến chính xác khi nhiệt độ thay đổi. Bài báo nền tảng của Hinton, Vinyals và Dean và hướng dẫn PyTorch nêu trên trình bày cách tiếp cận này. Bài tập sẽ cho phép tách riêng điều xảy ra khi bỏ hệ số này mà không đổi T.
Cài đặt và chuẩn bị ảnh
Giải nén ZIP và mở terminal trong thư mục gốc của nó. Mọi lệnh sau đây đều bắt đầu từ cùng thư mục đó. Các lệnh ban đầu tuân theo thứ tự trong README.md và lesson/tutorial.json.
sh scripts/setup.sh
docker compose config --quiet
docker compose build acquire gpu
docker compose run --rm acquire python scripts/acquire.py --config configs/minimum.yaml
docker compose run --rm gpu python scripts/check_environment.py --config configs/minimum.yaml
docker compose run --rm gpu python -m pytest -q
setup.sh chuẩn bị dự án. config --quiet kiểm tra cấu hình Compose, rồi build xây dựng image của hai dịch vụ. Bước thu thập lấy kho lưu trữ theo các lock; kiểm tra tiếp theo xác minh CUDA trong container. Cuối cùng, pytest chạy bộ kiểm thử của dự án.
Ở giai đoạn này, bạn cần một cài đặt nhất quán và các kiểm tra thành công, chưa phải độ chính xác phân loại tốt. Hãy sửa lỗi thu thập hoặc truy cập CUDA trước khi tiếp tục.
Tiếp theo, tạo các phân vùng, kiểm tra các mạng, huấn luyện giáo viên và kiểm tra mất mát trước khi học các học sinh:
docker compose run --rm gpu python -m vision_distill.cli prepare --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli inspect-models --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli train-teacher --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli check-loss --config configs/minimum.yaml
Sau prepare, hãy xem nhật ký các split và bản sao. Sau inspect-models, hãy liên hệ hình dạng tensor với 93 962 và 5 130 tham số đã nêu: bạn phải giải thích được điều gì đi vào mỗi mạng và điều gì đi ra.
train-teacher huấn luyện mạng sau đó sẽ cung cấp các phân phối mục tiêu. check-loss kiểm tra, nhất là trong trường hợp được kiểm soát có giáo viên giống hệt, rằng giáo viên không nhận gradient từ mất mát. Kiểm tra này xác minh cơ chế; nó không chứng minh giáo viên nhận ra mọi ảnh hay học sinh sẽ hưởng lợi từ sự trợ giúp của nó.
Huấn luyện, tiếp tục và đo lường
Giờ chúng ta có dữ liệu đã chuẩn bị và giáo viên. Hãy huấn luyện hai học sinh, rồi kiểm tra việc ngắt và tiếp tục trước khi đánh giá test:
docker compose run --rm gpu python -m vision_distill.cli train-students --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli interrupt-student --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli resume-student --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli compare-resume --config configs/minimum.yaml
docker compose run --rm gpu python -m vision_distill.cli evaluate --config configs/minimum.yaml
Học sinh dùng nhãn là baseline của chúng ta, tức tham chiếu đơn giản để so sánh chưng cất. Không nên bỏ nó: chỉ so sánh giáo viên với mô hình nhỏ đã chưng cất sẽ trộn lẫn hai thay đổi, kiến trúc và phương pháp học.
Ngắt và tiếp tục kiểm soát một trạng thái đầy đủ. Checkpoint là bản lưu cho phép tìm lại trạng thái tính toán; tiếp tục học không nhất thiết chỉ là nạp lại trọng số. Cần khôi phục cả những gì quyết định các lần cập nhật và đường đi dữ liệu tiếp theo. Chi tiết trạng thái lưu thuộc về dự án, và compare-resume là kiểm tra cần xem thay vì hài lòng với một lần chạy khởi động lại mà không lỗi.
Cuối cùng, evaluate tạo các phép đo của ba mô hình trên cùng 10 000 ảnh kiểm thử chính thức. Hãy giữ các kết quả này trước khi chuyển sang bài tập.
Chỉ số trước khi đo
Độ chính xác tổng thể: có bao nhiêu ảnh được phân loại đúng?
Trong bài này, độ chính xác tổng thể chỉ accuracy, còn gọi là độ đúng:
accuracy = nombre d'images correctement classées / nombre d'images évaluées.
Trong ví dụ hư cấu 100 ảnh, 80 lớp được dự đoán đúng cho 80 %. Điều đó chưa cho biết lớp nào gây vấn đề. Hai mô hình có cùng accuracy có thể sai trên những ảnh khác nhau.
Macro-F1: xem cả từng lớp
Cẩn thận với từ ngữ: precision của một lớp dùng trong F1 không có cùng mẫu số với accuracy tổng thể.
Hãy lấy một ví dụ hư cấu. Trong các ảnh mô hình thông báo là « áo chui đầu », 8 ảnh thật sự là áo chui đầu và 2 ảnh không phải. Bộ dữ liệu có tổng cộng 12 áo chui đầu thật: do đó mô hình bỏ sót 4 ảnh.
Precision của lớp này là 8 / 10 = 0,8: trong các dự đoán « áo chui đầu », phần nào đúng? Recall là 8 / 12 ≈ 0,6667: trong các áo chui đầu thật, nó tìm được bao nhiêu phần?
F1 kết hợp hai đại lượng này bằng trung bình điều hòa:
F1 = 2 × précision × rappel / (précision + rappel).
Ở đây nó bằng 16 / 22 ≈ 0,7273. Macro-F1 sau đó tính F1 riêng cho mỗi trong mười lớp, rồi lấy trung bình không trọng số theo số lượng của chúng. Đây không phải F1 được tính từ precision trung bình và recall trung bình.
Tài liệu scikit-learn về F1 trình bày chi tiết các định nghĩa này. Nó là tham chiếu cho chỉ số ở đây, không giả định thư viện được dùng trong dự án. Macro-F1 cho cùng trọng số cho mỗi lớp, nhưng vẫn là một trung bình: phân tích lỗi theo lớp vẫn hữu ích.
Ba loại chi phí không nên nhầm lẫn
Số tham số mô tả số giá trị mà mạng chứa. Kích thước trọng số mô tả không gian mà biểu diễn đã lưu của chúng chiếm. Hai đại lượng liên quan nhưng định dạng và độ chính xác số của việc lưu trữ cũng quan trọng. Kích thước tệp không phải là phép đo đầy đủ bộ nhớ cần khi chạy.
Thời gian nóng đo việc xử lý khi mô hình đã sẵn sàng, không phải cài đặt hoặc nạp ban đầu. Thời gian nóng trên mỗi ảnh của lộ trình này không phải độ trễ mạng hay benchmark dưới tải. Do đó, nó không đủ để hứa hẹn thời gian phản hồi cho người dùng ứng dụng của bạn.
Các kết quả số bên dưới không nêu giá trị thời gian nóng. Chúng ta không thể suy ra một tăng tốc đã đo được, dù số tham số giảm mạnh.
Kết quả thực tế và bài học
Đây là các giá trị của lần chạy r1 trên 10 000 ảnh kiểm thử, với các chữ số thập phân được báo cáo cho macro-F1:
| Mô hình | Độ chính xác tổng thể | Macro-F1 |
|---|---|---|
| Giáo viên | 78,52 % | 0,7756504071911894 |
| Học sinh dùng nhãn, CE | 64,23 % | 0,6256681401207919 |
| Học sinh chưng cất | 59,03 % | 0,5716481462359492 |
Các chi phí lưu trữ và kiến trúc được báo cáo như sau. Một Mio tương ứng với 1 048 576 byte.
| Mô hình | Tham số | Kích thước trọng số, Mio |
|---|---|---|
| Giáo viên | 93 962 | 0,3612794876098633 |
| Học sinh dùng nhãn, CE | 5 130 | 0,02199268341064453 |
| Học sinh chưng cất | 5 130 | 0,02199268341064453 |
Hai học sinh có số tham số ít hơn giáo viên khoảng 18,32 lần, tức giảm khoảng 94,54 %. Tỷ số kích thước trọng số xấp xỉ 16,43. Các tỷ số này được tính từ giá trị trong bảng, không phải phép đo tốc độ.
So sánh quyết định là giữa hai học sinh: 59,03 − 64,23 = −5,20 points de pourcentage. Trên 10 000 ảnh, các tỷ lệ tương ứng 5 903 và 6 423 phân loại đúng, tức chênh lệch ròng 520. Điều đó không có nghĩa chúng ta đã xác định đúng 520 ảnh chỉ bị suy giảm: cần so sánh dự đoán từng ảnh để biết điều đó.
Macro-F1 cũng giảm. Với các thiết lập và dữ liệu này, chưng cất không cải thiện học sinh. Lợi ích về kích thước đã có ở học sinh CE; sẽ sai nếu quy nó cho sự cải thiện chất lượng do chưng cất.
Vì sao có kết quả này? Chất lượng tín hiệu giáo viên, trọng số tương đối của hai loss, nhiệt độ, năng lực của học sinh hoặc thời lượng huấn luyện là các hướng cần xem xét. Bảng không cho phép tách một nguyên nhân. Nó cũng không chứng minh nhiệt độ khác hoặc huấn luyện lâu hơn sẽ giải quyết vấn đề.
Để đi sâu hơn, hãy giữ giáo viên, baseline CE và một giao thức dữ liệu ổn định. Chọn thiết lập mới bằng validation, rồi dùng cùng test để so sánh cuối cùng các biến thể được giữ lại. Liên tục chỉnh tham số bằng cách nhìn vào test sẽ biến nó thành công cụ điều chỉnh thay vì đánh giá độc lập.
Bài tập: dự đoán, rồi chạy
Dự đoán thay đổi trước khi đụng vào phép tính
Giữ T=3 và bỏ trong suy nghĩ hệ số T². Ảnh, logit và phân phối được cố định: chỉ trọng số của hạng tử KL thay đổi.
Với alpha=0,5, chúng ta chuyển từ:
0,5 × CE + 4,5 × KL
sang:
0,5 × CE + 0,5 × KL.
Vì vậy hạng tử KL có trọng số bị chia cho 9. Trên cùng lô này, gradient của nó cũng bị chia cho 9. Nhưng gradient tổng không nhất thiết bị chia cho 9: đóng góp CE không đổi.
Để thấy vì sao, hãy lấy ví dụ sư phạm có một tham số. Đóng góp CE đã có trọng số là +1, đóng góp KL đã có trọng số là −0,9. Tổng của chúng là +0,1. Sau khi chia đóng góp thứ hai cho 9, tổng thành +1 − 0,1 = +0,9. Việc giảm một đóng góp ở đây làm tăng chuẩn gradient tổng vì trước đó hai đóng góp bù trừ nhau.
Phản ví dụ này không mô tả gradient của mô hình r1. Nó giải thích vì sao cần phân biệt chuẩn gradient KL và chuẩn gradient của mất mát hoàn chỉnh.
Một bẫy khác: giá trị mất mát tổng có thể giảm chỉ vì bạn giảm một hệ số. Với các giá trị hư cấu CE=1,2 và KL=0,1, nó sẽ từ 1,05 xuống 0,65, không cần bất kỳ cải thiện dự đoán nào. Hai số này thuộc về hai mục tiêu có trọng số khác nhau.
Chạy và diễn giải
Bây giờ hãy chạy bài tập được cung cấp:
docker compose run --rm gpu python -m vision_distill.cli exercise --config configs/exercise.yaml
So sánh chẩn đoán gradient với dự đoán của bạn. Kiểm tra mỗi chuẩn biểu thị hạng tử nào và tách sự thay đổi thang đo khỏi phản ứng của gradient tổng. Đừng biến chẩn đoán trên một batch cố định thành bằng chứng rằng độ chính xác tương lai sẽ tăng: nó không thay thế cho huấn luyện rồi evaluate.
Kết thúc bằng các hình, checkpoint và dừng dự án:
docker compose run --rm gpu python lesson/figures/plot.py
docker compose run --rm gpu python scripts/check_checkpoints.py
docker compose run --rm gpu python scripts/clean.py --scope generated --dry-run
docker compose down --remove-orphans
plot.py tạo các hình. Kiểm tra tiếp theo xem xét checkpoint. Dọn dẹp chỉ là xem trước: --dry-run không xóa gì. Dừng Compose không xóa đầu ra của dự án.
Thích nghi, sản xuất, khắc phục sự cố và dọn dẹp
Từ ảnh nhỏ đến ứng dụng của bạn
Để thích nghi thí nghiệm này, hãy bắt đầu từ hợp đồng nghiệp vụ: bạn muốn phân biệt lớp nào và lỗi nào không thể chấp nhận? Trong ví dụ trang quản trị của chúng ta, một gợi ý được nhân viên xem lại không có cùng hậu quả với phân loại tự động không kiểm soát.
Hãy xây dựng bộ dữ liệu được phép và có phiên bản. Ghi lại các biến đổi áp dụng cho ảnh và giữ riêng các phân vùng train, validation và test. Xem lỗi theo lớp và chọn ngưỡng chất lượng trước khi cố giảm trọng số. Học sinh tốt là mô hình đáp ứng hợp đồng này, không chỉ là mô hình có ít tham số nhất.
Giáo viên vẫn là một giả thuyết giám sát, không phải trọng tài không thể sai. Hãy giữ học sinh CE và chỉ thay một yếu tố mỗi lần để hiểu kết quả của thí nghiệm mới. Giấy phép và khả năng có dữ liệu cá nhân cũng phải được kiểm tra trước khi dùng ảnh của chính bạn.
Sau đó, đo mô hình đã xuất trong môi trường đích, với tiền xử lý và tải đại diện của nó. Giảm tham số không tự động dẫn đến giảm độ trễ theo tỷ lệ trên mọi phần cứng. Lộ trình CUDA nêu ở đây không xác thực triển khai CPU, di động hay trình duyệt.
Khắc phục sự cố mà không âm thầm thay đổi thí nghiệm
Nếu CUDA lỗi, hãy chạy lại kiểm tra container và theo hướng dẫn NVIDIA Container Toolkit. Sửa quyền truy cập GPU trước khi thay đổi mô hình hoặc mất mát.
Nếu việc thu thập lỗi, hãy khôi phục truy cập mạng của dịch vụ acquire, rồi chạy lại lệnh tương ứng. Đừng thay kho lưu trữ hoặc phụ thuộc đã khóa bằng phiên bản khác chỉ để né lỗi.
Nếu hai học sinh cho điểm khác nhau, trước hết hãy đọc lại định nghĩa mục tiêu của chúng, nhật ký huấn luyện và lỗi theo lớp. Kết quả kém hơn tự nó không chứng minh có lỗi tính toán: chưng cất là phương pháp cần đánh giá, không phải bảo đảm tiến bộ.
Cuối cùng, docker compose down --remove-orphans dừng dịch vụ mà không xóa đầu ra. Kịch bản dọn dẹp vẫn ở chế độ dry-run. Hãy giữ cấu hình, phép đo và checkpoint cần thiết trước khi tự nguyện xóa các tệp thử nghiệm.
Điểm cần nhớ: giảm kiến trúc, truyền một phân phối và cải thiện dự đoán là ba việc khác nhau. Hướng dẫn này cho phép bạn đo chúng riêng rẽ, kể cả khi phương pháp phức tạp hơn không tạo ra học sinh tốt hơn.
Nguồn chính thức
Các phép đo r1 ở trên là của lộ trình dự án. Các tham chiếu sau giải thích dữ liệu, công thức và API; chúng không phải những lần chạy mới của thí nghiệm này.
- PyTorch: entropy chéo và tài liệu có phiên bản đã tham khảo: logit, nhãn và phép tính CE.
- PyTorch: phân kỳ KL và tài liệu có phiên bản đã tham khảo: chiều phân kỳ và khác biệt giữa
meanvàbatchmean. - Fashion-MNIST: định dạng ảnh, các phân vùng chính thức và nhãn.
- Docker Compose: hỗ trợ GPU: đưa GPU vào các dịch vụ.
- Hinton, Vinyals và Dean — Distilling the Knowledge in a Neural Network: tham chiếu nền tảng về chưng cất phân phối.
- PyTorch — Knowledge Distillation Tutorial: học giáo viên-học sinh, nhiệt độ và kết hợp mất mát.
- PyTorch — Tensor.detach: cắt liên kết với đồ thị gradient.
- Scikit-learn — F1 score: precision, recall và trung bình macro.
- NVIDIA Container Toolkit — cài đặt: tích hợp GPU, trình điều khiển và container.