目錄
走進決策樹
案例一
案例二
靈魂的樹
決策樹的選擇機制
節點純度的度量規則
純度的度量方法
決策樹演算法背景介紹
資訊(Information)和資訊的量化
資訊熵(Information Entropy)
條件熵(Conditional Entropy)
資訊增益(Information Gain,ID3演算法使用)
資訊增益總結
基尼指數(Gini Index,CART演算法使用)
代碼實作
特征的重要性
引數splitter
剪枝引數
代碼案例
手動對max depth 進行調參
min_impurity_decrease調參
網格搜索
帶入最佳引數進行訓練
決策樹模型特征選取
相關系數
輕量級的高效梯度提升樹特征選取
再次帶入模型進行訓練
決策樹可視化
ROC曲線AUC
總結
每文一語
走進決策樹
決策樹是廣泛用于分類和回歸任務的模型,本質上,它從一層層的 if/else 問題中進行學習,并得出結論,
說到決策樹,那么最容易想到的就是在程式語言中的條件判斷陳述句,if and else 可謂是是決策樹的本質,
下面通過兩個案例對其進行本質的剖析:
案例一
想象一下,你想要區分下面這四種動物:熊、鷹、企鵝和海豚,你的目標是通過提出盡可能少的 if/else 問題來得到正確答案,你可能首先會問:這種動物有沒有羽毛,這個問題會將可能的動物減少到只有兩種,如果答案是“有”,你可以問下一個問題,幫你區分鷹和企鵝,例如,你可以問這種動物會不會飛,如果這種動物沒有羽毛,那么可能是海豚或熊,所以你需要問一個問題來區分這兩種動物——比如問這種動物有沒有鰭,
在這張圖中,樹的每個結點代表一個問題或一個包含答案的終結點(也叫葉結點),樹的邊將問題的答案與將問的下一個問題連接起來,用機器學習的語言來說就是,為了區分四類動物(鷹、企鵝、海豚和熊),我們利用三個特征(“有沒有羽毛”“會不會飛”和“有沒有鰭”)來構建一個模型,我們可以利用監督學習從資料中學習模型,而無需人為構建模型,
案例二
理想總是很美好,但是現實確實很骨感,隨著中國人口比例失衡,很多適齡青年都會面對一個嚴峻的考驗,那就是“擇偶”,正所謂“你在橋上看風景,看風景的人在看你”,那么多少人在進行另一半的尋找的時候,會考慮什么因素呢?下面看一張決策樹的現象圖:
你是否也是上述的標準呢?
靈魂的樹
在編程中, if-else所依賴的判斷條件是由程式員來填寫,但在機器學習里,我們能做的只有兩件事,第一件事是選擇模型,第二件事是往模型“嘴”里塞資料,剩下的就只能坐在一旁干著急,上面這棵可以決策的樹得依靠我們把判別條件填進去,它要想成為真正的決策樹,就得學會怎樣挑選判別條件,這是決策樹演算法的靈魂,也是接下來需要重點探討的問題,
第一個要緊問題就是:判別條件從何而來呢?分類問題的資料集由許多樣本構成,而每個樣本資料又會有多個特征維度,譬如學生資料資料集的樣本就可能包含姓名、年齡、班級、學號等特征維度,它們本身也是一個集合,我們稱為特征維度集,資料樣本的特征維度都可能與最終的類別存在某種關聯關系,決策樹的判別條件正是從這個特征維度集里產生的,
部分教材認為只有真正有助于分類的才能叫特征,原始資料里面的這些記錄專案只能稱為屬性(Attribute),而把特征維度集稱為屬性集,所以在這些教材中,決策樹是從稱為樹形集的集合中選擇判別條件,這里為了保持本書用語的連貫性,我們仍然稱之為“特征維度”,當然,這只是用語習慣上的不同,在演算法原理上是沒有任何區別的,
決策樹的選擇機制
活經驗告訴我們:挑重要的問題先問,決策樹也確實是按這個思路來選擇決策條件的,思考這個問題,可以從“怎樣才算是好的決策條件”開始,決策樹最終是要解決分類問題,那么最理想的情況當然是選好決策條件后,一個if-else就正好把資料集按正類和負類分成兩個部分,
不過,現實通常沒有“一刀切”這么理想,總會有一些不識時務的樣本“跑”到不屬于自己的類別里,我們退而求其次,希望分類結果中這些不識時務的雜質越少越好,也就是分類結果越純越好,
依照這個目標,決策樹引入了“純度”的概念,集合中歸屬同一類別的樣本越多,我們就說這個集合的純度越高,每一次使用if-else進行判別,二元分類問題的資料集都會被分成兩個子集,那么怎么評價分類的效果呢?可以通過子集的純度,子集純度越高,說明雜質越少,分類效果就越好,
節點純度的度量規則
使用決策樹這套框架的分類演算法有很多,其中最著名的決策樹演算法一共有三種,分別是ID3、C4.5和CART,這三種決策樹演算法分別采用了資訊增益、增益率和基尼指數這三種不同的指標作為決策條件的選擇依據,
雖然三種決策樹演算法分別選擇了三種不同的數學指標,但這些指標都有一個共同的目的:提高分支下的節點純度(Purity),
決策樹演算法中使用了大量二叉樹進行判別,在一次判別后,最理想的情況就是二叉樹的一個分支純粹是正類,另一個分支純粹是負類,這樣就意味著完整和準確地完成了一次分類,但大多數的判別結果都沒有這么理性,所以一個分支下會既包含正類又包含負類,不過我們希望看到的是一個分支包含的樣本盡可能地都屬于同一個類,也就是希望這個分支下面的樣本類別越純越好,所以用了“純度”來進行描述,純度有三點需要記住:
當一個分支下的所有樣本都屬于同一個類時,純度達到最高值,
當一個分支下樣本所屬的類別一半是正類一半是負類時,純度取得最低值,
純度考察的是同一個類的占比,并不在乎該類究竟是正類還是負類,譬如某個分支下無論是正類占70%,還是負類占70%,純度的度量值都是一樣的,
純度的度量方法
我們的任務就是要找到一種滿足純度達到最大值和最小值條件的純度度量函式,它既要滿足這三點需求,又要能作為量化方法,
現在讓我們把這三點要求作成影像(可視化的影像有助于更直觀地理解),同時,如果我們能夠找到一款函式符合這個影像,就等于找到了符合條件的函式,我們約定所作影像的橫軸表示某個類的占比,縱軸表示純度值,首先來分析極值點的位置,
根據第一點要求,某個類占比分別達到最大值和最小值時,純度達到最高值,最大值好理解,為什么最小值也能令純度達到最高?可以反過來想,這個類取得最小值時,另一個類就取得了最大值,所以純度也就最高,根據分析,我們知道了純度將在橫坐標的頭尾兩個位置達到最大值,
根據第二點要求,純度的最小值出現在某個類占比為50%的時候,換句話說,當橫坐標為0.5時,純度取得最低值,
現在可以作出影像了,根據上述分析的純度最高值和最低值隨類占比的變化情況,我們用一條平滑的曲線連接起這三個點,則所作出來的影像應該類似一條微笑曲線
不過我們在機器學習中更喜歡計算的是“損失值”,那么對純度度量函式的要求正好與純度函式的要求相反,因為純度值越低意味著損失值越高,反之則越低,所以純度度量函式所作出來的影像正好相反

