Bài 10: Các kỹ thuật cơ bản trong deep learning | Deep Learning cơ bản
 

Bài 10: Các kỹ thuật cơ bản trong deep learning

| Posted in Deep Learning cơ bản

Bài này mình tổng hợp một số kĩ thuật để train model tốt hơn, cũng như một số khái niệm bạn sẽ gặp khi làm việc với deep learning. Đầu tiên mình nói về tầm quan trọng của vectorization, tiếp mình sẽ nói về kĩ thuật mini-batch gradient descent với lượng dữ liệu lớn. Sau đó mình nói về bias, variance, cách đánh giá bias-variance trong model và một số biện pháp để giải quyết vấn đề high bias, high variance. Mình có giải thích về kĩ thuật dropout để tránh overfitting. Phần cuối mình nói về vanishing và exploding gradient, cũng như giới thiệu một số hàm activation function phổ biến và cách chọn hàm activation.

Vectorization

Ngay từ bài đầu tiên về linear regression, mình đã giới thiệu về việc biểu diễn và tính toán dưới dạng vector. Việc biểu diễn bài toán dưới dạng vector như vậy gọi là vectorization. Nó không chỉ giúp code gọn lại mà còn tăng tốc độ tính đoán một cách đáng kể khi thực hiện các phép tính trên vector, ma trận so với for-loop.

Bạn sẽ thấy nếu dùng for-loop mất hơn 4s để nhân 2 vector trong khi dùng thư viện numpy để tính chỉ mất 0.01s. Tại sao lại như thế nhỉ?

Giả sử bạn có 10 tấn hàng cần vận chuyển từ A đến B và bạn có một xe tải với khả năng chở được 5 tấn mỗi lần. Vậy nếu chất đầy hàng mỗi lần chở thì chỉ cần 2 lần chạy là chuyển hết số hàng. Tuy nhiên nếu mỗi lần bạn chỉ chất 1 tấn hàng lên xe để chở đi thì xe cần đi tới 10 lần để chuyển hết số hàng.

Tương tự như vậy, khi nhân 2 vector ở trên bạn cần thực hiện 10000000 phép tính nhân 2 số. Giả sử máy tính có thể tính được tối đa 1000 phép tính nhân một lúc. Việc bạn dùng for-loop giống như mỗi thời điểm bạn chỉ yêu cầu máy tính thực hiện một phép nhân, nên để nhân 2 vector sẽ cần
10000000 đơn vị thời gian. Tuy nhiên thư viện numpy sẽ tối ưu việc tính toán bằng cách yêu cầu máy tính thực hiện 1000 phép tính một lúc, tức là chỉ cần \displaystyle\frac{10000000}{1000} = 10000 đơn vị thời gian để hoàn thành phép nhân 2 vector. Vậy nên là việc vectorization thông thường sẽ tính toán nhanh hơn.

Mini-batch gradient descent

Mini-batch gradient descent là gì

Ở trong thuật toán gradient descent, tại bước thứ hai khi ta tính đạo hàm của loss function với các biến. Trong bài linear regression, ta dùng tất cả các dữ liệu trong dataset để tính đạo hàm rồi cập nhật bước 2:

Thuật toán gradient descent chạy tốt nhưng số lượng dữ liệu trong training set chỉ là 30. Tuy nhiên nếu dữ liệu có kích thước lớn như ảnh và số lượng lớn hơn ví dụ 5000 thì việc tính đạo hàm với loss function với toàn bộ dữ liệu sẽ rất tốn thời gian. Và mini-batch gradient descent ra đời để giải quyết vấn đề đấy.

Dựa vào số lượng dữ liệu cho mỗi lần thực hiện bước 2 trong gradient descent là người ta chia ra làm 3 loại:

  • Batch gradient descent: Dùng tất cả dữ liệu trong training set cho mỗi lần thực hiện bước tính đạo hàm.
  • Mini-batch gradient descent: Dùng một phần dữ liệu trong training set cho mỗi lần thực hiện bước tính đạo hàm.
  • Stochastic gradient descent: Chỉ dùng một dữ liệu trong training set cho mỗi lần thực hiện bước tính đạo hàm.

