---
# System prepended metadata

title: Random Forest

---


# Random Forest
Random Forest 是以 Decision tree 為 base layer，再使用 bagging 的方法將各個 Decision tree 結合起來，實現「三個臭皮匠，勝過一個諸葛亮」，後續會在介紹 model 是如何運作的。

## Decision tree
Tree 是一種監督式學習(supervised learning)的模型，從根結點開始，根據 feature 將資料分到不同分之，使各節點中的資料盡量乾淨、並從中獲得最大的訊息增益。
> [!NOTE]
> 監督式學習 : 是將多個模型的預測結果結合(可以是同一種、多個)，形成一個更準確、穩定的最終模型的方法。
<div style="display:flex; gap:20px; justify-content:center;align-items:center;">
  <img src="https://hackmd.io/_uploads/BJWb91Wpel.png" style="width:48%; height:auto;">
  <img src="https://hackmd.io/_uploads/S1qW9ybagx.png" style="width:48%; height:auto;">
</div>

>決策樹的運作如上圖：在每個節點會先挑一個特徵（feature），再設定一個分割門檻（threshold），用來把資料分成兩群。
## bagging
bagging 為一種 Ensemble learning(集成學習) 的方法。使用 boostrap 抽樣的方式，從資料集隨機抽取樣本(可重複抽取)，獨立訓練多個 分類器/分類器 (各分類器為單獨個體，互不影響)，最後各分類器投票並預測最終的結果。
> [!Note]
> *boostrap* : 一種抽樣的方法，重點在於每次抽樣後，樣本會被放回資料池，使同一筆資料可能被多次抽中。
<div style="display:flex; gap:20px; justify-content:center;align-items:center;">
  <img src="https://hackmd.io/_uploads/H1WeiJb6xg.png" width="70%" style="display:inline-block;">
  <img src="https://hackmd.io/_uploads/S148oJWpel.png" width="70%" style="display:inline-block;">
</div>