決策樹演算法背景介紹
最早的決策樹演算法是由Hunt等人于1966年提出的CLS,后來的決策樹演算法基本都是基于Hunt演算法框架的改進,
當前最有影響力的決策樹演算法是Quinlan于1986年提出的ID3和1993年提出的C4.5(現在已經進化到C5.0),以及BFOS(Breiman、Friedman、Olshen、Stone)四位學者于1984年提出的CART演算法,
追溯其原理,決策樹的演算法原理就是如此的清晰 ,建立決策樹的關鍵,即在當前狀態下選擇哪個屬性作為分類依據

資訊(Information)和資訊的量化
假設:X為某隨機變數,xi表示X的某個取值,p(xi) 指當X=xi的概率,I(X=xi)表示X=xi的資訊量
該函式滿足: 當一個事件發生的概率越大(確定性越大), 它所攜帶的資訊量就越小, 反之, 當一個事件發生的概率越小(確定性越小), 它所攜帶的資訊量就越大,
1. 當小概率事件發生時, 我們才會感覺’資訊量大’
2. 當大概率事件發生時, 我們會感覺’理所應當’, ‘資訊量小-正常操作’
也就是越容易發生的事件,那么它所攜帶的資訊量就越小,因為不需要去尋找這些多因素
資訊熵(Information Entropy)
熵(Entropy): 事件不確定性的度量
資訊熵: 實質上就是對事件的不確定性程度的度量,也可以理解為一個事件集的平均資訊量

