機器學習——決策樹和隨機森林演算法
認識決策樹
決策樹思想的來源非常樸素,程式設計中的條件分支結構就是if-then結構,最早的決策樹就是利用這類結構分割資料的一種分類學習方法。
下面以一個問題引出決策樹的思想
這個問題用圖來表示就是這樣:
為什麼先把年齡放在第一個呢,下面就是一個概念:資訊熵
資訊熵
單位為位元
公式為:
資訊和消除不確定性是相聯絡的
資訊熵越大不確定性越大
決策樹的劃分依據:資訊增益
特徵A對訓練資料集D的資訊增益g(D,A),定義為集合D的資訊熵H(D)與特徵A給定條件下D的資訊條件熵H(D|A)之差,即公式為:
g(D,A)=H(D)-H(D|A) H(D)初始資訊熵大小
資訊增益:當得知一個特徵條件之後,減少的資訊熵的大小。
注意:資訊增益表示得知特徵X的資訊而使得類Y的資訊的不確定性減少的程度
下面用一個例子來說明
ID | 年齡 | 有工作 | 有自己的房子 | 信貸情況 | 類別 |
1 | 青年 | 否 | 否 | 一般 | 否 |
2 | 青年 | 否 | 否 | 好 | 否 |
3 | 青年 | 是 | 否 | 好 | 是 |
4 | 青年 | 是 | 是 | 一般 | 是 |
5 | 青年 | 否 | 否 | 一般 | 否 |
6 | 中年 | 否 | 否 | 一般 | 否 |
7 | 中年 | 否 | 否 | 好 | 否 |
8 | 中年 | 是 | 是 | 好 | 是 |
9 | 中年 | 否 | 是 | 非常好 | 是 |
10 | 中年 | 否 | 是 | 非常好 | 是 |
11 | 老年 | 否 | 是 | 非常好 | 是 |
12 | 老年 | 否 | 是 | 好 | 是 |
13 | 老年 | 是 | 否 | 好 | 是 |
14 | 老年 | 是 | 否 | 非常好 | 是 |
15 | 老年 | 否 | 否 | 一般 | 否 |
H(D)=-(9/15log9/15+6/15(6/15)) 總的資訊熵大小
g(D,年齡)=H(D)-H(D'|年齡)=0.971-[1/3H(青年)+1/3H(中年)+1/3H(老年)]
H(青年)=-(2/5log2/5+3/5log3/5)
H(中年) =-(2/5log2/5+3/5log3/5)
H(老年)=-(1/5log1/5+4/5log4/5)
決策樹的分類依據之一:資訊增益
常見決策樹使用的演算法
- ID3
資訊增益 最大原則
- C4.5
資訊增益比 最大的準則 即資訊增益比上原來的H(D)的比值大小
- CART
迴歸樹:平方誤差
分類樹:基尼係數 最小的準則 在sklearn中可以選擇劃分的預設原則
sklearn決策樹API
class sklearn.tree.DescisionTreeClassifier(criterion='gini',max_depth=None.random_state=None)
- 決策樹分類器
- criterion:預設是'gini'係數,也可以選擇資訊增益的熵'entropy'
- max_depth:樹的深度大小
- random_state:隨機數種子
- method:
- decision_path"返回決策樹的路徑
下面用一個例項說明:
預測泰坦尼克號人員的存活情況
部分資料截圖如下:
程式碼如下:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
import pandas as pd
def decision():
"""
決策樹對泰坦尼克號進行預測生死
:return:
"""
#獲取資料
titan=pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
#處理資料,找出特徵值和目標值
x=titan[['pclass','age','sex']] #特徵值
y=titan['survived'] #目標值
#缺失值處理
x['age'].fillna(x['age'].mean(),inplace=True)
#分割資料集到訓練集合測試集
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25)
#進行處理(特徵工程) 特徵=》 類別=》 one_hot編碼
dict=DictVectorizer(sparse=False)
x_train=dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
x_test=dict.transform(x_test.to_dict(orient="records"))
#用決策樹進行預測
dec=DecisionTreeClassifier(max_depth=5)
dec.fit(x_train,y_train)
#預測準確率
print(dec.score(x_test,y_test))
return None
if __name__=="__main":
decision()
執行結果如下:
決策樹的優缺點
優點:
- 簡單的理解和解釋,樹木視覺化。
- 需要很少的資料準備,其他技術通常需要資料歸一化。
缺點:
- 決策樹學習者可以建立不能很好地推廣資料的過於複雜的樹,這被稱為過擬合。
改進:
- 剪枝cart演算法(決策樹API當中已經實現,隨機森林引數調優有相關介紹)
- 隨機森林
隨機森林
整合學習方法
整合學習通過建立幾個模型組合的來解決單一預測問題。它的工作原理是生成多個分類器/模型,各自獨立地學習和作出預測。這些預測最後結合成單預測,因此優於任何一個單分類的做出預測。
隨機森林建立多個決策樹的過程: N個樣本,M個特徵
單個樹建立過程:
- 隨機在N個樣本當中選擇一個樣本,重複N次
- 隨機在M個特徵當中選出m個特徵 m取值
建立多棵決策樹,樣本,特徵大多不一樣 隨機有放回,建立決策樹
採取bootstrap抽樣
為什麼要隨機抽樣訓練集?
如果不進行隨機抽樣,每棵樹的訓練集都一樣,那麼最終訓練出的樹分類結果也是完全一樣的
為什麼要有放回地抽樣?
如果不是有放回的抽樣,那麼每棵樹的訓練樣本都是不同的,都是沒有交集的,這樣每棵樹都是"有偏的",都是絕對"片面的,也就是說每棵樹訓練出來都是有很大的差異的;而隨機森林最後分類取決於多棵樹(弱分類器)的投票表決。
隨機森林API
class sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion='gini',max_depth=None,bootstrap=True,random_state=None)
- 隨機森林分類器
- n_estimators:integer,optional(default=10)森林裡的數木數量120,200,300,500,800,1200
- criteria:string,可選(defalut="gini")分割特徵的測量方法
- max_depth:integer或None,可選(預設=無)樹的最大深度 5,8,15,25,30
- max_features="auto",每個決策樹的的最大特徵數量
- bootstrap:boolean,optional(default=True)是否在構建樹使用放回抽樣
程式碼如下所示:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
import pandas as pd
def decision():
"""
決策樹對泰坦尼克號進行預測生死
:return:
"""
#獲取資料
titan=pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
#處理資料,找出特徵值和目標值
x=titan[['pclass','age','sex']] #特徵值
y=titan['survived'] #目標值
#分割資料集到訓練集合測試集
x['age'].fillna(x['age'].mean(),inplace=True)
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25)
#進行處理(特徵工程) 特徵=》 類別=》 one_hot編碼
dict=DictVectorizer(sparse=False)
x_train=dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
rf=RandomForestClassifier()
param={"n_estimators":[120,200,300,500,800,1200],"max_depth":[5,8,15,25,30]}
#網格搜尋與交叉驗證調優
gc=GridSearchCV(rf,param_grid=param,cv=2)
gc.fit(x_train,y_train)
print("預測準確率為:",gc.score(x_test,y_test))
print("檢視選擇的引數模型:",gc.best_params_)
if __name__=="__main":
decision()
執行結果如下:
隨機森林的優點
- 在當前所有演算法中,具有極好的準確率
- 能夠有效地執行在大資料集上
- 能夠處理具有高維特徵的輸入樣本,而且不需要降維
- 能夠評估各個特徵在分類問題上的重要性