Bạn không cần đến giải tích ma trận
Giải tích ma trận thường được nhắc đến nhiều nhờ sự phổ biến của học máy, nhưng nó đòi hỏi vô số quy tắc phức tạp phụ thuộc vào vector hàng hay cột. Một cách tiếp cận đơn giản hơn nhiều là viết thẳng các chỉ số ra và dùng phép đạo hàm thông thường — cách này luôn hiệu quả, dễ nhớ và thường nhanh hơn.
Giải tích ma trận (matrix calculus) thỉnh thoảng lại nổi lên trên mạng xã hội, chủ yếu nhờ sự phổ biến ngày càng tăng của học máy. Nó cho phép bạn lấy đạo hàm các hàm của biến vector hoặc ma trận ngay cả khi bạn không phải là người hâm mộ của vi phân tự động (automatic differentiation).
Vấn đề là nó kéo theo đủ loại quy tắc phức tạp, phụ thuộc vào việc vector của bạn là vector hàng hay vector cột, và mọi thứ còn tệ hơn khi bước sang ma trận. Còn tensor thì khỏi phải nói.
Tin tốt: bạn hoàn toàn không cần nó
Khi các nhà vật lý bắt đầu làm việc với tensor gần một thế kỷ trước, họ đã tìm ra cách dễ dàng để xử lý chuyện này: thay vì cố nghĩ ra một hệ thống để đạo hàm tensor ∂A/∂B, chỉ cần viết thẳng công thức cho A_ijk và B_ijk rồi dùng phép đạo hàm thông thường.
Cách này có ba ưu điểm lớn:
- Luôn hiệu quả, bất kể công thức của bạn có dạng gì.
- Bạn chỉ cần biết đạo hàm thông thường, không phải học thuộc thêm quy tắc mới nào.
- Thường nhanh hơn, thậm chí nhanh hơn đáng kể.
Ngược lại, giải tích ma trận chỉ hoạt động với các công thức ở những dạng rất cụ thể, và bạn phải ghi nhớ một loạt quy tắc mới để áp dụng. Kể cả khi đã nhớ hết, nó cũng chẳng tiết kiệm được bao nhiêu thời gian, nếu có.
Chỉ cần viết các chỉ số ra thôi!
Ví dụ cụ thể: hàm kích hoạt của neuron
Hãy xét hàm kích hoạt của một neuron:
activation(x) = max(0, Ax + b)
Phép max ở đây được hiểu theo từng phần tử (elementwise):
activation(x)_i = max(0, (Ax)_i + b_i)
Tức là:
activation(x)_i = 0 nếu (Ax)_i + b_i < 0
activation(x)_i = (Ax)_i + b_i trong trường hợp còn lại
Giờ chỉ cần viết thẳng phép nhân ma trận ra:
activation(x)_i = 0 nếu (Ax)_i + b_i < 0
activation(x)_i = Σ_j A_ij * x_j + b_i trong trường hợp còn lại
Lấy đạo hàm theo cách thông thường
Đạo hàm hai vế:
activation(x)_i' = 0 nếu (Ax)_i + b_i < 0
activation(x)_i' = Σ_j (A_ij' * x_j + A_ij * x_j' + b_i') trong trường hợp còn lại
Lưu ý rằng ta chưa nói đang lấy đạo hàm theo biến nào, mà chỉ dùng ký hiệu y'. Ta có ba lựa chọn:
- Đạo hàm theo x_k
- Đạo hàm theo A_kl
- Đạo hàm theo b_k
Để làm điều đó, ta chỉ cần đặt biến có dấu phẩy tương ứng bằng 1 và các biến có dấu phẩy còn lại bằng 0.
Ba kết quả, một công sức
Ví dụ, để đạo hàm theo A_kl, ta đặt A_kl' = 1, mọi A_ij' = 0, x_i' = 0 và b_i' = 0:
∂activation(x)_i / ∂A_kl = 0 nếu (Ax)_i + b_i < 0
∂activation(x)_i / ∂A_kl = x_l trong trường hợp còn lại
Xong. Với hai trường hợp còn lại:
∂activation(x)_i / ∂x_k = 0 nếu (Ax)_i + b_i < 0
∂activation(x)_i / ∂x_k = A_ik trong trường hợp còn lại
∂activation(x)_i / ∂b_k = 0 nếu (Ax)_i + b_i < 0
∂activation(x)_i / ∂b_k = 1 nếu i = k
∂activation(x)_i / ∂b_k = 0 trong trường hợp còn lại
Ta có ba kết quả với giá của một. Hãy thử so sánh với cách suy diễn bằng giải tích ma trận. Bạn có giải mã được kết quả cuối cùng của họ cho đạo hàm theo w không? Nó khó hơn bạn tưởng đấy.
Vì sao điều này quan trọng với người làm AI
Với những ai đang làm việc với học sâu, hiểu rõ cơ chế lan truyền ngược (backpropagation) ở mức chỉ số là một lợi thế thực sự. Nó giúp bạn:
- Tự kiểm chứng kết quả khi gradient trông có vẻ sai mà không rõ nguyên nhân.
- Tự tay viết các lớp (layer) hoặc hàm mất mát tùy chỉnh mà không phụ thuộc hoàn toàn vào framework.
- Tránh nhầm lẫn giữa quy ước vector hàng và vector cột — nguồn gốc của vô số lỗi shape trong PyTorch hay TensorFlow.
Dĩ nhiên, trong thực tế hằng ngày, các framework như PyTorch hay JAX đã lo giúp bạn phần lớn công việc nhờ vi phân tự động. Nhưng hiểu bản chất bên dưới vẫn là điều đáng giá, nhất là khi bạn cần gỡ lỗi hoặc tối ưu hiệu năng.
Thông điệp cuối cùng rất đơn giản: đừng học thuộc thêm quy tắc, chỉ cần viết các chỉ số ra.