例如:已知小明及格的概率為0.2, 不及格的概率為0.8, 那么小明成績的不確定性如何度量呢?
H(小明成績)=?0.2?(log20.2)+(?0.8?(log20.8))=0.7219
這就是資訊熵的公式,那么假如小明的及格的概率是:0.5,不及格的概率也是:0.5,那么它的資訊熵就是:1
條件熵(Conditional Entropy)
條件熵:是為解釋資訊增益而引入的概念,即在給定條件X的情況下Y的資訊熵,以下是公式定義:

這是一個典型的二分類問題:是否為魚
資訊熵:H(是否為魚)=-P(是魚)*log2P(是魚)-P(不是魚)*log2P(不是魚)=-2/5*log22/5-3/5*log23/5=0.971
條件熵:H(是否為魚|是否用鰓呼吸)=P(用鰓呼吸)*H(是否為魚|用鰓呼吸)+P(不用鰓呼吸)*H(是否為魚|不用鰓呼吸)=3/5*(-2/3*log22/3-1/3*log21/3)+2/5(0-1log21)=0.551
H(是否為魚|是否有鰭)=P(有鰭)*H(是否為魚|有鰭)+P(沒有鰭)*H(是否為魚|沒有鰭)=4/5*(-1/2*log21/2-1/2*log21/2)+1/5(0-1log21)=0.8
資訊增益(Information Gain,ID3演算法使用)
資訊增益: 事件中某一影響因素的不確定性度量對事件資訊不確定性減少的程度,即得知特征X的資訊而使得類Y的資訊不確定性減少的程度,
如果H(D)為集合D的資訊熵,H(D|A)為集合D在特征A下的條件熵,則資訊增益可表述為如下數學公式:

即集合D的資訊熵H(D)與D在特征A下的條件熵H(D|A)之差
ID3演算法中選取最優分裂屬性的策略
首先計算未分裂前當前集合D的資訊熵H(D)
然后計算當前集合D對所包含的所有屬性A的條件熵H(D|A)
然后計算每個屬性的資訊增益IG(D|A):
IG (D|A)=H(D)?H(D|A)
選取資訊增益最大的屬性AIG=max作為決策樹進行分裂的屬性
資訊增益總結
優點:
1)考慮了特征出現與不出現的兩種情況,比較全面,
2)使用了所有樣例的統計屬性,減小了對噪聲的敏感度,
3)容易理解,計算簡單,
缺點:
1)資訊增益考察的是特征對整個系統的貢獻,沒有到具體的類別上,所以一般只能用來做全域的特征選擇,而沒法針對單個類別做特征選擇
2)演算法天生偏向選擇分支多的屬性,容易導致過擬合(overfitting)
極端的例子:如果ID被當成一個屬性,那么ID屬性的資訊增益會最大,因為按照ID劃分資料集合可以得到最純的子集,即每一個ID所在樣例都會歸屬于單一類別,故其條件熵為0,
資訊增益率: 因為資訊增益會傾向于取值最多的屬性,會導致過擬合問題,所以需要引入一個懲罰引數,即資料集D以特征A作為隨機變數的資訊熵的倒數:
存在與資訊增益相反的缺點,即偏向于取值最少的屬性,因為屬性A取值越少,H(A)也越小,導致IGA(D|A)越大,
基尼指數(Gini Index,CART演算法使用)
基尼指數: 是一種與資訊熵類似的做特征選擇的指標,可以用來表征資料的不純度,其計算公式為:

