機器學習十大經典算法之隨機森林

2021-01-10 人工智慧cv

隨機森林簡介

隨機森林是機器學習一種常用的方法。它是以決策樹為基礎,用隨機的方式排列建立的,森林裡每個決策樹之間都是沒有關聯的。 在得到森林之後,當有一個新的輸入樣本進入的時候,就讓森林中的每一棵決策樹分別進行一下判斷,看看這個樣本應該屬於哪一類(對於分類算法),然後看看哪一類被選擇最多,就預測這個樣本為那一類。隨機森林可以用來進行無監督學習聚類和異常點檢測。決策樹(decision tree)是一個樹結構(可以是二叉樹或非二叉樹)。其每個非葉節點表示一個特徵屬性上的測試,每個分支代表這個特徵屬性在某個值域上的輸出,而每個葉節點存放一個類別。使用決策樹進行決策的過程就是從根節點開始,測試待分類項中相應的特徵屬性,並按照其值選擇輸出分支,直到到達葉子節點,將葉子節點存放的類別作為決策結果。詳情請前往先前的推送。

算法流程

隨機森林裡每棵樹按照如下規則生成:

1、如果訓練集大小為N,對於每棵樹而言,隨機且有放回地從訓練集中的抽取N個訓練樣本,作為該樹的訓練集;PS:從這裡我們可以知道:每棵樹的訓練集都是不同的,而且裡面包含重複的訓練樣本。

2、如果每個樣本的特徵維度為M,指定一個常數m<<M,隨機地從M個特徵中選取m個特徵子集,每次樹進行分裂時,從這m個屬性中採用某種策略(比如說信息增益)來選擇1個屬性作為該節點的分裂屬性。3、每棵樹都盡最大程度的生長,並且沒有剪枝過程。4、 按照步驟1~3建立大量的決策樹,這樣就構成了隨機森林了。一開始我們提到的隨機森林中的「隨機」就是指的這裡的兩個隨機性。兩個隨機性的引入對隨機森林的分類性能至關重要。由於它們的引入,使得隨機森林不容易陷入過擬合,並且具有很好得抗噪能力(比如:對預設值不敏感)。

隨機森林優點

它能夠處理很高維度(feature很多)的數據,並且不用做特徵選擇(因為特徵子集是隨機選擇的)。在創建隨機森林的時候,對generlization error使用的是無偏估計,模型泛化能力強。訓練速度快,容易做成並行化方法(訓練時樹與樹之間是相互獨立的)。在訓練過程中,能夠檢測到feature間的互相影響。對於不平衡的數據集來說,它可以平衡誤差。隨機森林(Random Forest,簡稱RF)主要應用於

回歸和分類

,且擁有廣泛的應用前景,從市場營銷到醫療保健保險,既可以用來做市場營銷模擬的建模,統計客戶來源,保留和流失,也可用來預測疾病的風險和病患者的易感性。最近幾年的國內外大賽,包括2013年百度校園電影推薦系統大賽、2014年阿里巴巴天池大數據競賽以及Kaggle數據科學競賽,參賽者對隨機森林的使用佔有相當高的比例。而且隨機森林在運算量沒有顯著提高的情況下精度得到了很大的改善。

代碼實現

隨機森林實現分類算法

