
決策樹是一個函數,以屬性值向量作為輸入,返回一個“決策”。
如上圖,我們輸入一系列屬性值(天氣狀況,濕度,有無風)后會得到一個要不要出去玩的一個決策。
從樣例構建決策樹
對於原始樣例集,我們選取一個最好的屬性將其分裂,這樣我們會產生多個樣例子集,同時我們會把該屬性從屬性集去掉,並且繼續對各個樣例子集進行分裂操作,直到樣例集中的所有樣例具有相同的分類。顯然,這是一個遞歸分裂的問題,在這個分裂過程中我們會遇到以下四種情況:
- 樣例集合為空集
說明測試樣例中並沒有這樣的屬性組合,因此返回其父節點得票最多的分類。 - 屬性集合為空集
屬性用完了,樣例集合仍然有多種分類,說明擁有相同屬性組合的樣例有着不同的分類,這種情況的發生是因為數據存在了噪聲,此時我們返回樣例集合得票最多的分類。 - 樣例集合分類一致
返回一個“決策”。 - 樣例集合分類不一致
選擇一個最好的屬性繼續分裂。
對於這四種情況,我們采取不同的舉措,從而最終構建出一棵決策樹。
確定最優屬性
在分裂時,我們希望能找到一個最優屬性,那么到底什么樣的屬性是最優的呢?直觀上看,我們希望能找到這樣一個屬性,它可以將混亂的集合分裂成不那么混亂的子集。
我們首先定義熵來度量集合的混亂程度:
H(V) = -ΣP(Vk)log2P(Vk)
P(Vk) = 出現Vk的概率,因此∈(0, 1)
我們研究y = -P(Vk)log2P(Vk)的單調性會發現,P(Vk)→0時,y→0; P(Vk)→1, y→0;
因此當集合中的所有分類個數一致時(集合最混亂),熵最大;相反,當集合中只有一個分類的時候,熵最小。
現在假設A屬性將樣例集合分為E1,E2...Ed,其中Ek有nk個樣例。
對各個子集的熵進行加權求平均后獲得子集的剩余期望熵:
Remainder(A) = Σnk/nHk(V)
定義信息增益來描述分裂前后熵減少了多少:
Gain(A) = HA(V) - Remainder(A)
因此使得Gain(A)最大的屬性值A為最優屬性。
偽代碼
function DecisionTree(examples, attributes) returns a tree
if examples is empty
return parent's majority
if attributes is empty
return the majority of examples
if all examples have the same classification
return the classification
A = the best attribute
tree = a new tree
for each value vk of A do
newexamples = {e: e.A=vk}
subtree = DecisionTree(newexamples, attributes-A)
add subtree to tree
return tree
隨機森林
隨機森林是決策樹的一種優化方案,其主要思想是有放回的隨機抽取多個與原始樣例集大小一樣的集合,然后根據這些樣例集合構建多棵樹,形成一個隨機森林。在做決策的時候我們選取票數最高的決策作為最終的結果。
function RandomForest(examples, attributes) returns a decision
forest = a empty set
for i = 1 to k do
exs = RandomSelectFrom(examples)
tree = DecisionTree(exs, attributes)
forest.append(tree)
過度擬合
當我們把噪聲作為了分類屬性,那么可能會出現過度擬合的問題,表現在樣例集上泛化的非常好,但在實際測試樣例中卻表現平平。對於這種問題,我們可以對決策樹進行χ2剪枝。考查只有葉節點作為后代的測試節點,對其進行統計重要性測試。若發現該節點不相關,則將其剪枝。
那么為什么我們不在構造時就進行重要性測試,從而提前避免分裂呢?原因是可能不存在好的屬性,卻存在好的屬性組合。例如XOR:
a b y
0 0 1
0 1 0
1 0 0
1 1 1
不管我們選擇屬性a還是b進行分裂,都會發現分裂后的集合仍有一半是1,一半是0,如果這時進行剪枝的話,我們就沒辦法構建一棵有效的決策樹。反之,如果我們先用a進行分裂,然后再用b進行分裂,我們會發現樣例被很好的歸類。因此單個屬性a,b都不能很好的對樣例進行分類,但是組合a、b卻能對對樣例進行分類,后剪枝正是為了解決這樣一個問題。