Ví dụ điểm thi đại học trung bình của một trường trung học phổ thông là 24 điểm. Batch gradient descent giống như tính điểm trung bình tất cả học sinh thi đại học năm nay của trường, con số sẽ tương đối gần 24, ví dụ 24,5. Mini-batch sẽ chọn ngẫu nhiên một số học sinh, ví dụ 32 học sinh để tính điểm trung bình thì điểm trung bình sẽ xa 24 hơn ví dụ 22. Tuy nhiên, Stochastic giống như chỉ chọn một học sinh làm điểm trung bình, thì lúc này điểm trung bình có thể khác xa con số 24 rất nhiều, ví dụ 18 hoặc 29. Việc điểm trung bình ở mini-batch hay stochastic khác so với điểm trung bình toàn trường gọi là nhiễu trong dữ liệu. Hay giải thích đơn giản là chỉ lấy 1 hoặc một phần dữ liệu thì không thể mô tả hết được tất cả dữ liệu.

Do đó hàm loss-function với hệ số learning_rate phù hợp thì batch gradient descent theo epoch sẽ giảm đều đặn. Vì có nhiễu trong dữ liệu nên mini-batch thì vẫn giảm nhưng có dao động và stochastic có giảm nhưng dao động cực kì lớn.

Nguồn: Andrew Ng Machine Learning course (Coursera)

Hình dưới là biểu diễn biệc cập nhật hệ số trong gradient descent, điểm đỏ là giá trị nhỏ nhất ta cần tìm, các điểm ở ngoài cùng là giá trị khởi tạo của hệ số trong gradient descent. Ta có thể thấy vì không có nhiễu nên batch gradient descent thì hệ số cập nhật trực tiếp theo 1 đường thẳng. Mini-batch thì mất nhiều thời gian hơn và còn đi chệch hướng tuy nhiên thì vẫn đến được điểm đỏ. Còn stochastic thì đi khá lòng vòng để đến được điểm đỏ và vì dữ liệu quá nhiễu nên có thể thuật toán gradient descent chỉ quanh điểm đỏ mà không đến được điểm đỏ (minimum point).

Nguồn: Andrew Ng Machine Learning course (Coursera)

Batch gradient descent thường được dùng khi số lượng dữ liệu trong traning set nhỏ hơn 2000. Với lượng dữ liệu lớn thì mini-batch gradient descent được sử dụng. Nó có thể giải quyết được vấn đề lượng dữ liệu quá lớn như trong batch gradient descent; hơn nữa đỡ nhiễu và có thể dùng vectorization so với stochastic gradient descent nên thường được sử dụng trong deep learning.

Các thông số trong bini-batch gradient descent

Ví dụ code trong bài 7, trong bài toán phân loại chữ số cho dữ liệu MNIST

# 7. Thực hiện train model với data
H = model.fit(X_train, Y_train, validation_data=(X_val, Y_val),
          batch_size=32, epochs=10, verbose=1)

X_train, Y_train là dữ liệu và label cho training set. Tương tự X_val, Y_val là dữ liệu cho validation set.

batch_size: Là size trong mini-batch gradient descent, nghĩa là dùng bao nhiêu dữ liệu cho mỗi lần tính và cập nhật hệ số.

steps_per_epoch: Là bao nhiêu lần thực hiện bước 2 trong gradient descent trong mỗi epoch. Mặc định sẽ là số lượng dữ liệu chia cho batch_size. Hiểu đơn giản là mỗi epoch sẽ dùng hết các dữ liệu để tính gradient descent.

epochs: số lượng epoch thực hiện trong quá trình traning.

Vậy thực sự số lần thực hiện bước 2 trong gradient descent trong quá trình traning là: epochs * steps_per_epoch.

Lời khuyên:

  • Batch_size nên được chọn là số mũ của 2 ví dụ 16, 32, 64, 128 để CPU/GPU tính toán tốt hơn. Giá trị mặc định là 32.
  • Nên vẽ đồ thị loss/epoch để chọn batch_size phù hợp.

Bias và variance

Bias, variance là gì

Bias: nghĩa là độ lệch, biểu thị sự chênh lệch giữa giá trị trung bình mà mô hình dự đoán và giá trị thực tế của dữ liệu.

Variance: nghĩa là phương sai, biểu thị độ phân tán của các giá trị mà mô hình dự đoán so với giá trị thực tế.