1、Pk表示選中的樣本屬于k類別的概率,不屬于K類別的概率則為(1? Pk)
2、樣本集合中有K個類別,一個隨機選中的樣本可以屬于這k個類別中的任意一個,因而對類別就加和
3、當為二分類時,Gini(p)=2p(1?p)
基尼指數解讀
基尼指數越小表示集合中被選中的樣本被分錯的概率越小,也就是說集合的純度越高,反之集合越不純,即:基尼指數(基尼不純度)= 樣本被選中的概率 * 樣本被分錯的概率
樣本集合D的Gini指數:假設集合中有K個類別,則:

基于特征A劃分樣本集合D之后的基尼指數:
CART演算法中選取最優分裂屬性的策略
需要說明的是CART是個二叉樹,也就是當使用某個特征劃分樣本集合時只會有兩個子集合:1. 等于給定的特征值的樣本集合D1? ;2. 不等于給定的特征值的樣本集合D2,CART二叉樹實際上是對擁有多個取值的特征的二值處理,
首先對樣本集合D包含的每個特征屬性A根據其取值構造系列二分子集
然后計算D基于該屬性A的每一種取值劃分所獲得的二分子集的Gini指數
然后選取Gini指數最小的屬性取值作為最優劃分點
重復上述程序
代碼實作
引數介紹
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_decrease=0.0,
min_impurity_split=None,
class_weight=None,
presort=False)