import pandas as pdimport numpy as npimport randomimport mathimport collectionsfrom sklearn.externals.joblib import Parallel, delayedclass Tree(object):"""定義一棵決策樹"""def __init__(self): self.split_feature = None self.split_value = None self.leaf_value = None self.tree_left = None self.tree_right = None def calc_predict_value(self, dataset):"""通過遞歸決策樹找到樣本所屬葉子節點"""if self.leaf_value is not None:return self.leaf_valueelif dataset[self.split_feature] <= self.split_value:return self.tree_left.calc_predict_value(dataset)else:return self.tree_right.calc_predict_value(dataset) def describe_tree(self):"""以json形式列印決策樹,方便查看樹結構"""if not self.tree_left and not self.tree_right: leaf_info = "{leaf_value:" + str(self.leaf_value) + "}"return leaf_info left_info = self.tree_left.describe_tree() right_info = self.tree_right.describe_tree() tree_structure = "{split_feature:" + str(self.split_feature) + \",split_value:" + str(self.split_value) + \",left_tree:" + left_info + \",right_tree:" + right_info + "}"return tree_structureclass RandomForestClassifier(object): def __init__(self, n_estimators=10, max_depth=-1, min_samples_split=2, min_samples_leaf=1, min_split_gain=0.0, colsample_bytree=None, subsample=0.8, random_state=None):""" 隨機森林參數 n_estimators: 樹數量 max_depth: 樹深度,-1表示不限制深度 min_samples_split: 節點分裂所需的最小樣本數量,小於該值節點終止分裂 min_samples_leaf: 葉子節點最少樣本數量,小於該值葉子被合併 min_split_gain: 分裂所需的最小增益,小於該值節點終止分裂 colsample_bytree: 列採樣設置,可取[sqrt、log2]。sqrt表示隨機選擇sqrt(n_features)個特徵, log2表示隨機選擇log(n_features)個特徵,設置為其他則不進行列採樣 subsample: 行採樣比例 random_state: 隨機種子,設置之後每次生成的n_estimators個樣本集不會變,確保實驗可重複 """ self.n_estimators = n_estimators self.max_depth = max_depth if max_depth != -1 elsefloat('inf') self.min_samples_split = min_samples_split self.min_samples_leaf = min_samples_leaf self.min_split_gain = min_split_gain self.colsample_bytree = colsample_bytree self.subsample = subsample self.random_state = random_state self.trees = None self.feature_importances_ = dict() def fit(self, dataset, targets):"""模型訓練入口""" assert targets.unique().__len__() == 2, "There must be two class for targets!" targets = targets.to_frame(name='label')if self.random_state: random.seed(self.random_state) random_state_stages = random.sample(range(self.n_estimators), self.n_estimators)# 兩種列採樣方式if self.colsample_bytree == "sqrt": self.colsample_bytree = int(len(dataset.columns) ** 0.5)elif self.colsample_bytree == "log2": self.colsample_bytree = int(math.log(len(dataset.columns)))else: self.colsample_bytree = len(dataset.columns)# 並行建立多棵決策樹 self.trees = Parallel(n_jobs=-1, verbose=0, backend="threading")( delayed(self._parallel_build_trees)(dataset, targets, random_state)for random_state in random_state_stages) def _parallel_build_trees(self, dataset, targets, random_state):"""bootstrap有放回抽樣生成訓練樣本集,建立決策樹""" subcol_index = random.sample(dataset.columns.tolist(), self.colsample_bytree) dataset_stage = dataset.sample(n=int(self.subsample * len(dataset)), replace=True, random_state=random_state).reset_index(drop=True) dataset_stage = dataset_stage.loc[:, subcol_index] targets_stage = targets.sample(n=int(self.subsample * len(dataset)), replace=True, random_state=random_state).reset_index(drop=True) tree = self._build_single_tree(dataset_stage, targets_stage, depth=0)print(tree.describe_tree())return tree def _build_single_tree(self, dataset, targets, depth):"""遞歸建立決策樹"""# 如果該節點的類別全都一樣/樣本小於分裂所需最小樣本數量,則選取出現次數最多的類別。終止分裂if len(targets['label'].unique()) <= 1 or dataset.__len__() <= self.min_samples_split: tree = Tree() tree.leaf_value = self.calc_leaf_value(targets['label'])return treeif depth < self.max_depth: best_split_feature, best_split_value, best_split_gain = self.choose_best_feature(dataset, targets) left_dataset, right_dataset, left_targets, right_targets = \ self.split_dataset(dataset, targets, best_split_feature, best_split_value) tree = Tree()# 如果父節點分裂後,左葉子節點/右葉子節點樣本小於設置的葉子節點最小樣本數量,則該父節點終止分裂if left_dataset.__len__() <= self.min_samples_leaf or \ right_dataset.__len__() <= self.min_samples_leaf or \ best_split_gain <= self.min_split_gain: tree.leaf_value = self.calc_leaf_value(targets['label'])return treeelse:# 如果分裂的時候用到該特徵,則該特徵的importance加1 self.feature_importances_[best_split_feature] = \ self.feature_importances_.get(best_split_feature, 0) + 1 tree.split_feature = best_split_feature tree.split_value = best_split_value tree.tree_left = self._build_single_tree(left_dataset, left_targets, depth+1) tree.tree_right = self._build_single_tree(right_dataset, right_targets, depth+1)return tree# 如果樹的深度超過預設值,則終止分裂else: tree = Tree() tree.leaf_value = self.calc_leaf_value(targets['label'])return tree def choose_best_feature(self, dataset, targets):"""尋找最好的數據集劃分方式,找到最優分裂特徵、分裂閾值、分裂增益""" best_split_gain = 1 best_split_feature = None best_split_value = Nonefor feature in dataset.columns:if dataset[feature].unique().__len__() <= 100: unique_values = sorted(dataset[feature].unique().tolist())# 如果該維度特徵取值太多,則選擇100個百分位值作為待選分裂閾值else: unique_values = np.unique([np.percentile(dataset[feature], x)for x in np.linspace(0, 100, 100)])# 對可能的分裂閾值求分裂增益,選取增益最大的閾值for split_value in unique_values: left_targets = targets[dataset[feature] <= split_value] right_targets = targets[dataset[feature] > split_value] split_gain = self.calc_gini(left_targets['label'], right_targets['label'])if split_gain < best_split_gain: best_split_feature = feature best_split_value = split_value best_split_gain = split_gainreturn best_split_feature, best_split_value, best_split_gain @staticmethod def calc_leaf_value(targets):"""選擇樣本中出現次數最多的類別作為葉子節點取值""" label_counts = collections.Counter(targets) major_label = max(zip(label_counts.values(), label_counts.keys()))return major_label[1] @staticmethod def calc_gini(left_targets, right_targets):"""分類樹採用基尼指數作為指標來選擇最優分裂點""" split_gain = 0for targets in [left_targets, right_targets]: gini = 1# 統計每個類別有多少樣本,然後計算gini label_counts = collections.Counter(targets)for key in label_counts: prob = label_counts[key] * 1.0 / len(targets) gini -= prob ** 2 split_gain += len(targets) * 1.0 / (len(left_targets) + len(right_targets)) * ginireturn split_gain @staticmethod def split_dataset(dataset, targets, split_feature, split_value):"""根據特徵和閾值將樣本劃分成左右兩份,左邊小於等於閾值,右邊大於閾值""" left_dataset = dataset[dataset[split_feature] <= split_value] left_targets = targets[dataset[split_feature] <= split_value] right_dataset = dataset[dataset[split_feature] > split_value] right_targets = targets[dataset[split_feature] > split_value]return left_dataset, right_dataset, left_targets, right_targets def predict(self, dataset):"""輸入樣本,預測所屬類別""" res = []for _, row in dataset.iterrows(): pred_list = []# 統計每棵樹的預測結果,選取出現次數最多的結果作為最終類別for tree in self.trees: pred_list.append(tree.calc_predict_value(row)) pred_label_counts = collections.Counter(pred_list) pred_label = max(zip(pred_label_counts.values(), pred_label_counts.keys())) res.append(pred_label[1])return np.array(res)if __name__ == '__main__': df = pd.read_csv("source/wine.txt") df = df[df['label'].isin([1, 2])].sample(frac=1, random_state=66).reset_index(drop=True) clf = RandomForestClassifier(n_estimators=5, max_depth=5, min_samples_split=6, min_samples_leaf=2, min_split_gain=0.0, colsample_bytree="sqrt", subsample=0.8, random_state=66) train_count = int(0.7 * len(df)) feature_list = ["Alcohol", "Malic acid", "Ash", "Alcalinity of ash", "Magnesium", "Total phenols", "Flavanoids", "Nonflavanoid phenols", "Proanthocyanins", "Color intensity", "Hue", "OD280/OD315 of diluted wines", "Proline"] clf.fit(df.loc[:train_count, feature_list], df.loc[:train_count, 'label']) from sklearn import metricsprint(metrics.accuracy_score(df.loc[:train_count, 'label'], clf.predict(df.loc[:train_count, feature_list])))print(metrics.accuracy_score(df.loc[train_count:, 'label'], clf.predict(df.loc[train_count:, feature_list])))