Giá trị thật dữ liệu (ground truth) ở giữa tâm các đường tròn. Các dấu X là các giá trị dự đoán. Ta thấy nếu high bias thì giá trị dự đoán rất xa tâm. Tuy nhiên nếu high variance thì các giá trị dự đoán phân tán rộng dẫn đến việc ra giá trị thực tế. => Ta mong muốn low bias và low variance.

Đây là bài toán logistic regression, cần tìm đường phân chia dữ liệu.

  • Ở hình 1, thì đường phân chia có khá nhiều điểm bị lỗi => sự chênh lệch giữa mô hình dự đoán và giá trị thực tế của dữ liệu cao => high bias, hay còn được gọi là underfitting, ý hiểu là mô hình hiện tại đơn giản hơn và chưa mô tả được mô hình của dữ liệu thực tế.
  • Ở hình 2, đường phân chia vẫn có lỗi nhưng ở mức chấp nhận được và nó có thể mô tả dữ liệu => low bias, low variance.
  • Ở hình 3, đường phân chia có thể dự đoán đúng tất cả các điểm trong training set nhưng vì nó không tổng quát hóa mô hình dữ liệu thực sự nên khi áp dụng dự đoán vào validation set thì sẽ có rất nhiều lỗi => high variance hay còn được gọi là overfitting, ý hiểu là mô hình hiện tại thực hiện tốt với dữ liệu trong traing set nhưng dự đoán không tốt với validation set.

Thực ra khái niệm high bias và high variance khá trìu tượng và nhiều lúc dùng nhầm lẫn giữa thống kê và machine learning. Nên khái niệm hay được dùng hơn là underfitting overfitting.

Các điểm màu xanh là traning set, điểm màu đỏ là validation set

Ví dụ khi luyện thi đại học, nếu bạn chỉ luyện khoảng 1-2 đề trước khi thi thì bạn sẽ bị underfitting vì bạn chưa hiểu hết cấu trúc, nội dung của đề thi. Tuy nhiên nếu bạn chỉ luyện kĩ 50 đề thầy cô giáo bạn soạn và đưa cho thì khả năng bạn sẽ bị overfitting với các đề mà thầy cô giáo các bạn soạn mà khi thi đại học có thể điểm số của các bạn vẫn tệ.

Bias, variance tradeoff

Nếu model quá đơn giản thì ta sẽ bị high bias và low variance. Tuy nhiên nếu model quá phức tạp thì sẽ bị high variance và low bias. Đấy là bias, variance tradeoff. Do đó để train được model tốt ta cần cân bằng giữa bias và variance.

Đánh giá bias and variance

Có 2 thông số thường được sử dụng để đánh giá bias and variance của mô hình là training set error và validation set error. Ví dụ error (1-accuracy) trong logistic regression.

Train set error1%15%15%0.5%
Val set error11%16%30%1%
High varianceHigh biasHigh bias
High variance
Low bias
Low variance

Ta mong muốn model là low bias và low variance. Cùng xem một số cách để giải quyết vấn đề high bias hoặc high variance nhé.

Giải quyết high bias (underfitting): Ta cần tăng độ phức tạp của model

  • Tăng số lượng hidden layer và số node trong mỗi hidden layer.
  • Dùng nhiều epochs hơn để train model.

Giải quyết high variance (overfitting):

  • Thu thập thêm dữ liệu hoặc dùng data augmentation
  • Dùng regularization như: L1, L2, droupout

Dropout

Dropout là gì

Dropout với hệ số p nghĩa là trong quá trình train model, với mỗi lần thực hiện cập nhật hệ số trong gradient descent ta ngẫu nhiên loại bỏ p% số lượng node trong layer đấy, hay nói cách khác là dữ lại (1-p%) node. Mỗi layer có thể có các hệ số dropout p khác nhau.

Nguồn: Srivastava, Nitish, et al. ”Dropout: a simple way to prevent neural networks from
overfitting”, JMLR 2014

Ví dụ mô hình neural network 1-2-1: 1 input layer, 2 hidden layer và 1 output layer. Ví dụ như hidden layer 1, ta dùng dropout với p = 0.6, nên chỉ giữ lại 2 trên 5 node cho mỗi lần cập nhật.

