【Machine Learning】Vietnamese - Framework LightGBM (Updating)

# 1. LightGBM là gì?
LightGBM là một FrameWork để xử lý thuật toán tăng cường độ dốc (Gradient Boosting) được phát triển bởi Microsoft.

Gradient Boosting là một thuật toán xuất phát từ thuật toán Cây quyết định (Decision Tree), nó thực hiện việc xây dựng tuần tự nhiều Cây quyết định và tiến hành học tập. (Đoạn này hơi khoai, mình sửa sau)

Một công cụ khác cũng sử dụng thuật toán Gradient Boosting đó là XGBoost. Những thuật toán này đang được yêu thích và được sử dụng trong rất nhiều cuộc thi trên Kaggle. 

Trong bài viết này, mình sẽ tập trung vào cách sử dụng LightGBM như thế nào thông qua một vài ví dụ xây dựng model có sử dụng LightGBM.

# 2. Cài đặt LightGBM
Cái này dễ, search Google là ra nên bỏ qua nhé. Mình cho vào để mục lục nhìn dài và đẹp hơn chút.

# 3. Xây dựng Model trong bài toán phân loại
Dữ liệu ở đây mình dùng dữ liệu hoa Iris, có sẵn trong Module datasets của thư viện sklearn.

```python
# Import thư viện cần thiết.
import numpy as np
import lightgbm as lgb
from sklearn import datasets
from sklearn.model_selection import train_test_split

# Load bộ Dataset Iris
iris = datasets.load_iris()
X, y = iris.data, iris.target

# Sử dụng hàm của sklearn để chia dữ liệu thành 2 phần: Train data & Test data
# train_test_split() mặc định chia 25% dữ liệu thành Test data.
# Có thể thay đổi bằng cách set tham số test_size = 0.3, 0.2....
X_train, X_test, y_train, y_test = train_test_split(X, y)
```
## 3.1 Xây dựng Model
```python
# Tạo bộ dữ liệu cho Model
lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)

# Thiết lập tham số cho LightGBM
lgbm_params = {
    'objective': 'multiclass', # Bài toán phân loại nhiều lớp
    'num_class': 3, # Số Class trong bài toán này là 3
}

# Truyền tham số cho Model và tiến hành train model
model = lgb.train(lgbm_params, lgb_train, valid_sets=lgb_eval)
```
Ta sẽ thu được kết quả kiểu như sau:

