文章原創(chuàng),最近更新:2018-08-13
本章節(jié)的主要內(nèi)容是:
重點(diǎn)介紹項(xiàng)目案例1:判定魚(yú)類(lèi)和非魚(yú)類(lèi)選擇最好的數(shù)據(jù)集劃分方式的函數(shù)代碼。
1.決策樹(shù)項(xiàng)目案例介紹:
項(xiàng)目案例1:
判定魚(yú)類(lèi)和非魚(yú)類(lèi)
項(xiàng)目概述:
- 根據(jù)以下 2 個(gè)特征,將動(dòng)物分成兩類(lèi):魚(yú)類(lèi)和非魚(yú)類(lèi)。
- 特征: 1. 不浮出水面是否可以生存 2. 是否有腳蹼
開(kāi)發(fā)流程:
- 收集數(shù)據(jù):可以使用任何方法
- 準(zhǔn)備數(shù)據(jù):樹(shù)構(gòu)造算法只適用于標(biāo)稱(chēng)型數(shù)據(jù),因此數(shù)值型數(shù)據(jù)必須離散化
- 分析數(shù)據(jù):可以使用任何方法,構(gòu)造樹(shù)完成之后,我們應(yīng)該檢查圖形是否符合預(yù)期
- 訓(xùn)練算法:構(gòu)造樹(shù)的數(shù)據(jù)結(jié)構(gòu)
- 測(cè)試算法:使用決策樹(shù)執(zhí)行分類(lèi)
- 使用算法:此步驟可以適用于任何監(jiān)督學(xué)習(xí)算法,而使用決策樹(shù)可以更好地理解數(shù)據(jù)的內(nèi)在含義
數(shù)據(jù)集介紹

