ML算法基礎——分類算法-決策樹、隨機森林

1.決策樹

1.1 認識決策樹

決策樹思想的來源非常樸素,程序設計中的條件分支結構就是if-then結構,最早的決策樹就是利用這類結構分割數據的一種分類學習方法

1.2 信息論基礎-銀行貸款分析

如何去劃分是否能得到貸款?
image

1.2.1 信息論基礎-信息熵

香農被稱爲是“信息論之父”。人們通常將香農於1948年10月發表於《貝爾系統技術學報》上的論文《A Mathematical Theory of Communication》(通信的數學理論)作爲現代信息論研究的開端。這一文章部分基於哈里·奈奎斯特和拉爾夫·哈特利先前的成果。在該文中,香農給出了信息熵(以下簡稱爲“熵”)的定義:
image

H的專業術語稱之爲信息熵,單位爲比特。
這一定義可以用來推算傳遞經二進制編碼後的原信息所需的信道帶寬。熵度量的是消息中所含的信息量,其中去除了由消息的固有結構所決定的部分,比如,語言結構的冗餘性以及語言中字母、詞的使用頻度等統計特性。

注:信息和消除不確定性是相聯繫的

1.2.2 決策樹的劃分依據之一-信息增益

特徵A對訓練數據集D的信息增益g(D,A),定義爲集合D的信息熵H(D)與特徵A給定條件下D的信息條件熵H(D|A)之差,即公式爲:
image

注:信息增益表示得知特徵X的信息而使得類Y的信息的不確定性減少的程度

信息增益的計算
image
既然我們有了這兩個公式,我們可以根據前面的是否通過貸款申請的例子來通過計算得出我們的決策特徵順序。那麼我們首先計算總的經驗熵爲:

H(D)=-(9/15)log(9/15)-(6/15)log(6/15) = 0.971

然後我們讓A1,A2,A3,A4分別表示年齡、有工作、有自己的房子和信貸情況4個特徵,則計算出年齡的信息
年齡:

g(D,A1)=H(D)-[(5/15)H(D1)+(5/15)H(D2)+(5/15)H(D3)]
H(D1)=-(2/5)log(2/5)-(3/5)log(3/5)
H(D2)=-(3/5)log(3/5)-(2/5)log(2/5)
H(D3)=-(4/5)log(4/5)-(1/5)log(1/5)

同理其他的也可以計算出來, g(D,A2)=0.324,g(D,A3)=0.420,g(D,A4)=0.363,相比較來說其中特徵A3(有自己的房子)的信息增益最大,所以我們選擇特徵A3爲最有特徵

1.3 泰坦尼克號乘客生存分類

1.3.1 sklearn決策樹API

  • class sklearn.tree.DecisionTreeClassifier(criterion=’gini’,max_depth=None,random_state=None)
    • 決策樹分類器
  • criterion:默認是’gini’係數,也可以選擇信息增益的熵’entropy’
  • max_depth:樹的深度大小
  • random_state:隨機數種子
  • method:
  • decision_path:返回決策樹的路徑

1.3.2 泰坦尼克號乘客生存分類模型

泰坦尼克號數據

數據:http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt

在泰坦尼克號和titanic2數據幀描述泰坦尼克號上的個別乘客的生存狀態。在泰坦尼克號的數據幀不包含從劇組信息,但它確實包含了乘客的一半的實際年齡。關於泰坦尼克號旅客的數據的主要來源是百科全書Titanica。這裏使用的數據集是由各種研究人員開始的。其中包括許多研究人員創建的旅客名單,由Michael A. Findlay編輯。

我們提取的數據集中的特徵是票的類別,存活,乘坐班,年齡,登陸,home.dest,房間,票,船和性別。乘坐班是指乘客班(1,2,3),是社會經濟階層的代表。

其中age數據存在缺失。

流程

import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

def decision():
    #獲取數據
    titan=pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")


    #處理數據
    x=titan[['pclass','age','sex']]
    y=titan[['survived']]
    print(x)
    #缺失值處理
    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)
    #處理(特徵工程)特徵-類別-onehot
    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"))
    # print(x_train)
    #決策樹預測
    dec=DecisionTreeClassifier()

    dec.fit(x_train,y_train)
    #預測準確率
    print("預測的準確率:",dec.score(x_test,y_test))

    return None

decision()

結果:

預測的準確率: 0.8054711246200608

1.4 決策樹的結構、本地保存

1.4.1 導出DOT格式

sklearn.tree.export_graphviz()

