隨機森林算法&python應用

隨機森林算法

決策樹算法可以很容易的將模型進行可視化,同時它是將每個樣本特徵進行單獨處理,故而不需要的對數據進行轉換。但是決策樹會很容易出現過擬合,爲了避免過擬合現象,可以使用集合學習的方法,像:隨機森林算法。

隨機森林又被稱爲:隨機決策森林,是一種集合學習方法(參見下圖),既可以用於分類,也可以用作迴歸。分類:在森林內部會進行“投票”,每棵樹預測出數據類別的概率,隨機森林會把這些概率值求平均,讓後將樣本放入概率最大的分類中。迴歸:隨機森林會把所有決策樹預測的值取平均數。
集成學習
隨機森林算法之所以可以解決過擬合問題:因爲隨機森林是把不同的幾棵決策樹打包到一起,每棵樹的參數都不相同,然後我們把每棵樹預測的結果取平均值,這樣不僅可以保留決策樹工作的高效,又可以降低過擬合的風險。

隨機森林算法可以大致分爲兩個步驟:第一,創建決策樹,第二,根據第一步中決策樹的分類器結果做出預測。隨機森林算法與決策樹算法之間的區別是:前者查找根節點和分割特徵節點的過程是隨機進行的。

  • 構建過程:

(1)數據的隨機選取,若訓練集中有NN個樣本,又放回的隨機抽取nn個。這nn個樣本就作爲生成該決策樹的訓練集。

(2)特徵的隨機選取,對於每個樣本,如果有MM個輸入變量(特徵),指定一個常數mm,然後隨機的從MM中選取mm個最優的分裂特徵開分裂節點。

  • 預測過程:

(1)使用每一個隨機創建的決策樹的規則來測試特徵的結果(標籤)

(2)計算每個預測目標的票數

(3)獲得票數最高的結果將作爲隨機森林算法的最終預測。

:隨機森林算法也不要求對數據進行預處理,同時支持並行處理。此外,隨機森林生成每一棵決策樹的方法是隨機的,則不同的random_state參數會導致模型完全不同,所以爲了模型的相對穩定,要固化random_state這個參數的值。但是!!!隨機森林,對於高維數據集、稀疏數據集來說,很不適應。

構建決策樹

author by xiaoyao

# 導入libraries
import numpy as np
# 導入畫圖工具
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
# 導入tree模型和數據集加載工具
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
# 導入數據集拆分工具
from sklearn.model_selection import train_test_split
wine = datasets.load_wine()
# 這裏只選取數據集的前兩個特徵
X = wine.data[:,:2]
y = wine.target
# 將數據集劃分爲訓練集個測試集
X_train, X_test, y_train, y_test = train_test_split(X, y)

# 忽略警告
import warnings
warnings.filterwarnings("ignore")
# 暫時設定隨機森林中有6棵樹
forest = RandomForestClassifier(n_estimators=6, random_state=3)
# 使用模型擬合數據
forest.fit(X_train, y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                       max_depth=None, max_features='auto', max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=6,
                       n_jobs=None, oob_score=False, random_state=3, verbose=0,
                       warm_start=False)

其中,bootstrap參數:代表的是bootstrap sample。也就是又放回抽樣,bootstrap生成的數據集和原始數據集在數據量上是一致的,但由於進行了重複採樣,因此其中有一些數據點會丟失。通過重新生成數據集,可以讓隨機森林中的每一棵決策樹在構建的時候,彼此之間有差異。max_features的取值越高,隨機森林中的每一棵樹就會"越相似",從而因爲有更多的不同特徵值可以取,也就會更容易取擬合數據。

# 定義圖像中分區的顏色和散點的顏色
cmap_light = ListedColormap(["#FFAAAA", "#AAFFAA", "#AAAAFF"])
cmap_bold = ListedColormap(["#FF0000", "#00FF00", "#0000FF"])

# 分別用樣本的兩個特徵值創建圖像和橫軸、縱軸
x_min, x_max = X_train[:,0].min() - 1, X_train[:,0].max() + 1
y_min, y_max = X_train[:,1].min() - 1, X_train[:,1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),np.arange(y_min, y_max, .02))
z = forest.predict(np.c_[xx.ravel(), yy.ravel()])
# 給每個分類中的樣本分配不同的顏色
z = z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, z, cmap=cmap_light)

