標籤:變數 col img 沒有 原因 預測 分享 bubuko 縮放
決策樹(Decision Tree)是在已知各種情況發生機率的基礎上,通過構成決策樹來求取淨現值的期望值大於等於零的機率,評價項目風險,判斷其可行性的決策分析方法,是直觀運用機率分析的一種圖解法。由於這種決策分支畫成圖形很像一棵樹的枝幹,故稱決策樹。在機器學習中,決策樹是一個預測模型,他代表的是對象屬性與對象值之間的一種映射關係。
一、初識決策樹
決策樹是一種樹形結構,一般的,一棵決策樹包含一個根結點,若干個內部結點和若干個葉結點:
葉結點:樹的一個方向的最末端,表示結果的輸出;
根結點:初始樣本全體;
內部結點:每個內部結點對應一個屬性測試(即一次決策)
從根結點——每個葉結點,形成各條判定序列;我們的進行決策樹分類器訓練的學習目的是產生一棵泛化能力強,即處理未見樣本能力強的決策樹,其基本流程遵循“分而治之”的策略:
演算法過程:
Step1:輸入樣本集D{(x1,y1),(x2,y2),...,(xn,yn)},屬性集A{a1,a2,...,ad},全體樣本集儲存在根結點中;
Step2:從屬性集A中經過一定的規則(具體規則由演算法決定)挑選出一個最佳屬性a1,所有樣本從根結點流向該決策結點,根據樣本在a1這個屬性上的取值,流向對應的方向(如):
在樣本集通過某個屬性判斷,確定不同的流向後,會有以下幾種情況:
1.流向某個方向的所有樣本只存在一個類別y0,這時把這個方向標記為葉結點,即最終從這個方向流出的樣本都可直接判定為類別y0;
2.通過當前屬性判斷後,某個方向沒有樣本流出,這通常是樣本量不夠多導致的樣本多樣性不足,這時可以將這方向標記為葉結點,將訓練集中各類別的比例作為先驗機率,將所有從這個方向流出的新樣本都標記為先驗機率最大的那個類別;
3.在某個屬性判斷上,所有訓練樣本都取同一個值,和情況2相似,也是在其他可能方向上無訓練樣本流出,在對新樣本處理時方法同2;
Step3:通過Step2的過程將所有屬性利用完之後,形成了一棵完整的樹,其每個判斷路徑上都經過了所有屬性,這時對所有的葉結點規定輸出類別為訓練過程中到達該葉結點中的樣本中比例最大(即利用了先驗分布)的那一類,至此,一棵決策樹訓練完成。
二、訓練流程屬性的選擇
現在我們知道了決策樹的訓練過程,但對於哪一個屬性放在第一位,哪個放在第二位以此類推,還依然不知曉,這就是決策樹中非常重要也非常巧妙的一點——劃分選擇;
劃分選擇:決策樹學習的關鍵是如何選擇最優劃分屬性,我們希望隨著劃分過程不斷進行,決策樹的分支結點所包含的樣本儘可能屬於同一類別,即結點的純度(purity)越來越高,下面我們介紹幾種不同的衡量樣本純度的規則,他們也分別產生了不同的決策樹演算法:
1.資訊增益
在定義資訊增益之前,我們先介紹以下概念:
資訊熵(information entropy):
度量樣本集合純度最常用的一種指標,假定當前樣本集合D中第k類樣本所佔的比例為pk(k=1,2,...,|y|),則D的資訊熵定義為:
Ent(D)越小,D的純度越高,其中|y|表示屬性的可能取值數,假定對離散屬性a有V個可能的取值{a1,a2,...,aV},使用a來對樣本集D進行劃分,產生V個分支結點,其中第v個分枝結點流入D中所有在屬性a取值為aV的樣本,記作DV,則屬性a對D進行劃分所獲得的資訊增益為:
其中|DV|指D中在a屬性取aV的樣本數量,則|DV| / |D|可看作在aV方向上的權重;
*原則:資訊增益越大,意味著使用a屬性進行劃分所劃得的“純度提升”最大,即當前最優劃分為:
2.增益率
有些時候,若樣本集中含有“編號”這種使得分支結點純度遠大於其他有效屬性的非有效屬性(因為編號會將每一個樣本獨立分開),導致各個編號的分支能變成葉結點(對應特殊情況中的1),這樣的決策樹顯然不具有泛化能力,無法對新樣本進行預測,即,這種情況下資訊增益準則對可取值數目較多的屬性有所偏好,為減少這種偏好可能帶來的不利影響,下面引入:
C4.5演算法:
不直接使用資訊增益,而是使用“增益率”來選擇當前最優劃分屬性;
增益率定義為:
其中,
叫做屬性a的固有值,屬性a的可能取值數目越大(即V越大),則IV(a)的值通常會越大;與資訊增益相比,增益率對屬性取值數目較少的屬性有偏好,因此C4.5演算法並不直接以所有屬性的增益率作為比較依據,而是有一個啟發學習法的過程:先選擇候選劃分屬性中資訊增益高於平均水平的屬性,再從中選擇增益率最高的。
3.基尼係數
CART決策樹(Classfication and Regression Tree)使用基尼指數來選擇劃分屬性,則資料D的純度可用基尼值來度量:
Gini(D)反映了從資料集D中抽取兩個樣本,其類別標記不一致的機率,即Gini(D)越小,資料集D的純度越高,則對一個屬性a,其基尼指數為:
所以在候選屬性集合A中,選擇當前剩餘屬性中使得劃分後基尼指數最小的作為當前最優劃分屬性,即:
三、剪枝處理
在決策樹學習中,為了儘可能正確分類訓練樣本,結點劃分過程不斷重複,有時會造成決策樹分支過多,這時就可能因訓練集過度學習,以致於把訓練集本身的一些特點當作所有資料都具有的一般性質,從而導致過擬合。
通過主動去掉一些分支來降低過擬合的風險的過程就叫做剪枝。
決策樹剪枝的基本策略:
1.預剪枝(prepruning)
在決策樹產生過程中,對每個結點在劃分前先進行效能估計,若當前結點的劃分不能帶來決策樹泛化效能的提升,則停止劃分並將當前結點標記為葉結點;
2.後剪枝(post-pruning)
先從訓練集產生一棵完整的決策樹,然後自底向上地對非葉結點進行考察,若將該結點對應的子樹替換成葉結點能帶來決策樹泛化能力提升,則將該子樹替換成葉結點。
預剪枝:
步驟:
Step1:為衡量泛化能力,利用留出法,劃分樣本集為訓練集和驗證集;
Step2:根據資訊增益準則,選出a*作為根結點下第一個非葉結點,分別訓練通過這一屬性進行分類的模型,和將該結點作為葉結點的模型,比較這兩個模型在驗證集上的正確率,選擇更優的方案;
Step3:重複Step2對所有屬性進行考察,直到最終決策樹完成;
*僅有一層劃分的決策樹稱為“決策樹樁”(decision stump)
原則:剪去(淘汰)正確率小於或等於當前正確率(即當前最高正確率)的分支操作;
優點:預剪枝使得決策樹的很多分支沒有展開,降低了模型過擬合的風險,還顯著減少了決策樹的訓練時間開銷和測試時間開銷;
缺點:有些分支的當前劃分雖不能提升泛化能力,甚至可能導致泛化能力暫時下降,但在其基礎上進行的後續劃分卻有可能導致效能顯著提升;
預剪枝基於“貪心”本質禁止這些分支展開,只關心當前效能表現,給預剪枝決策樹模型帶來了欠擬合的風險。
後剪枝:
步驟:
Step1:對於不經任何剪枝處理,僅依據某個資訊純度評價方法最終形成的一棵完整的使用了所有屬性的決策樹,從其最靠後的非葉結點開始,分別訓練不剪去該結點和剪去該結點時的模型,比較泛化能力;
Step2:若泛化能力得到了提高,則採取相應的模型變更/維持原狀操作;
Step3:重複上述過程直到所有非葉結點完成剪枝效果評估。
原則:若剪枝後正確率得到提高,則採取剪枝操作,否則不變;
優點:欠擬合風險很小,泛化能力往往優於預剪枝決策樹;
缺點:後剪枝過程是在產生完全決策樹之後進行的,並且需自底向上對樹中所有非葉結點進行逐一考察後,因此訓練時間開銷巨大。
以上就是決策樹演算法的一些基本常識,下面我們分別在Python和R中實現決策樹演算法:
四、Python
我們利用sklearn模組中的tree下屬的DecisionTreeClassifier()進行決策樹分類,關於其細節在sklearn的官網中有詳細介紹:http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier,下面我們對其主要參數進行介紹:
criterion : 字元型,用來確定劃分選擇依據的演算法,有對應CART樹演算法的“gini”和對應ID3演算法的“entropy”,預設為“gini”
splitter : 字元型,用來確定選擇每個屬性判斷結點的方式,依據的是criterion中確定的指標數值,有對應最佳結點的“best”和對應隨機播放的“random”,預設是“best”
max_depth :整型,用來確定決策樹的最大深度(即最多的非葉結點數目規模),預設為None,即不限制深度
min_samples_split :有兩種情況,
1.整型,這時該參數確定用於分割非葉結點的最小樣本數,即如果小於該預設值,則該結點因為資訊不足可以直接根據先驗分布產生為葉結點輸出結果,預設值2;
2.浮點型,這時該參數功能不變,只是確定的min_samples_split變為min_samples_split*n_samples,這裡代表百分比。
min_samples_leaf :有兩種情況,
1.整型,這時該參數確定用於產生葉結點的最小樣本數,即小於該數值時不可產生葉結點,預設值為1;
2.浮點型,同min_samples_split
min_weight_fraction_leaf :浮點型,該參數用於確定每個樣品的權重,在最終在葉結點產生結果時起作用,主要用於類別不平衡時的再縮放操作,預設每個樣品權重相等;
max_features : 該參數用於確定每一次非葉結點屬性劃分時使用到的屬性數目(在資訊增益和基尼指數的計算中起作用),預設使用全部屬性,有以下幾種情況:
1.整型,這時傳入的整數即為每次分割時考慮的最大屬性數;
2.浮點型,這時最大屬性數是該浮點參數*屬性總數;
3.字元型,“auto”時,最大屬性數為屬性總數開根號;“sqrt”時,同“auto”;“log2”時,最大屬性數為屬性總數取對數;
4.None,這時最大屬性數即為屬性總數;
max_leaf_nodes : 該參數用於確定最終的決策樹模型的最大葉結點數量,預設為無限制,即None
class_weight :用於處理類別不平衡問題的權重,建議使用“balanced”,即自動根據先驗分布賦權,預設為None,即忽略權重,每一類同等看待
以上就是sklearn.tree.DecisionTreeClassifier的主要參數介紹,下面我們以kaggle playground中的泰坦尼克號遇難者資料作為示範資料對生還與否進行二分類:
資料說明:
代碼:
from sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_splitimport pandas as pdimport numpy as np‘‘‘讀入資料‘‘‘raw_train_data = pd.read_csv(‘train.csv‘)train = raw_train_data.dropna()target_train = train[‘Survived‘].tolist()#Ticket classpclass = train[‘Pclass‘].tolist()sex = train[‘Sex‘].tolist()Sex = []for i in range(len(sex)): if sex[i] == ‘male‘: Sex.append(1) else: Sex.append(0)age = train[‘Age‘].tolist()#在船上兄弟姐妹的數量SibSp = train[‘SibSp‘].tolist()#在船上父母或孩子的數量Parch = train[‘Parch‘].tolist()Fare = train[‘Fare‘].tolist()#登船的港口Embarked = train[‘Embarked‘].tolist()sabor_C = []sabor_Q = []#為登船港口設定啞變數for i in range(len(Embarked)): if Embarked[i] == ‘C‘: sabor_C.append(1) sabor_Q.append(0) elif Embarked[i] == ‘Q‘: sabor_Q.append(1) sabor_C.append(0) else: sabor_Q.append(0) sabor_C.append(0)‘‘‘定義自變數與目標‘‘‘train_ = np.array([Sex,age,sabor_C,sabor_Q]).Ttarget_ = np.array(target_train)‘‘‘重複多次隨機分割樣本集的訓練取正確率平均值‘‘‘S = []for i in range(1000): X_train, X_test, y_train, y_test = train_test_split(train_, target_, test_size=0.3) clf = DecisionTreeClassifier(class_weight=‘balanced‘,max_depth=2) clf = clf.fit(X_train,y_train) S.append(clf.score(X_test,y_test))‘‘‘列印結果‘‘‘print(‘平均正確率:‘+str(np.mean(S)))
訓練效果:
R
在R中使用決策樹相關演算法有一個很大的方便之處,就是在對決策樹可視化的時候,我們都知道決策樹是一種解釋性很強的機器學習演算法,這是它被廣泛使用的一個原因之一,在R中繪製決策樹非常方便;在R中,一棵決策樹的初步產生與剪枝是使用兩個不同的函數進行操作的,我們這裡使用rpart包來建立分類樹,其中rpart()函數建立決策樹,prune()函數用來進行樹的剪枝,具體參數如下:
對rpart():
formula:這是R中很多演算法的輸入格式,用~串連左端的target列名稱和右端的自變數列名稱;
data:輸入資料框的名稱;
weights:可選的自訂類別權重,主要在類別不平衡時使用,類似邏輯分類中的再縮放;
na.action:對缺失值進行處理,預設刪去target列缺失的樣本,但保留自變數存在缺失的樣本(決策樹中對缺失值較為寬容,有對應的處理方法)
parms:預設為“gini”指數,即CART決策樹分割結點的方法;
> rm(list=ls())> library(rpart.plot)> library(rpart)> data(iris)> data <- iris> sam <- sample(1:150,120)> train_data <- data[sam,]> test_data <- data[-sam,]> dtree <- rpart(Species~.,data=train_data)> plotcp(dtree)> dtree.pruned <- prune(dtree, cp=0.01)> prp(dtree.pruned)> dtree.pred <- predict(dtree.pruned,test_data[,1:4],type=‘class‘)> dtree.perf <- table(test_data[,5],dtree.pred)> dtree.perf dtree.pred setosa versicolor virginica setosa 10 0 0 versicolor 0 10 0 virginica 0 3 7
(資料科學學習手劄23)決策樹分類原理詳解&Python與R實現