Hướng dẫn dùng Random Forest trên Sklearn

·

16 min read

Step 1:

Step 2: chuẩn bị dataset (Iris dataset)

info of dataset

image.png

code bên dưới sẽ làm nhiệm vụ tạo dataframe của dataset, split ra 2 bộ train/test và đổi thành dạng Array.

#%%
# load dataset ( we will use iris dataset)
bunch = sklearn.datasets.load_iris()

# extract dataset
data = bunch['data']
target = bunch['target']
frame = bunch['frame']
target_names = bunch['target_names']
feature_name = bunch['feature_names']

# create dataframe
df = pd.DataFrame(data, columns=["fea_1", "fea_2", "fea_3", "fea_4"])
df['target'] = target

# split train/test
df_train = df.sample(frac=0.7, random_state=0)
df_test = df.drop(df_train.index)

# create train_label, train_target array
df_train_tmp = df_train.copy()
train_target = np.array(df_train_tmp.pop('target'))
train_label = df_train_tmp.__array__()

# create test_label, test_target
df_test_tmp = df_test.copy()
test_target = np.array(df_test_tmp.pop('target'))
test_label = df_test_tmp.__array__()

Tìm hiểu về config của Decision Tree trên sklearn

from sklearn import tree

clf_config = tree.DecisionTreeClassifier(
    criterion="gini",
    splitter="best",
    max_depth=None,
    min_samples_split=2,
    min_samples_leaf=1,
    min_weight_fraction_leaf=0,
    max_features=None,
    random_state=None,
    max_leaf_nodes=None,
    min_impurity_decrease=0,
    min_impurity_split=0,
    class_weight=None,
    ccp_alpha=0,
)

chúng ta sẽ đi tìm hiểu về các parameter trong này, mỗi parameter mình sẽ cho điểm về mức độ quan trọng mà mọi người cần lưu ý, ví dụ splitter (3/5)

1. criterion (5/5)

quantdare.com/decision-trees-gini-vs-entropy

criterion sẽ dùng để đánh giá xem feature nào sẽ được làm root, và kế tiếp sau đó theo mức độ ưu tiên

hiện tại có 2 tiêu chuẩn để đánh giá là ginientropy

Gini: image.png Entropy: image.png

ưu điểm: Gini nhanh hơn vì Entropy phải sử dụng hàm log trong công thức

tuy nhiên, bạn có thể build cả 2 mô hình để xem thử criterion nào hiệu quả hơn

khuyên dùng: Gini

2. Splitter (1/5)

Splitter dùng để hỏi bạn xem bạn có muốn split internal node theo 2 cách best hoặc random không

cứ để mặc định là best thôi, không thì 1 đống setting phía sau coi như bị giảm tác dụng.

3. max_depth (4/5)

        `The maximum depth of the tree. If None, then nodes are expanded until
        all leaves are pure or until all leaves contain less than
        min_samples_split samples.`

thông thường, decision tree sẽ tạo nhánh cho tới khi nào gini của child node lớn hơn gini của parent node ( nghĩa là việc chia nhánh không hiệu quả bằng việc để yên như cũ ) thì lúc đó parent node sẽ dừng tại đó, lúc này sẽ gọi là leaf hay leaf node

nếu set max_depth = None, thì tree sẽ chạy như đã nói ở trên, hoặc nếu ta set min_samples_split thì nó sẽ dừng khi min_samples_split thỏa điều kiện.

min_samples_split sẽ nói sau

còn nếu set max_depth = int , tree sẽ chia nhánh cho tới khi đạt tới ngưỡng đã set

4. min_samples_split (2/5)

thông số này dùng để kiểm soát node được split, phải có ít nhất 1 số lượng sample trong đó. ví dụ set min_sample_split = 50 thì nếu 1 node muốn split 1 child node có 49 samples trong đó cũng sẽ không thực hiện được

5. min_samples_leaf (2/5)

tương tự, số này dùng để kiểm soát samples trong leaf, nếu 1 node có ít hơn số lượng sample được set trong min_sample_leaf thì node đó chắc chắn không thể là leaf node

6. min_weight_fraction_leaf (2/5)

kiểm soát weight của các samples trong leaf ( mình không hiểu lắm, cứ để default thôi, không quan trọng)

7. max_features (4/5)

đây là 1 thông số quan trọng, dùng để kiểm soát số lượng features dùng để split mỗi lần

ví dụ, khi bạn có 10 features, tuy nhiên max_features = 5, thì mỗi lần split, thuật toán chỉ bốc 5 feature ra để đánh giá thôi.