Dropout hạn chế việc overfitting

Overfitting là mô hình đang dùng quá phức tạp so với mô hình thật của dữ liệu. Khi ta dùng dropout như hình trên thì rõ ràng mô hình bên phải đơn giản hơn => tránh overfitting.

Thêm vào đó, vì mỗi bước khi train model thì ngẫu nhiên (1-p%) các node bị loại bỏ nên model không thể phụ thuộc vào bất kì node nào của layer trước mà thay vào đó có xu hướng trải đều weight, giống như trong L2 regularization => tránh được overfitting.

Lời khuyên khi dùng dropout

  • Hệ số p nên ở khoảng [0.2, 0.5] . Nếu p quá nhỏ thì không có tác dụng chống overfitting, tuy nhiên nếu p quá lớn thì gần như loại bỏ layer đấy và có dễ dẫn đến underfitting.
  • Nên dùng model lớn, phức tạp hơn vì ta có dropout chống overfitting.
  • Dropout chỉ nên dùng cho fully connected layer, ít khi được dùng cho ConvNet layer
  • Hệ số p ở các layer nên tỉ lệ với số lượng node trong FC layer đó.

Activation function

Non-linear activation function

Hàm activation function được dùng sau bước tính tổng linear trong neural network hoặc sau convolutional layer trong CNN. Và hàm activation là non-linear function.

Linear function là gì? Theo wiki, “a linear function from the real numbers to the real numbers is a function whose graph is a line in the plane “, tóm lại linear function là một đường thẳng dạng y = a*x + b. Vậy sẽ ra sao nếu hàm activation trong neural network là một linear function?

Giả sử hàm activation dạng y = f(x) = 2*x + 3 và neural network như sau:

Mô hình neural network, 1-2-1.

