EduCoder 机器学习 决策树
決策樹說通俗點(diǎn)就是一棵能夠替我們做決策的樹,或者說是我們?nèi)祟愒谝鰶Q策時腦回路的一種表現(xiàn)形式。
本實(shí)訓(xùn)項目的主要內(nèi)容是基于 python 語言搭建出決策樹模型對數(shù)據(jù)分類,并使用 sklearn 的決策時模型對鳶尾花數(shù)據(jù)進(jìn)行分類。
第1關(guān):什么是決策樹
- 任務(wù)描述
- 相關(guān)知識
- 引例
- 決策樹的相關(guān)概念
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):根據(jù)本節(jié)課所學(xué)知識完成本關(guān)所設(shè)置的選擇題。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握決策樹的相關(guān)基礎(chǔ)知識。
引例
在炎熱的夏天,沒有什么比冰鎮(zhèn)后的西瓜更能令人感到心曠神怡的了。現(xiàn)在我要去水果店買西瓜,但什么樣的西瓜能入我法眼呢?那根據(jù)我的個人習(xí)慣,在挑西瓜時可能就有這樣的腦回路。
假設(shè)現(xiàn)在水果店里有3個西瓜,它們的屬性如下:
| 1 | 是 | 否 | 是 | 否 |
| 2 | 是 | 是 | 否 | 是 |
| 3 | 否 | 是 | 是 | 否 |
那么根據(jù)我的腦回路我會買1和2號西瓜。
其實(shí)我的腦回路可以看成一棵樹,并且這棵樹能夠幫助我對買不買西瓜這件事做決策,所以它就是一棵決策樹。
決策樹的相關(guān)概念
決策樹是一種可以用于分類與回歸的機(jī)器學(xué)習(xí)算法,但主要用于分類。用于分類的決策樹是一種描述對實(shí)例進(jìn)行分類的樹形結(jié)構(gòu)。決策樹由結(jié)點(diǎn)和邊組成,其中結(jié)點(diǎn)分為內(nèi)部結(jié)點(diǎn)和葉子結(jié)點(diǎn),內(nèi)部結(jié)點(diǎn)表示一個特征或者屬性,葉子結(jié)點(diǎn)表示標(biāo)簽(腦回路圖中黃色的是內(nèi)部結(jié)點(diǎn),藍(lán)色的是葉子結(jié)點(diǎn))。
從代碼角度來看,決策樹其實(shí)可以看成是一堆if-else語句的集合,例如引例中的決策樹完全可以看成是如下代碼:
因此決策樹的一個非常大的優(yōu)勢就是模型的可理解性非常高,甚至可以用來挖掘數(shù)據(jù)中比較重要的信息。
那么如何構(gòu)造出一棵好的決策樹呢?其實(shí)構(gòu)造決策樹時會遵循一個指標(biāo),有的是按照信息增益來構(gòu)建,如ID3算法;有的是信息增益率來構(gòu)建,如C4.5算法;有的是按照基尼系數(shù)來構(gòu)建的,如CART算法。但不管是使用哪種構(gòu)建算法,決策樹的構(gòu)建過程通常都是一個遞歸選擇最優(yōu)特征,并根據(jù)特征對訓(xùn)練集進(jìn)行分割,使得對各個子數(shù)據(jù)集有一個最好的分類的過程。
這一過程對應(yīng)著對特征空間的劃分,也對應(yīng)著決策樹的構(gòu)建。一開始,構(gòu)建決策樹的根結(jié)點(diǎn),將所有訓(xùn)練數(shù)據(jù)都放在根結(jié)點(diǎn)。選擇一個最優(yōu)特征,并按照這一特征將訓(xùn)練數(shù)據(jù)集分割成子集,使得各個子集有一個在當(dāng)前條件下最好的分類。如果這些子集已經(jīng)能夠被基本正確分類,那么構(gòu)建葉子結(jié)點(diǎn),并將這些子集分到所對應(yīng)的葉結(jié)點(diǎn)中去;如果還有子集不能被基本正確分類,那么就對這些子集選擇新的最優(yōu)特征,繼續(xù)對其進(jìn)行分割,并構(gòu)建相應(yīng)的結(jié)點(diǎn)。如此遞歸進(jìn)行下去,直至所有訓(xùn)練數(shù)據(jù)子集被基本正確分類,或者沒有合適的特征為止。最后每個子集都被分到葉子結(jié)點(diǎn)上,即都有了明確的類別。這就構(gòu)建出了一棵決策樹。
編程要求
根據(jù)本關(guān)所學(xué)習(xí)到的知識,完成所有選擇題。
測試說明
平臺會對你的選項進(jìn)行判斷,如果實(shí)際輸出結(jié)果與預(yù)期結(jié)果相同,則通關(guān);反之,則 GameOver。
開始你的任務(wù)吧,祝你成功!
1、下列說法正確的是?(AB)
A、訓(xùn)練決策樹的過程就是構(gòu)建決策樹的過程
B、ID3算法是根據(jù)信息增益來構(gòu)建決策樹
C、C4.5算法是根據(jù)基尼系數(shù)來構(gòu)建決策樹
D、決策樹模型的可理解性不高
2、下列說法錯誤的是?(B)
A、從樹的根節(jié)點(diǎn)開始,根據(jù)特征的值一步一步走到葉子節(jié)點(diǎn)的過程是決策樹做決策的過程
B、決策樹只能是一棵二叉樹
C、根節(jié)點(diǎn)所代表的特征是最優(yōu)特征
第2關(guān):信息熵與信息增益
- 任務(wù)描述
- 相關(guān)知識
- 信息熵
- 條件熵
- 信息增益
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):掌握什么是信息增益,完成計算信息增益的程序設(shè)計。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握:
信息熵;
條件熵;
信息增益。
信息熵
信息是個很抽象的概念。人們常常說信息很多,或者信息較少,但卻很難說清楚信息到底有多少。比如一本五十萬字的中文書到底有多少信息量。
直到1948年,香農(nóng)提出了“信息熵”的概念,才解決了對信息的量化度量問題。信息熵這個詞是香農(nóng)從熱力學(xué)中借用過來的。熱力學(xué)中的熱熵是表示分子狀態(tài)混亂程度的物理量。香農(nóng)用信息熵的概念來描述信源的不確定度。信源的不確定性越大,信息熵也越大。
從機(jī)器學(xué)習(xí)的角度來看,信息熵表示的是信息量的期望值。如果數(shù)據(jù)集中的數(shù)據(jù)需要被分成多個類別,則信息量I(xi?)的定義如下(其中xi?表示多個類別中的第i個類別,p(xi?)數(shù)據(jù)集中類別為xi?的數(shù)據(jù)在數(shù)據(jù)集中出現(xiàn)的概率表示):
I(Xi?)=?log2?p(xi?)
由于信息熵是信息量的期望值,所以信息熵H(X)的定義如下(其中n為數(shù)據(jù)集中類別的數(shù)量):
H(X)=?sumi=1n?p(xi?)log2?p(xi?)
從這個公式也可以看出,如果概率是0或者是1的時候,熵就是0(因?yàn)檫@種情況下隨機(jī)變量的不確定性是最低的)。那如果概率是0.5,也就是五五開的時候,此時熵達(dá)到最大,也就是1。(就像扔硬幣,你永遠(yuǎn)都猜不透你下次扔到的是正面還是反面,所以它的不確定性非常高)。所以呢,熵越大,不確定性就越高。
條件熵
在實(shí)際的場景中,我們可能需要研究數(shù)據(jù)集中某個特征等于某個值時的信息熵等于多少,這個時候就需要用到條件熵。條件熵H(Y|X)表示特征X為某個值的條件下,類別為Y的熵。條件熵的計算公式如下:
H(Y∣X)=sumi=1n?pi?H(Y∣X=xi?)
當(dāng)然條件熵的性質(zhì)也和熵的性質(zhì)一樣,概率越確定,條件熵就越小,概率越五五開,條件熵就越大。
信息增益
現(xiàn)在已經(jīng)知道了什么是熵,什么是條件熵。接下來就可以看看什么是信息增益了。所謂的信息增益就是表示我已知條件X后能得到信息Y的不確定性的減少程度。
就好比,我在玩讀心術(shù)。你心里想一件東西,我來猜。我已開始什么都沒問你,我要猜的話,肯定是瞎猜。這個時候我的熵就非常高。然后我接下來我會去試著問你是非題,當(dāng)我問了是非題之后,我就能減小猜測你心中想到的東西的范圍,這樣其實(shí)就是減小了我的熵。那么我熵的減小程度就是我的信息增益。
所以信息增益如果套上機(jī)器學(xué)習(xí)的話就是,如果把特征A對訓(xùn)練集D的信息增益記為g(D, A)的話,那么g(D, A)的計算公式就是:
g(D,A)=H(D)?H(D,A)
為了更好的解釋熵,條件熵,信息增益的計算過程,下面通過示例來描述。假設(shè)我現(xiàn)在有這一個數(shù)據(jù)集,第一列是編號,第二列是性別,第三列是活躍度,第四列是客戶是否流失的標(biāo)簽(0表示未流失,1表示流失)。
| 1 | 男 | 高 | 0 |
| 2 | 女 | 中 | 0 |
| 3 | 男 | 低 | 1 |
| 4 | 女 | 高 | 0 |
| 5 | 男 | 高 | 0 |
| 6 | 男 | 中 | 0 |
| 7 | 男 | 中 | 1 |
| 8 | 女 | 中 | 0 |
| 9 | 女 | 低 | 1 |
| 10 | 女 | 中 | 0 |
| 11 | 女 | 高 | 0 |
| 12 | 男 | 低 | 1 |
| 13 | 女 | 低 | 1 |
| 14 | 男 | 高 | 0 |
| 15 | 男 | 高 | 0 |
假如要算性別和活躍度這兩個特征的信息增益的話,首先要先算總的熵和條件熵。總的熵其實(shí)非常好算,就是把標(biāo)簽作為隨機(jī)變量X。上表中標(biāo)簽只有兩種(0和1)因此隨機(jī)變量X的取值只有0或者1。所以要計算熵就需要先分別計算標(biāo)簽為0的概率和標(biāo)簽為1的概率。從表中能看出標(biāo)簽為0的數(shù)據(jù)有10條,所以標(biāo)簽為0的概率等于2/3。標(biāo)簽為1的概率為1/3。所以熵為:
?(1/3)?log(1/3)?(2/3)?log(2/3)=0.9182
接下來就是條件熵的計算,以性別為男的熵為例。表格中性別為男的數(shù)據(jù)有8條,這8條數(shù)據(jù)中有3條數(shù)據(jù)的標(biāo)簽為1,有5條數(shù)據(jù)的標(biāo)簽為0。所以根據(jù)條件熵的計算公式能夠得出該條件熵為:
?(3/8)?log(3/8)?(5/8)?log(5/8)=0.9543
根據(jù)上述的計算方法可知,總熵為:
?(5/15)?log(5/15)?(10/15)?log(10/15)=0.9182
性別為男的熵為:
?(3/8)?log(3/8)?(5/8)?log(5/8)=0.9543
性別為女的熵為:
?(2/7)?log(2/7)?(5/7)?log(5/7)=0.8631
活躍度為低的熵為:
?(4/4)?log(4/4)?0=0
活躍度為中的熵為:
?(1/5)?log(1/5)?(4/5)?log(4/5)=0.7219
活躍度為高的熵為:
?0?(6/6)?log(6/6)=0
現(xiàn)在有了總的熵和條件熵之后就能算出性別和活躍度這兩個特征的信息增益了。
性別的信息增益=總的熵-(8/15)*性別為男的熵-(7/15)*性別為女的熵=0.0064
*活躍度的信息增益=總的熵-(6/15)活躍度為高的熵-(5/15)*活躍度為中的熵-(4/15)*活躍度為低的熵=0.6776
那信息增益算出來之后有什么意義呢?回到讀心術(shù)的問題,為了我能更加準(zhǔn)確的猜出你心中所想,我肯定是問的問題越好就能猜得越準(zhǔn)!換句話來說我肯定是要想出一個信息增益最大(減少不確定性程度最高)的問題來問你。其實(shí)ID3算法也是這么想的。ID3算法的思想是從訓(xùn)練集D中計算每個特征的信息增益,然后看哪個最大就選哪個作為當(dāng)前結(jié)點(diǎn)。然后繼續(xù)重復(fù)剛剛的步驟來構(gòu)建決策樹。
編程要求
根據(jù)提示,在右側(cè)編輯器補(bǔ)充代碼,完成calcInfoGain函數(shù)實(shí)現(xiàn)計算信息增益。
calcInfoGain函數(shù)中的參數(shù):
feature:測試用例中字典里的feature,類型為ndarray;
label:測試用例中字典里的label,類型為ndarray;
index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。
測試說明
平臺會對你編寫的代碼進(jìn)行測試,期望您的代碼根據(jù)輸入來輸出正確的信息增益,以下為其中一個測試用例:
測試輸入: {'feature':[[0, 1], [1, 0], [1, 2], [0, 0], [1, 1]], 'label':[0, 1, 0, 0, 1], 'index': 0}
預(yù)期輸出: 0.419973
提示: 計算log可以使用NumPy中的log2函數(shù)
開始你的任務(wù)吧,祝你成功!
import numpy as npdef calcInfoGain(feature, label, index):'''計算信息增益:param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:信息增益,類型float'''#*********** Begin ***********## 計算熵def calcInfoEntropy(feature, label):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:return:信息熵,類型float'''label_set = set(label)result = 0for l in label_set:count = 0for j in range(len(label)):if label[j] == l:count += 1# 計算標(biāo)簽在數(shù)據(jù)集中出現(xiàn)的概率p = count / len(label)# 計算熵result -= p * np.log2(p)return result# 計算條件熵def calcHDA(feature, label, index, value):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:param index:需要使用的特征列索引,類型為int:param value:index所表示的特征列中需要考察的特征值,類型為int:return:信息熵,類型float'''count = 0# sub_feature和sub_label表示根據(jù)特征列和特征值分割出的子數(shù)據(jù)集中的特征和標(biāo)簽sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][index] == value:count += 1sub_feature.append(feature[i])sub_label.append(label[i])pHA = count / len(feature)e = calcInfoEntropy(sub_feature, sub_label)return pHA * ebase_e = calcInfoEntropy(feature, label)f = np.array(feature)# 得到指定特征列的值的集合f_set = set(f[:, index])sum_HDA = 0# 計算條件熵for value in f_set:sum_HDA += calcHDA(feature, label, index, value)# 計算信息增益return base_e - sum_HDA#*********** End *************#第3關(guān):使用ID3算法構(gòu)建決策樹
- 任務(wù)描述
- 相關(guān)知識
- ID3算法
- 使用決策樹進(jìn)行預(yù)測
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):補(bǔ)充python代碼,完成DecisionTree類中的fit和predict函數(shù)。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握:
ID3算法構(gòu)造決策樹的流程;
如何使用構(gòu)造好的決策樹進(jìn)行預(yù)測。
ID3算法
ID3算法其實(shí)就是依據(jù)特征的信息增益來構(gòu)建樹的。其大致步驟就是從根結(jié)點(diǎn)開始,對結(jié)點(diǎn)計算所有可能的特征的信息增益,然后選擇信息增益最大的特征作為結(jié)點(diǎn)的特征,由該特征的不同取值建立子結(jié)點(diǎn),然后對子結(jié)點(diǎn)遞歸執(zhí)行上述的步驟直到信息增益很小或者沒有特征可以繼續(xù)選擇為止。
因此,ID3算法偽代碼如下:
使用決策樹進(jìn)行預(yù)測
決策樹的預(yù)測思想非常簡單,假設(shè)現(xiàn)在已經(jīng)構(gòu)建出了一棵用來決策是否買西瓜的決策樹。
并假設(shè)現(xiàn)在在水果店里有這樣一個西瓜,其屬性如下:
| 是 | 否 | 是 | 否 |
那買不買這個西瓜呢?只需把西瓜的屬性代入決策樹即可。決策樹的根結(jié)點(diǎn)是瓤是否夠紅,所以就看西瓜的屬性,經(jīng)查看發(fā)現(xiàn)夠紅,因此接下來就看夠不夠冰。而西瓜不夠冰,那么看是否便宜。發(fā)現(xiàn)西瓜是便宜的,所以這個西瓜是可以買的。
因此使用決策樹進(jìn)行預(yù)測的偽代碼也比較簡單,偽代碼如下:
編程要求
填寫fit(self, feature, label)函數(shù),實(shí)現(xiàn)ID3算法,要求決策樹保存在self.tree中。其中:
feature:訓(xùn)練集數(shù)據(jù),類型為ndarray,數(shù)值全為整數(shù);
label:訓(xùn)練集標(biāo)簽,類型為ndarray,數(shù)值全為整數(shù)。
填寫predict(self, feature)函數(shù),實(shí)現(xiàn)預(yù)測功能,并將標(biāo)簽返回,其中:
- feature:測試集數(shù)據(jù),類型為ndarray,數(shù)值全為整數(shù)。(PS:feature中有多條數(shù)據(jù))
測試說明
只需完成fit與predict函數(shù)即可,程序內(nèi)部會調(diào)用您所完成的fit函數(shù)構(gòu)建模型并調(diào)用predict函數(shù)來對數(shù)據(jù)進(jìn)行預(yù)測。預(yù)測的準(zhǔn)確率高于0.92視為過關(guān)。(PS:若self.tree is None則會打印決策樹構(gòu)建失敗)
開始你的任務(wù)吧,祝你成功!
import numpy as np class DecisionTree(object):def __init__(self):#決策樹模型self.tree = {}def calcInfoGain(self, feature, label, index):'''計算信息增益:param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:信息增益,類型float'''# 計算熵def calcInfoEntropy(label):'''計算信息熵:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:return:信息熵,類型float'''label_set = set(label)result = 0for l in label_set:count = 0for j in range(len(label)):if label[j] == l:count += 1# 計算標(biāo)簽在數(shù)據(jù)集中出現(xiàn)的概率p = count / len(label)# 計算熵result -= p * np.log2(p)return result# 計算條件熵def calcHDA(feature, label, index, value):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:param index:需要使用的特征列索引,類型為int:param value:index所表示的特征列中需要考察的特征值,類型為int:return:信息熵,類型float'''count = 0# sub_feature和sub_label表示根據(jù)特征列和特征值分割出的子數(shù)據(jù)集中的特征和標(biāo)簽sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][index] == value:count += 1sub_feature.append(feature[i])sub_label.append(label[i])pHA = count / len(feature)e = calcInfoEntropy(sub_label)return pHA * ebase_e = calcInfoEntropy(label)f = np.array(feature)# 得到指定特征列的值的集合f_set = set(f[:, index])sum_HDA = 0# 計算條件熵for value in f_set:sum_HDA += calcHDA(feature, label, index, value)# 計算信息增益return base_e - sum_HDA# 獲得信息增益最高的特征def getBestFeature(self, feature, label):max_infogain = 0best_feature = 0for i in range(len(feature[0])):infogain = self.calcInfoGain(feature, label, i)if infogain > max_infogain:max_infogain = infogainbest_feature = ireturn best_featuredef createTree(self, feature, label):# 樣本里都是同一個label沒必要繼續(xù)分叉了if len(set(label)) == 1:return label[0]# 樣本中只有一個特征或者所有樣本的特征都一樣的話就看哪個label的票數(shù)高if len(feature[0]) == 1 or len(np.unique(feature, axis=0)) == 1:vote = {}for l in label:if l in vote.keys():vote[l] += 1else:vote[l] = 1max_count = 0vote_label = Nonefor k, v in vote.items():if v > max_count:max_count = vvote_label = kreturn vote_label# 根據(jù)信息增益拿到特征的索引best_feature = self.getBestFeature(feature, label)tree = {best_feature: {}}f = np.array(feature)# 拿到bestfeature的所有特征值f_set = set(f[:, best_feature])# 構(gòu)建對應(yīng)特征值的子樣本集sub_feature, sub_labelfor v in f_set:sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][best_feature] == v:sub_feature.append(feature[i])sub_label.append(label[i])# 遞歸構(gòu)建決策樹tree[best_feature][v] = self.createTree(sub_feature, sub_label)return treedef fit(self, feature, label):''':param feature: 訓(xùn)練集數(shù)據(jù),類型為ndarray:param label:訓(xùn)練集標(biāo)簽,類型為ndarray:return: None'''#************* Begin ************#self.tree = self.createTree(feature, label)#************* End **************#def predict(self, feature):''':param feature:測試集數(shù)據(jù),類型為ndarray:return:預(yù)測結(jié)果,如np.array([0, 1, 2, 2, 1, 0])'''#************* Begin ************#result = []def classify(tree, feature):if not isinstance(tree, dict):return treet_index, t_value = list(tree.items())[0]f_value = feature[t_index]if isinstance(t_value, dict):classLabel = classify(tree[t_index][f_value], feature)return classLabelelse:return t_valuefor f in feature:result.append(classify(self.tree, f))return np.array(result)#************* End **************#第4關(guān):信息增益率
- 任務(wù)描述
- 相關(guān)知識
- 信息增益率
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):根據(jù)本關(guān)所學(xué)知識,完成calcInfoGainRatio函數(shù)。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握:信息增益率
信息增益率
由于在使用信息增益這一指標(biāo)進(jìn)行劃分時,更喜歡可取值數(shù)量較多的特征。為了減少這種偏好可能帶來的不利影響,Ross Quinlan使用了信息增益率這一指標(biāo)來選擇最優(yōu)劃分屬性。
信息增益率的數(shù)學(xué)定義為如下,其中D表示數(shù)據(jù)集,a表示數(shù)據(jù)集中的某一列,Gain(D,a)表示D中a的信息增益,V表示a這一列中取值的集合,v表示V中的某種取值,∣D∣表示D中樣本的數(shù)量,∣Dv∣表示D中a這一列中值等于v的數(shù)量。
Gain_ratio(D,a)=?v=1∑V?∣D∣∣Dv∣?log2?∣D∣∣Dv∣?Gain(D,a)?
從公式可以看出,信息增益率很好算,只是用信息增益除以另一個分母,該分母通常稱為固有值。舉個例子,還是使用第二關(guān)中提到過的數(shù)據(jù)集,第一列是編號,第二列是性別,第三列是活躍度,第四列是客戶是否流失的標(biāo)簽(0表示未流失,1表示流失)。
| 1 | 男 | 高 | 0 |
| 2 | 女 | 中 | 0 |
| 3 | 男 | 低 | 1 |
| 4 | 女 | 高 | 0 |
| 5 | 男 | 高 | 0 |
| 6 | 男 | 中 | 0 |
| 7 | 男 | 中 | 1 |
| 8 | 女 | 中 | 0 |
| 9 | 女 | 低 | 1 |
| 10 | 女 | 中 | 0 |
| 11 | 女 | 高 | 0 |
| 12 | 男 | 低 | 1 |
| 13 | 女 | 低 | 1 |
| 14 | 男 | 高 | 0 |
| 15 | 男 | 高 | 0 |
根據(jù)第二關(guān)已經(jīng)知道性別的信息增益為0.0064,設(shè)a為性別,則有Gain(D,a)=0.0064。由根據(jù)數(shù)據(jù)可知,V=2,假設(shè)當(dāng)v=1時表示性別為男,v=2時表示性別為女,則有∣D∣=15,∣D1∣=8,∣D2∣=7。因此根據(jù)信息增益率的計算公式可知Gainr?atio(D,a)=0.0642。同理可以算出活躍度的信息增益率為0.4328。
編程要求
根據(jù)提示,在右側(cè)編輯器補(bǔ)充代碼,完成calcInfoGainRatio函數(shù)實(shí)現(xiàn)計算信息增益。
calcInfoGainRatio函數(shù)中的參數(shù):
feature:測試用例中字典里的feature,類型為ndarray;
label:測試用例中字典里的label,類型為ndarray;
index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益率。
測試說明
平臺會對你編寫的代碼進(jìn)行測試,期望您的代碼根據(jù)輸入來輸出正確的信息增益,以下為其中一個測試用例:
測試輸入: {'feature':[[0, 1], [1, 0], [1, 2], [0, 0], [1, 1]], 'label':[0, 1, 0, 0, 1], 'index': 0}
預(yù)期輸出: 0.432538
提示: 計算log可以使用NumPy中的log2函數(shù)
開始你的任務(wù)吧,祝你成功!
import numpy as npdef calcInfoGain(feature, label, index):'''計算信息增益:param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:信息增益,類型float'''# 計算熵def calcInfoEntropy(label):'''計算信息熵:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:return:信息熵,類型float'''label_set = set(label)result = 0for l in label_set:count = 0for j in range(len(label)):if label[j] == l:count += 1# 計算標(biāo)簽在數(shù)據(jù)集中出現(xiàn)的概率p = count / len(label)# 計算熵result -= p * np.log2(p)return result# 計算條件熵def calcHDA(feature, label, index, value):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:param index:需要使用的特征列索引,類型為int:param value:index所表示的特征列中需要考察的特征值,類型為int:return:信息熵,類型float'''count = 0# sub_feature和sub_label表示根據(jù)特征列和特征值分割出的子數(shù)據(jù)集中的特征和標(biāo)簽sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][index] == value:count += 1sub_feature.append(feature[i])sub_label.append(label[i])pHA = count / len(feature)e = calcInfoEntropy(sub_label)return pHA * ebase_e = calcInfoEntropy(label)f = np.array(feature)# 得到指定特征列的值的集合f_set = set(f[:, index])sum_HDA = 0# 計算條件熵for value in f_set:sum_HDA += calcHDA(feature, label, index, value)# 計算信息增益return base_e - sum_HDAdef calcInfoGainRatio(feature, label, index):'''計算信息增益率:param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:信息增益率,類型float'''#********* Begin *********#info_gain = calcInfoGain(feature, label, index)unique_value = list(set(feature[:, index]))IV = 0for value in unique_value:len_v = np.sum(feature[:, index] == value)IV -= (len_v/len(feature))*np.log2((len_v/len(feature)))return info_gain/IV#********* End *********#第5關(guān):基尼系數(shù)
- 任務(wù)描述
- 相關(guān)知識
- 基尼系數(shù)
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):根據(jù)本關(guān)所學(xué)知識,完成calcGini函數(shù)。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握:基尼系數(shù)。
基尼系數(shù)
在ID3算法中我們使用了信息增益來選擇特征,信息增益大的優(yōu)先選擇。在C4.5算法中,采用了信息增益率來選擇特征,以減少信息增益容易選擇特征值多的特征的問題。但是無論是ID3還是C4.5,都是基于信息論的熵模型的,這里面會涉及大量的對數(shù)運(yùn)算。能不能簡化模型同時也不至于完全丟失熵模型的優(yōu)點(diǎn)呢?當(dāng)然有!那就是基尼系數(shù)!
CART算法使用基尼系數(shù)來代替信息增益率,基尼系數(shù)代表了模型的不純度,基尼系數(shù)越小,則不純度越低,特征越好。這和信息增益與信息增益率是相反的(它們都是越大越好)。
基尼系數(shù)的數(shù)學(xué)定義為如下,其中D表示數(shù)據(jù)集,pk?表示D中第k個類別在D中所占比例。
Gini(D)=1?sumk=1∣y∣?pk2?
從公式可以看出,相比于信息增益和信息增益率,計算起來更加簡單。舉個例子,還是使用第二關(guān)中提到過的數(shù)據(jù)集,第一列是編號,第二列是性別,第三列是活躍度,第四列是客戶是否流失的標(biāo)簽(0表示未流失,1表示流失)。
| 1 | 男 | 高 | 0 |
| 2 | 女 | 中 | 0 |
| 3 | 男 | 低 | 1 |
| 4 | 女 | 高 | 0 |
| 5 | 男 | 高 | 0 |
| 6 | 男 | 中 | 0 |
| 7 | 男 | 中 | 1 |
| 8 | 女 | 中 | 0 |
| 9 | 女 | 低 | 1 |
| 10 | 女 | 中 | 0 |
| 11 | 女 | 高 | 0 |
| 12 | 男 | 低 | 1 |
| 13 | 女 | 低 | 1 |
| 14 | 男 | 高 | 0 |
| 15 | 男 | 高 | 0 |
從表格可以看出,D中總共有2個類別,設(shè)類別為0的比例為p1?,則有p1?=1510?。設(shè)類別為1的比例為p2?,則有p2?=155?。根據(jù)基尼系數(shù)的公式可知Gini(D)=1?(p12?+p22?)=0.4444。
上面是基于數(shù)據(jù)集D的基尼系數(shù)的計算方法,那么基于數(shù)據(jù)集D與特征a的基尼系數(shù)怎樣計算呢?其實(shí)和信息增益率的套路差不多。計算公式如下:
Gini(D,a)=sumv=1V?∣D∣∣Dv∣?Gini(Dv)
還是以用戶流失的數(shù)據(jù)為例,現(xiàn)在算一算性別的基尼系數(shù)。設(shè)性別男為v=1,性別女為v=2則有∣D∣=15,∣D1∣=8,∣D2∣=7,Gini(D1)=0.46875,Gini(D2)=0.40816。所以Gini(D,a)=0.44048。
編程要求
根據(jù)提示,在右側(cè)編輯器補(bǔ)充代碼,完成calcGini函數(shù)實(shí)現(xiàn)計算信息增益。
calcGini函數(shù)中的參數(shù):
feature:測試用例中字典里的feature,類型為ndarray;
label:測試用例中字典里的label,類型為ndarray;
index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算基尼系數(shù)。
測試說明
平臺會對你編寫的代碼進(jìn)行測試,期望您的代碼根據(jù)輸入來輸出正確的信息增益,以下為其中一個測試用例:
測試輸入: {'feature':[[0, 1], [1, 0], [1, 2], [0, 0], [1, 1]], 'label':[0, 1, 0, 0, 1], 'index': 0}
預(yù)期輸出: 0.266667
開始你的任務(wù)吧,祝你成功!
import numpy as np def calcGini(feature, label, index):'''計算基尼系數(shù):param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:基尼系數(shù),類型float'''#********* Begin *********#def _gini(label):unique_label = list(set(label))gini = 1for l in unique_label:p = np.sum(label == l)/len(label)gini -= p**2return giniunique_value = list(set(feature[:, index]))gini = 0for value in unique_value:len_v = np.sum(feature[:, index] == value)gini += (len_v/len(feature))*_gini(label[feature[:, index] == value])return gini#********* End *********#第6關(guān):預(yù)剪枝與后剪枝
- 任務(wù)描述
- 相關(guān)知識
- 為什么需要剪枝
- 預(yù)剪枝
- 后剪枝
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):補(bǔ)充python代碼,完成DecisionTree類中的fit和predict函數(shù)。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握:
為什么需要剪枝;
預(yù)剪枝;
后剪枝。
為什么需要剪枝
決策樹的生成是遞歸地去構(gòu)建決策樹,直到不能繼續(xù)下去為止。這樣產(chǎn)生的樹往往對訓(xùn)練數(shù)據(jù)有很高的分類準(zhǔn)確率,但對未知的測試數(shù)據(jù)進(jìn)行預(yù)測就沒有那么準(zhǔn)確了,也就是所謂的過擬合。
決策樹容易過擬合的原因是在構(gòu)建決策樹的過程時會過多地考慮如何提高對訓(xùn)練集中的數(shù)據(jù)的分類準(zhǔn)確率,從而會構(gòu)建出非常復(fù)雜的決策樹(樹的寬度和深度都比較大)。在之前的實(shí)訓(xùn)中已經(jīng)提到過,模型的復(fù)雜度越高,模型就越容易出現(xiàn)過擬合的現(xiàn)象。所以簡化決策樹的復(fù)雜度能夠有效地緩解過擬合現(xiàn)象,而簡化決策樹最常用的方法就是剪枝。剪枝分為預(yù)剪枝與后剪枝。
預(yù)剪枝
預(yù)剪枝的核心思想是在決策樹生成過程中,對每個結(jié)點(diǎn)在劃分前先進(jìn)行一個評估,若當(dāng)前結(jié)點(diǎn)的劃分不能帶來決策樹泛化性能提升,則停止劃分并將當(dāng)前結(jié)點(diǎn)標(biāo)記為葉結(jié)點(diǎn)。
想要評估決策樹算法的泛化性能如何,方法很簡單。可以將訓(xùn)練數(shù)據(jù)集中隨機(jī)取出一部分作為驗(yàn)證數(shù)據(jù)集,然后在用訓(xùn)練數(shù)據(jù)集對每個結(jié)點(diǎn)進(jìn)行劃分之前用當(dāng)前狀態(tài)的決策樹計算出在驗(yàn)證數(shù)據(jù)集上的正確率。正確率越高說明決策樹的泛化性能越好,如果在劃分結(jié)點(diǎn)的時候發(fā)現(xiàn)泛化性能有所下降或者沒有提升時,說明應(yīng)該停止劃分,并用投票計數(shù)的方式將當(dāng)前結(jié)點(diǎn)標(biāo)記成葉子結(jié)點(diǎn)。
舉個例子,假如上一關(guān)中所提到的用來決定是否買西瓜的決策樹模型已經(jīng)出現(xiàn)過擬合的情況,模型如下:
假設(shè)當(dāng)模型在劃分是否便宜這個結(jié)點(diǎn)前,模型在驗(yàn)證數(shù)據(jù)集上的正確率為0.81。但在劃分后,模型在驗(yàn)證數(shù)據(jù)集上的正確率降為0.67。此時就不應(yīng)該劃分是否便宜這個結(jié)點(diǎn)。所以預(yù)剪枝后的模型如下:
從上圖可以看出,預(yù)剪枝能夠降低決策樹的復(fù)雜度。這種預(yù)剪枝處理屬于貪心思想,但是貪心有一定的缺陷,就是可能當(dāng)前劃分會降低泛化性能,但在其基礎(chǔ)上進(jìn)行的后續(xù)劃分卻有可能導(dǎo)致性能顯著提高。所以有可能會導(dǎo)致決策樹出現(xiàn)欠擬合的情況。
后剪枝
后剪枝是先從訓(xùn)練集生成一棵完整的決策樹,然后自底向上地對非葉結(jié)點(diǎn)進(jìn)行考察,若將該結(jié)點(diǎn)對應(yīng)的子樹替換為葉結(jié)點(diǎn)能夠帶來決策樹泛化性能提升,則將該子樹替換為葉結(jié)點(diǎn)。
后剪枝的思路很直接,對于決策樹中的每一個非葉子結(jié)點(diǎn)的子樹,我們嘗試著把它替換成一個葉子結(jié)點(diǎn),該葉子結(jié)點(diǎn)的類別我們用子樹所覆蓋訓(xùn)練樣本中存在最多的那個類來代替,這樣就產(chǎn)生了一個簡化決策樹,然后比較這兩個決策樹在測試數(shù)據(jù)集中的表現(xiàn),如果簡化決策樹在驗(yàn)證數(shù)據(jù)集中的準(zhǔn)確率有所提高,那么該子樹就可以替換成葉子結(jié)點(diǎn)。該算法以bottom-up的方式遍歷所有的子樹,直至沒有任何子樹可以替換使得測試數(shù)據(jù)集的表現(xiàn)得以改進(jìn)時,算法就可以終止。
從后剪枝的流程可以看出,后剪枝是從全局的角度來看待要不要剪枝,所以造成欠擬合現(xiàn)象的可能性比較小。但由于后剪枝需要先生成完整的決策樹,然后再剪枝,所以后剪枝的訓(xùn)練時間開銷更高。
編程要求
填寫fit(self, train_feature, train_label, val_featrue, val_label)函數(shù),實(shí)現(xiàn)帶后剪枝的ID3算法,要求決策樹保存在self.tree中。其中:
train_feature:訓(xùn)練集數(shù)據(jù),類型為ndarray,數(shù)值全為整數(shù);
train_label:訓(xùn)練集標(biāo)簽,類型為ndarray,數(shù)值全為整數(shù);
val_feature:驗(yàn)證集數(shù)據(jù),類型為ndarray,數(shù)值全為整數(shù);
val_label:驗(yàn)證集標(biāo)簽,類型為ndarray,數(shù)值全為整數(shù)。
填寫predict(self, feature)函數(shù),實(shí)現(xiàn)預(yù)測功能,并將標(biāo)簽返回,其中:
- feature:測試集數(shù)據(jù),類型為ndarray,數(shù)值全為整數(shù)。(PS:feature中有多條數(shù)據(jù))
測試說明
只需完成fit與predict函數(shù)即可,程序內(nèi)部會調(diào)用您所完成的fit函數(shù)構(gòu)建模型并調(diào)用predict函數(shù)來對數(shù)據(jù)進(jìn)行預(yù)測。預(yù)測的準(zhǔn)確率高于0.935視為過關(guān)。(PS:若self.tree is None則會打印決策樹構(gòu)建失敗)
import numpy as np from copy import deepcopyclass DecisionTree(object):def __init__(self):#決策樹模型self.tree = {}def calcInfoGain(self, feature, label, index):'''計算信息增益:param feature:測試用例中字典里的feature,類型為ndarray:param label:測試用例中字典里的label,類型為ndarray:param index:測試用例中字典里的index,即feature部分特征列的索引。該索引指的是feature中第幾個特征,如index:0表示使用第一個特征來計算信息增益。:return:信息增益,類型float'''# 計算熵def calcInfoEntropy(feature, label):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:return:信息熵,類型float'''label_set = set(label)result = 0for l in label_set:count = 0for j in range(len(label)):if label[j] == l:count += 1# 計算標(biāo)簽在數(shù)據(jù)集中出現(xiàn)的概率p = count / len(label)# 計算熵result -= p * np.log2(p)return result# 計算條件熵def calcHDA(feature, label, index, value):'''計算信息熵:param feature:數(shù)據(jù)集中的特征,類型為ndarray:param label:數(shù)據(jù)集中的標(biāo)簽,類型為ndarray:param index:需要使用的特征列索引,類型為int:param value:index所表示的特征列中需要考察的特征值,類型為int:return:信息熵,類型float'''count = 0# sub_feature和sub_label表示根據(jù)特征列和特征值分割出的子數(shù)據(jù)集中的特征和標(biāo)簽sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][index] == value:count += 1sub_feature.append(feature[i])sub_label.append(label[i])pHA = count / len(feature)e = calcInfoEntropy(sub_feature, sub_label)return pHA * ebase_e = calcInfoEntropy(feature, label)f = np.array(feature)# 得到指定特征列的值的集合f_set = set(f[:, index])sum_HDA = 0# 計算條件熵for value in f_set:sum_HDA += calcHDA(feature, label, index, value)# 計算信息增益return base_e - sum_HDA# 獲得信息增益最高的特征def getBestFeature(self, feature, label):max_infogain = 0best_feature = 0for i in range(len(feature[0])):infogain = self.calcInfoGain(feature, label, i)if infogain > max_infogain:max_infogain = infogainbest_feature = ireturn best_feature# 計算驗(yàn)證集準(zhǔn)確率def calc_acc_val(self, the_tree, val_feature, val_label):result = []def classify(tree, feature):if not isinstance(tree, dict):return treet_index, t_value = list(tree.items())[0]f_value = feature[t_index]if isinstance(t_value, dict):classLabel = classify(tree[t_index][f_value], feature)return classLabelelse:return t_valuefor f in val_feature:result.append(classify(the_tree, f))result = np.array(result)return np.mean(result == val_label)def createTree(self, train_feature, train_label):# 樣本里都是同一個label沒必要繼續(xù)分叉了if len(set(train_label)) == 1:return train_label[0]# 樣本中只有一個特征或者所有樣本的特征都一樣的話就看哪個label的票數(shù)高if len(train_feature[0]) == 1 or len(np.unique(train_feature, axis=0)) == 1:vote = {}for l in train_label:if l in vote.keys():vote[l] += 1else:vote[l] = 1max_count = 0vote_label = Nonefor k, v in vote.items():if v > max_count:max_count = vvote_label = kreturn vote_label# 根據(jù)信息增益拿到特征的索引best_feature = self.getBestFeature(train_feature, train_label)tree = {best_feature: {}}f = np.array(train_feature)# 拿到bestfeature的所有特征值f_set = set(f[:, best_feature])# 構(gòu)建對應(yīng)特征值的子樣本集sub_feature, sub_labelfor v in f_set:sub_feature = []sub_label = []for i in range(len(train_feature)):if train_feature[i][best_feature] == v:sub_feature.append(train_feature[i])sub_label.append(train_label[i])# 遞歸構(gòu)建決策樹tree[best_feature][v] = self.createTree(sub_feature, sub_label)return tree# 后剪枝def post_cut(self, val_feature, val_label):# 拿到非葉子節(jié)點(diǎn)的數(shù)量def get_non_leaf_node_count(tree):non_leaf_node_path = []def dfs(tree, path, all_path):for k in tree.keys():if isinstance(tree[k], dict):path.append(k)dfs(tree[k], path, all_path)if len(path) > 0:path.pop()else:all_path.append(path[:])dfs(tree, [], non_leaf_node_path)unique_non_leaf_node = []for path in non_leaf_node_path:isFind = Falsefor p in unique_non_leaf_node:if path == p:isFind = Truebreakif not isFind:unique_non_leaf_node.append(path)return len(unique_non_leaf_node)# 拿到樹中深度最深的從根節(jié)點(diǎn)到非葉子節(jié)點(diǎn)的路徑def get_the_most_deep_path(tree):non_leaf_node_path = []def dfs(tree, path, all_path):for k in tree.keys():if isinstance(tree[k], dict):path.append(k)dfs(tree[k], path, all_path)if len(path) > 0:path.pop()else:all_path.append(path[:])dfs(tree, [], non_leaf_node_path)max_depth = 0result = Nonefor path in non_leaf_node_path:if len(path) > max_depth:max_depth = len(path)result = pathreturn result# 剪枝def set_vote_label(tree, path, label):for i in range(len(path)-1):tree = tree[path[i]]tree[path[len(path)-1]] = vote_labelacc_before_cut = self.calc_acc_val(self.tree, val_feature, val_label)# 遍歷所有非葉子節(jié)點(diǎn)for _ in range(get_non_leaf_node_count(self.tree)):path = get_the_most_deep_path(self.tree)# 備份樹tree = deepcopy(self.tree)step = deepcopy(tree)# 跟著路徑走for k in path:step = step[k]# 葉子節(jié)點(diǎn)中票數(shù)最多的標(biāo)簽vote_label = sorted(step.items(), key=lambda item: item[1], reverse=True)[0][0]# 在備份的樹上剪枝set_vote_label(tree, path, vote_label)acc_after_cut = self.calc_acc_val(tree, val_feature, val_label)# 驗(yàn)證集準(zhǔn)確率高于0.9才剪枝if acc_after_cut > acc_before_cut:set_vote_label(self.tree, path, vote_label)acc_before_cut = acc_after_cutdef fit(self, train_feature, train_label, val_feature, val_label):''':param train_feature:訓(xùn)練集數(shù)據(jù),類型為ndarray:param train_label:訓(xùn)練集標(biāo)簽,類型為ndarray:param val_feature:驗(yàn)證集數(shù)據(jù),類型為ndarray:param val_label:驗(yàn)證集標(biāo)簽,類型為ndarray:return: None'''#************* Begin ************#self.tree = self.createTree(train_feature, train_label)# 后剪枝self.post_cut(val_feature, val_label)#************* End **************#def predict(self, feature):''':param feature:測試集數(shù)據(jù),類型為ndarray:return:預(yù)測結(jié)果,如np.array([0, 1, 2, 2, 1, 0])'''#************* Begin ************#result = []# 單個樣本分類def classify(tree, feature):if not isinstance(tree, dict):return treet_index, t_value = list(tree.items())[0]f_value = feature[t_index]if isinstance(t_value, dict):classLabel = classify(tree[t_index][f_value], feature)return classLabelelse:return t_valuefor f in feature:result.append(classify(self.tree, f))return np.array(result)#************* End **************#第7關(guān):鳶尾花識別
- 任務(wù)描述
- 相關(guān)知識
- 數(shù)據(jù)簡介
- DecisionTreeClassifier
- 編程要求
- 測試說明
任務(wù)描述
本關(guān)任務(wù):使用sklearn完成鳶尾花分類任務(wù)。
相關(guān)知識
為了完成本關(guān)任務(wù),你需要掌握如何使用sklearn提供的DecisionTreeClassifier。
數(shù)據(jù)簡介
鳶尾花數(shù)據(jù)集是一類多重變量分析的數(shù)據(jù)集。通過花萼長度,花萼寬度,花瓣長度,花瓣寬度4個屬性預(yù)測鳶尾花卉屬于(Setosa,Versicolour,Virginica)三個種類中的哪一類(其中分別用0,1,2代替)。
數(shù)據(jù)集中部分?jǐn)?shù)據(jù)與標(biāo)簽如下圖所示:
DecisionTreeClassifier
DecisionTreeClassifier的構(gòu)造函數(shù)中有兩個常用的參數(shù)可以設(shè)置:
- criterion:劃分節(jié)點(diǎn)時用到的指標(biāo)。有g(shù)ini(基尼系數(shù)),entropy(信息增益)。若不設(shè)置,默認(rèn)為gini
- max_depth:決策樹的最大深度,如果發(fā)現(xiàn)模型已經(jīng)出現(xiàn)過擬合,可以嘗試將該參數(shù)調(diào)小。若不設(shè)置,默認(rèn)為None
和sklearn中其他分類器一樣,DecisionTreeClassifier類中的fit函數(shù)用于訓(xùn)練模型,fit函數(shù)有兩個向量輸入:
X:大小為[樣本數(shù)量,特征數(shù)量]的ndarray,存放訓(xùn)練樣本;
Y:值為整型,大小為[樣本數(shù)量]的ndarray,存放訓(xùn)練樣本的分類標(biāo)簽。
DecisionTreeClassifier類中的predict函數(shù)用于預(yù)測,返回預(yù)測標(biāo)簽,predict函數(shù)有一個向量輸入:
- X:大小為[樣本數(shù)量,特征數(shù)量]的ndarray,存放預(yù)測樣本。
DecisionTreeClassifier的使用代碼如下:
編程要求
補(bǔ)充python代碼,實(shí)現(xiàn)鳶尾花數(shù)據(jù)的分類任務(wù),其中訓(xùn)練集數(shù)據(jù)保存在./step7/train_data.csv中,訓(xùn)練集標(biāo)簽保存在。./step7/train_label.csv中,測試集數(shù)據(jù)保存在。./step7/test_data.csv中。請將對測試集的預(yù)測結(jié)果保存至。./step7/predict.csv中。這些csv文件可以使用pandas讀取與寫入。
注意:當(dāng)使用pandas讀取完csv文件后,請將讀取到的DataFrame轉(zhuǎn)換成ndarray類型。這樣才能正常的使用fit和predict。
示例代碼:
數(shù)據(jù)文件格式如下圖所示:
標(biāo)簽文件格式如下圖所示:
PS:predict.csv文件的格式必須與標(biāo)簽文件格式一致。
測試說明
只需將結(jié)果保存至./step7/predict.csv即可,程序內(nèi)部會檢測您的代碼,預(yù)測準(zhǔn)確率高于0.95視為過關(guān)。
開始你的任務(wù)吧,祝你成功!
#********* Begin *********# import pandas as pd from sklearn.tree import DecisionTreeClassifiertrain_df = pd.read_csv('./step7/train_data.csv').as_matrix() train_label = pd.read_csv('./step7/train_label.csv').as_matrix() test_df = pd.read_csv('./step7/test_data.csv').as_matrix()dt = DecisionTreeClassifier() dt.fit(train_df, train_label) result = dt.predict(test_df)result = pd.DataFrame({'target':result}) result.to_csv('./step7/predict.csv', index=False)#********* End *********#總結(jié)
以上是生活随笔為你收集整理的EduCoder 机器学习 决策树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EduCoder 机器学习 逻辑回归
- 下一篇: Hive 任务卡在 map = 0%,