sklearn分类器算法:决策树与随机森林及案例分析
分類算法之決策樹
決策樹是一種基本的分類方法,當(dāng)然也可以用于回歸。我們一般只討論用于分類的決策樹。決策樹模型呈樹形結(jié)構(gòu)。在分類問題中,表示基于特征對(duì)實(shí)例進(jìn)行分類的過程,它可以認(rèn)為是if-then規(guī)則的集合。在決策樹的結(jié)構(gòu)中,每一個(gè)實(shí)例都被一條路徑或者一條規(guī)則所覆蓋。通常決策樹學(xué)習(xí)包括三個(gè)步驟:特征選擇、決策樹的生成和決策樹的修剪
優(yōu)點(diǎn):計(jì)算復(fù)雜度不高,輸出結(jié)果易于理解,對(duì)中間值的缺失不敏感,可以處理邏輯回歸等不能解決的非線性特征數(shù)據(jù)
缺點(diǎn):可能產(chǎn)生過度匹配問題
適用數(shù)據(jù)類型:數(shù)值型和標(biāo)稱型
特征選擇
特征選擇在于選取對(duì)訓(xùn)練數(shù)據(jù)具有分類能力的特征。這樣可以提高決策樹學(xué)習(xí)的效率,如果利用一個(gè)特征進(jìn)行分類的結(jié)果與隨機(jī)分類的結(jié)果沒有很大差別,則稱這個(gè)特征是沒有分類能力的。經(jīng)驗(yàn)上扔掉這樣的特征對(duì)決策樹學(xué)習(xí)的京都影響不大。通常特征選擇的準(zhǔn)則是信息增益,這是個(gè)數(shù)學(xué)概念。通過一個(gè)例子來了解特征選擇的過程。
| 1 | 青年 | 否 | 否 | 一般 | 否 |
| 2 | 青年 | 否 | 否 | 好 | 否 |
| 3 | 青年 | 是 | 否 | 好 | 是 |
| 4 | 青年 | 是 | 是 | 一般 | 是 |
| 5 | 青年 | 否 | 否 | 一般 | 否 |
| 6 | 中年 | 否 | 否 | 一般 | 否 |
| 7 | 中年 | 否 | 否 | 好 | 否 |
| 8 | 中年 | 是 | 是 | 好 | 是 |
| 9 | 中年 | 否 | 是 | 非常好 | 是 |
| 10 | 中年 | 否 | 是 | 非常好 | 是 |
| 11 | 老年 | 否 | 是 | 非常好 | 是 |
| 12 | 老年 | 否 | 是 | 好 | 是 |
| 13 | 老年 | 是 | 否 | 好 | 是 |
| 14 | 老年 | 是 | 否 | 非常好 | 是 |
| 15 | 老年 | 否 | 否 | 一般 | 否 |
我們希望通過所給的訓(xùn)練數(shù)據(jù)學(xué)習(xí)一個(gè)貸款申請(qǐng)的決策樹,用以對(duì)文萊的貸款申請(qǐng)進(jìn)行分類,即當(dāng)新的客戶提出貸款申請(qǐng)是,根據(jù)申請(qǐng)人的特征利用決策樹決定是否批準(zhǔn)貸款申請(qǐng)。特征選擇其實(shí)是決定用那個(gè)特征來劃分特征空間。下圖中分別是按照年齡,還有是否有工作來劃分得到不同的子節(jié)點(diǎn)
問題是究竟選擇哪個(gè)特征更好些呢?那么直觀上,如果一個(gè)特征具有更好的分類能力,是的各個(gè)自己在當(dāng)前的條件下有最好的分類,那么就更應(yīng)該選擇這個(gè)特征。信息增益就能很好的表示這一直觀的準(zhǔn)則。這樣得到的一棵決策樹只用了兩個(gè)特征就進(jìn)行了判斷:
通過信息增益生成的決策樹結(jié)構(gòu),更加明顯、快速的劃分類別。下面介紹scikit-learn中API的使用
信息的度量和作用
我們常說信息有用,那么它的作用如何客觀、定量地體現(xiàn)出來呢?信息用途的背后是否有理論基礎(chǔ)呢?這個(gè)問題一直沒有很好的回答,直到1948年,香農(nóng)在他的論文“通信的數(shù)學(xué)原理”中提到了“信息熵”的概念,才解決了信息的度量問題,并量化出信息的作用。
一條信息的信息量與其不確定性有著直接的關(guān)系,比如我們要搞清一件非常不確定的事,就需要大量的信息。相反如果對(duì)某件事了解較多,則不需要太多的信息就能把它搞清楚。所以從這個(gè)角度看,可以認(rèn)為,信息量就等于不確定的多少。那么如何量化信息量的度量呢?2022年舉行世界杯,大家很關(guān)系誰是冠軍。假如我錯(cuò)過了看比賽,賽后我問朋友,“誰是冠軍”?他不愿意直接告訴我,讓我每猜一次給他一塊錢,他告訴我是否猜對(duì)了,那么我需要掏多少錢才能知道誰是冠軍?我可以把球編上號(hào),從1到32,然后提問:冠軍在1-16號(hào)嗎?依次詢問,只需要五次,就可以知道結(jié)果。所以誰是世界杯冠軍這條消息只值五塊錢。當(dāng)然香農(nóng)不是用錢,而是用“比特”這個(gè)概念來度量信息量。一個(gè)比特是一位二進(jìn)制數(shù),在計(jì)算機(jī)中一個(gè)字節(jié)是8比特。
那么如果說有一天有64支球隊(duì)進(jìn)行決賽階段的比賽,那么“誰是世界杯冠軍”的信息量就是6比特,因?yàn)橐嗖乱淮?#xff0c;有的同學(xué)就會(huì)發(fā)現(xiàn),信息量的比特?cái)?shù)和所有可能情況的對(duì)數(shù)函數(shù)log有關(guān),(log32=5,log64=6)
另外一方面你也會(huì)發(fā)現(xiàn)實(shí)際上我們不需要猜五次就能才出冠軍,因?yàn)橄裎靼嘌?、巴西、德?guó)、意大利這樣的球隊(duì)奪得冠軍的可能性比南非、尼日利亞等球隊(duì)大得多,因此第一次猜測(cè)時(shí)不需要把32支球隊(duì)等分成兩個(gè)組,而可以把少數(shù)幾支最有可能的球隊(duì)分成一組,把其他球隊(duì)分成一組。然后才冠軍球隊(duì)是否在那幾支熱門隊(duì)中。這樣,也許三次就猜出結(jié)果。因此,當(dāng)每支球隊(duì)奪冠的可能性不等時(shí),“誰是世界杯冠軍”的信息量比5比特少。香農(nóng)指出,它的準(zhǔn)確信息量應(yīng)該是:
H = -(p1logp1 + p2logp2 + ... + p32log32)
其中,p1...p32為這三支球隊(duì)奪冠的概率。H的專業(yè)術(shù)語(yǔ)稱之為信息熵,單位為比特,當(dāng)這32支球隊(duì)奪冠的幾率相同時(shí),對(duì)應(yīng)的信息熵等于5比特,這個(gè)可以通過計(jì)算得出。有一個(gè)特性就是,5比特是公式的最大值。那么信息熵(經(jīng)驗(yàn)熵)的具體定義可以為如下:
$$H\left(X\right){=}\sum_{x\in{X}}P\left(x\right)logP\left(x\right)$$
信息增益
自古以來,信息和消除不確定性是相聯(lián)系的。所以決策樹的過程其實(shí)是在尋找某一個(gè)特征對(duì)整個(gè)分類結(jié)果的不確定減少的過程。那么這樣就有一個(gè)概念叫做信息增益(information gain)。
那么信息增益表示得知特征X的信息而是的類Y的信息的不確定性減少的程度,所以我們對(duì)于選擇特征進(jìn)行分類的時(shí)候,當(dāng)然選擇信息增益較大的特征,這樣具有較強(qiáng)的分類能力。特征A對(duì)訓(xùn)練數(shù)據(jù)集D的信息增益g(D,A),定義為集合D的經(jīng)驗(yàn)熵H(D)與特征A給定條件下D的經(jīng)驗(yàn)條件熵H(D|A)之差,即公式為:
$$g\left({D,A}\right){=}H\left(D\right) {-} H\left(D|A\right)$$
根據(jù)信息增益的準(zhǔn)則的特征選擇方法是:對(duì)于訓(xùn)練數(shù)據(jù)集D,計(jì)算其每個(gè)特征的信息增益,并比較它們的阿笑,選擇信息增益最大的特征
信息增益的計(jì)算
假設(shè)訓(xùn)練數(shù)據(jù)集為D,|D|表示樣本個(gè)數(shù)。設(shè)有K個(gè)類$$Ck$$,k=1,2,3,4...k,$$|C_k|$$為屬于類$$C_k$$的樣本個(gè)數(shù),$$\sum{k=1}^{K}{=}{|D|}$$.設(shè)特征A有n個(gè)不同的取值{a1,a2,...,an},根據(jù)特征A的取值將D劃分為n個(gè)子集D1,D2,...,Dn,$$|Di|$$為樣本個(gè)數(shù),其中Di中屬于Ck類的樣本的集合為$$D_ik$$
所以首先對(duì)于經(jīng)驗(yàn)熵來說,計(jì)算如下:
那么條件熵計(jì)算如下:
既然我們有了這兩個(gè)公式,我們可以根據(jù)前面的是否通過貸款申請(qǐng)的例子來通過計(jì)算得出我們的決策特征順序。那么我們首先計(jì)算總的經(jīng)驗(yàn)熵為:
然后我們讓$$A_1,A_2,A_3,A_4$$分別表示年齡、有工作、有自己的房子和信貸情況4個(gè)特征,則計(jì)算出年齡的信息增益為:
同理其他的也可以計(jì)算出來,g(D,A2)=0.324,g(D,A3)=0.420,g(D,A4)=0.363,相比較來說其中特征A3(有自己的房子)的信息增益最大,所以我們選擇特征A3為最有特征
sklearn.tree.DecisionTreeClassifier
sklearn.tree.DecisionTreeClassifier是一個(gè)能對(duì)數(shù)據(jù)集進(jìn)行多分類的類
class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_split=1e-07, class_weight=None, presort=False)""":param max_depth:int或None,可選(默認(rèn)=無)樹的最大深度。如果沒有,那么節(jié)點(diǎn)將被擴(kuò)展,直到所有的葉子都是純類,或者直到所有的葉子都包含少于min_samples_split樣本:param random_state:random_state是隨機(jī)數(shù)生成器使用的種子"""首先我們導(dǎo)入類,以及數(shù)據(jù)集,還有將數(shù)據(jù)分成訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集兩部分
from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.tree import DecisionTreeClassifier iris = load_iris() X = iris.data y = iris.target X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) estimator = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0) estimator.fit(X_train, y_train)method
apply返回每個(gè)樣本被預(yù)測(cè)的葉子的索引
estimator.apply(X)array([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5, 5, 15, 5, 5, 5, 5, 5, 5, 10, 5, 5, 5, 5, 5, 10, 5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 16, 16,16, 16, 16, 16, 6, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,8, 16, 16, 16, 16, 16, 16, 14, 16, 16, 11, 16, 16, 16, 8, 8, 16,16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16])decision_path返回樹中的決策路徑
dp = estimator.decision_path(X_test)fit_transform(X,y=None,fit_params)**輸入數(shù)據(jù),然后轉(zhuǎn)換
predict(X)預(yù)測(cè)輸入數(shù)據(jù)的類型,完整代碼
estimator.predict(X_test) array([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0,0, 1, 0, 0, 1, 1, 0, 2, 1, 0, 1, 2, 1, 0, 2])print y_testarray([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1, 0,0, 2, 0, 0, 1, 1, 0, 2, 1, 0, 2, 2, 1, 0, 1])score(X,y,sample_weight=None)返回給定測(cè)試數(shù)據(jù)的準(zhǔn)確精度
estimator.score(X_test,y_test)0.89473684210526316決策樹本地保存
sklearn.tree.export_graphviz()該函數(shù)能夠?qū)С鯠OT格式
from sklearn.datasets import load_iris from sklearn import tree clf = tree.DecisionTreeClassifier() iris = load_iris() clf = clf.fit(iris.data, iris.target) tree.export_graphviz(clf,out_file='tree.dot')那么有了tree.dot文件之后,我們可以通過命令轉(zhuǎn)換為png或者pdf格式,首先得安裝graphviz
ubuntu:sudo apt-get install graphviz Mac:brew install graphviz然后我們運(yùn)行這個(gè)命令
$ dot -Tps tree.dot -o tree.ps $ dot -Tpng tree.dot -o tree.png或者,如果我們安裝了Python模塊pydotplus,我們可以直接在Python中生成PDF文件,通過pip install pydotplus,然后運(yùn)行
import pydotplus dot_data = tree.export_graphviz(clf, out_file=None) graph = pydotplus.graph_from_dot_data(dot_data) graph.write_pdf("iris.pdf")查看決策樹結(jié)構(gòu)圖片,這個(gè)結(jié)果是經(jīng)過決策樹學(xué)習(xí)的三個(gè)步驟之后形成的。當(dāng)作了解
擴(kuò)展:所有各種決策樹算法是什么,它們之間有什么不同?哪一個(gè)在scikit-learn中實(shí)現(xiàn)?
ID3 --- 信息增益 最大的準(zhǔn)則
C4.5 --- 信息增益比 最大的準(zhǔn)則
CART回歸樹: 平方誤差 最小分類樹: 基尼系數(shù) 最小的準(zhǔn)則在sklearn中可以選擇劃分的原則
決策樹優(yōu)缺點(diǎn)分析
決策樹的一些優(yōu)點(diǎn)是:
簡(jiǎn)單的理解和解釋。樹木可視化。
需要很少的數(shù)據(jù)準(zhǔn)備。其他技術(shù)通常需要數(shù)據(jù)歸一化,需要?jiǎng)?chuàng)建虛擬變量,并刪除空值。但請(qǐng)注意,此模塊不支持缺少值。
使用樹的成本(即,預(yù)測(cè)數(shù)據(jù))在用于訓(xùn)練樹的數(shù)據(jù)點(diǎn)的數(shù)量上是對(duì)數(shù)的。
決策樹的缺點(diǎn)包括:
決策樹學(xué)習(xí)者可以創(chuàng)建不能很好地推廣數(shù)據(jù)的過于復(fù)雜的樹。這被稱為過擬合。修剪(目前不支持)的機(jī)制,設(shè)置葉節(jié)點(diǎn)所需的最小采樣數(shù)或設(shè)置樹的最大深度是避免此問題的必要條件。
決策樹可能不穩(wěn)定,因?yàn)閿?shù)據(jù)的小變化可能會(huì)導(dǎo)致完全不同的樹被生成。通過使用合奏中的決策樹來減輕這個(gè)問題。
集成方法(分類)之隨機(jī)森林
在機(jī)器學(xué)習(xí)中,隨機(jī)森林是一個(gè)包含多個(gè)決策樹的分類器,并且其輸出的類別是由個(gè)別樹輸出的類別的眾數(shù)而定。利用相同的訓(xùn)練數(shù)搭建多個(gè)獨(dú)立的分類模型,然后通過投票的方式,以少數(shù)服從多數(shù)的原則作出最終的分類決策。例如, 如果你訓(xùn)練了5個(gè)樹, 其中有4個(gè)樹的結(jié)果是True, 1個(gè)數(shù)的結(jié)果是False, 那么最終結(jié)果會(huì)是True.
在前面的決策當(dāng)中我們提到,一個(gè)標(biāo)準(zhǔn)的決策樹會(huì)根據(jù)每維特征對(duì)預(yù)測(cè)結(jié)果的影響程度進(jìn)行排序,進(jìn)而決定不同的特征從上至下構(gòu)建分裂節(jié)點(diǎn)的順序,如此以來,所有在隨機(jī)森林中的決策樹都會(huì)受這一策略影響而構(gòu)建的完全一致,從而喪失的多樣性。所以在隨機(jī)森林分類器的構(gòu)建過程中,每一棵決策樹都會(huì)放棄這一固定的排序算法,轉(zhuǎn)而隨機(jī)選取特征。
學(xué)習(xí)算法
根據(jù)下列算法而建造每棵樹:
- 用N來表示訓(xùn)練用例(樣本)的個(gè)數(shù),M表示特征數(shù)目。
- 輸入特征數(shù)目m,用于確定決策樹上一個(gè)節(jié)點(diǎn)的決策結(jié)果;其中m應(yīng)遠(yuǎn)小于M。
- 從N個(gè)訓(xùn)練用例(樣本)中以有放回抽樣的方式,取樣N次,形成一個(gè)訓(xùn)練集(即bootstrap取樣),并用未抽到的用例(樣本)作預(yù)測(cè),評(píng)估其誤差。
- 對(duì)于每一個(gè)節(jié)點(diǎn),隨機(jī)選擇m個(gè)特征,決策樹上每個(gè)節(jié)點(diǎn)的決定都是基于這些特征確定的。根據(jù)這m個(gè)特征,計(jì)算其最佳的分裂方式。
sklearn.ensemble,集成方法模塊
sklearn.ensemble提供了準(zhǔn)確性更加好的集成方法,里面包含了主要的RandomForestClassifier(隨機(jī)森林)方法。
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, oob_score=False, n_jobs=1, random_state=None)""":param n_estimators:integer,optional(default = 10) 森林里的樹木數(shù)量。:param criteria:string,可選(default =“gini”)分割特征的測(cè)量方法:param max_depth:integer或None,可選(默認(rèn)=無)樹的最大深度:param bootstrap:boolean,optional(default = True)是否在構(gòu)建樹時(shí)使用自舉樣本。"""屬性
- classes_:shape = [n_classes]的數(shù)組或這樣的數(shù)組的列表,類標(biāo)簽(單輸出問題)或類標(biāo)簽數(shù)組列表(多輸出問題)。
- featureimportances:array = [n_features]的數(shù)組, 特征重要性(越高,功能越重要)。
方法
fit(X,y [,sample_weight]) 從訓(xùn)練集(X,Y)構(gòu)建一棵樹林。
predict(X) 預(yù)測(cè)X的類
score(X,y [,sample_weight]) 返回給定測(cè)試數(shù)據(jù)和標(biāo)簽的平均精度。
decision_path(X) 返回森林中的決策路徑
泰坦尼克號(hào)乘客數(shù)據(jù)案例
這里我們通過決策樹和隨機(jī)森林對(duì)這個(gè)數(shù)據(jù)進(jìn)行一個(gè)分類,判斷乘客的生還。
完整代碼
import pandas as pd import sklearn from sklearn.cross_validation import train_test_split from sklearn.feature_extraction import DictVectorizer from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import classification_report from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifiertitanic = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt')#選取一些特征作為我們劃分的依據(jù) x = titanic[['pclass', 'age', 'sex']] y = titanic['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)dt = DictVectorizer(sparse=False)print(x_train.to_dict(orient="record"))# 按行,樣本名字為鍵,列名也為鍵,[{"1":1,"2":2,"3":3}] x_train = dt.fit_transform(x_train.to_dict(orient="record"))x_test = dt.fit_transform(x_test.to_dict(orient="record"))# 使用決策樹 dtc = DecisionTreeClassifier()dtc.fit(x_train, y_train)dt_predict = dtc.predict(x_test)print(dtc.score(x_test, y_test))print(classification_report(y_test, dt_predict, target_names=["died", "survived"]))# 使用隨機(jī)森林rfc = RandomForestClassifier()rfc.fit(x_train, y_train)rfc_y_predict = rfc.predict(x_test)print(rfc.score(x_test, y_test))print(classification_report(y_test, rfc_y_predict, target_names=["died", "survived"]))總結(jié)
以上是生活随笔為你收集整理的sklearn分类器算法:决策树与随机森林及案例分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟主机不支持mysql_虚拟主机能用m
- 下一篇: 数组排序(冒泡、排序)