max_feature dùng để tunning trong thuật toán Random Forest, còn nếu chỉ dùng Decision Tree, bạn có thể đơn giản là set max_feature = None, nghĩa là dùng toàn bộ features cho mỗi lần split.

8. random_state (2/5)

random_state dùng để random cho thằng max_feature. như mình đã nói ở trên, với 10 feature, max_feature = 5 thì mỗi lần split, thuật toán sẽ bốc random 5 feature để đánh giá, còn cách bốc random như thế nào thì tham số random_state sẽ giải quyết

9. max_leaf_nodes (3/5)

kiểm soát số lượng leaf node tối đa trong 1 decision tree.

ví dụ set max_leaf_nodes = 5 thì trong tree đó tối đa chỉ có 5 leaf node

1 thông số cũng khá quan trọng, vì leaf node chính là kết quả của decision tree. tuy nhiên cũng khá abstract nên có thể dùng làm thông số để tunning.

10. min_impurity_decrease (2/5)

thông số này khá giống thông số early stopping trong mấy thuật toán gradient descent. nghĩa là nếu child node không giảm gini ( hoặc entropy) được 1 lượng là bao nhiêu đó, thì nó sẽ không cho split.

lượng đó được quy định trong min_impurity_dcrease

11. min_impurity_split (2/5)

không khác lắm cái min_impurity_decrease ( nên bỏ qua tham số này và chỉ dùng tham số min_impurity_descrease ở trên)

12. class_weight (3/5)

set trọng số cho mỗi class. một thông số cũng khá quan trong, có thể cân nhắc tunning trong 1 số trường hợp ví dụ như có sự chênh lệch về số lượng sample mỗi class, hoặc bạn hiểu được 1 số class quan trọng hơn chẳng hạn.

tuy nhiên hầu hết trường hợp mình sẽ set = "balance"

bạn có thể đọc thêm về cách set trọng số trong document của sklearn decision tree đại khái là nó kiểu như này:

[{1:1}, {2:5}, {3:1}, {4:1}]

13: ccp_alpha (?/5)

tham số mới được thằng sklearn thêm vào, chưa hiểu lắm cách hoạt động, nên set default lun.

fit and test

#### try decision tree with config
clf_config = tree.DecisionTreeClassifier(
    criterion="gini",
    splitter="best",
    max_depth=None,
    min_samples_split=2,
    min_samples_leaf=1,
    min_weight_fraction_leaf=0,
    max_features=None,
    random_state=None,
    max_leaf_nodes=None,
    min_impurity_decrease=0,
    min_impurity_split=0,
    class_weight=None,
    ccp_alpha=0,
)

clf.fit(train_label, train_target)

clf.score(test_label, test_target)

ok mình sẽ để setting như trên và fit thử với bộ train set, sau đó kiểm tra với test set

image.png

ta có kết quá là 0.95, nghĩa là 95%

bạn có thể dùng GridSearchCV của thằng sklearn để thử tuning các tham số trên, khả năng là sẽ cao hơn 95% đấy !

Tìm hiểu về config của Random Forest trên sklearn

from sklearn.ensemble import RandomForestClassifier

clf_rand_forest = RandomForestClassifier(
    n_estimators=100,
    criterion="gini",
    max_depth=None,
    min_samples_split=2,
    min_samples_leaf=1,
    min_weight_fraction_leaf=0,
    max_features="auto",
    max_leaf_nodes=None,
    min_impurity_decrease=0,
    min_impurity_split=None,
    bootstrap=True,
    oob_score=False,
    n_jobs=None,
    random_state=None,
    verbose=0,
    warm_start=False,
    class_weight=None,
    ccp_alpha=0,
    max_samples=None,
)

vì random forest thực chất chỉ là tập hợp của nhiều decision tree, nên đa số các tham số xuất hiện ở decision tree sẽ có trong này, mình sẽ đi nhanh qua những tham số nào bị trùng lặp

1. n_estimators (5/5)

số lượng tree trong forest. thông số quan trọng để tuning model

2. criterion (5/5)

xem ở phần decision tree

3. min_samples_split (2/5)

xem ở phần decision tree

4. min_samples_leaf (2/5)

xem ở phần decision tree

5. min_weight_fraction_leaf (2/5)

xem ở phần decision tree

6. max_features (4/5)

xem ở phần decision tree

7. max_leaf_nodes (2/5)

xem ở phần decison tree

8. min_impurity_decrease (2/5)

xem ở phần decision tree

9. bootstrap (1/5)

bootstrap là 1 tập dataset tuy nhiên không đầy đủ