特征的重要性
前期我們也介紹了,特征選取的重要性,詳情點擊下面的文章即可查看詳細的解說:
特征選取之單變數統計、基于模型選擇、迭代選擇
clf.feature_importances_ 回傳特征的重要性 以后可以用決策樹對特征進行選擇
我通過反復的的測驗和迭代,發現決策樹選好特征數量,可以高效的提升模型的效果和各項評估指標,前面的KNN演算法,我們通過了特征選取之后,反而對模型的效果造成了干擾,但是決策樹不一樣,
機器學習需要靈活的轉變,不一定是按照某一種固定的思維來,比如網格搜索出來的引數一定是完美的嗎?不一定哦,有時手動調參出來的引數,比網格搜索要好,因為網格搜索一般加入了一些不需要的引數進去,
引數splitter
- splitter也是用來控制決策樹中的隨機選項的,有兩種輸入值:
- 輸入”best",決策樹在分枝時雖然隨機,但是還是會優先選擇更重要的特征進行分枝(重要性可以通過屬性feature_importances_查看)
- 輸入“random",決策樹在分枝時會更加隨機,樹會因為含有更多的不必要資訊而更深更大,并因這些不必要資訊而降低對訓練集的擬合,這也是防止過擬合的一種方式,
- 當你預測到你的模型會過擬合,用splitter和random_state這兩個引數來幫助你降低樹建成之后過擬合的可能性,
剪枝引數
- 在不加限制的情況下,一棵決策樹會生長到衡量不純度的指標最優,或者沒有更多的特征可用為止,這樣的決策樹 往往會過擬合,這就是說,它會在訓練集上表現很好,在測驗集上卻表現糟糕,我們收集的樣本資料不可能和整體 的狀況完全一致,因此當一棵決策樹對訓練資料有了過于優秀的解釋性,它找出的規則必然包含了訓練樣本中的噪 聲,并使它對未知資料的擬合程度不足,
- 為了讓決策樹有更好的泛化性,我們要對決策樹進行剪枝,剪枝策略對決策樹的影響巨大,正確的剪枝策略是優化 決策樹演算法的核心,sklearn為我們提供了不同的剪枝策略:
- max_depth:限制樹的最大深度,超過設定深度的樹枝全部剪掉
- 這是用得最廣泛的剪枝引數,在高維度低樣本量時非常有效,決策樹多生長一層,對樣本量的需求會增加一倍,所 以限制樹深度能夠有效地限制過擬合,在集成演算法中也非常實用,實際使用時,建議從=3開始嘗試,看看擬合的效 果再決定是否增加設定深度,
- min_samples_leaf & min_samples_split:
- min_samples_leaf限定,一個節點在分枝后的每個子節點都必須包含至少min_samples_leaf個訓練樣本,否則分 枝就不會發生,或者,分枝會朝著滿足每個子節點都包含min_samples_leaf個樣本的方向去發生,一般搭配max_depth使用,這個引數的數量設定得太小會引 起過擬合,設定得太大就會阻止模型學習資料,一般來說,建議從=5開始使用,
- min_samples_split限定,一個節點必須要包含至少min_samples_split個訓練樣本,這個節點才允許被分枝,否則 分枝就不會發生,
代碼案例
匯入第三方庫
#匯入所需要的包
from sklearn.metrics import precision_score
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
from sklearn.model_selection import GridSearchCV #網格搜索
import matplotlib.pyplot as plt#可視化
import seaborn as sns#繪圖包
初次匯入資料,不加入任何引數進行訓練
# 加載模型
model = DecisionTreeClassifier()
# 訓練模型
model.fit(X_train,y_train)
# 預測值
y_pred = model.predict(X_test)
'''
評估指標
'''
# 求出預測和真實一樣的數目
true = np.sum(y_pred == y_test )
print('預測對的結果數目為:', true)
print('預測錯的的結果數目為:', y_test.shape[0]-true)
# 評估指標
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('預測資料的準確率為: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('預測資料的精確率為:{:.4}%'.format(
precision_score(y_test,y_pred)*100))
print('預測資料的召回率為:{:.4}%'.format(
recall_score(y_test,y_pred)*100))
# print("訓練資料的F1值為:", f1score_train)
print('預測資料的F1值為:',
f1_score(y_test,y_pred))
print('預測資料的Cohen’s Kappa系數為:',
cohen_kappa_score(y_test,y_pred))
# 列印分類報告
print('預測資料的分類報告為:','\n',
classification_report(y_test,y_pred))
效果一般般,下面進行改進措施
手動對max depth 進行調參
def cv_score(d):
clf = DecisionTreeClassifier(max_depth=d)
clf.fit(X_train, y_train)
return(clf.score(X_train, y_train), clf.score(X_test, y_test))
depths = np.arange(1,10)
scores = [cv_score(d) for d in depths]
tr_scores = [s[0] for s in scores]
te_scores = [s[1] for s in scores]
# 找出交叉驗證資料集評分最高的索引
tr_best_index = np.argmax(tr_scores)
te_best_index = np.argmax(te_scores)
print("bestdepth:", te_best_index+1, " bestdepth_score:", te_scores[te_best_index], '\n')
# 可視化
%matplotlib inline
from matplotlib import pyplot as plt
depths = np.arange(1,10)
plt.figure(figsize=(6,4), dpi=120)
plt.grid()
plt.xlabel('max depth of decison tree')
plt.ylabel('Scores')
plt.plot(depths, te_scores, label='test_scores')
plt.plot(depths, tr_scores, label='train_scores')
plt.legend()
取到5和9的時候,看起來還不錯,但是一般是不會取到9,因為可能會造成過擬合
下面對其中的某一個引數進行調優,主要是介紹這種思想
min_impurity_decrease調參
def minsplit_score(val):
clf = DecisionTreeClassifier(criterion='gini',max_depth=5, min_impurity_decrease=val)
clf.fit(X_train, y_train)
return (clf.score(X_train, y_train), clf.score(X_test, y_test), )
# 指定引數范圍,分別訓練模型并計算得分
vals = np.linspace(0, 0.2, 100)
scores = [minsplit_score(v) for v in vals]
tr_scores = [s[0] for s in scores]
te_scores = [s[1] for s in scores]
bestmin_index = np.argmax(te_scores)
bestscore = te_scores[bestmin_index]
print("bestmin:", vals[bestmin_index])
print("bestscore:", bestscore)
plt.figure(figsize=(6,4), dpi=120)
plt.grid()
plt.xlabel("min_impurity_decrease")
plt.ylabel("Scores")
plt.plot(vals, te_scores, label='test_scores')
plt.plot(vals, tr_scores, label='train_scores')
plt.legend()
這里看起來效果有了提升
通過手動調參,主要確定了兩個引數的范圍
網格搜索
import numpy as np from sklearn.model_selection import GridSearchCV parameters = {'splitter':('best','random') ,'criterion':("gini","entropy") ,"max_depth":[np.arange(4,10,1)] ,"max_depth":[*range(1,10)] ,'min_samples_leaf':[*range(1,50,5)] } clf = DecisionTreeClassifier(random_state=25) GS = GridSearchCV(clf, parameters, cv=5) # cv交叉驗證 GS.fit(X_train,y_train) GS.best_params_
又確定了幾個主要的引數
帶入最佳引數進行訓練
# 加載模型
model = DecisionTreeClassifier(criterion='gini',max_depth=5, splitter= 'random')
# 訓練模型
model.fit(X_train,y_train)
# 預測值
y_pred = model.predict(X_test)
'''
評估指標
'''
# 求出預測和真實一樣的數目
true = np.sum(y_pred == y_test )
print('預測對的結果數目為:', true)
print('預測錯的的結果數目為:', y_test.shape[0]-true)
# 評估指標
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('預測資料的準確率為: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('預測資料的精確率為:{:.4}%'.format(
precision_score(y_test,y_pred)*100))
print('預測資料的召回率為:{:.4}%'.format(
recall_score(y_test,y_pred)*100))
# print("訓練資料的F1值為:", f1score_train)
print('預測資料的F1值為:',
f1_score(y_test,y_pred))
print('預測資料的Cohen’s Kappa系數為:',
cohen_kappa_score(y_test,y_pred))
# 列印分類報告
print('預測資料的分類報告為:','\n',
classification_report(y_test,y_pred))

