數學推導+純Python實現機器學習算法20:隨機森林

2021-03-02 機器學習實驗室

Python機器學習算法實現

Author:louwill

Machine Learning Lab

     

    自從第14篇文章結束,所有的單模型基本就講完了。而後我們進入了集成學習的系列,整整花了5篇文章的篇幅來介紹集成學習中最具代表性的Boosting框架。從AdaBoost到GBDT系列,對XGBoost、LightGBM和CatBoost作了較為詳細的了解。本文作為集成學習的最後一篇文章,來介紹與Boosting框架有所不同的Bagging框架。

Bagging與隨機森林

    Bagging是並行式集成學習方法最典型的代表框架。其核心概念在於自助採樣(Bootstrap Sampling),給定包含m個樣本的數據集,有放回的隨機抽取一個樣本放入採樣集中,經過m次採樣,可得到一個和原始數據集一樣大小的採樣集。我們可以採樣得到T個包含m個樣本的採樣集,然後基於每個採樣集訓練出一個基學習器,最後將這些基學習器進行組合。這便是Bagging的主要思想。Bagging與Boosting圖示如下:

    可以清楚的看到,Bagging是並行的框架,而Boosting則是序列框架(但也可以實現並行)。

    有了之前多篇關於決策樹的基礎以及前述關於Bagging基本思想的闡述,隨機森林(Random Forest)就沒有太多難以理解的地方了。所謂隨機森林,就是有很多棵決策樹構建起來的森林,因為構建過程中的隨機性,故而稱之為隨機森林。隨機森林算法是Bagging框架的一個典型代表。

    關於構建決策樹的過程,可以參考前述第4~5篇,這裡不做重複闡述。因為基礎的推導工作都是前述章節都已完成,這裡我們可以直接闡述隨機森林的算法過程,簡單來說就是兩個隨機性。具體如下:

假設有M個樣本,有放回的隨機選擇M個樣本(每次隨機選擇一個放回後繼續選)。

假設樣本有N個特徵,在決策時的每個節點需要分裂時,隨機地從這N個特徵中選取n個特徵,滿足n<<N,從這n個特徵中選擇特徵進行節點分裂。

基於抽樣的M個樣本n個特徵按照節點分裂的方式構建決策樹。

按照1~3步構建大量決策樹組成隨機森林,然後將每棵樹的結果進行綜合(分類使用投票法,回歸可使用均值法)。

    所以,當我們熟悉了Bagging的基本思想和決策樹構建的過程後,隨機森林就很好理解了。

隨機森林算法實現

    本文我們使用numpy來手動實現一個隨機森林算法。隨機森林算法本身是實現思路我們是非常清晰的,但其原始構建需要大量搭建決策樹的工作,比如定義樹節點、構建基本決策樹、在基本決策樹基礎上構建分類樹和回歸樹等。這些筆者在前述章節均已實現過,這裡不再重複。

    在此基礎上,隨機森林算法的構建主要包括隨機選取樣本、隨機選取特徵、構造森林並擬合其中的每棵樹、基於每棵樹的預測結果給出隨機森林的預測結果。

    導入相關模塊並生成模擬數據集。

import numpy as npfrom ClassificationTree import *from sklearn.datasets import make_classificationfrom sklearn.model_selection import train_test_splitn_estimators = 10max_features = 15X, y = make_classification(n_samples=1000, n_features=20, n_redundant=0, n_informative=2,                           random_state=1, n_clusters_per_class=1)rng = np.random.RandomState(2)X += 2 * rng.uniform(size=X.shape)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)

定義第一個隨機性,行抽樣選取樣本:

def bootstrap_sampling(X, y):    X_y = np.concatenate([X, y.reshape(-1,1)], axis=1)    np.random.shuffle(X_y)    n_samples = X.shape[0]    sampling_subsets = []
for _ in range(n_estimators): idx1 = np.random.choice(n_samples, n_samples, replace=True) bootstrap_Xy = X_y[idx1, :] bootstrap_X = bootstrap_Xy[:, :-1] bootstrap_y = bootstrap_Xy[:, -1] sampling_subsets.append([bootstrap_X, bootstrap_y]) return sampling_subsets