>上圖為 bagging 的流程。
## Random Forest
### Discription :
Random Forest 是一種基於 Bagging 的集成學習方法。它透過對訓練資料進行多次隨機抽樣，建立多棵 Decision Tree 作為基礎分類器，並將各樹的預測結果進行投票或平均，以提升模型的穩定性與泛化能力（generalization ability）。
![image](https://hackmd.io/_uploads/rJQd8e-Tle.png)
>上圖為 Random Forest 的整體運作流程。中間紅框區塊為訓練完成的多棵 Decision Tree；當新的資料輸入時，會依據訓練階段學的分類規則進行分類或回歸，並透過投票或平均的方式整合各樹的輸出，產生最終預測結果。
### choose feature :
如上述所說的，Random Forest 會用 boostrap 的方法抽樣，並建立特徵池，接著從這些候選特徵中，挑選出最能有效區分資料的特徵，作為該節點的分裂依據。
>[!Important]如何找到「有效」區分資料的特徵?
> - 分類的任務中有幾種方法可以評估 &rightarrow; 使用 Gini impurity 或 Entropy(由於 Gini impurity為比較常見的方式，主要介紹此種方式)。
> - 回歸任務 → 使用 MSE(均方誤差)。

![image](https://hackmd.io/_uploads/Bkf-XgWTee.png)
> - 上圖所寫的 $Gini$ 皆代表 $\Delta Gini$。
> - 用 "數字" 分類代表 : 使用 "數字" 這個特徵進行分類。
> - 下面的 data 為此節點(Node) 「現在」的資料樣式，如 : positive 是從父節點，也就是全部 data 所分類出結果為 positive 的資料。
### 計算 $\Delta Gini$ :
Gini（Gini Impurity，不純度）是一個用來量化「節點裡資料有多混亂」的指標。
在決策樹或隨機森林裡，每次要分裂資料時，我們會計算 分裂前後的 Gini 值，找出「能讓資料變得最乾淨（Gini 降最多）」的特徵和 threshold 來切。
Gini 值的公式如下 :
$${Gini}(t) = 1 - \sum_{k=1}^{K} p_{k}^2$$

>[!Tip]我們先來說明如何實際「選擇特徵與 threshold」，以下圖為此次的 dataset：
**Step 1 計算 $Gini(root)$**
$Gini(𝑟𝑜𝑜𝑡)= 1\ \ –\ \ (0.5^2 + 0.5^2) = 0.5$
> 為什麼為 0.5, 0.5 ?
> 原 dataset 是 3 個 1、3 個 0，故要計算結果為 1 的 $p_{k}$ 就會是
> $\frac{result \ \ 為\ \ 1 \ \ 的數量= 3}{總數 = 6} = 0.5$。同理，結果為 0 的 $p_{k}$ 也是 0.5。
>
>
>**Step 2 計算 Threshold**
$X_1$ 由小到大排序：2, 3, 5, 7, 9, 11
$X_1$ Threshold = {2.5, 4, 6, 8, 10}
>
>**Step 3 計算各 threshold 所得的 $\Delta Gini$**
$Threshold = 2.5 → Gini(split) = 0.4,\ \ \Delta Gini = 0.5 \ \ –\ \ 0.4 = 0.1$
$Threshold = 4 → Gini(split) = 0.25,\ \ ΔGini = 0.25$
$Threshold = 6 → Gini(split) = 0,\ \ ΔGini = 0.5$
$Threshold = 8 → Gini(split) = 0.25,\ \ ΔGini = 0.25$
$Threshold = 10 → Gini(split) = 0.4,\ \ \Delta Gini = 0.1$
>
>**Step 4 重複上述步驟計算$X_2$**
>
>**Step 5 選用來分類的 feature**
$X_1$ $\Delta Gini(Max) = 0.5$ (選擇的 threshold = 0.6 & 此 feature 來做分類) 
$X_2$ $\Delta Gini(Max) = 0.2$

![image](https://hackmd.io/_uploads/B1rT3EZale.png)

>[!Tip] 接下來說明如何計算左右子集的 Gini 以及 ΔGini。:
>假設我們已經決定好 Threshold = **2.5**、使用的 feature : **$X_1$**、原本的 Gini 值為 **0.5**
>在 Left 子集 (以 $X_1$ ≤ 2.5 為篩選條件) &rightarrow; 符合條件的值為 : 2 &rightarrow; dataset 上的 result = [1]
>在 Right 子集 (以 $X_1$ > 2.5 為篩選條件) &rightarrow; 符合條件的值為 : 3, 5, 7, 9, 11 &rightarrow; dataset 上的 result = [1, 1, 0, 0, 0]
>
>*從上述可得 :*
>
>$$Left\ \ Node: gini(left) = 1\ \ –\ \ (1^2 + 0^2) = 0$$
>$$Right \ \ Node : gini(right) = 1 \ \ –\ \ (0.4^2 + 0.6^2)  = 0.48$$
>$$Gini(split) = {0 * \frac{1}{6} + 0.48 * \frac{5}{6} = 0.4}$$ 
>$$\Delta Gini(X_1) = Gini(parent)\ \ - \ \ Gini(split)= 0.5 - 0.4 = 0.1$$

### 在 Python 上如何使用 :
以下使用 `scikit-learn` 套件建立簡單的隨機森林分類器：

```python
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier


# 1. 分割訓練 / 測試資料
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 建立 Random Forest 模型
rf = RandomForestClassifier(n_estimators=100,max_depth=3,random_state=42)

# 3. 訓練模型
rf.fit(X_train, y_train)
```
>`test_size` : **資料切分比例**，決定多少資料要拿來當作「測試集」。例如 0.2 代表 20% 為測試集、80% 為訓練集。
>`n_estimators` : **樹的數量**，要訓練多少棵 Decision Tree。
>`max_depth` : **樹的最大深度**，控制每棵樹可以生長的層數，越深代表模型越複雜。