export_graphviz(dec,out_file="./tree.dot",feature_names=['年齡', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=女性', 'sex=男性'])

1.4.2 安裝graphviz

工具:(能夠將dot文件轉換爲pdf、png)

  • ubuntu:sudo apt-get install graphviz
  • Mac:brew install graphviz
  • windows:jingyan.baidu.com/article/020278115032461bcc9ce598.html

1.4.3 運行命令

注意:windows下ctrl+r打開cmd,輸入完整“dot.exe”的路徑才能轉換成圖片

E:\pycharmproject>"D:\***\graphviz-2.38\bin\dot.exe" -Tpng tree.dot -o tree.png

image
可以看到已經轉換成png格式,打卡文件
image

1.5 決策樹的優缺點以及改進

  • 優點:
    • 簡單的理解和解釋,樹木可視化
    • 需要很少的數據準備,其他技術通常需要數據歸一化
  • 缺點:
    • 決策樹學習者可以創建不能很好地推廣數據的過於複雜的樹,這被稱爲過擬合。
    • 決策樹可能不穩定,因爲數據的小變化可能會導致完全不同的樹
      被生成
  • 改進:
    • 減枝cart算法(決策樹API中已經實現)
    • 隨機森林

2.集成學習方法-隨機森林

集成學習方法

集成學習通過建立幾個模型組合的來解決單一預測問題。它的工作原理是生成多個分類器/模型,各自獨立地學習和作出預測。這些預測最後結合成單預測,因此優於任何一個單分類的做出預測。

2.1 隨機森林簡述

定義:在機器學習中,隨機森林是一個包含多個決策樹的分類器,並且其輸出的類別是由個別樹輸出的類別的衆數而定。

學習算法
根據下列算法而建造每棵樹:

用N來表示訓練用例(樣本)的個數,M表示特徵數目。
輸入特徵數目m,用於確定決策樹上一個節點的決策結果;其中m應遠小於M。

從N個訓練用例(樣本)中以有放回抽樣的方式,取樣N次,形成一個訓練集(即bootstrap取樣),並用未抽到的用例(樣本)作預測,評估其誤差。

爲什麼要隨機抽樣訓練集?

如果不進行隨機抽樣,每棵樹的訓練集都一樣,那麼最終訓練出的樹分類結果也是完全一樣的

爲什麼要有放回地抽樣?

如果不是有放回的抽樣,那麼每棵樹的訓練樣本都是不同的,都是沒有交集的,這樣每棵樹都是“有偏的”,都是絕對“片面的”(當然這樣說可能不對),也就是說每棵樹訓練出來都是有很大的差異的;而隨機森林最後分類取決於多棵樹(弱分類器)的投票表決。

2.2 集成學習API

  • class sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion=’gini’,max_depth=None, bootstrap=True,random_state=None)
    • 隨機森林分類器
    • n_estimators:integer,optional(default = 10) 森林裏的樹木數量
    • criteria:string,可選(default =“gini”)分割特徵的測量方法
    • max_depth:integer或None,可選(默認=無)樹的最大深度
    • bootstrap:boolean,optional(default = True)是否在構建樹時使用放回抽樣
    • max_features=“auto”,每個決策樹的最大特徵數量
      • If “auto”, then ‘max_ features= =sqrt(n_ features)’.
      • If “sqrt”, then ‘max_ features= =sqrt(n_ features)’(same as “auto”).
      • If “log2”, then ‘max_ features: =log2(n_ features)’.
      • If None, then ‘max_ features=n_ features’.

2.3 泰坦尼克號乘客生存分類分析

import pandas as pd
import numpy as np
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV

def decision():
    #獲取數據
    titan=pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")


    #處理數據
    x=titan[['pclass','age','sex']]
    y=titan[['survived']]
    #print(x)
    #缺失值處理
    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)
    #處理(特徵工程)特徵-類別-onehot
    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"))
    # print(x_train)
    #隨機森林預測(超參數調優)
    rf=RandomForestClassifier()
    param={"n_estimators":[100,200,300,500,800,1200],"max_depth":[5,8,15,25,30]}
    #網格搜索與交叉驗證
    gc=GridSearchCV(rf,param_grid=param,cv=2)
    print(y_train)
    y_train=np.ravel(y_train)
    print("_____________________________")
    print(y_train)
    gc.fit (x_train,y_train)
    print("準確率爲:",gc.score(x_test,y_test))
    print("選擇的參數模型:", gc.best_params_)

    return None
 
decision()

2.4 隨機森林的優點

  • 在當前所有算法中,具有極好的準確率
  • 能夠有效地運行在大數據集上
  • 能夠處理具有高維特徵的輸入樣本,而且不需要降維
  • 能夠評估各個特徵在分類問題上的重要性
  • 對於缺省值問題也能夠獲得很好得結果
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章