# 使用散點圖進行表示
plt.scatter(X[:,0], X[:,1], c=y, cmap=cmap_bold, edgecolor="k",s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("Classifier:(max_depth = 3)")
plt.show()

在這裏插入圖片描述

隨機森林實例

author by xiaoyao

# 導入相應的libraries
import pandas as pd
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# 忽略警告
import warnings
warnings.filterwarnings("ignore")
# 導入數據集,數據集下載地址:http://archive.ics.uci.edu/ml/machine-learning-databases/adult/
# 原始數據無列名(屬性名)
data = pd.read_csv("./datasets/adult.csv", header=None,index_col=False,
                  names=['年齡','單位性質','權重','學歷','受教育時常',
                         '婚姻狀況','職業','家庭情況','種族','性別',
                         '資產所得','資產損失','周工作時長','原籍','收入'])
data.head()
年齡 單位性質 權重 學歷 受教育時常 婚姻狀況 職業 家庭情況 種族 性別 資產所得 資產損失 周工作時長 原籍 收入
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K
import pandas_profiling
rep = pandas_profiling.ProfileReport(data)
# 將生成的數據分析報告保存至本地html文件
rep.to_file("./rep.html")

報告具體形式:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
\vdots
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 32561 entries, 0 to 32560
Data columns (total 15 columns):
年齡       32561 non-null int64
單位性質     32561 non-null object
權重       32561 non-null int64
學歷       32561 non-null object
受教育時常    32561 non-null int64
婚姻狀況     32561 non-null object
職業       32561 non-null object
家庭情況     32561 non-null object
種族       32561 non-null object
性別       32561 non-null object
資產所得     32561 non-null int64
資產損失     32561 non-null int64
周工作時長    32561 non-null int64
原籍       32561 non-null object
收入       32561 non-null object
dtypes: int64(6), object(9)
memory usage: 3.7+ MB

可以看到在數據集中,很多的列取值都是字符串,不方便進行建模。我將其處理爲:整型數值,操作如下:

# 使用get_dummies將文本數據轉化爲數值
data_dummies = pd.get_dummies(data)
# 分別輸出原始特徵和處理之後的特徵
print("原始特徵:",(data.columns))
print("處理後的特徵:",(data_dummies.columns))
原始特徵: Index(['年齡', '單位性質', '權重', '學歷', '受教育時常', '婚姻狀況', '職業', '家庭情況', '種族', '性別',
       '資產所得', '資產損失', '周工作時長', '原籍', '收入'],
      dtype='object')
處理後的特徵: Index(['年齡', '權重', '受教育時常', '資產所得', '資產損失', '周工作時長', '單位性質_ ?',
       '單位性質_ Federal-gov', '單位性質_ Local-gov', '單位性質_ Never-worked',
       ...
       '原籍_ Scotland', '原籍_ South', '原籍_ Taiwan', '原籍_ Thailand',
       '原籍_ Trinadad&Tobago', '原籍_ United-States', '原籍_ Vietnam',
       '原籍_ Yugoslavia', '收入_ <=50K', '收入_ >50K'],
      dtype='object', length=110)
data.head()
年齡 單位性質 權重 學歷 受教育時常 婚姻狀況 職業 家庭情況 種族 性別 資產所得 資產損失 周工作時長 原籍 收入
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K
data_dummies.head()
年齡 權重 受教育時常 資產所得 資產損失 周工作時長 單位性質_ ? 單位性質_ Federal-gov 單位性質_ Local-gov 單位性質_ Never-worked ... 原籍_ Scotland 原籍_ South 原籍_ Taiwan 原籍_ Thailand 原籍_ Trinadad&Tobago 原籍_ United-States 原籍_ Vietnam 原籍_ Yugoslavia 收入_ <=50K 收入_ >50K
0 39 77516 13 2174 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
1 50 83311 13 0 0 13 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
2 38 215646 9 0 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
3 53 234721 7 0 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
4 28 338409 13 0 0 40 0 0 0 0 ... 0 0 0 0 0 0 0 0 1 0

5 rows × 110 columns

將各列分配給特徵向量XX和分類標籤yy

# 定義數據集的特徵值
features = data_dummies.loc[:, '年齡':'原籍_ Yugoslavia']
X = features.values
# 將收入大於50k作爲預測的目標
y = data_dummies['收入_ >50K'].values
# 輸出特徵與標籤的形態
print("特徵形態:{} 標籤形態:{}".format(X.shape, y.shape))
特徵形態:(32561, 108) 標籤形態:(32561,)
# 先使用決策數模型進行預測
# 將數據拆分爲訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1)
# 設最大深度爲5
dt_tree =tree.DecisionTreeClassifier(max_depth=5)
dt_tree.fit(X_train, y_train)
dt_tree.score(X_test, y_test)
0.8550546615894853
# 使用交叉驗證,平均水平依然接近上面的
from sklearn.model_selection import cross_val_score
scores = cross_val_score(dt_tree, X, y, cv=20,scoring='accuracy')
print(scores)
print(scores.mean())
[0.83977901 0.84275184 0.8482801  0.84336609 0.85012285 0.8531941
 0.82555283 0.84398034 0.8458231  0.85380835 0.85995086 0.83783784
 0.85257985 0.84889435 0.86425061 0.85257985 0.8507371  0.86302211
 0.84766585 0.84643735]
0.8485307193180122
# 使用隨機森林算法
forest = RandomForestClassifier(n_estimators = 5,random_state=0)
forest.fit(X_train, y_train)
forest.score(X_test, y_test)
0.8431396634320109
# 使用交叉驗證
scores = cross_val_score(forest, X, y,cv=5,scoring='accuracy')
print(scores)
print(scores.mean())
[0.82320442 0.83968059 0.83230958 0.84336609 0.82862408 0.85012285
 0.82678133 0.8458231  0.84336609 0.83108108 0.83722359 0.83046683
 0.84336609 0.83599509 0.8482801  0.84213759 0.84766585 0.85257985
 0.83169533 0.84459459]
0.8389182062524604
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章