ví dụ tập data của bạn có 50 samples KHÔNG TRÙNG LẶP. Ta sẽ lấy ra 2/3 (hoặc 1 số lượng nào đó) các samples để tạo thành 1 tập data mới gọi là bootstrap.

tập bootstrap có đặc điểm là các sample CÓ THỂ TRÙNG LẶP NHAU.

tham số có giá trị boolean, dùng hoặc không dùng boostrap

mặc dù boostrap là 1 trong những khái niệm quan trọng nhất của Random Forest, tuy nhiên vì lí do đó mà hầu như mọi trường hợp mình đều sẽ set bootstrap = True, nên tham số này gần như mặc định là vậy

10. oob_score (5/5)

oob trong oob_score nghĩa là out of bags . Ý nói đến các sample bị loại khỏi bootstrap. như vậy khi ta build random forest trên tập bootstrap đó, các oob này có thể được dùng làm 1 tập data để đánh giá kết quả của random forest đó.

tham số boolean, dùng hoặc không dùng out of bag để đánh giá kết quả của từng tree.

mặc dù sklearn mặc định là False, tuy nhiên mình thường set oob_score = True để việc đánh giá chính xác hơn.

11. n_jobs (4/5)

cái này mình hiểu cơ bản là vầy

ví dụ khi bắt đầu build Random forest, ta sẽ cần tạo các bootstrap trước. giả sử ta tạo 10 bootstrap

sau đó mỗi bootstrap sẽ đi làm nhiệm vụ tạo các decision tree, như vậy n_jobs là tham số kiểm soát xem bao nhiêu bootstrap chạy song song nhau.

nếu tất cả đều chạy parallel thì model sẽ chạy nhanh hơn

12. random_state (2/5)

giống với ở Decision Tree, ngoài ra còn kiểm soát random của bootstrap

13. verbose (1/5)

dùng để mô tả chi tiết hoạt động của model

14. warm_start (4/5)

set = True sẽ giữ lại những gì đã được học, có thể dùng để đi tuning tiếp mà không tốn nhiều thời gian, phù hợp cho tuning dùng grid search

ví dụ, ta dùng grid search cv để tìm ra model tốt nhất với 5 phương án:

n_estimators = [10, 20, 30, 40 ,50]

như vậy nếu ta không dùng warm_start, với mỗi phương án n_estimators, model sẽ phải đi train lại từ đầu, rất tốn thời gian

nếu dùng warm_start, model sẽ lưu lại những giá trị của model trước

ví dụ sau khi train xong model với n_estimators = 10, khi train tiếp với n_estimators = 20, model sẽ chỉ add thêm 10 trees mới vào, còn 10 trees cũ vẫn giữ của model trước đó.

15. class_weight (3/5)

tương tự như ở Decision Tree

16. ccp_alpha (?/5)

tương tự như ở Decision Tree

max_samples (4/5)

số lượng sample lấy ra từ tập data để bỏ vào bootstrap.

khuyến khích dùng dạng float giá trị từ (0,1) , đọc document của random forest sklearn để biết thêm cách dùng

fit and test

image.png

dựa vào kết quả default, ta thấy thậm chí random forest cho kết quả còn tệ hơn là build 1 decision tree đơn thuần :)

giải thích:

có thể vấn đề ở đây nằm ở bootstrap, ta hiểu đơn giản rằng, Decision tree thực chất là Random forest mà set bootstrap = False.

mặc dù thực tế random forest sau khi chia bootstrap, thuật toán sẽ chọn tiếp random chỉ 1 số các features để build tree, để nhằm mục đích tạo ra nhiều tree hơn, nếu mà dùng toàn bộ feature và set bootstrap = False thì Random forest chỉ có đúng 1 cây duy nhất, đó chính là Decision Tree nguyên bản.

như vậy nếu ta set bootstrap = False, v thì có khả năng cao là 1 trong 100 tree kia sẽ ít nhất là có tree giống y chang với decision tree nguyên bản, nghĩa là ít nhất sẽ >= 95%.

ta tiến hành thử bằng cách set bootstrap = False và train lại model:

image.png

ta thấy tỉ lệ lên 95%. giống với tỉ lệ của bên Decision Tree ta train hồi nãy. có nghĩa là trong 100 cây đó đã có 1 cây trùng với decision tree ta train ban đầu. Và cây đó cũng là cây có kết quả tốt nhất :)

=> kết luận: không phải lúc nào thuật toán phức tạp cũng cho ra kết quả tốt hơn. chúng ta cần nắm và phối hợp linh hoạt các thuật toán với nhau để đem lại 1 phương án phù hợp nhất.