現在實現隨機森林基本上都是可以直接調用

sklearn

裡面的API。

from sklearn.ensemble import RandomForestClassifier

參考資料

[1]

https://blog.csdn.net/yangyin007/article/details/82385967

[2]

https://zhuanlan.zhihu.com/p/22097796

[3]

https://github.com/zhaoxingfeng/RandomForest/blob/master/RandomForestClassification.py

相關焦點

  • 隨機森林(Random Forest)算法原理
    :  在機器學習中,隨機森林是一個包含多個決策樹的分類器,並且其輸出的類別是由個別樹輸出的類別的眾數而定。基於樹分類器的集成算法(Ensemble Learning),其包含了2種十分有效地機器學習技術:Bagging和隨機變量選擇,隨機森林它屬於Bagging類型,通過組合多個弱分類器,最終結果通過投票或取均值,使得整體模型的結果具有較高的精確度和泛化性能。
  • 機器學習初學者必須知道的十大算法
    還在為不知道學什麼算法入門機器學習感到頭疼?本文作者通過自身的學習向初學者介紹十大機器學習(ML)算法,並附有數字和實例以便於理解。哈佛商業評論稱數據科學家是21世紀最性感的工作。所以,對於那些ML剛剛開始的人來說,這篇博客機器學習算法工程師需要知道的十大算法是非常有用的。ML算法是可以從數據中學習並從中改進的算法,無需人工幹預。
  • 機器學習十大算法都是何方神聖?
    跟我們生活息息相關的最常見機器學習算法包括電影推薦算法、圖書推薦算法。這些算法都是基於你的電影觀看記錄或圖書購買記錄來給你做推薦的。James Le在KDnuggets上發布了一篇文章,介紹了他是如何入門機器學習的。此外,他在其中摸索出十大常用的機器學習算法,並逐一進行介紹。雷鋒網編譯如下,未經許可不得轉載。如果你想學機器學習,那怎麼入門呢?
  • WePay機器學習反欺詐實踐:Python+scikit-learn+隨機森林
    【編者按】將機器學習算法用於金融領域的一個很好的突破口是反欺詐,在這篇博文中,WePay介紹了支付行業構建機器學習模型應對很難發現的shell selling欺詐的實踐心得。WePay採用了流行的Python、scikit-learn開源學習機器學習工具以及隨機森林算法。
  • 五分鐘了解機器學習十大算法
    本文為有志於成為數據科學家或對此感興趣的讀者們介紹最流行的機器學習算法。機器學習是該行業的一個創新且重要的領域。我們為機器學習程序選擇的算法類型,取決於我們想要實現的目標。現在,機器學習有很多算法。因此,如此多的算法,可能對於初學者來說,是相當不堪重負的。
  • 史上最全十大機器學習算法,入門必看!
    本文中所介紹的前五個算法(線性回歸,邏輯回歸,分類回歸樹,樸素貝葉斯,K最近鄰算法)均是有監督學習的例子。除此之外,集成學習也是一種有監督學習。它是將多個不同的相對較弱的機器學習模型的預測組合起來,用來預測新的樣本。本文中所介紹的第九個和第十個算法(隨機森林裝袋法,和XGBoost算法)便是集成技術的例子。
  • 十大機器學習算法之旅已啟程
    大的原則  然而,有一個共同的原則,即所有監督機器學習算法預測建模的基礎。  機器學習算法被描述為學習一個目標函數,將輸入變量(X)最佳映射到輸出變量(Y)的目標函數(f):Y = f(X)  這是一個通用的學習任務,我們希望在未來(Y)給出預測輸入變量(X)的新例子。我們不知道函數(f)是什麼樣子或是它的形式。
  • 流行的機器學習算法總結,幫助你開啟機器學習算法學習之旅
    AI的ML領域是為實現非常精確的目標而創建的,它引入了多種算法,從而可以更順暢地進行數據處理和決策。什麼是機器學習算法?機器學習算法是任何模型背後的大腦,可讓機器學習並使其更智能。這些算法的工作方式是,為它們提供第一批數據,並且隨著時間的流逝和算法的準確性的提高,額外的數據也被引入到算法中。
  • 盤點:十大機器學習算法及其應用
    毫無疑問,過去兩年中,機器學習和人工智慧的普及度得到了大幅提升。如果你想學習機器算法,要從何下手呢?以我為例,我是在哥本哈根留學期間,學習AI課程入門的。我們用的教科書是一本AI經典:《Peter Norvig’s Artificial Intelligence?—?A Modern Approach》。
  • 用Python實現隨機森林算法
    除了仍然根據從訓練數據樣本建立複合模型之外,隨機森林對用做構建樹(tree)的數據特徵做了一定限制,使得生成的決策樹之間沒有關聯,從而提升算法效果。本文章旨在探討如何用 Python 實現隨機森林算法。
  • 【技術必備】解讀 2016 年十大機器學習算法及其應用
    原標題:【技術必備】解讀 2016 年十大機器學習算法及其應用 新智元編譯 來源:kdnuggets 【新智元導讀】 機器學習領域都有哪些常用算法?本文帶來盤點。 毫無疑問,過去兩年中,機器學習和人工智慧的普及度得到了大幅提升。 如果你想學習機器算法,要從何下手呢?
  • 隨機森林(Random Forest)
    作為新興起的、高度靈活的一種機器學習算法,隨機森林(Random Forest,簡稱RF)擁有廣泛的應用前景,從市場營銷到醫療保健保險,既可以用來做市場營銷模擬的建模,統計客戶來源,保留和流失,也可用來預測疾病的風險和病患者的易感性。最初,我是在參加校外競賽時接觸到隨機森林算法的。
  • 新手必看的十種機器學習算法
    然而,在眾多的機器學習算法中,哪些是又上手快捷又功能強大、適合新手學習的呢?Towards Data Science 上一篇文章就介紹了十種新手必看的機器學習算法,雷鋒網 AI 科技評論全文編譯如下。如果早就知道,我們就可以直接使用它,而不需要再通過機器學習算法從數據中進行學習了。最常見的機器學習就是學習 Y=f(X) 的映射,針對新的 X 預測 Y。這叫做預測建模或預測分析。我們的目標就是讓預測更加精確。針對希望對機器學習有個基本了解的新人來說,下面將介紹數據科學家們最常使用的 10 種機器學習算法。1.
  • 機器學習算法基礎(使用Python代碼)
    今天,作為一名數據科學家,我可以用每小時幾美元的成本,用複雜算法構建數據處理機器。但是實現這並不容易!因為我需要面臨度過無數個黑暗的日日夜夜。機器學習算法類型從廣義上講,有3種類型的機器學習算法。K均值隨機森林降維算法梯度增強算法GBMXGBoost
  • 盤點| 機器學習入門算法:從線性模型到神經網絡
    原標題:盤點 | 機器學習入門算法:從線性模型到神經網絡 選自Dataconomy 機器之心編譯 參與:王宇欣、吳攀、蔣思源幾十年來,機器學習實際上已經變成了一門獨立的領域。由於現代計算能力的進步,我們最近才能夠真正大規模地利用機器學習。而實際上機器學習是如何工作的呢?答案很簡單:算法(algorithm)。 機器學習是人工智慧(artificial intelligence)的一種,其本質上講,就是計算機可以在無需編程的情況下自己學習概念(concept)。
  • 機器學習十大算法都是何方神聖?看完你就懂了
    大數據原本在工業界中就已經炙手可熱,而基於大數據的機器學習則更加流行,因為其通過對數據的計算,可以實現數據預測、為公司提供決策依據。跟我們生活息息相關的最常見機器學習算法包括電影推薦算法、圖書推薦算法。這些算法都是基於你的電影觀看記錄或圖書購買記錄來給你做推薦的。James Le 在 KDnuggets 上發布了一篇文章,介紹了他是如何入門機器學習的。
  • 入門| 機器學習新手必看10大算法
    如果我們知道的話,我們將會直接使用它,不需要用機器學習算法從數據中學習。 最常見的機器學習算法是學習映射 Y = f(X) 來預測新 X 的 Y。這叫做預測建模或預測分析,我們的目標是儘可能作出最準確的預測。 對於想了解機器學習基礎知識的新手,本文將概述數據科學家使用的 top 10 機器學習算法。
  • 【乾貨】隨機森林的Python實現
    【新智元導讀】在機器學習中,隨機森林是一個包含多個決策樹的分類器,並且其輸出的類別是由個別樹輸出的類別的眾數而定。隨機森林幾乎是任何預測類問題(甚至非線性問題)的首選。本文介紹了隨機森林的原理、用途,以及用 Python 實現隨機森林的方法。
  • 機器學習算法一覽(附python和R代碼)
    )6.K鄰近算法(KNN)7.K-均值算法(K-means)8.隨機森林 (Random Forest)9.降低維度算法(Dimensionality Reduction Algorithms)10.Gradient Boost和Adaboost算法 1.線性回歸 (Linear Regression) 線性回歸是利用連續性變量來估計實際數值
  • 機器學習萌新必學的Top10算法
    大的原則不過呢,對於所有預測建模的監督學習算法來說,還是有一些通用的底層原則的。機器學習算法,指的是要學習一個目標函數,能夠儘可能地還原輸入和輸出之間的關係。然後根據新的輸入值X,來預測出輸出值Y。精準地預測結果是機器學習建模的任務。