别以为if slse很简单——决策树
怎么分——熵與Gini指數
熵,表示信息量的期望,含義是混亂程度,也是對隨機變量編碼所需的最小比特數。請參考之前的文章。
信息增益建立在熵之上,是選擇某特征之后熵減少的多少(熵減少即信息增加),等于信息熵-條件熵,
基尼不純度?,它表示是分錯的概率的期望。Gini不純度其實可以看作是熵的近似值,形式一樣沒有取對數更容易計算,二分類時,都是概率取0.5時達到最大值。Gini不純度是一種不等性度量,取值[0,1],當數據完全相等時取0.
K表示類別數目,那么對于數據集(樣本集合)D,它的基尼不純度:
D經過特征A后分裂為兩個子集,新的不純度就是兩個子集不純度的加權和(因為Gini不純度本來也是加權和):.我們的目標就是使得分裂后的不純度最小。
ID3
ID3是最早的決策樹,使用信息增益作為分裂準則。特點是特征必須是離散的,離散意味著特征是類別特征,那就也意味著特征不會被復用(該特征下的結果只能是屬于或者不屬于,而像連續特征可以換個閾值重新使用)。而既然是類別特征,當然類別越多分得越細(ID3可能是多叉樹),所以ID3會傾向于選擇類別較多的特征(直接念身份證號得了)。但其實不是說特征類別更多帶來的增益就一定更大,從熵的公式看,他們極有可能是一樣的,,只是可能性更大,即便帶來的增益相等,類別過多將原有數據集劃分為更多更小的子集,極容易過擬合。
此外ID3沒有考慮缺失特征帶來的影響。
ID3的作者Quinlan繼續提出了C4.5。特征類別過多時這個特征自身的熵會升高(稱為屬性熵split info),所以可以將信息增益調整為信息增益率=信息增益/屬性熵,這樣就限制了屬性熵的值不能過高。其實信息增益率可以看作是信息增益與代價的比(屬性熵越大代價越大),核心目的仍然是為了讓信息增益最大(在特征為連續值時,只使用信息增益)。信息增益率又有可能偏向于類別較少的特征,所以C4.5真正的做法是先選取信息增益高于均值的幾種,在這幾種里面再按照信息增益率選取。
對于特征值缺失的問題,意思是對于某一類別特征,有一些樣本我們不知道它到底屬于哪一類。所以在計算增益時就只以不缺失的數據來計算;當正好選取了缺失的特征后,對于不知道它屬于哪一類的樣本,就按照概率進行分類。
CART
CART樹最大特定是既可以用于分類也可以用于回歸。首先它是二叉樹,遞歸劃分,對于分類可以化為one vs others,對于連續特征,則選定某一特征的一個值,按大小分為兩類。CART使用Gini不純度代替熵,避免了對數運算。
怎么剪——剪枝
決策樹在訓練過程中采取貪婪策略的方法進行分裂,很容易過擬合。控制深度,葉子節點數的方法又有點武斷(這種方法其實叫做預剪枝)。
關于后剪枝方法,C4.5使用悲觀剪枝PEP(Pessimostic Error Pruning),CART樹中可以使用代價復雜度的方法進行剪枝CCP。
PEP的好處是決策樹的生成和剪枝使用相同的訓練集。它比較的是待剪去的子樹和新的葉子結點處的誤判率。前者使用公式:
,表示該子樹每個葉子結點的誤判個數,L表示有多少個葉子結點,N表示該子樹根節點處的總數。
而新葉子節點處的誤判率就很好算了,誤判數目/總數。新葉子節點誤判率總是高于子樹誤判率,當差距小于一個閾值時就認為可以剪枝。這個閾值通過子樹的標準差來確定:正確判斷與誤判看作二項分布,那么
CCP涉及到代價,那自然是在追求準確度的基礎上增加一項正則項,正則項通過葉子節點的數目表示樹結構的復雜度。所以代價復雜度函數就是:
= 錯誤率 + 葉子結點個數
假設在節點處剪枝,以為根節點的子樹為,剪枝前后的代價復雜度函數分別為,
解釋一下從(1)到(2)的推導。有兩點問題首先要清楚,樹的誤差體現在其葉子節點的加權誤差();剪枝的過程本質是用一個節點代替其底部更深的所有節點。所以剪枝前后的結構對應的誤差等價于節點處的誤差和以為根的樹的葉子節點的誤差:。而剪枝前后的樹的復雜度變化就是葉子節點個數的變化,剪枝之后葉子結點數首先減少了個,但剪枝處的節點成為新的一個葉子節點,所以葉子節點的變化情況是
所以在確定了之后,所需要做的就是嘗試刪除一個個節點之下的樹,尋找使得剪枝前后代價函數變化最小的那個節點。當然,剪枝之后還是要在測試集中測試,選擇最優的作為最終的決策樹。這也就是所謂的生成子樹序列+測試集上的交叉驗證。
但是,在更多的資料中,會令(2)等于0,可以得到。這是認為剪枝的充分條件是剪枝前后的代價函數相等,剪枝前后的代價函數可以相等,但是誤差肯定是增大的,所以分子大于0,所以>0。有無限多,我們不能一個個試,但是子樹的結構是有限的。仔細看,其實可以代表剪枝帶來的增益,分子越小,損失變化越小;分母越大,表示葉子節點減小得越多。所以真正的做法是遍歷節點剪枝,得到最小的剪枝處,迭代多次直至剪枝之后只剩下根節點,就可以得到子樹構成的序列和對應的構成的序列,將這些序列對應的模型再代入測試集驗證。
怎么用——sklearn實戰
傻瓜式操作,只需要創建一個實例類,然后對訓練數據執行fit()操作。
在tree的實例類中可以指定我們分裂所使用的度量方法,可以是entropy,可以是gini(默認)
訓練的數據應該是在csv文件中指定特征后的數據
這里的score不是指決策樹預測的概率值,因為輸入樣本落入某節點必須是屬于某一類的(硬分類)。注意到這個函數同時需要輸入標簽值,它返回的其實只是一個值,意為預測的準確率accuracy。
from sklearn import treeclf = tree.DecisionTreeClassifier(criterion="entropy")# criterion選擇entropy,這里表示選擇ID3算法 clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) #返回預測的準確度accuracy可視化
out_file指定生成的dot文件位置。dot文件是微軟開發的用于頁面布局的文件,可以使用Word打開。打開之后可以發現它保存的就是各個節點的信息:該節點的信息增益,顏色,所屬類別等。
import graphviz dot_data = tree.export_graphviz(clf, out_file=".\Tree.dot",feature_names = feature_name,class_names=["琴酒","雪莉","貝爾摩德"],filled=True,rounded=True)漢字支持
dot文件內有一個關鍵字fontname,它指定了字符的編碼格式,所以我們為了支持漢字,核心就是將原有的編碼格式Helvetica(在拉丁文中意為“瑞士的”)改為微軟雅黑。可以使用代碼自動修改。
import re # 打開 dot_data.dot,修改 fontname="支持的中文字體" f = open("./Tree.dot", "r+", encoding="utf-8") open('./Tree_utf8.dot', 'w', encoding="utf-8").write(re.sub(r'fontname=helvetica', 'fontname="Microsoft YaHei"', f.read())) f.close()在修改之后可以open,得到一個TextIOWarpper類型的變量,對其取read()得到文件中的字符串,類型為str。然后可以使用?pydotplus.graph_from_dot_data保存:
with?open((r'./Tree_utf8.dot',"r",encoding='utf-8')?as?f:text?=?f.read()?graph?=?pydotplus.graph_from_dot_data(text)graph.write_png("試試.png") ??graph.write_pdf("iris.pdf")或者使用命令行保存:
dot -Tjpg Tree.dot -o tree.jpg怎么解讀畫出的圖像呢。
基尼不純度gini應該是越來越小的。每個圓角矩形代表一個節點,在每個節點中alue的維度和標簽的種類數一致,三種類別中符合以上條件的數目。他們的數目之和即這個節點的samples值,而每層的samples之和就是測試集的總數。有的節點的value中,只有一個非零值,代表只有該類符合之上的條件,所以gini不純度也是0,這時候該節點就成為葉子節點,不會繼續向下生長。決策樹會傾向于一直生長(除非指定深度),直至使得每個葉子節點的gini等于0,所以容易過擬合,極端情況就是為每個樣本量身定制了一份判斷條件。所以為了防止過擬合,除了限制生長的深度,還可以指定葉子所需的最小樣本數,樣本數再小就沒必要再生長了。
Reference:
1.sklearn手冊https://sklearn.apachecn.org/docs/0.21.3/11.html
2.少年阿斌https://www.cnblogs.com/wqbin/p/11689709.html
3.https://zhuanlan.zhihu.com/p/85731206
4.CCPhttp://mlwiki.org/index.php/Cost-Complexity_Pruning
5.https://zhuanlan.zhihu.com/p/76667156
6.https://www.jianshu.com/p/b90a9ce05b28
7.https://zhuanlan.zhihu.com/p/93936294
總結
以上是生活随笔為你收集整理的别以为if slse很简单——决策树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android实现支持缩放平移图片
- 下一篇: Boost简介