1. 程式人生 > >隨機森林(Random Forest)入門與實戰

隨機森林(Random Forest)入門與實戰

前言

整合學習(ensemble learning)是通過構建並結合多個學習器來完成學習任務,主要包含兩類,一是個體學習器間存在強依賴關係、必須序列生成的序列化方法,比如前幾篇博文介紹提升學習方法提升樹GBDT 詳解xgboost等,主要思想是boosting迭代將弱學習器提升為強學習器;二是個體學習器之間不存在強依賴關係、可同時生成的並行化方法,該類的代表是bagging和隨機森林。

Bagging

想要得到泛化能力強的整合,整合中的個體學習應該儘可能的相互獨立,所以設法是的基學習器儘可能的具有較大的差異。給定一個訓練資料集將其隨機抽樣成n份子樣本集,然後每個子集訓練得出一個個體學習器,這樣得到的基學習器就會有比較大的差異,從而獲得好的整合;但是因為每個基學習器只用了一小部分的資料,這不能保證個體學習器的學習的有效性,因此,為了解決這個問題可以考慮使用相互有交疊的取樣子集。

Bagging就是採用這種思想,對於給定的m個樣本資料集,先隨機取出一個樣本放入取樣集,再把這部分樣本放回初始資料集,使得下次取樣時該樣本仍然有可能被選中,這樣經過m次隨機取樣操作得到含m個樣本的取樣集。初始訓練集中的樣本有的在取樣集中多次出現,有的則未出現。這樣經過T輪,我們可以得到T個含m個訓練樣本的取樣集,基於每個取樣集訓練得到一個基學習器,然後再將這些基學習器進行結合。在對預測值輸出結合的時候,Bagging通常對分類問題使用簡單投票法,對迴歸問題使用簡單平均法。 

隨機森林

隨機森林是Bagging的一個拓展變體,RF在以決策樹為基學習器構建Bagging整合的基礎上,進一步在決策樹的訓練過程中引入了隨機屬性選擇。傳統決策樹在選擇劃分屬性時是在當前結點的屬性集合(假定d個屬性)中選擇一個最優屬性;而在RF中,對基決策樹的每個結點,先從該結點的屬性集合中隨機選擇一個包含k個屬性的子集,然後再從這個子集中選擇一個最優屬性用於劃分。這裡的引數k控制了隨機性的引入程度:若令k=d,則決策樹的構建與傳統決策樹相同;若令k=1,則是隨機選擇一個屬性用於劃分,一般情況下k=log2(d)。 
隨機森林對Bagging只做了小改動,但是與Bagging中基學習器的“多樣性”—僅通過樣本擾動不同,隨機森林還加入了隨機屬性擾動,這是的最終整合的泛化效能可通過個體學習器之間差異度的增加而進一步提升。 
隨機森林的收斂性與Bagging相似(如下圖),隨機森林的起始效能相對較差,特別是只包含一個基學習器的時候(因為通過引入屬性擾動,隨機森林中個體學習器的效能往往有所降低,然而隨著個體學習器數目的增加隨機森林通常會收斂到更低的泛化誤差)。此外,隨機森林的訓練效率往往優於Bagging(決策樹生成劃分屬性時只需要考察一個屬性子集)。 

結合策略

 
1.平均法 :對數字型輸出通常用平均法(averaging) 
(1)簡單平均法 
 
(2)加權平均法 
 
 
2.投票法:對分類任務來說,每個學習器預測出一個標記,然後採用投票法(voting)得出最終結果 
(1)絕對多數投票法 
 
即若某標記得票過半,則預測為該標記,否則就拒絕預測 
(2)相對多數投票法 
 
即預測為得票最多的標記,若同時有多個標記獲最高票,則從中隨機選取一個。 
(3)加權投票法 
 
 
3.學習法:當訓練資料很多時,通過另外一個學習器進行結合—Stacking。Stacking先從初始資料集訓練出初級學習器,然後生成一個新資料集用於訓練次級學習器,在這個新資料集中,初級學習器的輸出被當做樣例輸入特徵,而初始樣本的標記仍被當做樣例標記。演算法流程如下圖所示,這裡假定初級學習器使用不同學習演算法產生,及初級整合是異質的。 

 
在訓練階段,次級訓練集是利用初級學習器產生的,若直接用初級學習器的訓練集來產生次級訓練集,則過擬合風險會比較大;因此一般採用交叉驗證或留一法這樣的方式,用訓練初級學習器未使用的樣本來產生次級學習器的訓練樣本。 
 

Random Forest實戰

完整程式碼:

# -*- coding: utf-8 -*-
"""

"""
# Imports
import pandas as pd # load csv's (pd.read_csv)
import numpy as np # math (lin. algebra)

import sklearn as skl # machine learning
from sklearn.ensemble import RandomForestClassifier

# Visualisation
import matplotlib.pyplot as plt # plot the data
import seaborn as sns # data visualisation
sns.set(color_codes=True)
#% matplotlib inline

# load data as Pandas.DataFrame
train_df = pd.read_csv('input/train.csv')
train_data = train_df.values

test_df = pd.read_csv('input/test.csv')
test_data = test_df.values

plt.figure(figsize=(12,8))
sns.countplot(x='label', data=train_df)
plt.title('Distribution of Numbers')
plt.xlabel('Numbers');

# Holdout ( 2/3 to 1/3 )
num_features = train_data.shape[0] # number of features
print("Number of all features: \t\t", num_features)
split = int(num_features * 2/3)

train = train_data[:split]
test = train_data[split:]

print("Number of features used for training: \t", len(train), 
      "\nNumber of features used for testing: \t", len(test))

# Classifier
clf = RandomForestClassifier(n_estimators=100) # 100 trees

# train model / ravel to flatten the array structure from [[]] to []
model = clf.fit(train[:,1:], train[:,0].ravel())

# evaluate on testdata
output = model.predict(test[:,1:])

# calculate accuracy
acc = np.mean(output == test[:,0].ravel()) * 100 # calculate accuracy
print("The accuracy of the pure RandomForest classifier is: \t", acc, "%")

# Classifier
clf = RandomForestClassifier(n_estimators=100) # 100 trees

# train model / ravel to flatten the array structure from [[]] to []
target = train_data[:,0].ravel()
train = train_data[:,1:]
model = clf.fit(train, target)

# modify the test_data, so the number of attributes match with the training data (missing label column)

# evaluate on testdata
output = model.predict(test_data)

pd.DataFrame({"ImageId": range(1, len(output)+1), "Label": output}).to_csv('out.csv', index=False, header=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

結果:

此處先留個坑。。。不同版本的執行結果我會陸續貼出來。

版本1: 
這裡寫圖片描述

成績稍微比之前xgboost的結果差一些。0.96743