```c
[1]	valid_0's multi_logloss: 0.977255
[2]	valid_0's multi_logloss: 0.869206
[3]	valid_0's multi_logloss: 0.780723
・・・
[99]	valid_0's multi_logloss: 0.176328
[100]	valid_0's multi_logloss: 0.176575
```
```python
# Dự đoán đối với bộ dữ liệu Test
y_pred = model.predict(X_test, num_iteration=model.best_iteration)
y_pred_max = np.argmax(y_pred, axis=1)  # Trả về trị số index của các giá trị tối đa, được gom thành một array 1 chiều. 
```
![1.png](https://qiita-image-store.s3.amazonaws.com/0/324823/0df20422-2912-83b8-c024-77505f62c7a0.png)
![2.png](https://qiita-image-store.s3.amazonaws.com/0/324823/4762b5d6-68b3-fcf6-de54-f05ecbe3f8e2.png)

## 3.2 Đánh giá Model.
```
accuracy = sum(y_test == y_pred_max) / len(y_test)
print(accuracy)
```
```c
0.9736842105263158
```
Trong lần thực hiện này, độ chính xác đã đạt được là 97,36%. Giá trị này có thể thay đổi ít nhiều qua mỗi lần train khác nhau, do ở đây, Train data và Test data được phân chia ngẫu nhiên.
## 3.3 Cách xây dựng Model sử dụng interface sklearn
LightGBM cũng có interface tương thích với scikit-learn.

```python
# Khai báo Model
model = lgb.LGBMClassifier()

# Train Model
model.fit(X_train, y_train)

# Dự đoán với Test data
y_pred = model.predict_proba(X_test)
y_pred_max = np.argmax(y_pred, axis=1) 

# Đánh giá độ chính xác Model
accuracy = sum(y_test == y_pred_max) / len(y_test)
print(accuracy)
```
```c
0.9736842105263158
```

# 4. Parameters Tuning
Tham khảo tại [website chính thức của LightGBM ](https://lightgbm.readthedocs.io/en/latest/Parameters-Tuning.html)
Hướng dẫn điều chính tham số cho các kịch bản khác nhau. 

## 4.1. Điều chỉnh các tham số cho Leaf-wise (Best-first) Tree.
LightGBM sử dụng thuật toán ***leaf-wise tree growth***, trong khi nhiều công cụ phổ biến khác sử dụng thuật toán ***depth-wise tree growth***.
(Đọc thêm về [leaf-wise tree growth](https://lightgbm.readthedocs.io/en/latest/Features.html#leaf-wise-best-first-tree-growth))
So với thuật toán ***depth-wise tree growth***, thuật toán ***leaf-wise tree growth*** có thể hội tụ nhanh hơn nhiều.
Tuy nhiên, ***leaf-wise tree growth*** có thể over-fitting nếu không được sử dụng với các parameters thích hợp.
Để có kết quả tốt khi sử dụng ***leaf-wise tree growth***, đây là một số thông số quan trọng:

***1. num_leaves：***
Đây là tham số chính để kiểm soát độ phức tạp của mô hình cây.
Về mặt lý thuyết, chúng ta có thể đặt num_leaves = 2 ^ (max_depth) để có được số lượng lá giống như depth-wise tree. Tuy nhiên, phép chuyển đổi đơn giản này không tốt trong thực tế. Lý do là một leaf-wise tree thường sâu hơn nhiều so với depth-wise tree cho một số lượng lá cố định. (Với cùng số lượng lá, leaf-wise tree thường sâu hơn?)
Độ sâu không giới hạn có thể gây ra over-fitting. Vì vậy, khi cố gắng điều chỉnh  tham số num_leaves, chúng ta ***nên để nó nhỏ hơn 2 ^ (max_depth).*** 
Ví dụ: khi max_depth = 7, depth-wise tree có thể có độ chính xác tốt, nhưng đặt num_leaves = 127 có thể gây ra over-fitting, và đặt nó = 70 hoặc 80 có thể có độ chính xác tốt hơn so với depth-wise.

***2. min_data_in_leaf：*** 
Đây là một thông số rất quan trọng để ngăn chặn over-fitting trong leaf-wise tree. Giá trị tối ưu của nó phụ thuộc vào số lượng dữ liệu training và num_leaves. Đặt nó một giá trị lớn có thể tránh mô hình quá phức tạp, nhưng có thể gây ra under-fitting. 
Trong thực tế, đặt nó thành hàng trăm hoặc hàng ngàn là đủ cho một tập dữ liệu lớn.

***3. max_depth：***
Bạn cũng có thể sử dụng max_depth để giới hạn tree depth một cách rõ ràng.

## 4.2. Để có tốc độ học nhanh hơn
・Sử dụng bagging bằng cách đặt <b>bagging_fraction</b> và ***bagging_freq***.
・Sử dụng feature sub-sampling bằng cách đặt ***Feature_fraction***
・Sử dụng ***max_bin*** nhỏ.
・Sử dụng ***save_binary*** để tăng tốc độ tải dữ liệu trong future learning.
・Sử dụng học song song, tham khảo [Parallel Learning Guide](https://lightgbm.readthedocs.io/en/latest/Parallel-Learning-Guide.html)

## 4.3. Để có độ chính xác tốt hơn
・Sử dụng ***max_bin*** lớn (có thể chậm hơn)
・Sử dụng ***learning_rate*** nhỏ với ***num_iterations*** lớn
・Sử dụng ***num_leaves*** lớn (có thể gây ra over-fitting)
・Sử dụng dữ liệu đào tạo lớn hơn
・Thử ***dart***

# 4.4. Giải pháp với Over-fitting
・Sử dụng ***max_bin*** nhỏ.
・Sử dụng ***num_leaves*** nhỏ.
・Sử dụng ***min_data_in_leaf*** và ***min_sum_hessian_in_leaf***.
・Sử dụng ***bagging*** bằng cách đặt ***bagging_fraction*** và ***bagging_freq***.
・Sử dụng ***feature sub-sampling*** bằng cách đặt ***Feature_fraction***.
・Sử dụng dữ liệu đào tạo lớn hơn.
・Hãy thử ***lambda_l1***, ***lambda_l2*** và ***min_gain_to_split*** để chuẩn hóa.
・Hãy thử ***max_depth*** để tránh mô hình quá sâu.

***Note***
Trong cuộc thi [santander-customer-transaction-prediction trên Kaggle](https://www.kaggle.com/c/santander-customer-transaction-prediction) việc thiết lập Feature_fraction nhỏ, kết hợp với 10 folds cv đưa ra kết quả dự đoán rất tốt cho cuộc thi. 
Tham khảo 2 bộ tham số trong 2 kernel:
[Santander Improved Starter Solution](https://www.kaggle.com/gpreda/santander-improved-starter-solution)

```python
    param = {
        'bagging_freq': 5,
        'bagging_fraction': 0.38,
        'boost_from_average':'false',
        'boost': 'gbdt',
        'feature_fraction': 0.045,
        'learning_rate': 0.0095,
        'max_depth': -1,  
        'metric':'auc',
        'min_data_in_leaf': 80,
        'min_sum_hessian_in_leaf': 10.0,
        'num_leaves': 13,
        'num_threads': 8,
        'tree_learner': 'serial',
        'objective': 'binary', 
        'verbosity': 1
    }
```
[Nothing Works](https://www.kaggle.com/brandenkmurray/nothing-works)

```R
params <- list(objective = "binary", 
               boost="gbdt",
               metric="auc",
               boost_from_average="false",
               num_threads=28,
               learning_rate = 0.01,
               num_leaves = 13,
               max_depth=-1,
               tree_learner = "serial",
               feature_fraction = 0.05,
               bagging_freq = 5,
               bagging_fraction = 0.4,
               min_data_in_leaf = 80,
               min_sum_hessian_in_leaf = 10.0,
               verbosity = 1)
```



# 5. Link tham khảo: 
https://qiita.com/nabenabe0928/items/6b9772131ba89da00354
https://blog.amedama.jp/entry/2018/05/01/081842

# 6. Link liên quan
https://lightgbm.readthedocs.io/en/latest/Parameters-Tuning.html