2.選擇最好的數(shù)據(jù)集劃分方式的函數(shù)代碼
接下來(lái)我們將遍歷整個(gè)數(shù)據(jù)集,循環(huán)計(jì)算香農(nóng)熵和 splitDataSet()函數(shù),找到最好的特征劃分方式。熵計(jì)算將會(huì)告訴我們?nèi)绾蝿澐謹(jǐn)?shù)據(jù)集是最好的數(shù)據(jù)組織方式.
打開(kāi)文本編輯器,在 trees.py文件中輸入下面的程序代碼。
def chooseBestFeatTopSplit(dataSet):
"""chooseBestFeatureToSplit(選擇最好的特征)
Args:
dataSet 數(shù)據(jù)集
Returns:
bestFeature 最優(yōu)的特征列
"""
# 求第一行有多少列的 Feature, 減去1,是因?yàn)樽詈笠涣惺莑abel列
numFeatures = len(dataSet[0])-1
# 計(jì)算沒(méi)有經(jīng)過(guò)劃分的數(shù)據(jù)的香農(nóng)熵
baseEntropy = calcShannonEnt(dataSet)
# 最優(yōu)的信息增益值
bestInfoGain = 0.0
#最優(yōu)的Featurn編號(hào)
bestFeature = -1
for i in range(numFeatures):
# 創(chuàng)建唯一的分類(lèi)標(biāo)簽列表,獲取第i個(gè)的所有特征(信息元縱排列!)
featList = [example[i] for example in dataSet]
"""
print(featList)結(jié)果為
[1, 1, 1, 0, 0]
[1, 1, 0, 1, 1]
"""
# 使用set集,排除featList中的重復(fù)標(biāo)簽,得到唯一分類(lèi)的集合
uniqueVals = set(featList)
"""
print(uniqueVals)結(jié)果為
{0, 1}
{0, 1}
"""
newEntropy = 0.0
# 遍歷當(dāng)次uniqueVals中所有的標(biāo)簽value(這里是0,1)
for value in uniqueVals:
# 對(duì)第i個(gè)數(shù)據(jù)劃分?jǐn)?shù)據(jù)集, 返回所有包含i的數(shù)據(jù)(已排除第i個(gè)特征)
subDataSet = splitDataSet(dataSet, i, value)
"""
print(subDataSet)結(jié)果為
[[1, 'no'], [1, 'no']]
[[1, 'yes'], [1, 'yes'], [0, 'no']]
[[1, 'no']]
[[1, 'yes'], [1, 'yes'], [0, 'no'], [0, 'no']]
"""
# 計(jì)算包含個(gè)i的數(shù)據(jù)占總數(shù)據(jù)的百分比
prob = len(subDataSet)/float(len(dataSet))
"""
print(prob)結(jié)果為
0.4
0.6
0.2
0.8
"""
# 計(jì)算新的香農(nóng)熵,不斷進(jìn)行迭代,這個(gè)計(jì)算過(guò)程僅在包含指定特征標(biāo)簽子集中進(jìn)行
newEntropy += prob * calcShannonEnt(subDataSet)
"""
print(calcShannonEnt(subDataSet))
0.0
0.9182958340544896
0.0
1.0
print(newEntropy)結(jié)果為
0.0
0.5509775004326937
0.0
0.8
"""
# 計(jì)算信息增益
infoGain = baseEntropy - newEntropy
# 如果信息增益大于最優(yōu)增益,即新增益newEntropy越小,信息增益越大,分類(lèi)也就更優(yōu)(分類(lèi)越簡(jiǎn)單越好)
"""
print(infoGain)結(jié)果為
0.4199730940219749
0.17095059445466854
"""
if (infoGain > bestInfoGain):
# 更新信息增益
bestInfoGain = infoGain
# 確定最優(yōu)增益的特征索引
bestFeature = i
# 更新信息增益
# 返回最優(yōu)增益的索引
return bestFeature
測(cè)試代碼及其 結(jié)果如下:
import trees
myDat,labels=trees.createDataSet()
myDat
Out[182]: [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
trees.chooseBestFeatTopSplit(myDat)
Out[183]: 0
通過(guò)數(shù)學(xué)計(jì)算演算以上數(shù)據(jù)集的最優(yōu)增益,具體如下:

整個(gè)樣本集合的熵公式,如下:
為了簡(jiǎn)便運(yùn)算,屬于魚(yú)類(lèi)的設(shè)為y,不屬于魚(yú)類(lèi)的設(shè)為n,具體見(jiàn)表格:
| 類(lèi)別 | 屬于魚(yú)類(lèi)y | 不屬于魚(yú)類(lèi)n | 總共 |
|---|---|---|---|
| 個(gè)數(shù) | 2 | 3 | 5 |
| 所占比例 | 1 |
由此可知,區(qū)分是否魚(yú)類(lèi)的整個(gè)樣本的熵為如下計(jì)算過(guò)程:
???
???
假設(shè)用某一個(gè)字段A來(lái)劃分,在這種劃分規(guī)則下的熵為
由數(shù)據(jù)集可知道,數(shù)據(jù)集有特征1和特征2,因此我們分別計(jì)算特征1和特征2的熵.
假設(shè)用特征1來(lái)劃分:
這里的特征1(不浮出水面是否可以生存)共有2個(gè)枚舉值(是、否),表示劃分成2組,那么本案例中特征1字段劃分就是v=2的情況。表示這種分組產(chǎn)生的概率,即不浮出水面是否可以生存各自的比例,具體可見(jiàn)如下表格:

為了簡(jiǎn)便運(yùn)算,浮出水面可以生存的設(shè)為,浮出水面不可以生存的設(shè)為
,則特征1的熵(
)計(jì)算結(jié)果如下:
=
(浮出水面可以生存
浮出水面不可以生存
浮出水面可以生存分割熵)
浮出水面不可以生存分割熵
假設(shè)用特征2來(lái)劃分:
這里的特征2(是否有腳蹼)共有2個(gè)枚舉值(是、否),表示劃分成2組,那么本案例中特征2字段劃分就是v=2的情況。表示這種分組產(chǎn)生的概率,即是否有腳蹼各自的比例,具體可見(jiàn)如下表格:

為了簡(jiǎn)便運(yùn)算,有腳蹼的設(shè)為,無(wú)腳蹼設(shè)為
,則特征2的熵(
)計(jì)算結(jié)果如下:
=
(有腳蹼
無(wú)腳蹼
有腳蹼分割熵)
無(wú)腳蹼分割熵
信息增益公式如下:
由此可以得到以特征1為根的信息增量為:
由此可以得到以特征2為根的信息增量為:
因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=Gain(A_%7B1%7D)" alt="Gain(A_{1})">>,所以特征1是最好的用于劃分?jǐn)?shù)據(jù)集的特征.
3.相關(guān)知識(shí)點(diǎn):信息增量的小案例
假設(shè)相親信息表如下所示:
| 網(wǎng)站ID | 年齡(歲) | 身高(cm) | 年收入(萬(wàn)元) | 學(xué)歷 | 是否相親 |
|---|---|---|---|---|---|
| XXXXXXX | 25 | 179 | 15 | 大專(zhuān) | N |
| XXXXXXX | 33 | 190 | 19 | 大專(zhuān) | Y |
| XXXXXXX | 28 | 180 | 18 | 碩士 | Y |
| XXXXXXX | 25 | 178 | 18 | 碩士 | Y |
| XXXXXXX | 46 | 177 | 100 | 碩士 | N |
| XXXXXXX | 40 | 170 | 70 | 本科 | N |
| XXXXXXX | 34 | 174 | 20 | 碩士 | Y |
| XXXXXXX | 36 | 181 | 55 | 本科 | N |
| XXXXXXX | 35 | 170 | 25 | 碩士 | Y |
| XXXXXXX | 30 | 180 | 35 | 本科 | Y |
| XXXXXXX | 28 | 174 | 30 | 本科 | N |
| XXXXXXX | 29 | 176 | 36 | 本科 | Y |
假設(shè)拿到真實(shí)的12個(gè)樣本,由于網(wǎng)站ID這種信息對(duì)大齡女青年們做出相親決策沒(méi)有什么影響,所以直接忽略,下面來(lái)看后面的數(shù)據(jù)項(xiàng)。
整個(gè)樣本集合的熵如下:
為了簡(jiǎn)便運(yùn)算,屬于相親的設(shè)為y,不相親的設(shè)為n,具體見(jiàn)表格:
| 類(lèi)別 | 相親y | 不相親n | 總共 |
|---|---|---|---|
| 個(gè)數(shù) | 7 | 5 | 12 |
| 所占比例 | 1 |
由此可知,區(qū)分是否相親的整個(gè)樣本的熵為如下計(jì)算過(guò)程:
???
???
現(xiàn)在要做的是挑出這個(gè)“樹(shù)根”,挑出“樹(shù)根”的原則是這一個(gè)點(diǎn)挑出來(lái)一刀切下去,要盡可能消除不確定性,最好一刀下去就把兩個(gè)類(lèi)分清楚,如果不行才會(huì)選擇在下面的子節(jié)點(diǎn)再切一次,切的次數(shù)越少越好。`
假設(shè)用某一個(gè)字段A來(lái)劃分,在這種劃分規(guī)則下的熵為
以“學(xué)歷”字段做分割的情況下,熵有什么變化。,具體運(yùn)算過(guò)程如下:
是指要求的熵,右側(cè)從1到v做加和,其中v表示一共劃分為多少組,A字段有3個(gè)枚舉值,表示劃分成3組,如例子中“學(xué)歷”字段就有3個(gè)枚舉值,那么用“學(xué)歷”字段劃分就是v=3的情況。Pj表示這種分組產(chǎn)生的概率,也可以認(rèn)為是一種權(quán)重,即3種學(xué)歷各自占的比例,這里大專(zhuān)是2/12,本科是5/12,碩士是5/12。
是在當(dāng)前分組狀態(tài)下的期望信息值。

=
大專(zhuān)項(xiàng)
本科項(xiàng)
碩士項(xiàng)
大專(zhuān)
大專(zhuān)分割熵)
本科
本科分割熵
碩士
碩士分割熵
則以“學(xué)歷”字段作為根的信息增益如下:
Gain(學(xué)歷)=Info-Info(學(xué)歷)=0.98-0.872=0.108bit
如果希望挑選到的是增益最大的那種方式,那么還需要試試其他字段是否有更大的信息增益。
總結(jié):
信息熵,是用來(lái)描述信息混亂程度或者說(shuō)確定程度的一個(gè)值。熵越大說(shuō)明信息混亂程度越高,做切割時(shí)越復(fù)雜,要切割若干次才能完成;熵越小說(shuō)明信息混亂程度越低,做切割時(shí)越容易,切割次數(shù)也就越少。