然後基於分類樹構建隨機森林:

trees = []# 基於決策樹構建森林for _ in range(n_estimators):    tree = ClassificationTree(min_samples_split=2, min_impurity=0,                              max_depth=3)    trees.append(tree)

定義訓練函數,對隨機森林中每棵樹進行擬合。

def fit(X, y):        n_features = X.shape[1]    sub_sets = bootstrap_sampling(X, y)    for i in range(n_estimators):        sub_X, sub_y = sub_sets[i]                idx2 = np.random.choice(n_features, max_features, replace=True)        sub_X = sub_X[:, idx2]        trees[i].fit(sub_X, sub_y)        trees[i].feature_indices = idx2        print('The {}th tree is trained done...'.format(i+1))

    我們將上述過程進行封裝,分別定義自助抽樣方法、隨機森林訓練方法和預測方法。完整代碼如下:

class RandomForest():    def __init__(self, n_estimators=100, min_samples_split=2, min_gain=0,                 max_depth=float("inf"), max_features=None):                self.n_estimators = n_estimators                self.min_samples_split = min_samples_split                self.min_gain = min_gain                self.max_depth = max_depth                self.max_features = max_features
self.trees = [] for _ in range(self.n_estimators): tree = ClassificationTree(min_samples_split=self.min_samples_split, min_impurity=self.min_gain, max_depth=self.max_depth) self.trees.append(tree) def bootstrap_sampling(self, X, y): X_y = np.concatenate([X, y.reshape(-1,1)], axis=1) np.random.shuffle(X_y) n_samples = X.shape[0] sampling_subsets = []
for _ in range(self.n_estimators): idx1 = np.random.choice(n_samples, n_samples, replace=True) bootstrap_Xy = X_y[idx1, :] bootstrap_X = bootstrap_Xy[:, :-1] bootstrap_y = bootstrap_Xy[:, -1] sampling_subsets.append([bootstrap_X, bootstrap_y]) return sampling_subsets def fit(self, X, y): sub_sets = self.bootstrap_sampling(X, y) n_features = X.shape[1] if self.max_features == None: self.max_features = int(np.sqrt(n_features)) for i in range(self.n_estimators): sub_X, sub_y = sub_sets[i] idx2 = np.random.choice(n_features, self.max_features, replace=True) sub_X = sub_X[:, idx2] self.trees[i].fit(sub_X, sub_y) self.trees[i].feature_indices = idx2 print('The {}th tree is trained done...'.format(i+1)) def predict(self, X): y_preds = [] for i in range(self.n_estimators): idx = self.trees[i].feature_indices sub_X = X[:, idx] y_pred = self.trees[i].predict(sub_X) y_preds.append(y_pred) y_preds = np.array(y_preds).T res = [] for j in y_preds: res.append(np.bincount(j.astype('int')).argmax()) return res

    基於上述隨機森林算法封裝來對模擬數據集進行訓練並驗證:

rf = RandomForest(n_estimators=10, max_features=15)rf.fit(X_train, y_train)y_pred = rf.predict(X_test)print(accuracy_score(y_test, y_pred))

    sklearn也為我們提供了隨機森林算法的api,我們也嘗試一下與numpy手寫的進行效果對比:

from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(max_depth=3, random_state=0)clf.fit(X_train, y_train)y_pred = clf.predict(X_test)print(accuracy_score(y_test, y_pred))

    可以看到sklearn的預測結果要略高於我們手寫的結果。當然我們的訓練結果還可以經過調參進一步提高。隨機森林調參可參考sklearn官方文檔,這裡略過。

參考資料:

機器學習 周志華

往期精彩:

數學推導+純Python實現機器學習算法19:CatBoost

數學推導+純Python實現機器學習算法18:LightGBM

數學推導+純Python實現機器學習算法17:XGBoost

一個算法工程師的成長之路

長按二維碼.關注機器學習實驗室

