決策樹的學習記錄

決策樹

西瓜書的中介紹了決策樹的一些基本算法和思想,學習後,在此記錄一番:
決策樹是模擬人在生活中的一類分類思想,那就是基於樣本的特徵不斷的劃分,直至它歸屬於最終的一類。

1. 決策樹的算法

輸入:訓練集D={{x1,y1},{x2,y2},...{xm},{ym}}.

​ 屬性集A={a1,a2,...,am}.

過程:函數TreeGenerate(D,A)

  1. 生成節點Node
  2. if D中樣本全部屬於同一類別C then
  3. ​ 將Node節點標記爲C類葉子結點 return
  4. endif
  5. if A=空集 OR D在A上的取值全部相同 then
  6. ​ 將Node節點標記爲葉子結點,分爲D中樣本最多的類別 return
  7. endif
  8. 從A中選擇最優劃分屬性a
  9. for a 的每一個值 av do
  10. ​ 爲node 生成一個分支;令Dv 表示D中在a 取值爲av 的子集
  11. ​ if Dv 爲空集
  12. ​ 將分支結點標記爲葉子結點,類別爲D中樣本最多的類 return
  13. ​ else
  14. ​ 以TreeGenerate( Dv ,A\ a )爲分支結點
  15. ​ endif
  16. endfor

​ 輸出:以node結點爲根結點的一顆決策樹

遞歸生成一個決策樹。

2. 選擇最優劃分

​ 信息熵(information entropy):度量信息集合純度的指標。

Ent(D)=k=1|ψ|pklog2pk

​ 信息熵越小,信息純度越大。

​ 信息增益:信息集合劃分前後的信息熵的差。

Gain(D,ai)=Ent(D)v=1V|Dv||D|Ent(Dv)

​ 最優化分即劃分後信息集合純度和×集合大小的權值的值最大。

a=akA|aiA(Gain(D,ai)<=Gain(D,ak))

3.增益率

​ 信息增益偏好於可取數目較多的屬性,因此有時候並不可靠。

​ 消除這種影響,則使用增益率代替信息增益:

Gainratio(D,ai)=Gain(D,ai)IV(a)

IV(a)=v=1|V||Dv||D|log2|Dv||D|

​ 增益率偏好於可取數目較少的屬性,所以有啓發式算法C4.5,先選出信息增益

​ 高於平均的屬性,再選擇增益率最高的。

4.基尼指數

​ 基尼值也是體現了信息集合的純度的一種指標,它的含義是,在集合中任意

​ 抽取兩個樣本,樣本類別不一致的概率。

Gini(D)=k=1|y|t!=k|y|pkpt=1k=1|y|pk2

​ 基尼值越小,信息集合純度越高。

​ 基尼指數大概類比信息增益:

Giniindex(D,a)=v=1|V||Dv||D|Gini(Dv)

​ 選擇基尼指數最小的屬性爲劃分屬性。

5. 剪枝處理

​ 預剪枝和後剪枝兩種,剪枝與否的依據是該次劃分是否提高了決策樹泛化

​ 性能。泛化性能的度量使用性能評估方法,如留出法,交叉驗證法,自助法。

​ 評估決策樹對驗證集的泛化精度。決定是否展開結點分支。

​ 特點:預剪枝,容易導致欠擬合,使得很多的分支不得展開。後剪枝,消耗的

​ 時間很多,時間開銷巨大,優點,比預處理的擬合度一般要好。

6. 連續值離散化

​ 對於有的屬性是連續的值,採用離散化的方法,例如:連續值屬性a,D上

​ 樣本在屬性a上有n個取值,則對n個屬性取值排序,求得n-1箇中間值,作爲待

​ 劃分點,這些點就可以和普通的屬性相同的看待了。所以一個待劃分的屬性a

​ 變成了n-1個待劃分的屬性一樣。對於這n-1個值中的任意值ai ,D中樣本比ai

​ 小的歸爲一個子集,比ai 大的歸爲一個子集,所以算是一種二劃分屬性。書上

​ 計算公式和Gain無異,故不再記錄。

​ 值得注意的是,連續屬性在一次分類後,後續的分類任然要考慮此屬性。

對於這裏的處理我有寫一點代碼,模擬這種情況,數據來自西瓜書的p84頁的西瓜

數據。

import re
from numpy import *
from math import log

def Ent(p0,p1):
    sum = 0
    if p0!=0:
        sum += p0*log(p0,2)
    if p1!=0:
        sum +=p1*log(p1,2)
    return -sum


file = open('mido.txt')
testArray = zeros((1,17))
testLabel = []

dataList = re.split(r'[ \n]',file.readline())
dataList.pop()

testLabel = re.split(r' ',file.readline())
file.close()
dataDir = {}                                #樣本的字典
for i in range(len(dataList)):  
    dataDir[dataList[i]] = testLabel[i]
dataList = sorted(dataList)                 #樣本有序化
t = []
for i in range(1,len(dataList)):
    a = float(dataList[i-1])
    b = float(dataList[i])
    t.append((a+b)/2)
dataV = len(dataList)                       #樣本空間的數量|y|
maxGain = -1
answer = 0
for i in range(1,dataV):
    sum = 0.0
    p0 = 0
    p1 = 0
    for j in range(i):
        if dataDir[dataList[j]]== '0':
            p0+=1
        elif dataDir[dataList[j]]=='1':
            p1+=1
    sum += ((i)/dataV)*Ent(p0/i,p1/i)
    p0=0
    p1=0
    for j in range(i,dataV):
        if dataDir[dataList[j]]== '0':
            p0+=1
        elif dataDir[dataList[j]]=='1':
            p1+=1
    sum += (1-i/dataV)*Ent(p0/(dataV-i),p1/(dataV-i))
    sum = Ent(8/dataV,9/dataV) - sum
    print(sum)
    if sum>maxGain:
        answer = t[i-1]
        maxGain = sum
print('最優的劃分點:',answer,' 信息增益爲:',maxGain)

手工寫制,只是一個腳本文件略顯粗糙,但是其思想與書上吻合,是決策樹求最優

劃分的集中實現,並沒有直接求出決策樹。計算的結果也是 一致的,因爲初學,中

間的計算沒有用到numpy的一些特性。

7.缺失值處理

  當有樣本中有些屬性有部分樣本缺失的情況下依然可以通過加權值處理,利用樣本產生決策樹。而不是浪費了數據。對於這樣的樣本,需要解決兩個問題:
1. 在屬性值缺失的情況下怎麼選擇劃分屬性。
2. 給定劃分屬性,如果樣本在該屬性上存在缺失,怎麼對樣本進行劃分。

如果存在訓練集D,屬性a,D˘ 爲D中在a屬性上不存在缺失的樣本的子集。我們僅僅用D˘ 驗證a屬性的優劣。若給定樣本x 的權值爲wx

ρ=xDwxxDwx

pk=xDkwxxDwx,1k|Y|

rv=xDvwxxDwx,1vV

基於上面的定義對信息增益式進行推廣:
Gain(D,a)=ρ×Gain(D,a)

=ρ×(Ent(D)v=1vVEnt(Dv))

Ent(Dv)=k=1|Y|pklog2pk).

7.決策樹算法

  • IDE3 信息增益
  • C4.5 增益率 缺失值處理 連續值離散處理
  • CART 基尼指數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章