z_1^{(1)} = b_1^{(1)} + x*w_{11}^{(1)} => a_1^{(1)} = f(z_1^{(1)} = 2 * z_1^{(1)} + 3 = 2*( b_1^{(1)} + x*w_{11}^{(1)}) + 3

Tương tự

a_2^{(1)} = 2*( b_2^{(1)} + x*w_{12}^{(1)}) + 3

Do đó

\hat{y} = a_1^{(2)} = f(z_1^{(2)}) = 2 * z_1^{(2)} + 3 = 2*(b_1^{(2)} + a_1^{(1)}*w_{11}^{(2)} + a_2^{(1)}*w_{21}^{(2)}) + 3 = 2 * (b_1^{(2)} + (2*( b_1^{(1)} + x*w_{11}^{(1)}) + 3 ) * w_{11}^{(2)} + (2*( b_2^{(1)} + x*w_{12}^{(1)}) + 3) * w_{21}^{(2)}) + 3 = x * (4*w_{11}^{(1)}*w_{11}^{(2)} + 4*w_{12}^{(1)}*w_{21}^{(2)}) + (2*(b_1^{(2)} + (2*b_1^{(1)} + 3)*w_{11}^{(2)} + (2*b_2^{(1)} + 3)*w_{21}^{(2)}) + 3)\newline

Tóm lại \hat{y} = x * a + b hay nói cách khác mô hình neural network chỉ là mô hình linear regression đơn giản => Hàm activation function phải là non-linear function.

Vanishing và exploding gradient

Backpropagation là thuật toán được dùng để tính đạo hàm các hệ số trong neural network với loss function đề rồi áp dụng gradient descent để tìm các hệ số.

Mô hình neural network 2-3-3-1
Quá trình backpropagation

Ta có:

\displaystyle \frac{\partial J}{\partial \hat{A^{(2)}}}= ( \frac {\partial J}{\partial \hat{Y}} \otimes \frac{\partial A^{(3)}}{\partial Z^{(3)}}) * (W^{(3)})^T\displaystyle \frac{\partial J}{\partial \hat{A^{(1)}}}= ( \frac {\partial J}{\partial A^{(2)}} \otimes \frac{\partial A^{(2)}}{\partial Z^{(2)}}) * (W^{(2)})^T

Do đó \displaystyle \frac{\partial J}{\partial \hat{A^{(1)}}}= (((\frac {\partial J}{\partial \hat{Y}} \otimes \frac{\partial A^{(3)}}{\partial Z^{(3)}}) * (W^{(3)})^T) \otimes \frac{\partial A^{(2)}}{\partial Z^{(2)}}) * (W^{(2)})^T

Ta tạm kí hiệu đạo hàm của biến qua hàm activation \displaystyle \frac {\partial A^{(i)}}{\partial Z^{(i)}} = D^{(i)}

Có thể tạm hiểu là: \displaystyle \frac{\partial J}{\partial \hat{A^{(1)}}}= \frac {\partial J}{\partial \hat{Y}} * D^{(3)} * D^{(2)} * W^{(3)} * W^{(2)}

Nếu neural network có n layer thì \displaystyle \frac{\partial J}{\partial \hat{A^{(l)}}}= \frac {\partial J}{\partial \hat{Y}} * \prod_{i=l+1}^n D^{(i)} * \prod_{i=l+1}^n W^{(i)}. (1)

Nhận xét:

  • Nếu các hệ số W và D đều nhỏ hơn 1 thì khi tính gradient ở các layer đầu ta sẽ phải nhân tích của rất nhiều số nhỏ hơn 1 nên giá trị sẽ tiến dần về 0 và bước cập nhật hệ số trong gradient descent trở nên vô nghĩa và các hệ số neural network sẽ không học được nữa. => Vanishing gradient
  • Nếu các hệ số W và D đều lớn hơn 1 thì khi tính gradient ở các layer đầu ta sẽ phải nhân tích của rất nhiều số lớn hơn 1 nên giá trị sẽ tiến dần về vô cùng và bước cập nhật hệ số trong gradient descent trở nên không chính xác và các hệ số neural network sẽ không học được nữa. => Exploding gradient

Cách giải quyết vaninshing/exproding gradient là lựa chọn các giá trị khởi tạo cho hệ số phù hợp và chọn activation function phù hợp.

Một số activation thông dụng

Sigmoid activation function

Hàm sigmoid

Đạo hàm hàm sigmoid

\displaystyle \sigma(x)\frac{1}{1+e^{-x}} => \frac{d(\sigma(x))}{dx} = \sigma(x) * (1 - \sigma(x)), do \displaystyle \sigma(x) > 0 =>\sigma(x) * (1 - \sigma(x)) <= \frac{1}{4}

Ví dụ \displaystyle (\frac{1}{4})^{20} = 9 * 10^{-13} nên nếu bạn nhìn vào công thức (1) ở trên thì ở những layer đầu tiên sẽ bị vanishing gradient,

Tanh activation function

Hàm tanh

Hàm tanh: \displaystyle g(x) = \frac{e^{x} - e^{-x}}{e^{x} + e^{-x}}, giá trị g(x) trong đoạn (-1,1)

Đạo hàm hàm tanh: \displaystyle \frac{d(g(x))}{dx} = 1 - g(x)^2 <= 1. Do đó khi dùng tanh activation function sẽ bị vanishing gradient.

ReLU activation function

Hàm ReLU

Hàm relu (rectified linear unit): \displaystyle y = max(0, x)

Nhận xét:

  • Hàm ReLU activation đơn giản để tính => thời gian train model nhanh hơn.
  • Đạo hàm là 1 với x >= 0 nên không bị vanishing gradient.

Tuy nhiên với các node có giá trị nhỏ hơn 0, qua ReLU activation sẽ thành 0, hiện tượng đấy gọi là “Dying ReLU“. Nếu các node bị chuyển thành 0 thì sẽ không có ý nghĩa với bước linear activation ở lớp tiếp theo và các hệ số tương ứng từ node đấy cũng không được cập nhật với gradient descent. => Leaky ReLU ra đời.

Leaky ReLU

Hàm Leaky ReLU

Hàm Leaky ReLU có các điểm tốt của hàm ReLU và giải quyết được vấn đề Dying ReLU bằng cách xét một độ dốc nhỏ cho các giá trị âm thay vì để giá trị là 0.

Lời khuyên: Mặc định nên dùng ReLU làm hàm activation. Không nên dùng hàm sigmoid.


Deep Learning cơ bản ©2024. All Rights Reserved.
Powered by WordPress. Theme by Phoenix Web Solutions