1. 決策樹的定義
決策樹,顧名思義,就是用來決策的樹,通常來說,決策樹分為C4.5,CART等,其實他們都是一個東西,區別就是在於他們的分支方法不同。決策樹我們只要理解,他是一種將數據依據某幾個最顯著的屬性,不斷划分,以后遇到新的數據時,可以利用我們之前得到的決策樹進行判斷,分析新的數據和歷史數據中的哪一個類最相似。這就是決策樹。在基於決策樹的其他算法例如隨機森林,gbdt,xgboost等,只不過是使用了一些提升算法,本質上他們都是類似的,他們區別就是在於如何生成樹,如何生成樹,其實就是如何分裂樹枝。就像GLM一樣,可以解釋邏輯斯特回歸,高斯回歸等一系列模型。
2. 決策樹的分支
上一段我也說了,決策樹的核心就是在於分支的確定,而實際上,我們通常使用熵,基尼系數等損失函數來划分決策樹,對於回歸變量我們通常使用最小化方差(MSE)。
我們計算某一個類別的基尼系數時,我們只要將這一類從總的數據集中抽取出來,計算划分后的兩個集合的損失與原集合的差值來判斷是否采用這一個屬性來划分數據集。
基尼系數的計算:
def giniimpurity(rows): total=len(rows) countresult=uniquecount(rows) // 其中 uniquecount 函數是計算每一個屬性有多少個類別,並統計數量。 giniimp=0 for num in countresult: p1=float(countresult[num])/total for num2 in countresult: if num==num2: continue p2=float(countresult[num2])/total giniimp += p1*p2 return giniimp
熵的計算:
def entropy(rows): from math import log log2=lambda x:log(x)/log(2) entro=0 total=len(rows) countresult = uniquecount(rows) for name in countresult: pi=float(countresult[name])/total entro =entro - pi*log2(pi) return entro
方差的計算:
def MSE(rows): datamean = float(np.mean(rows)) R2 = sum([(x - datamean)**2 for x in rows]) return R2
有了我們的計算損失的方式,我們便可以計算采用哪一個屬性划分數據:
def selectBestFeature(rows,scoref=MSE): best_gain = float('inf') best_col=0 best_iden=None for col in xrange(len(rows[0])-1): eachtypenum=counteachtype(rows,col)#對於每一列計算他們每一列有哪些屬性。 for iden in eachtypenum.keys(): (set1,set2)=divideSetLast(rows,col,iden) #按照每一列的每一個屬性划分數據集 if len(set1)==0 and len(set2)!=0: gain=scoref(set2) if len(set1)!=0 and len(set2) ==0: gain=scoref(set1) if len(set1) !=0 and len(set2) !=0: gain=scoref(set1)+scoref(set2)#計算划分后的得分 if gain < best_gain and len(set1)>0 and len(set2)>0: best_gain=gain best_col=col best_iden=iden return (best_col,best_iden,best_gain)
所以我們得到了最優分裂特征后便按照這個特征划分數據集,將數據集按照這個特征的值的大小分成兩個部分,這便是樹枝的分叉。
3. 決策樹處理缺失數據
決策樹處理缺失數據是一個非常好的方式,但是,我覺得它更適合處理只有少部分缺失,對於稀疏數據使用決策樹來處理不是一個非常好的選擇。
決策樹來處理缺失數據依然是在樹枝分裂的階段,我們可以看到在我們的最優特征的選擇上的代碼中,我們是如何計算score的值的呢? 使用的是我們預設的價值函數。實際上,我們處理缺失值也是在這里做文章,對於缺失值,我們先不管他,先將其中非缺失的部分做一個划分,然后對於缺失值,我們依次填充缺失值,那么我們得到的是這個缺失值在每一個類別的可能性。也就是說,我們最后得到的不是一個確定的集合,而是數據屬於這個集合的可能性!
這里也是解釋了我為什么說適用於少部分缺失,如果大部分缺失的話,就是造成很大的困擾,每一次分裂,都有太多的可能性,造成決策樹過於龐大,同時可視化程度降低,造成數據過擬合和欠擬合。
4. 決策樹的剪枝
決策樹的剪枝,就是在生成一顆決策樹后對決策樹進行結構上的優化,通常分為預剪枝,后剪枝。在周志華的西瓜書中說:訓練集用來決定樹生成過程中每個結點划分所選擇的屬性;驗證集在預剪枝中用於決定該結點是否有必要依據該屬性進行展開,在后剪枝中用於判斷該結點是否需要進行剪枝。
預剪枝就是在生成樹的同時進行剪枝,也就是說在進行分叉的同時,計算分叉與不分叉兩種情況下,樹的預測性能是否有提高,如果有提高那么就進行分叉,否則拋棄這一次的分叉。
這個地方我想提的是,XGboost 的剪枝算法是使用樹的層數和分支樹作為懲罰項,這樣可以有效的避免樹的過擬合。
后剪枝葉就是在一棵樹的生成后,自下而上地進行收縮,步驟類似於預剪枝,看兩課子樹如果合並的話,對於樹的性能是否有提高