Thêm một chút về Neural Network

Như các bạn đã biết ở phần trước thì Neural Network thật sự chỉ là một đồ thị (hay đúng hơn là một hàm số) và có các trọng số như hình dưới:

Multi-layer Perceptron Image
Deep Neural Network biểu diễn dưới dạng ma trận và vector

Hàm số "neural network" sẽ có dạng như sau:

y=ϕY(WN+1ϕN(WNϕN1ϕ1(W1x)))\mathbf{y} = \phi_Y(W_{N+1}\phi_N(W_{N}\phi_{N-1} \cdots \phi_1(W_1 \mathbf{x}) \cdots ))

Vậy để thực sự "học" được data, ta cần phải tìm ra bộ trọng số phù hợp nhất. Thế nhưng để biết như thế nào là "phù hợp nhất", ta cần định nghĩa neural network "phù hợp" với data như nào. Và ta sẽ dùng error function (hay hàm lỗi) để đánh giá độ phù hợp, hàm lỗi là hàm có input là bộ trọng số của mô hình. Sẽ có nhiều hàm lỗi khác nhau, thế nhưng thông dụng nhất sẽ là:

  • Hàm lỗi MSE (Mean-Square-Root error), thường dùng cho bài toán hồi quy (regression) (thật ra nó là kiểu quốc dân ý, cứ hồi quy là MSE, vẫn còn rất nhiều hàm khác):
E(w)=1Nn=1N(f(xn,w)+yn)2E(\mathbf{w}) = \dfrac{1}{N} \sum_{n=1}^N (f(x_n, \mathbf{w}) + y_n)^2
  • Hàm lỗi Cross-Entropy (Cross-Entropy Loss), tương tự MSE, cũng là một hàm lỗi quốc dân và được dùng cho bài toán phân loại (classification):
E(w)=n=1Nynlog(f(xn,w))E(\mathbf{w}) = - \sum_{n=1}^N y_n \log(f(x_n, \mathbf{w}))

Trong đó f(xn,w)f(x_n, \mathbf{w}) là một hàm số có bộ trọng số là w\mathbf{w} và có input là một số thực xnx_n. Còn ở đây ff của chúng ta chính là neural network, có các bộ trọng số W1,W2,,WN+1W_1, W_2, \cdots, W_{N+1} và có input là một vector x\mathbf{x}:

f(x,W1,W2,,WN+1)=ϕY(WN+1ϕN(WNϕN1ϕ1(W1x)))f(\mathbf{x}, W_1, W_2, \cdots, W_{N+1}) = \phi_Y(W_{N+1}\phi_N(W_{N}\phi_{N-1} \cdots \phi_1(W_1 \mathbf{x}) \cdots ))

Do chúng ta sẽ làm với bộ dữ liệu MNIST1 và đây là một bài toán phân loại nên mình sẽ tập trung vào hàm lỗi Cross-Entropy, formal hơn tí, ta sẽ có hàm lỗi được viết lại cho Neural Network như sau:

E(W1,,WN+1)=m=1Mymlog(f(xn,W1,,WN+1))E(W_1, \cdots, W_{N+1}) = - \sum_{m=1}^{M} \mathbf{y}_m \log(f(\mathbf{x}_n, W_1, \cdots, W_{N+1}))

trong đó xM\mathbf{x}_M là vector input thứ mm trong bộ data gồm MM quan sát2ym\mathbf{y}_m là nhãn thứ mm trong MM nhãn2.

Giờ đã có hàm lỗi để đánh giá độ phù hợp của Neural Network với data, giờ ta cần tìm "phù hợp nhất". Đúng như cái tên của nó, hàm lỗi có giá trị càng cao thì Neural Network càng không phù hợp với data, do đó việc tiếp theo cần làm là "minimizing" hay tối thiểu hàm lỗi theo trọng số, tức là tìm bộ trọng số để hàm lỗi có giá trị nhỏ nhất. Vậy ta tối thiểu hàm lỗi như nào, nếu các bạn học toán cấp 3 rồi, thì ta phải đạo hàm theo trọng số, sau đó tìm giá trị mà tại đó đạo hàm bằng 00.

Đạo hàm và Gradient Descent

Giờ ví dụ như một Neural Network gồm 1 neuron input, 1 hidden layer có 1 neuron và activation là Sigmoid, 1 output layer có 1 neuron và activation là Sigmoid, khi đó neural network có công thức là:

