標籤:des style class blog http ext
1、介紹
?決策樹(decision tree)是一種有監督的機器學習演算法,是一個分類演算法。在給定訓練集的條件下,產生一個自頂而下的決策樹,樹的根為起點,樹的葉子為樣本的分類,從根到葉子的路徑就是一個樣本進行分類的過程。
?為一個決策樹的例子,見http://zh.wikipedia.org/wiki/%E5%86%B3%E7%AD%96%E6%A0%91 ? 可見,決策樹上的判斷節點是對某一個屬性進行判斷,產生的路徑數量為該屬性可能的取值,最終到葉子節點時,就完成一個分類(或預測)。決策樹具有直觀、易於解釋的特性。
2、決策樹產生演算法 ?本文主要討論如何由一個給定的訓練集產生一個決策樹。如果都一個資料集合$D$,其特徵集合為$A$,那麼以何種順序對A中的特徵進行判斷就成為決策樹產生過程中的關鍵。首先給出一個決策樹產生演算法-ID3演算法(參考《統計學習方法》李航著)--------------------我是演算法開始分割線-------------------------------------------
ID3演算法: 輸入:訓練資料集D,特徵集A,閾值e 輸出:決策樹T (1)若D中所有樣本屬於同一類Ck,則T為單節點樹,並將類Ck作為該節點的類標記,返回T; (2)A為空白集,T為單節點樹,將D中執行個體數最大的類Ck作為該節點的類標記,返回T; (3)否則,計算A中各特徵對D的資訊增益,選擇資訊增益最大的特徵值Ag; (4)如果Ag<e,則置T為單節點樹,將D中執行個體數最大的類Ck作為該節點的類標記,返回T; (5)否則,對Ag的每一個可能的取值ai,依Ag=ai將D分割為若干非空子集Di,將Di中執行個體數最大的類作為標記,構建子節點,由節點及其子節點構成樹T,返回T; (6)對第i個子節點,以Di為訓練集,以 A-{Ag}為特徵集,遞迴調用(1)~(5)步,得到子樹Ti,返回Ti。--------------------我是演算法結束分割線------------------------------------------- 演算法第(3)步中,資訊增益是評估每一個特徵值對D的劃分效果,劃分的原則為將無序的資料變得盡量有序。評價隨機變數不確定性一個概念是熵,熵越大,不確定性越大。如果確定一個特徵Ag,在確定該特徵前後,D的熵的變化值就是特徵Ag的資訊增益。
3、熵及資訊增益
熵: 設X是一個取有限個值(n)的離散隨機變數,其機率分布為\[P(X=x_{i})=P_{i}, i=1,2,...,n\]則隨機變數X的熵定義為\[H(x) = - \sum\limits_{i = 1}^n {{P_i}\log {P_i}} \]
資訊增益: 訓練集為\(D\),\(|D|\)為樣本容量,設有k個類\({C_k}\),k=1,...k, \({|C_k|}\)為類\({C_k}\)的樣本個數,且有\(\sum\limits_{i = 1}^k {|{C_k}|} = |D|\) 設特徵A有n個不同取值\(\{ {a_{1,}}{a_2}, \cdots ,{a_n}\} \) ,根據A的值,將D劃分為n個子集\({D_1},{D_2}, \cdots ,{D_n}\), \({|D_i|}\)為\({D_i}\) 的樣本數,\(\sum\limits_{i = 1}^n {|{D_i}|} = |D|\)。 記子集\({D_i}\)中屬於類\({C_k}\)的樣本集合為\({D_{ik}}\),即\({D_{ik}} = {D_i} \cap {C_k}\)。 \({|D_{ik}|}\)為\({D_{ik}}\)的樣本個數。 (1)資料集D的經驗熵H(D)\[H(D) = - \sum\limits_{k = 1}^K {\frac{{|{C_k}|}}{{|D|}}{{\log }_2}} \frac{{|{C_k}|}}{{|D|}}\] (2)特徵A對資料集D的經驗條件熵H(D|A)\[H(D|A) = \sum\limits_{i = 1}^n {\frac{{|{D_i}|}}{{|D|}}H({D_i}) = - } \sum\limits_{i = 1}^n {\frac{{|{D_i}|}}{{|D|}}\sum\limits_{k = 1}^K {\frac{{|{D_{ik}}|}}{{|{D_i}|}}} } {\log _2}\frac{{|{D_{ik}}|}}{{|{D_i}|}}\] (3)計算資訊增益\[g(D,A) = H(D) - H(D|A)\]資訊增益越大,表示A對D趨於有序的貢獻越大。 -------------------------------分割線------------------------------------------------
決策樹的R語言實現如下: library(plyr) # 測試資料集 http://archive.ics.uci.edu/ml/datasets/Car+Evaluation ##計算訓練集合D的熵H(D)##輸入:trainData 訓練集,類型為資料框## nClass 指明訓練集中第nClass列為分類結果##輸出:訓練集的熵cal_HD <- function(trainData, nClass){ if ( !(is.data.frame(trainData) & is.numeric(nClass)) ) "input error" if (length(trainData) < nClass) "nClass is larger than the length of trainData" rownum <- nrow(trainData) #對第nClass列的值統計頻數 calss.freq <- count(trainData,nClass) #計算每個取值的 機率*log2(機率) calss.freq <- mutate(calss.freq, freq2 = (freq / rownum)*log2(freq / rownum)) -sum(calss.freq[,"freq2"]) #使用arrange代替order,方便的按照多列對資料框進行排序 #mtcars.new2 <- arrange(mtcars, cyl, vs, gear) } #cal_HD(mtcars,11) ##計算訓練集合D對特徵值A的條件熵H(D|A)##輸入:trainData 訓練集,類型為資料框## nClass 指明訓練集中第nClass列為分類結果## nA 指明trainData中條件A的列號##輸出:訓練集trainData對特徵A的條件熵cal_HDA <- function(trainData, nClass, nA){ rownum <- nrow(trainData) #對第nA列的特徵A計算頻數 nA.freq <- count(trainData,nA) i <- 1 sub.hd <- c() for (nA.value in nA.freq[,1]){ #取特徵值A取值為na.value的子集 sub.trainData <- trainData[which(trainData[,nA] == nA.value),] sub.hd[i] <- cal_HD(sub.trainData,nClass) i <- i+1 } nA.freq <- mutate(nA.freq, freq2 = (freq / rownum)*sub.hd) sum(nA.freq[,"freq2"])} ##計算訓練集合D對特徵值A的資訊增益g(D,A)##輸入:trainData 訓練集,類型為資料框## nClass 指明訓練集中第nClass列為分類結果## nA 指明trainData中特徵A的列號##輸出:訓練集trainData對特徵A的資訊增益g_DA <- function(trainData, nClass, nA){ cal_HD(trainData, nClass) - cal_HDA(trainData, nClass, nA)} ##根據訓練集合產生決策樹##輸入:trainData 訓練集,類型為資料框## strRoot 指明根節點的屬性名稱## strRootAttri 指明根節點的屬性取值## nClass 指明訓練集中第nClass列為分類結果## cAttri 向量,表示當前可用的特徵集合,用列號表示## e 如果特徵的最大資訊增益小於e,則剩餘作為一個分類,類頻數最高的最為分類結果##輸出:決策樹Tgen_decision_tree <- function(trainData, strRoot, strRootAttri, nClass, cAttri, e){ # 樹的描述,(上級節點名稱、上級節點屬性值、自己節點名稱,自己節點的取值) decision_tree <- data.frame() nClass.freq <- count(trainData,nClass) ##類別出現的頻數 nClass.freq <- arrange(nClass.freq, desc(freq)) ##按頻數從低到高排列 col.name <- names(trainData) ##trainData的列名 ##1、如果D中所有屬於同一類Ck,則T為單節點樹 if nrow(nClass.freq) == 1{ rbind(decision_tree, c(strRoot, strRootAttri, nClass.freq[1,1], ‘‘)) return decision_tree } ##2、如果屬性cAttri為空白,將D中頻數最高的類別返回 if length(cAttri) == 0{ rbind(decision_tree, c(strRoot, strRootAttri, nClass.freq[1,1], ‘‘)) return decision_tree } ##3、計算cAttri中各特徵值對D的資訊增益,選擇資訊增益最大的特徵值Ag及其資訊增益 maxDA <- 0 #記錄最大的資訊增益 maxAttriName <- ‘‘ #記錄最大資訊增益對應的屬性名稱 maxAttriIndex <- ‘‘ #記錄最大資訊增益對應的屬性列號 for(i in cAttri){ curDA <- g_DA(trainData,nClass,i) if (maxDA <= curDA){ maxDA <- curDA maxAttriName <- col.name[i] } } ##4、如果最大資訊增益小於閾值e,將D中頻數最高的類別返回 if (maxDA < e){ rbind(decision_tree, c(strRoot, strRootAttri, nClass.freq[1,1], ‘‘)) return decision_tree } ##5、否則,對Ag的每一可能值ai,依Ag=ai將D分割為若干非空子集Di ## 將Di中執行個體數最大的類作為標記,構建子節點 ## 由節點及其子節點構成樹T,返回T for (oneValue in unique(trainData[,maxAttriName])){ sub.train <- trainData[which(trainData[,maxAttriName] == oneValue),] #Di #sub.trian.freq <- count(sub.train,nClass) ##類別出現的頻數 #sub.trian.freq <- arrange(sub.trian.freq, desc(freq)) ##按頻數從低到高排列 rbind(decision_tree, c(strRoot, strRootAttri, maxAttriName , oneValue)) ##6、遞迴構建下一步 # 剔除已經使用的屬性 next.cAttri <- cAttri[which(cAttri !=maxAttriIndex)] # 遞迴調用 next.dt <-gen_decision_tree(sub.train, maxAttriName, oneValue, nClass, next.cAttri, e) rbind(decision_tree, next.dt) } names(decision_tree) <- c(‘preName‘,‘preValue‘,‘curName‘,‘curValue‘) decision_tree} ---------------決策樹總結-------------------1、R中有實現決策樹演算法的包rpart,和畫出決策樹的包rpart.plot,本例自己實現決策樹演算法是為了更好的理解。2、由於決策樹只能處理離散屬性,因此連續屬性應首先進行離散化。3、決策樹易於理解,對業務的解釋性較強。4、ID3演算法容易引起過擬合,需考慮樹的剪枝。