《Machine Learning in Action》—— Taoye給你講講決策樹(shù)到底是支什么“鬼”
前面我們已經(jīng)詳細(xì)講解了線(xiàn)性SVM以及SMO的初步優(yōu)化過(guò)程,具體可看:
- 《Machine Learning in Action》—— 剖析支持向量機(jī)店乐,優(yōu)化SMO
- 《Machine Learning in Action》—— 剖析支持向量機(jī)逆巍,單手狂撕線(xiàn)性SVM
關(guān)于SVM非線(xiàn)性相關(guān)的內(nèi)容,我們留著下個(gè)星期來(lái)撕
這篇文章我們先來(lái)看看決策樹(shù)的內(nèi)容,決策樹(shù)相對(duì)于SVM來(lái)講要簡(jiǎn)單不少,也沒(méi)有多么復(fù)雜的公式。我理解的決策樹(shù)房待,簡(jiǎn)單來(lái)說(shuō)就是通過(guò)已有的數(shù)據(jù)集訓(xùn)練出一個(gè)樹(shù)形結(jié)構(gòu)的模型,以便我們能夠依據(jù)該模型對(duì)不知分類(lèi)結(jié)果的數(shù)據(jù)進(jìn)行預(yù)測(cè)驼抹。簡(jiǎn)單的決策樹(shù)就有點(diǎn)類(lèi)似于我們?cè)趯W(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時(shí)候的二叉排序樹(shù)桑孩。當(dāng)然了,決策樹(shù)除了能夠進(jìn)行分類(lèi)之外框冀,還能進(jìn)行回歸流椒,這里主要討論的是分類(lèi)問(wèn)題。
關(guān)于決策樹(shù)相關(guān)的內(nèi)容左驾,可能會(huì)肝兩篇文章來(lái)介紹镣隶。第一篇主要是講解決策樹(shù)先關(guān)的基本知識(shí),及其決策訓(xùn)練的過(guò)程诡右,也就是我們的這篇文章安岂,重在理論及推導(dǎo),也重在理解帆吻。而第二篇文章寫(xiě)的主要內(nèi)容是決策樹(shù)的代碼實(shí)戰(zhàn)域那,而代碼實(shí)戰(zhàn)是在熟悉理論基礎(chǔ)的前提之下來(lái)進(jìn)行的,所以對(duì)于決策樹(shù)相關(guān)的理論知識(shí)還是有必要了解的猜煮〈卧保可能的話(huà),還會(huì)有第三篇王带,主要是關(guān)羽防止決策樹(shù)過(guò)擬合的剪枝操作的內(nèi)容淑蔚。
一、什么是決策樹(shù)
關(guān)于決策樹(shù)的定義愕撰,李航——《統(tǒng)計(jì)學(xué)習(xí)方法》(第二版)這本書(shū)中是這樣描述的:
分類(lèi)決策樹(shù)模型是一種描述對(duì)實(shí)例進(jìn)行分類(lèi)的樹(shù)形結(jié)構(gòu)刹衫,決策樹(shù)由節(jié)點(diǎn)(node)和有向邊(directed edge)組成醋寝。節(jié)點(diǎn)有兩種類(lèi)型:內(nèi)部節(jié)點(diǎn)(iternal node)和葉節(jié)點(diǎn)(leaf node)。內(nèi)部節(jié)點(diǎn)表示一個(gè)特征或?qū)傩源伲~節(jié)點(diǎn)表示一個(gè)類(lèi)音羞。
上述提到的內(nèi)部節(jié)點(diǎn)可以理解成樣本的屬性特征,而葉節(jié)點(diǎn)可以理解成樣本的標(biāo)簽仓犬,而有向邊可以理解成不同的屬性特征結(jié)果嗅绰。一般我們?cè)诶L制決策樹(shù)的時(shí)候,內(nèi)部節(jié)點(diǎn)用方框或長(zhǎng)方形表示搀继,而葉節(jié)點(diǎn)用圓形或橢圓表示窘面。(注意:這個(gè)并不是絕對(duì)的,在不同資料中可能有不同的表示方法叽躯,比如《統(tǒng)計(jì)學(xué)習(xí)方法》一書(shū)中用圓表示內(nèi)部節(jié)點(diǎn)民镜,用方形表示葉子節(jié)點(diǎn),而在《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》一書(shū)中表示方式正好相反)
枯燥的文字說(shuō)明總是會(huì)降低讀者的閱讀欲望险毁,下面我們不妨通過(guò)一個(gè)實(shí)際的例子來(lái)說(shuō)明下,從而加強(qiáng)讀者對(duì)決策樹(shù)的理解们童。
比如說(shuō)畔况,形容女生美與丑的時(shí)候一般會(huì)存在多個(gè)指標(biāo),這個(gè)例子感覺(jué)有點(diǎn)危險(xiǎn)慧库,還是換個(gè)吧跷跪。
例子來(lái)源:李航——《統(tǒng)計(jì)學(xué)習(xí)方法》(第二版)
比如說(shuō),我們沒(méi)Money用了齐板,想要去銀行貸款吵瞻,這個(gè)時(shí)候銀行就會(huì)根據(jù)你自己的個(gè)人附帶特征來(lái)決定是否給你放款。假設(shè)這里的屬性特征有四個(gè)甘磨,分別是年紀(jì)橡羞、是否工作、是否有房子济舆、信用情況卿泽,這些屬性特征就相當(dāng)于是內(nèi)部節(jié)點(diǎn),標(biāo)簽(結(jié)果)是否放款相當(dāng)于葉子節(jié)點(diǎn)滋觉,而不同屬性特征的結(jié)果表示有向邊签夭,像年紀(jì)中有青年、中年椎侠、老年第租,信用情況有好、一般我纪、非常好等表示不同的有向邊慎宾。
對(duì)此丐吓,我們可以根據(jù)自己的感覺(jué)來(lái)手動(dòng)繪制一個(gè)簡(jiǎn)單的決策樹(shù)模型:
<img src="https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/jueceshu_1.jpg" width="400">
我們知道,上述決策樹(shù)僅僅是我們自己手動(dòng)來(lái)實(shí)現(xiàn)的璧诵,不一定能夠運(yùn)用于解決實(shí)際問(wèn)題汰蜘。而決策樹(shù)的任務(wù),則是根據(jù)已有的數(shù)據(jù)樣本集訓(xùn)練得到這么一顆樹(shù)形結(jié)構(gòu)模型之宿,以此來(lái)對(duì)未知分類(lèi)的數(shù)據(jù)進(jìn)行類(lèi)別預(yù)測(cè)族操。對(duì)此,我們要向得到這么一顆盡可能理想的決策樹(shù)比被,則不得不考慮以下幾個(gè)問(wèn)題:
- 決策樹(shù)的指標(biāo)(屬性特征)選擇的順序應(yīng)該是怎樣的的色难?哪個(gè)特征應(yīng)當(dāng)被優(yōu)先考慮呢?
- 如果構(gòu)建出的決策樹(shù)出現(xiàn)了過(guò)擬合問(wèn)題等缀,也就說(shuō)我們的訓(xùn)練的時(shí)候還不錯(cuò)枷莉,但是一測(cè)試就GG,這個(gè)時(shí)候我們應(yīng)當(dāng)怎么解決呢尺迂?
本篇文章笤妙,主要內(nèi)容是屬性特征的優(yōu)先選取問(wèn)題。
二噪裕、屬性特征的選擇
對(duì)于屬性特征的選擇蹲盘,我們應(yīng)當(dāng)優(yōu)先選取對(duì)訓(xùn)練數(shù)據(jù)集具有明顯分類(lèi)能力的特征,這樣可以提高我們決策樹(shù)的學(xué)習(xí)效率膳音。假如說(shuō)一個(gè)屬性特征的分類(lèi)結(jié)果與隨機(jī)分類(lèi)基本沒(méi)什么差別召衔,則我們可以說(shuō)這個(gè)屬性特征基本是沒(méi)有分類(lèi)能力的。
比如說(shuō)祭陷,我們這里有12個(gè)關(guān)于女生美與丑的數(shù)據(jù)樣本苍凛,其中六個(gè)是丑女,另外六個(gè)是美女兵志,六個(gè)丑女身高有三個(gè)是165cm醇蝴、三個(gè)是185cm,而另外六個(gè)美女身高同樣如此毒姨,這樣的話(huà)哑蔫,我們僅僅通過(guò)身高來(lái)對(duì)女生美貌的判斷基本是沒(méi)有分類(lèi)能力的。(僅僅是個(gè)例子弧呐,不代表任何觀點(diǎn))
所以闸迷,我們理想情況下決策樹(shù)的生成理應(yīng)是這樣的:隨著決策過(guò)程的不斷進(jìn)行,我們希望決策樹(shù)的分支節(jié)點(diǎn)所包含的樣本盡可能的屬于同一類(lèi)別(標(biāo)簽相同)俘枫,也就是節(jié)點(diǎn)的“純度”越來(lái)越高腥沽。
所以,決策樹(shù)的關(guān)鍵技術(shù)在于屬性特征的選擇鸠蚪。對(duì)于屬性特征的選擇今阳,我們通常有三個(gè)準(zhǔn)則:信息增益师溅、信息增益比(增益率)和基尼指數(shù)。
2.1 信息增益
上面提到了樣本濃度盾舌,比如說(shuō)我這里有10個(gè)女生墓臭,10個(gè)都是美女,那就說(shuō)此時(shí)的樣本濃度高妖谴,假如美女和丑女五五分窿锉,那這個(gè)時(shí)候的濃度就比較低了。這里的“濃度”表達(dá)的就是這個(gè)意思膝舅,它主要針對(duì)的是標(biāo)簽(結(jié)果)嗡载。
而表示樣本“濃度”的指標(biāo),最常用的就是“信息熵”了仍稀。假定當(dāng)前樣本集合中第
類(lèi)(總共
類(lèi))樣本所占的比例為
洼滚,則此時(shí)樣本
的信息熵為:
通過(guò)上述公式,我們可以知道10個(gè)美女(一個(gè)類(lèi)別)的信息熵為
美女丑女五五分(兩類(lèi))的信息熵為:
通過(guò)上面信息熵的簡(jiǎn)單計(jì)算技潘,我們可以知道遥巴,信息熵的值越小,則純度越高享幽。
既然我們已經(jīng)了解了信息增益的計(jì)算公式及其所表達(dá)的意義挪哄,那么對(duì)于一個(gè)數(shù)據(jù)樣本集,我們應(yīng)當(dāng)如何用代碼來(lái)進(jìn)行計(jì)算呢琉闪?下面我們來(lái)試試吧。
本次使用到的數(shù)據(jù)樣本來(lái)自 李航——《統(tǒng)計(jì)學(xué)習(xí)方法》(第二版)砸彬,數(shù)據(jù)是關(guān)于貸款申請(qǐng)的颠毙,具體如下:
那么現(xiàn)在我們來(lái)通過(guò)代碼形式計(jì)算下這個(gè)數(shù)據(jù)樣本集的信息熵吧:
首先創(chuàng)建一個(gè)establish_data
方法來(lái)建立一個(gè)二維數(shù)組用于存儲(chǔ)上述數(shù)據(jù)樣本集的相關(guān)信息(關(guān)于屬性特征所對(duì)于的值0,1,2之類(lèi)的,大家可以參考上述表格對(duì)號(hào)入座砂碉,這里就不做過(guò)多解釋了):
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:創(chuàng)建訓(xùn)數(shù)據(jù)集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 樣本數(shù)據(jù)集相關(guān)信息蛀蜜,前面幾項(xiàng)代表屬性特征,最后一項(xiàng)表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data)
隨后增蹭,我們創(chuàng)建一個(gè)calc_information_entropy
方法用于計(jì)算信息熵滴某,計(jì)算過(guò)程的代碼可結(jié)合上述的公式來(lái)看。另外滋迈,需要說(shuō)一點(diǎn)的是霎奢,為了方便對(duì)放款結(jié)果進(jìn)行分類(lèi),我們使用pandas
包進(jìn)行處理饼灿,關(guān)于pandas
的使用幕侠,大伙可以參考文檔,Taoye后期也會(huì)整理一份碍彭。當(dāng)然了晤硕,不用pandas
模塊也能實(shí)現(xiàn)這個(gè)功能悼潭,有興趣的讀者可自行嘗試,也不難舞箍。calc_information_entropy
具體代碼如下:
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
print(item[1])
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy
我們運(yùn)行上述代碼舰褪,來(lái)看看具體的信息熵結(jié)果:
<img src="https://gitee.com/tianxingjian123/my-images-repository/raw/master/img/jueceshu_3_.jpg" width="500">
相比大家都了解了信息熵的概念,并能夠手動(dòng)計(jì)算樣本集的信息熵了疏橄,現(xiàn)在我們?cè)賮?lái)把信息增益搬出來(lái)吧占拍。
假設(shè)一個(gè)屬性特征有
個(gè)可能的取值
,若使用
來(lái)對(duì)樣本集
進(jìn)行劃分软族,這樣的話(huà)就會(huì)產(chǎn)生
個(gè)分支節(jié)點(diǎn)刷喜,其中第
個(gè) 分支節(jié)點(diǎn)包含了
中所有在屬性
上取值為
的樣本,記為
立砸。于是可計(jì)算出用屬性特征
對(duì)樣本集
進(jìn)行劃分所獲得的“信息增益”(information gain)為:
以上是周志華——《機(jī)器學(xué)習(xí)》一書(shū)中對(duì)信息增益的相關(guān)說(shuō)明掖疮。
枯燥的文字說(shuō)明總是會(huì)降低讀者的閱讀欲望,上述符號(hào)也是有點(diǎn)多颗祝,我們不妨拿上面的貸款數(shù)據(jù)來(lái)進(jìn)一步理解下上述信息增益的內(nèi)容:
我們單獨(dú)拿年齡這一個(gè)屬性特征來(lái)計(jì)算其信息增益吧浊闪,其有青年、中年螺戳、老年三個(gè)可能的值搁宾,也就是說(shuō)上述的,
倔幼,而數(shù)據(jù)樣本集
為上述15個(gè)數(shù)據(jù)樣本盖腿,由于年齡有三個(gè)可能的值,所以此時(shí)會(huì)產(chǎn)生三個(gè)分支损同,即
翩腐。之前我們已經(jīng)計(jì)算得到
,現(xiàn)在我們只要計(jì)算出后一項(xiàng)
的值即可得到該屬性特征所對(duì)應(yīng)的信息增益:
通過(guò)數(shù)據(jù)膏燃,我們觀察得到如下信息:
- 對(duì)于年齡這個(gè)屬性特征來(lái)講茂卦,青年、中年组哩、老年分別有5個(gè)等龙。
- 5個(gè)青年中有2個(gè)允許貸款,有三個(gè)不允許貸款伶贰;中年中有3個(gè)允許貸款蛛砰,2個(gè)不允許貸款;老年中有4個(gè)允許貸款黍衙,有1個(gè)不允許貸款暴备。
對(duì)此,我們可以計(jì)算:
對(duì)此们豌,我們的計(jì)算處年齡這個(gè)屬性特征所對(duì)應(yīng)的信息增益值為:
我們可以把后一項(xiàng)的內(nèi)容理解成條件概率涯捻。另外浅妆,信息增益越大,則其所對(duì)應(yīng)的屬性特征的分類(lèi)能力也就越強(qiáng)障癌,也就是我們應(yīng)當(dāng)優(yōu)先選取的特征凌外。
同理,我們可以計(jì)算出工作涛浙、房子康辑、信用屬性特征所對(duì)應(yīng)的信息增益:
我們比較哥哥屬性特征的信息增益值,可以發(fā)現(xiàn)房子這個(gè)屬性特征最大轿亮,所以它應(yīng)該是我們優(yōu)先選擇的屬性特征疮薇。
了解了信息增益的計(jì)算及其意義,下面我們來(lái)通過(guò)代碼計(jì)算一下(代碼含義見(jiàn)注釋?zhuān)?/p>
import numpy as np
import pandas as pd
np.__version__
pd.__version__
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:創(chuàng)建訓(xùn)數(shù)據(jù)集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 樣本數(shù)據(jù)集相關(guān)信息我注,前面幾項(xiàng)代表屬性特征按咒,最后一項(xiàng)表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data)
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:找出對(duì)應(yīng)屬性特征值的樣本,比如找出所有年紀(jì)為青年的樣本數(shù)據(jù)集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value: result_data.append(item)
return result_data
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算最大的信息增益但骨,并輸出其所對(duì)應(yīng)的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和對(duì)應(yīng)的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
print("第%d個(gè)屬性特征所對(duì)應(yīng)的的增益為%.3f" % (index + 1, temp_information_gain)) # 輸出每個(gè)特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益励七,確定的最大的信息增益對(duì)應(yīng)的索引
return best_feature
if __name__ == "__main__":
data = establish_data()
print("屬性特征對(duì)應(yīng)的最大的信息增益對(duì)應(yīng)的索引為:%d" % calc_information_gain(data))
運(yùn)行上述代碼,可見(jiàn)輸出的各個(gè)屬性特征的信息增益奔缠,以及最大信息增益對(duì)應(yīng)的特征索引:
可以發(fā)現(xiàn)掠抬,和我們手動(dòng)計(jì)算的如出一轍,所以此時(shí)我們應(yīng)當(dāng)優(yōu)先選取索引為2的屬性特征作為決策標(biāo)準(zhǔn)校哎,也就是房子两波。
2.2 信息增益比(增益率)
我們使用信息增益作為選取特征指標(biāo)的時(shí)候,存在偏向于選擇取值較多的特征的問(wèn)題闷哆。
比如我們將id作為上述數(shù)據(jù)集的一個(gè)分類(lèi)屬性雨女,通過(guò)計(jì)算可以發(fā)現(xiàn)該信息增益最大,但實(shí)際上該id對(duì)類(lèi)別不具有什么分類(lèi)能力阳准,所以這樣得到的決策樹(shù)不具有泛化能力,無(wú)法對(duì)新樣本進(jìn)行有效預(yù)測(cè)馏臭。
為了解決信息增益存在的這個(gè)問(wèn)題野蝇,我們就引入了信息增益比(增益率)的概念,著名的C4.5算法就是用“增益率”來(lái)作為選取最優(yōu)劃分屬性括儒。增益率定義為:
稱(chēng)為
的“固有值”(intrinsic value)。通常
的取值數(shù)目越多帮寻,則
的值會(huì)越大乍狐。其中的
的取值比如說(shuō):上述的年紀(jì)有青年、中年固逗、老年三種取值浅蚪。
對(duì)于上述的貸款數(shù)據(jù)集來(lái)說(shuō)藕帜,信用情況有一般、好和非常好三種惜傲,比例分為是盗誊。毒刺时甚,我們可以計(jì)算信用情況的“固有值”:
所以,對(duì)于信用屬性來(lái)講哈踱,其增益率為:
同理荒适,我們可以計(jì)算出其他屬性特征的增益率:
計(jì)算增益率的具體代碼可參考如下:
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算增益率
"""
def calc_gain_ratio(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv = 0.0, 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
gain_ratio = temp_information_gain / iv
print("第%d個(gè)屬性特征所對(duì)應(yīng)的增益率為%.3f,信息增益為%.3f" % (index + 1, gain_ratio, temp_information_gain)) # 輸出每個(gè)特征的信息增益
運(yùn)行結(jié)果如下:
在C4.5算法中开镣,并不是直接單一的使用增益率來(lái)對(duì)屬性特征的選取進(jìn)行決策刀诬,而是先在信息增益中選取高于平均水平的屬性作為候選,然后從候選中選取增益率最高的哑子。
關(guān)于C4.5算法舅列,我們后期會(huì)講到。
2.3 基尼指數(shù)
基尼指數(shù)是另外一種選取屬性的指標(biāo)卧蜓。
前面我們提到了帐要,信息熵是描述數(shù)據(jù)樣本純度一個(gè)標(biāo)準(zhǔn),而在基尼指數(shù)中的基尼值同樣可以體現(xiàn)數(shù)據(jù)樣本的純度弥奸。數(shù)據(jù)樣本集的基尼值可以用
來(lái)表示(其中
表示有
個(gè)標(biāo)簽結(jié)果):
基尼值越小榨惠,說(shuō)明數(shù)據(jù)樣本純度越高。而屬性
對(duì)應(yīng)的基尼指數(shù)
可以定義為:
我們同樣來(lái)分別計(jì)算下上述貸款數(shù)據(jù)集的基尼指數(shù)盛霎。
對(duì)于信用情況這一屬性特征來(lái)講赠橙,其基尼指數(shù)的手動(dòng)計(jì)算過(guò)程如下所示:
對(duì)于其他屬性的基尼指數(shù),讀者可自行根據(jù)上述過(guò)程進(jìn)行計(jì)算(真的很簡(jiǎn)單)愤炸。關(guān)于基尼指數(shù)的計(jì)算代碼期揪,可參考如下:
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算基尼指數(shù)
"""
def calc_gini_index(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv, gini_index = 0.0, 0.0, 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
temp_df = pd.DataFrame(sub_data)
yes_proportion = temp_df[temp_df[temp_df.shape[1]-1] == "Y"].shape[0] / len(sub_data)
gini_value = 1 - (yes_proportion ** 2) - ((1- yes_proportion) ** 2)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
gini_index += gini_value * proportion # 計(jì)算基尼指數(shù)
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
gain_ratio = temp_information_gain / iv
print("第%d個(gè)屬性特征所對(duì)應(yīng)的信息增益為%.3f,增益率為%.3f, 基尼指數(shù)為%.3f" % (index + 1, temp_information_gain, gain_ratio, gini_index))
運(yùn)行結(jié)果:
以上就是基尼指數(shù)的計(jì)算及其相關(guān)代碼规个,一般來(lái)講凤薛,基尼指數(shù)越小就優(yōu)先被劃分。
上述內(nèi)容的完整代碼如下:
import numpy as np
import pandas as pd
np.__version__
pd.__version__
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:創(chuàng)建訓(xùn)數(shù)據(jù)集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 樣本數(shù)據(jù)集相關(guān)信息诞仓,前面幾項(xiàng)代表屬性特征缤苫,最后一項(xiàng)表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data)
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:找出對(duì)應(yīng)屬性特征值的樣本,比如找出所有年紀(jì)為青年的樣本數(shù)據(jù)集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value: result_data.append(item)
return result_data
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算最大的信息增益墅拭,并輸出其所對(duì)應(yīng)的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和對(duì)應(yīng)的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
print("第%d個(gè)屬性特征所對(duì)應(yīng)的的增益為%.3f" % (index + 1, temp_information_gain)) # 輸出每個(gè)特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益活玲,確定的最大的信息增益對(duì)應(yīng)的索引
return best_feature
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算增益率
"""
def calc_gain_ratio(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv = 0.0, 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
gain_ratio = temp_information_gain / iv
print("第%d個(gè)屬性特征所對(duì)應(yīng)的增益率為%.3f,信息增益為%.3f" % (index + 1, gain_ratio, temp_information_gain)) # 輸出每個(gè)特征的信息增益
"""
Author: Taoye
微信公眾號(hào): 玩世不恭的Coder
Explain:計(jì)算基尼指數(shù)
"""
def calc_gini_index(data):
feature_number = data.shape[1] - 1 # 屬性特征的數(shù)量
base_entropy = calc_information_entropy(data) # 計(jì)算總體數(shù)據(jù)集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv, gini_index = 0.0, 0.0, 0.0
for set_item in feat_set: # 計(jì)算屬性特征劃分后的信息增益
sub_data = handle_data(data, index, set_item)
temp_df = pd.DataFrame(sub_data)
yes_proportion = temp_df[temp_df[temp_df.shape[1]-1] == "Y"].shape[0] / len(sub_data)
gini_value = 1 - (yes_proportion ** 2) - ((1- yes_proportion) ** 2)
proportion = len(sub_data) / float(data.shape[0]) # 計(jì)算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
gini_index += gini_value * proportion
temp_information_gain = base_entropy - new_entropy # 計(jì)算信息增益
gain_ratio = temp_information_gain / iv
print("第%d個(gè)屬性特征所對(duì)應(yīng)的信息增益為%.3f,增益率為%.3f, 基尼指數(shù)為%.3f" % (index + 1, temp_information_gain, gain_ratio, gini_index))
if __name__ == "__main__":
data = establish_data()
calc_gini_index(data)
優(yōu)先選取屬性特征的指標(biāo)主要有三個(gè)舒憾,分別是信息增益镀钓、增益率、基尼指數(shù)珍剑。對(duì)上述內(nèi)容做個(gè)簡(jiǎn)單的總結(jié)吧:
- 屬性特征的信息增益越高掸宛,按道理來(lái)講應(yīng)當(dāng)被優(yōu)先選取,常用于
算法
- 屬性特征的增益率越高招拙,按道理來(lái)講應(yīng)當(dāng)被優(yōu)先選取唧瘾,常用與
算法
- 屬性特征的尼基指數(shù)低,按道理來(lái)講應(yīng)當(dāng)被優(yōu)先選取别凤,常用于
算法
本文主要是決策樹(shù)的理論部分內(nèi)容饰序,介紹了什么決策樹(shù),以及生成決策樹(shù)時(shí)所需要優(yōu)先選取的三種決策標(biāo)準(zhǔn)规哪。有學(xué)習(xí)的過(guò)SVM求豫,或閱讀過(guò)Taoye之前寫(xiě)的幾篇SVM內(nèi)容的文章可以發(fā)現(xiàn),決策樹(shù)相對(duì)于SVM來(lái)講要簡(jiǎn)單很多诉稍,沒(méi)有太多且復(fù)雜的公式推導(dǎo)蝠嘉。關(guān)于決策樹(shù)的其他內(nèi)容,比如決策樹(shù)的生成杯巨、可視化蚤告、剪枝等,我們放在后面幾篇文章來(lái)寫(xiě)服爷。
我是Taoye杜恰,愛(ài)專(zhuān)研,愛(ài)分享仍源,熱衷于各種技術(shù)心褐,學(xué)習(xí)之余喜歡下象棋、聽(tīng)音樂(lè)笼踩、聊動(dòng)漫逗爹,希望借此一畝三分地記錄自己的成長(zhǎng)過(guò)程以及生活點(diǎn)滴,也希望能結(jié)實(shí)更多志同道合的圈內(nèi)朋友嚎于,更多內(nèi)容歡迎來(lái)訪微信公主號(hào):玩世不恭的Coder掘而。
參考資料:
<font style="font-size:13px;opacity:0.7">[1] 《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》:Peter Harrington 人民郵電出版社</font>
<font style="font-size:13px;opacity:0.7">[2] 《統(tǒng)計(jì)學(xué)習(xí)方法》:李航 第二版 清華大學(xué)出版社</font>
<font style="font-size:13px;opacity:0.7">[3] 《機(jī)器學(xué)習(xí)》:周志華 清華大學(xué)出版社</font>
推薦閱讀
《Machine Learning in Action》—— 剖析支持向量機(jī),優(yōu)化SMO
《Machine Learning in Action》—— 剖析支持向量機(jī)匾旭,單手狂撕線(xiàn)性SVM
print( "Hello,NumPy圃郊!" )
干啥啥不行价涝,吃飯第一名
Taoye滲透到一家黑平臺(tái)總部,背后的真相細(xì)思極恐
《大話(huà)數(shù)據(jù)庫(kù)》-SQL語(yǔ)句執(zhí)行時(shí)持舆,底層究竟做了什么小動(dòng)作色瘩?
那些年伪窖,我們玩過(guò)的Git,真香
基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度學(xué)習(xí)環(huán)境
網(wǎng)絡(luò)爬蟲(chóng)之頁(yè)面花式解析
手握手帶你了解Docker容器技術(shù)
一文詳解Hexo+Github小白建站
?打開(kāi)ElasticSearch居兆、kibana覆山、logstash的正確方式