效果還是一般,總的來說有了提升,但是不夠明顯,需要進一步
下面進行特征選取,在決策樹里面,特征選取重要性還是比較的強,下面進行多方面的特征選取,看看是否可以提升模型的效果
決策樹模型特征選取
feature_weight = model.feature_importances_
feature_name = df.columns[:-1]
feature_sort = pd.Series(data = feature_weight ,index = feature_name)
feature_sort = feature_sort.sort_values(ascending = False)
plt.figure(figsize=(10,8))
sns.barplot(feature_sort.values,feature_sort.index, orient='h')
相關系數
plt.subplots(figsize=(10, 15))
sns.heatmap(df.corr()[['n23']].sort_values(by="n23",ascending=False), annot=True, vmax=1, square=True, cmap="Blues")
plt.rcParams['axes.unicode_minus']=False
# plt.rcParams['font.sans-serif']=['HeiTi']
plt.show()
X_name=df.corr()[["n23"]].sort_values(by="n23",ascending=False).iloc[1:7].index.values.astype("U")
print(X_name)
這種方法是基于數學理論知識進行匹配的,一共選取了6種重要的特征
輕量級的高效梯度提升樹特征選取
from sklearn.model_selection import train_test_split,cross_val_score #拆分訓練集和測驗集
import lightgbm as lgbm #輕量級的高效梯度提升樹
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,stratify=y,random_state=1)
lgbm_class = lgbm.LGBMClassifier(max_depth=5,num_leaves=25,learning_rate=0.005,n_estimators=1000,min_child_samples=80, subsample=0.8,colsample_bytree=1,reg_alpha=0,reg_lambda=0)
lgbm_class.fit(X_train, y_train)
#選擇最重要的20個特征,繪制他們的重要性排序圖
lgbm.plot_importance(lgbm_reg, max_num_features=14)
##也可以不使用自帶的plot_importance函式,手動獲取特征重要性和特征名,然后繪圖
feature_weight = lgbm_class.feature_importances_
feature_name = lgbm_class.feature_name_
feature_sort = pd.Series(data = feature_weight ,index = feature_name)
feature_sort = feature_sort.sort_values(ascending = False)
# plt.figure(figsize=(10,8))
# sns.barplot(feature_sort.values,feature_sort.index, orient='h')
lgbm_name=feature_sort.index[:8].tolist()
lgbm_name