相關焦點

  • 數學推導+純Python實現機器學習算法30:系列總結與感悟
    實現機器學習算法3:k近鄰數學推導+純Python實現機器學習算法4:決策樹之ID3算法數學推導+純Python實現機器學習算法5:決策樹之CART算法數學推導+純Python實現機器學習算法6:感知機數學推導+純Python實現機器學習算法7:神經網絡數學推導+純Python實現機器學習算法
  • 【機器學習基礎】數學推導+純Python實現機器學習算法21:馬爾可夫鏈蒙特卡洛
    19:PCA降維數學推導+純Python實現機器學習算法18:奇異值分解SVD數學推導+純Python實現機器學習算法17:XGBoost數學推導+純Python實現機器學習算法16:Adaboost>數學推導+純Python實現機器學習算法15:GBDT數學推導+純Python實現機器學習算法14:Ridge嶺回歸數學推導+純Python實現機器學習算法13:Lasso回歸
  • 數學推導+純Python實現機器學習算法12:貝葉斯網絡
    其中DAG由節點(node)和有向邊(edge)組成,節點表示特徵屬性或隨機變量,有向邊表示各變量之間的依賴關係。貝葉斯網絡的一個重要性質是:當一個節點的父節點概率分布確定之後,該節點條件獨立於其所有的非直接父節點。這個性質方便於我們計算變量之間的聯合概率分布。     一般來說,多變量非獨立隨機變量的聯合概率分布計算公式如下:
  • 【機器學習基礎】數學推導+純Python實現機器學習算法12:貝葉斯網絡
    其中DAG由節點(node)和有向邊(edge)組成,節點表示特徵屬性或隨機變量,有向邊表示各變量之間的依賴關係。貝葉斯網絡的一個重要性質是:當一個節點的父節點概率分布確定之後,該節點條件獨立於其所有的非直接父節點。這個性質方便於我們計算變量之間的聯合概率分布。     一般來說,多變量非獨立隨機變量的聯合概率分布計算公式如下:
  • 數學推導+純Python實現機器學習算法17:XGBoost
    Python機器學習算法實現Author:louwillMachine
  • 數學推導+純Python實現機器學習算法28:奇異值分解SVD
    Python機器學習算法實現Author:louwillMachine
  • 【機器學習基礎】數學推導+純Python實現機器學習算法10:線性不可分支持向量機
    雖然凸優化問題可以直接求解,但當數據量很大時,直接求解將會非常低效,這時候可能需要一些高效的訓練算法,比如說SMO(序列最小最優化)算法。關於SMO算法的內容這裡不展開敘述,可參考統計學習方法了解更多內容。
  • 數學推導+純Python實現機器學習算法18:LightGBM
    Python機器學習算法實現Author:louwillMachine
  • 隨機森林算法入門(Python)
    昨天收到yhat推送了一篇介紹隨機森林算法的郵件,感覺作為介紹和入門不錯,就順手把它翻譯一下。目錄1.1 集成學習1.2 隨機決策樹1.3 隨機森林1.4 投票前言: 隨機森林是一個非常靈活的機器學習方法,從市場營銷到醫療保險有著眾多的應用。它可以用於市場營銷對客戶獲取和存留建模或預測病人的疾病風險和易感性。
  • python機器學習預測分析核心算法.pdf
    AI項目體驗地址 https://loveai.tech《Python機器學習 預測分析核心算法》內容簡介  在學習和研究機器學習的時候,面臨令人眼花繚亂的算法,機器學習新手往往會不知所措。本書從算法和Python語言實現的角度,幫助讀者認識機器學習。
  • Python大數據綜合應用 :零基礎入門機器學習、深度學習算法原理與案例
    共4天8節,講解機器學習和深度學習的模型理論和代碼實踐,梳理機器學習、深度學習、計算機視覺的技術框架,從根本上解決如何使用模型、優化模型的問題;每次課中,首先闡述算法理論和少量公式推導,然後使用真實數據做數據挖掘、機器學習、深度學習的數據分析、特徵選擇、調參和結果比較。
  • 機器學習、深度學習算法原理與案例實踐暨Python大數據綜合應用...
    共4天8節,講解機器學習和深度學習的模型理論和代碼實踐,梳理機器學習、深度學習、計算機視覺的技術框架,從根本上解決如何使用模型、優化模型的問題;每次課中,首先闡述算法理論和少量公式推導,然後使用真實數據做數據挖掘、機器學習、深度學習的數據分析、特徵選擇、調參和結果比較。
  • 【機器學習基礎】數學推導+純Python實現機器學習算法8-9:線性可分支持向量機和線性支持向量機
    第二步:線性可分支持向量機的簡單實現     這裡我們基採取和之前感知機模型一樣的優化思想來求解線性可分支持向量機的原始問題。完整代碼文件和數據可參考筆者GitHub地址:https://github.com/luwill/machine-learning-code-writing參考資料:https://pythonprogramming.net/https://github.com/SmirkCao/
  • 隨機森林的原理及Python代碼實現
    公眾號: datayx最近在做kaggle的時候,發現隨機森林這個算法在分類問題上效果十分的好,大多數情況下效果遠要比svm,log回歸,knn等算法效果好。因此想琢磨琢磨這個算法的原理。要學隨機森林,首先先簡單介紹一下集成學習方法和決策樹算法。Bagging和Boosting 概念及區別Bagging和Boosting都是將已有的分類或回歸算法通過一定方式組合起來,形成一個性能更加強大的分類器,更準確的說這是一種分類算法的組裝方法。即將弱分類器組裝成強分類器的方法。
  • 機器學習之隨機森林算法(Random Forest)及python代碼實現
    隨機森林的名稱中有兩個關鍵詞,一個是「隨機」,一個就是「森林」。「森林」很好理解,一棵叫做樹,那麼成百上千棵就可以叫做森林了,這也是隨機森林的主要思想--集成思想的體現。至於「隨機」也是極其關鍵的一步,具體什麼含義在下面會再做具體介紹。
  • WePay機器學習反欺詐實踐:Python+scikit-learn+隨機森林
    【編者按】將機器學習算法用於金融領域的一個很好的突破口是反欺詐,在這篇博文中,WePay介紹了支付行業構建機器學習模型應對很難發現的shell selling欺詐的實踐心得。WePay採用了流行的Python、scikit-learn開源學習機器學習工具以及隨機森林算法。以下是文章內容:什麼是shellselling?
  • 【機器學習基礎】數學推導+純Python實現機器學習算法3:k近鄰
    ,k 近鄰在眾多有監督機器學習算法中算是一種比較獨特的方法。說它獨特,是因為 k 近鄰不像其他模型有損失函數、有優化算法、有訓練過程。對於給定的實例數據和實例數據對應所屬類別,當要對新的實例進行分類時,根據這個實例最近的 k 個實例所屬的類別來決定其屬於哪一類。所以相對於其它機器學習模型和算法,k 近鄰總體上而言是一種非常簡單的方法。
  • python實現隨機森林
    Bagging和Boosting的概念與區別隨機森林屬於集成學習(Ensemble Learning)中的bagging算法。在集成學習中,主要分為bagging算法和boosting算法。我們先看看這兩種方法的特點和區別。
  • 機器學習算法——隨機森林算法簡介
    1 什麼是隨機森林在機器學習中,隨機森林是一個包含多個決策樹的分類器, 並且其輸出的類別是由個別樹輸出的類別的眾數而定。其實從直觀角度來解釋,每棵決策樹都是一個分類器(假設現在針對的是分類問題),那麼對於一個輸入樣本,N棵樹會有N個分類結果。
  • 數學推導+純Python實現機器學習算法:LightGBM
    LightGBM全稱為輕量的梯度提升機(Light Gradient Boosting Machine),由微軟於2017年開源出來的一款SOTA Boosting算法框架。跟XGBoost一樣,LightGBM也是GBDT算法框架的一種工程實現,不過更加快速和高效。