f(x)=ϕ(w2[ϕ(w1x)])vớiϕ(x)=11+exp(x)\begin{aligned} f(x) &= \phi(w_2[\phi(w_1x)]) \\ \text{với} \hspace{5pt} \phi(x) &= \dfrac{1}{1 + \exp(-x)} \end{aligned}

Việc tìm công thức đạo hàm cho Neural Network trên khó đúng không ? Tưởng tượng nếu ta làm việc này cho các Neural Network hiện giờ với đến hàng trăm, hàng ngàn neuron mỗi layer, và có đến hàng trăm, hàng ngàn layer.

Cách đạo hàm tìm ra công thức thường được gọi là Symbolic Differentiation. Do việc này quá khó, ta dùng một cách khác để tìm đạo hàm, ta gọi cách khác này là Automatic Differentiation, cách này sẽ tận dụng tối đa một quy tắc được gọi là Chain rule (mình không nhớ tên tiếng việt).

Chain rule

🚧 TODO: viết Chain Rule và Automatic Differentiation

Gradient Descent

Sau khi đã tính được đạo hàm của Neural Network rồi, giờ chỉ cần tìm điểm làm hàm lỗi nhỏ nhất thôi. Thế nhưng đạo hàm không phải là công thức mà chỉ là giá trị thôi nên không có chuyện biến đổi công thức để tìm được giá trị làm đạo hàm bằng 00 đâu 😭.

Vậy ta sẽ dùng thuật toán, sẽ có rất nhiều thuật toán dựa trên đạo hàm để tìm ra điểm tối ưu (điểm làm hàm lỗi nhỏ nhất) nhưng thuật toán đơn giản nhất đó là Gradient Descent. Trong mỗi lần chạy, Gradient Descent sẽ "update" trọng số bằng công thức sau:

Wnew=WoldμFWoldW_{new} = W_{old} - \mu \dfrac{\partial F}{\partial W_{old}}

Trong đó FF là hàm mà ta cần tối ưu (tìm nhỏ nhất), WnewW_{new} là weight mới và WoldW_{old} là weight cũ, còn μ\mu được gọi là learning rate. Ở trường hợp của Neural Network, với nhiều bộ trọng số WnW_{n} trong đó n=1N+1n = 1 \cdots N+1 (như ảnh đầu) thì ta phải dùng Gradient Descent lên từng trọng số ấy và hàm cần tối ưu ở đây là hàm lỗi EE:

W1_new=W1μEW1W2_new=W2μEW2WN+1_new=WN+1μEWN+1\begin{aligned} W_{1\_{new}} &= W_{1} - \mu \dfrac{\partial E}{\partial W_{1}} \\ W_{2\_{new}} &= W_{2} - \mu \dfrac{\partial E}{\partial W_{2}} \\ &\cdots \\ W_{{N+1}\_new} &= W_{N+1} - \mu \dfrac{\partial E}{\partial W_{N+1}} \\ \end{aligned}

References

  1. An Introduction to Neural Networks, Neural Networks and Deep Learning: A Textbook,
    Aggarwal, Charu.
    Springer International Publishing, 2023,
    https://doi.org/10.1007/978-3-031-29642-0_1
  2. The Backpropagation Algorithm, Neural Networks and Deep Learning: A Textbook,
    Aggarwal, Charu.
    Springer International Publishing, 2023,
    https://doi.org/10.1007/978-3-031-29642-0_2

Footnotes

  1. https://www.kaggle.com/datasets/hojjatk/mnist-dataset

  2. Quan sát (hay observation) là cách gọi cho một "dữ liệu", ví dụ như ta có một tập dữ liệu gồm NN lần mua bánh, mỗi lần sẽ mua một cái bánh khác nhau, nên 1 lần mua được gọi là một "quan sát", ngoài ra tương ứng với mỗi quan sát là một nhãn (hay label), ví dụ như cái bánh ta mua là bánh bò hay bánh tiêu (nhãn bánh bò, nhãn bánh tiêu). Đây được gọi là học có giám sát (supervised learning), bởi vì với mỗi quan sát ta sẽ có mỗi nhãn, và dựa trên những quan sát với nhãn ấy, mục đích của ta là dự đoán nhãn cho một quan sát mới. 2