再次帶入模型進行訓練
把剛剛用相關系數所選取的6個特征帶入模型進行訓練,再次查看效果
# 加載模型
model = DecisionTreeClassifier(criterion='gini',max_depth=5, splitter= 'random')
# 訓練模型
model.fit(X_train,y_train)
# 預測值
y_pred = model.predict(X_test)
'''
評估指標
'''
# 求出預測和真實一樣的數目
true = np.sum(y_pred == y_test )
print('預測對的結果數目為:', true)
print('預測錯的的結果數目為:', y_test.shape[0]-true)
# 評估指標
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('預測資料的準確率為: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('預測資料的精確率為:{:.4}%'.format(
precision_score(y_test,y_pred)*100))
print('預測資料的召回率為:{:.4}%'.format(
recall_score(y_test,y_pred)*100))
# print("訓練資料的F1值為:", f1score_train)
print('預測資料的F1值為:',
f1_score(y_test,y_pred))
print('預測資料的Cohen’s Kappa系數為:',
cohen_kappa_score(y_test,y_pred))
# 列印分類報告
print('預測資料的分類報告為:','\n',
classification_report(y_test,y_pred))
現在發現,效果明顯的提升了,準確率達到了93%,召回率也比較的高

決策樹可視化
import graphviz
from IPython.display import Image
dot_data = tree.export_graphviz(model
,feature_names= ["簽署知情同意書","認知功能","自理能力三級","行動能力","有無管道","身體攻擊行為"]
#'n22' 'n8' 'n10new' 'MOBILITY' 'n19f1' 'n13'
,class_names=["不需要","需要"]
,filled=True
,rounded = True
,out_file =None#圖片保存路徑
)
graph = graphviz.Source(dot_data.replace('helvetica','"Microsoft YaHei"'), encoding='utf-8')
graph.view()

這就是決策樹模型下的可視化,可以高效率的展示出分類程序,其中

ROC曲線AUC
from sklearn.metrics import precision_recall_curve
from sklearn import metrics
# 預測正例的概率
y_pred_prob=model.predict_proba(X_test)[:,1]
# y_pred_prob ,回傳兩列,第一列代表類別0,第二列代表類別1的概率
#https://blog.csdn.net/dream6104/article/details/89218239
fpr, tpr, thresholds = metrics.roc_curve(y_test,y_pred_prob, pos_label=2)
#pos_label,代表真陽性標簽,就是說是分類里面的好的標簽,這個要看你的特征目標標簽是0,1,還是1,2
roc_auc = metrics.auc(fpr, tpr) #auc為Roc曲線下的面積
# print(roc_auc)
plt.figure(figsize=(8,6))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.plot(fpr, tpr, 'r',label='AUC = %0.2f'% roc_auc)
plt.legend(loc='lower right')
# plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1.1])
plt.ylim([0, 1.1])
plt.xlabel('False Positive Rate') #橫坐標是fpr
plt.ylabel('True Positive Rate') #縱坐標是tpr
plt.title('Receiver operating characteristic example')
plt.show()

這就是決策樹下的預測分類,在本次模型中,首先采取的模型引數調優,然后進行的特性選取,一般來說首先應該進行特征選取然后去進行引數調優,通過驗證,本次資料集下的模型效果一致,

主要的max depth=5,是符合模型的最優選擇的
總結
如前所述,控制決策樹模型復雜度的引數是預剪枝引數,它在樹完全展開之前停止樹的構造,通常來說,選擇一種預剪枝策略(設定 max_depth、 max_leaf_nodes 或 min_samples_leaf)足以防止過擬合,
與前面討論過的許多演算法相比,決策樹有兩個優點:一是得到的模型很容易可視化,非專家也很容易理解(至少對于較小的樹而言);二是演算法完全不受資料縮放的影響,由于每個特征被單獨處理,而且資料的劃分也不依賴于縮放,因此決策樹演算法不需要特征預處理,比如歸一化或標準化,特別是特征的尺度完全不一樣時或者二元特征和連續特征同時存在時,決策樹的效果很好,
決策樹的主要缺點在于,即使做了預剪枝,它也經常會過擬合,泛化性能很差,因此,在
大多數應用中,往往使用后續的隨機森林,介紹的集成方法來替代單棵決策樹,
每文一語
要拿的起,也要放得下
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423424.html
標籤:AI













